diff --git a/src/core/window.c b/src/core/window.c
index aebdc40a5..9e329671d 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -2968,6 +2968,9 @@ meta_window_maximize_internal (MetaWindow *window,
meta_window_recalc_features (window);
set_net_wm_state (window);
+ if (window->surface && window->maximized_horizontally && window->maximized_vertically)
+ meta_wayland_surface_send_maximized (window->surface);
+
g_object_freeze_notify (G_OBJECT (window));
g_object_notify (G_OBJECT (window), "maximized-horizontally");
g_object_notify (G_OBJECT (window), "maximized-vertically");
@@ -3419,6 +3422,9 @@ meta_window_unmaximize_internal (MetaWindow *window,
set_net_wm_state (window);
}
+ if (window->surface && !window->maximized_horizontally && !window->maximized_vertically)
+ meta_wayland_surface_send_unmaximized (window->surface);
+
g_object_freeze_notify (G_OBJECT (window));
g_object_notify (G_OBJECT (window), "maximized-horizontally");
g_object_notify (G_OBJECT (window), "maximized-vertically");
@@ -3525,6 +3531,9 @@ meta_window_make_fullscreen_internal (MetaWindow *window)
/* For the auto-minimize feature, if we fail to get focus */
meta_screen_queue_check_fullscreen (window->screen);
+ if (window->surface)
+ meta_wayland_surface_send_fullscreened (window->surface);
+
g_object_notify (G_OBJECT (window), "fullscreen");
}
}
@@ -3581,6 +3590,9 @@ meta_window_unmake_fullscreen (MetaWindow *window)
meta_window_update_layer (window);
+ if (window->surface)
+ meta_wayland_surface_send_unfullscreened (window->surface);
+
g_object_notify (G_OBJECT (window), "fullscreen");
}
}
@@ -5554,6 +5566,14 @@ meta_window_appears_focused_changed (MetaWindow *window)
if (window->frame)
meta_frame_queue_draw (window->frame);
+
+ if (window->surface)
+ {
+ if (meta_window_appears_focused (window))
+ meta_wayland_surface_activated (window->surface);
+ else
+ meta_wayland_surface_deactivated (window->surface);
+ }
}
/**
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index 77000b274..e4d3cb8c0 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -519,42 +519,12 @@ sync_reactive (MetaWaylandSurface *surface)
surface_should_be_reactive (surface));
}
-static void
-surface_state_changed (MetaWaylandSurface *surface)
-{
- if (surface->window)
- meta_wayland_surface_configure_notify (surface,
- surface->window->rect.width,
- surface->window->rect.height);
-}
-
-static void
-window_appears_focused_changed (MetaWindow *window,
- GParamSpec *pspec,
- gpointer user_data)
-{
- MetaWaylandSurface *surface = user_data;
-
- surface_state_changed (surface);
-}
-
void
meta_wayland_surface_set_window (MetaWaylandSurface *surface,
MetaWindow *window)
{
- if (surface->window)
- {
- g_signal_handlers_disconnect_by_func (surface->window, window_appears_focused_changed, surface);
- }
-
surface->window = window;
- if (surface->window)
- {
- g_signal_connect (surface->window, "notify::appears-focused",
- G_CALLBACK (window_appears_focused_changed), surface);
- }
-
sync_reactive (surface);
}
@@ -821,9 +791,46 @@ xdg_surface_resize (struct wl_client *client,
}
static void
-xdg_surface_ack_configure (struct wl_client *client,
- struct wl_resource *resource,
- uint32_t serial)
+xdg_surface_set_output (struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *output)
+{
+ g_warning ("TODO: support xdg_surface.set_output");
+}
+
+static void
+xdg_surface_request_change_state (struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t state_type,
+ uint32_t value,
+ uint32_t serial)
+{
+ MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
+
+ surface->state_changed_serial = serial;
+
+ switch (state_type)
+ {
+ case XDG_SURFACE_STATE_MAXIMIZED:
+ if (value)
+ meta_window_maximize (surface->window, META_MAXIMIZE_BOTH);
+ else
+ meta_window_unmaximize (surface->window, META_MAXIMIZE_BOTH);
+ break;
+ case XDG_SURFACE_STATE_FULLSCREEN:
+ if (value)
+ meta_window_make_fullscreen (surface->window);
+ else
+ meta_window_unmake_fullscreen (surface->window);
+ }
+}
+
+static void
+xdg_surface_ack_change_state (struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t state_type,
+ uint32_t value,
+ uint32_t serial)
{
/* Do nothing for now. In the future, we'd imagine that
* we'd ignore attaches when we have a state pending that
@@ -832,44 +839,12 @@ xdg_surface_ack_configure (struct wl_client *client,
* client gets the new state. */
}
-static void
-xdg_surface_set_maximized (struct wl_client *client,
- struct wl_resource *resource)
-{
- MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
- meta_window_maximize (surface->window, META_MAXIMIZE_BOTH);
-}
-
-static void
-xdg_surface_unset_maximized (struct wl_client *client,
- struct wl_resource *resource)
-{
- MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
- meta_window_unmaximize (surface->window, META_MAXIMIZE_BOTH);
-}
-
-static void
-xdg_surface_set_fullscreen (struct wl_client *client,
- struct wl_resource *resource,
- struct wl_resource *output_resource)
-{
- MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
- meta_window_make_fullscreen (surface->window);
-}
-
-static void
-xdg_surface_unset_fullscreen (struct wl_client *client,
- struct wl_resource *resource)
-{
- MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
- meta_window_unmake_fullscreen (surface->window);
-}
-
static void
xdg_surface_set_minimized (struct wl_client *client,
struct wl_resource *resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
+
meta_window_minimize (surface->window);
}
@@ -881,11 +856,9 @@ static const struct xdg_surface_interface meta_wayland_xdg_surface_interface = {
xdg_surface_set_app_id,
xdg_surface_move,
xdg_surface_resize,
- xdg_surface_ack_configure,
- xdg_surface_set_maximized,
- xdg_surface_unset_maximized,
- xdg_surface_set_fullscreen,
- xdg_surface_unset_fullscreen,
+ xdg_surface_set_output,
+ xdg_surface_request_change_state,
+ xdg_surface_ack_change_state,
xdg_surface_set_minimized,
};
@@ -1688,57 +1661,82 @@ meta_wayland_shell_init (MetaWaylandCompositor *compositor)
g_error ("Failed to register a global wl-subcompositor object");
}
-static void
-fill_states (struct wl_array *states, MetaWindow *window)
-{
- uint32_t *s;
-
- if (META_WINDOW_MAXIMIZED (window))
- {
- s = wl_array_add (states, sizeof *s);
- *s = XDG_SURFACE_STATE_MAXIMIZED;
- }
- if (meta_window_is_fullscreen (window))
- {
- s = wl_array_add (states, sizeof *s);
- *s = XDG_SURFACE_STATE_FULLSCREEN;
- }
- if (meta_grab_op_is_resizing (window->display->grab_op))
- {
- s = wl_array_add (states, sizeof *s);
- *s = XDG_SURFACE_STATE_RESIZING;
- }
- if (meta_window_appears_focused (window))
- {
- s = wl_array_add (states, sizeof *s);
- *s = XDG_SURFACE_STATE_ACTIVATED;
- }
-}
-
void
meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
int new_width,
int new_height)
{
if (surface->xdg_surface.resource)
- {
- struct wl_client *client = wl_resource_get_client (surface->xdg_surface.resource);
- struct wl_display *display = wl_client_get_display (client);
- uint32_t serial = wl_display_next_serial (display);
- struct wl_array states;
-
- wl_array_init (&states);
- fill_states (&states, surface->window);
-
- xdg_surface_send_configure (surface->xdg_surface.resource, new_width, new_height, &states, serial);
-
- wl_array_release (&states);
- }
+ xdg_surface_send_configure (surface->xdg_surface.resource,
+ new_width, new_height);
else if (surface->wl_shell_surface.resource)
wl_shell_surface_send_configure (surface->wl_shell_surface.resource,
0, new_width, new_height);
}
+static void
+send_change_state (MetaWaylandSurface *surface,
+ uint32_t state_type,
+ uint32_t value)
+{
+ if (surface->xdg_surface.resource)
+ {
+ uint32_t serial;
+
+ if (surface->state_changed_serial != 0)
+ {
+ serial = surface->state_changed_serial;
+ surface->state_changed_serial = 0;
+ }
+ else
+ {
+ struct wl_client *client = wl_resource_get_client (surface->xdg_surface.resource);
+ struct wl_display *display = wl_client_get_display (client);
+ serial = wl_display_next_serial (display);
+ }
+
+ xdg_surface_send_change_state (surface->xdg_surface.resource, state_type, value, serial);
+ }
+}
+
+void
+meta_wayland_surface_send_maximized (MetaWaylandSurface *surface)
+{
+ send_change_state (surface, XDG_SURFACE_STATE_MAXIMIZED, TRUE);
+}
+
+void
+meta_wayland_surface_send_unmaximized (MetaWaylandSurface *surface)
+{
+ send_change_state (surface, XDG_SURFACE_STATE_MAXIMIZED, FALSE);
+}
+
+void
+meta_wayland_surface_send_fullscreened (MetaWaylandSurface *surface)
+{
+ send_change_state (surface, XDG_SURFACE_STATE_FULLSCREEN, TRUE);
+}
+
+void
+meta_wayland_surface_send_unfullscreened (MetaWaylandSurface *surface)
+{
+ send_change_state (surface, XDG_SURFACE_STATE_FULLSCREEN, FALSE);
+}
+
+void
+meta_wayland_surface_activated (MetaWaylandSurface *surface)
+{
+ if (surface->xdg_surface.resource)
+ xdg_surface_send_activated (surface->xdg_surface.resource);
+}
+
+void
+meta_wayland_surface_deactivated (MetaWaylandSurface *surface)
+{
+ if (surface->xdg_surface.resource)
+ xdg_surface_send_deactivated (surface->xdg_surface.resource);
+}
+
void
meta_wayland_surface_ping (MetaWaylandSurface *surface,
guint32 serial)
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index 62d631e61..fc744e81e 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -106,6 +106,8 @@ struct _MetaWaylandSurface
GSList *pending_placement_ops;
} sub;
+ uint32_t state_changed_serial;
+
/* All the pending state that wl_surface.commit will apply. */
MetaWaylandPendingState pending;
};
@@ -123,6 +125,13 @@ void meta_wayland_surface_set_window (MetaWaylandSurface *surface
void meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
int width,
int height);
+void meta_wayland_surface_send_maximized (MetaWaylandSurface *surface);
+void meta_wayland_surface_send_unmaximized (MetaWaylandSurface *surface);
+void meta_wayland_surface_send_fullscreened (MetaWaylandSurface *surface);
+void meta_wayland_surface_send_unfullscreened (MetaWaylandSurface *surface);
+
+void meta_wayland_surface_activated (MetaWaylandSurface *surface);
+void meta_wayland_surface_deactivated (MetaWaylandSurface *surface);
void meta_wayland_surface_ping (MetaWaylandSurface *surface,
guint32 serial);
diff --git a/src/wayland/protocol/xdg-shell.xml b/src/wayland/protocol/xdg-shell.xml
index 3c186102b..788269347 100644
--- a/src/wayland/protocol/xdg-shell.xml
+++ b/src/wayland/protocol/xdg-shell.xml
@@ -241,6 +241,40 @@
+
+
+ The configure event asks the client to resize its surface.
+
+ The size is a hint, in the sense that the client is free to
+ ignore it if it doesn't resize, pick a smaller size (to
+ satisfy aspect ratio or resize in steps of NxM pixels).
+
+ The client is free to dismiss all but the last configure
+ event it received.
+
+ The width and height arguments specify the size of the window
+ in surface local coordinates.
+
+
+
+
+
+
+
+
+ Set the default output used by this surface when it is first mapped.
+
+ If this value is NULL (default), it's up to the compositor to choose
+ which display will be used to map this surface.
+
+ When fullscreen or maximized state are set on this surface, and it
+ wasn't mapped yet, the output set with this method will be used.
+ Otherwise, the output where the surface is currently mapped will be
+ used.
+
+
+
+
The different state values used on the surface. This is designed for
@@ -263,78 +297,89 @@
0x1000 - 0x1FFF: GNOME
- The surface is maximized. The window geometry specified in the configure
- event must be obeyed by the client.
+ A non-zero value indicates the surface is maximized. Otherwise,
+ the surface is unmaximized.
- The surface is fullscreen. The window geometry specified in the configure
- event must be obeyed by the client.
-
-
- The surface is being resized. The window geometry specified in the
- configure event is a maximum; the client cannot resize beyond it.
- Clients that have aspect ratio or cell sizing configuration can use
- a smaller size, however.
-
-
- Client window decorations should be painted as if the window is
- active. Do not assume this means that the window actually has
- keyboard or pointer focus.
+ A non-zero value indicates the surface is fullscreen. Otherwise,
+ the surface is not fullscreen.
-
-
- The configure event asks the client to resize its surface.
+
+
+ This asks the compositor to change the state. If the compositor wants
+ to change the state, it will send a change_state event with the same
+ state_type, value, and serial, and the event flow continues as if it
+ it was initiated by the compositor.
- The width and height arguments specify a hint to the window
- about how its surface should be resized in surface local
- coordinates. The states listed in the event specify how the
- width/height arguments should be interpreted.
+ If the compositor does not want to change the state, it will send a
+ change_state to the client with the old value of the state.
+
+
+
+
+ This serial is so the client can know which change_state event corresponds
+ to which request_change_state request it sent out.
+
+
- A client should arrange a new surface, and then send a
- ack_configure request with the serial sent in this configure
- event before attaching a new surface.
-
- If the client receives multiple configure events before it
- can respond to one, it is free to discard all but the last
- event it received.
+
+
+ This event tells the client to change a surface's state. The client
+ should respond with an ack_change_state request to the compositor to
+ guarantee that the compositor knows that the client has seen it.
-
-
-
-
+
+
+
-
-
- When a configure event is received, a client should then ack it
- using the ack_configure request to ensure that the compositor
+
+
+ When a change_state event is received, a client should then ack it
+ using the ack_change_state request to ensure that the compositor
knows the client has seen the event.
By this point, the state is confirmed, and the next attach should
- contain the buffer drawn for the configure event you are acking.
+ contain the buffer drawn for the new state value.
+
+ The values here need to be the same as the values in the cooresponding
+ change_state event.
-
+
+
+
-
-
-
-
-
- Make the surface fullscreen.
-
- You can specify an output that you would prefer to be fullscreen.
- If this value is NULL, it's up to the compositor to choose which
- display will be used to map this surface.
+
+
+ Minimize the surface.
-
-
-
+
+
+ The activated_set event is sent when this surface has been
+ activated, which means that the surface has user attention.
+ Window decorations should be updated accordingly. You should
+ not use this event for anything but the style of decorations
+ you display, use wl_keyboard.enter and wl_keyboard.leave for
+ determining keyboard focus.
+
+
+
+
+
+ The deactivate event is sent when this surface has been
+ deactivated, which means that the surface lost user attention.
+ Window decorations should be updated accordingly. You should
+ not use this event for anything but the style of decorations
+ you display, use wl_keyboard.enter and wl_keyboard.leave for
+ determining keyboard focus.
+
+