Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sequence xdg-top-level and xdg-surface configure events correctly. #281

Merged
merged 5 commits into from
Mar 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 1 addition & 21 deletions src/server/frontend_wayland/wl_surface_role.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,27 +139,7 @@ void WlAbstractMirWindow::commit(WlSurfaceState const& state)

geometry::Size WlAbstractMirWindow::window_size()
{
if (window_size_.is_set())
{
return window_size_.value();
}
else
{
auto buffer_size = surface->buffer_size();

// Sometimes, when using xdg-shell, qterminal creates an insanely tall buffer
const auto max_allowed_buffer_height = geometry::Height{10000};
const auto corrected_buffer_height = geometry::Height{1000};

if (buffer_size.height > max_allowed_buffer_height)
{
log_warning("Insane buffer height sanitized: buffer_size.height = %d (was %d)",
corrected_buffer_height.as_int(), buffer_size.height.as_int());
buffer_size.height = corrected_buffer_height;
}

return buffer_size;
}
return window_size_.is_set()? window_size_.value() : surface->buffer_size();
}

void WlAbstractMirWindow::visiblity(bool visible)
Expand Down
2 changes: 1 addition & 1 deletion src/server/frontend_wayland/wl_surface_role.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,12 @@ class WlAbstractMirWindow : public WlSurfaceRole

geometry::Size window_size();
shell::SurfaceSpecification& spec();
void commit(WlSurfaceState const& state) override;

private:
std::unique_ptr<shell::SurfaceSpecification> pending_changes;
bool buffer_list_needs_refresh = true;

void commit(WlSurfaceState const& state) override;
void visiblity(bool visible) override;
};

Expand Down
61 changes: 45 additions & 16 deletions src/server/frontend_wayland/xdg_shell_v6.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,15 @@ class XdgSurfaceV6 : wayland::XdgSurfaceV6, WlAbstractMirWindow
void get_popup(uint32_t id, struct wl_resource* parent, struct wl_resource* positioner) override;
void set_window_geometry(int32_t x, int32_t y, int32_t width, int32_t height) override;
void ack_configure(uint32_t serial) override;
void commit(WlSurfaceState const& state) override;

void set_parent(optional_value<SurfaceId> parent_id);
void set_title(std::string const& title);
void move(struct wl_resource* seat, uint32_t serial);
void resize(struct wl_resource* /*seat*/, uint32_t /*serial*/, uint32_t edges);
void set_notify_resize(std::function<void(geometry::Size const& new_size, MirWindowState state, bool active)> notify_resize);
void set_next_commit_action(std::function<void()> action);
void clear_next_commit_action();
void set_max_size(int32_t width, int32_t height);
void set_min_size(int32_t width, int32_t height);
void set_maximized();
Expand All @@ -75,6 +78,7 @@ class XdgSurfaceV6 : wayland::XdgSurfaceV6, WlAbstractMirWindow
struct wl_resource* const parent;
std::shared_ptr<Shell> const shell;
std::shared_ptr<XdgSurfaceV6EventSink> const sink;
std::function<void()> next_commit_action{[]{}};
};

class XdgSurfaceV6EventSink : public BasicSurfaceEventSink
Expand All @@ -91,15 +95,13 @@ class XdgSurfaceV6EventSink : public BasicSurfaceEventSink
[](auto, auto, auto){};

private:
void post_configure(int serial) const;

std::shared_ptr<bool> const destroyed;
};

class XdgPopupV6 : wayland::XdgPopupV6
{
public:
XdgPopupV6(struct wl_client* client, struct wl_resource* parent, uint32_t id);
XdgPopupV6(struct wl_client* client, struct wl_resource* parent, uint32_t id, XdgSurfaceV6* self);

void grab(struct wl_resource* seat, uint32_t serial) override;
void destroy() override;
Expand Down Expand Up @@ -242,7 +244,7 @@ void mf::XdgSurfaceV6::get_popup(uint32_t id, struct wl_resource* parent, struct
params->aux_rect_placement_offset_y = pos->aux_rect_placement_offset_y;
params->placement_hints = mir_placement_hints_slide_any;

new XdgPopupV6{client, parent, id};
new XdgPopupV6{client, parent, id, this};
surface->set_role(this);
}

Expand Down Expand Up @@ -433,15 +435,35 @@ void mf::XdgSurfaceV6::unset_maximized()
}
}

void mir::frontend::XdgSurfaceV6::clear_next_commit_action()
{
next_commit_action = []{};
}

void mir::frontend::XdgSurfaceV6::set_next_commit_action(std::function<void()> action)
{
next_commit_action = [this, action]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[non-blocking] perhaps next_commit_action could be a vector so multiple lambdas can be added and executed with no danger of overwriting and not running an action.

{
action();
auto const serial = wl_display_next_serial(wl_client_get_display(client));
zxdg_surface_v6_send_configure(event_sink, serial);
};
}

void mir::frontend::XdgSurfaceV6::commit(mir::frontend::WlSurfaceState const& state)
{
WlAbstractMirWindow::commit(state);
next_commit_action();
clear_next_commit_action();
}

// XdgSurfaceV6EventSink

mf::XdgSurfaceV6EventSink::XdgSurfaceV6EventSink(WlSeat* seat, wl_client* client, wl_resource* target,
wl_resource* event_sink, std::shared_ptr<bool> const& destroyed)
: BasicSurfaceEventSink(seat, client, target, event_sink),
destroyed{destroyed}
{
auto const serial = wl_display_next_serial(wl_client_get_display(client));
post_configure(serial);
}

void mf::XdgSurfaceV6EventSink::send_resize(geometry::Size const& new_size) const
Expand All @@ -454,19 +476,15 @@ void mf::XdgSurfaceV6EventSink::send_resize(geometry::Size const& new_size) cons
}));
}

void mf::XdgSurfaceV6EventSink::post_configure(int serial) const
{
seat->spawn(run_unless(destroyed, [event_sink= event_sink, serial]()
{
zxdg_surface_v6_send_configure(event_sink, serial);
}));
}

// XdgPopupV6

mf::XdgPopupV6::XdgPopupV6(struct wl_client* client, struct wl_resource* parent, uint32_t id)
mf::XdgPopupV6::XdgPopupV6(struct wl_client* client, struct wl_resource* parent, uint32_t id, XdgSurfaceV6* self)
: wayland::XdgPopupV6(client, parent, id)
{}
{
// TODO Make this readable!!! This "works" by exploiting the non-obvious side-effect
// of causing a zxdg_surface_v6_send_configure() event to become pending.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding this comment

self->set_next_commit_action([]{});
}

void mf::XdgPopupV6::grab(struct wl_resource* seat, uint32_t serial)
{
Expand All @@ -490,6 +508,8 @@ mf::XdgToplevelV6::XdgToplevelV6(struct wl_client* client, struct wl_resource* p
self->set_notify_resize(
[this](geom::Size const& new_size, MirWindowState state, bool active)
{
this->self->clear_next_commit_action();

wl_array states;
wl_array_init(&states);

Expand Down Expand Up @@ -521,6 +541,15 @@ mf::XdgToplevelV6::XdgToplevelV6(struct wl_client* client, struct wl_resource* p

wl_array_release(&states);
});

self->set_next_commit_action(
[resource = this->resource, self]
{
wl_array states;
wl_array_init(&states);
zxdg_toplevel_v6_send_configure(resource, 0, 0, &states);
wl_array_release(&states);
});
}

void mf::XdgToplevelV6::destroy()
Expand Down