diff options
-rw-r--r-- | src/toytoolkit/window.c | 147 | ||||
-rw-r--r-- | src/toytoolkit/xdg-shell-client-protocol.h | 150 | ||||
-rw-r--r-- | src/toytoolkit/xdg-shell-protocol.c | 30 |
3 files changed, 173 insertions, 154 deletions
diff --git a/src/toytoolkit/window.c b/src/toytoolkit/window.c index f816ea7..5b5dc0b 100644 --- a/src/toytoolkit/window.c +++ b/src/toytoolkit/window.c @@ -217,6 +217,7 @@ struct window { struct rectangle saved_allocation; struct rectangle min_allocation; struct rectangle pending_allocation; + struct rectangle last_geometry; int x, y; int redraw_needed; int redraw_task_scheduled; @@ -3847,53 +3848,64 @@ widget_schedule_resize(struct widget *widget, int32_t width, int32_t height) window_schedule_resize(widget->window, width, height); } -static void -handle_surface_configure(void *data, struct xdg_surface *xdg_surface, - int32_t width, int32_t height) +static int +window_get_shadow_margin(struct window *window) { - struct window *window = data; - - window_schedule_resize(window, width, height); + if (window->frame && !window->fullscreen && !window->maximized) + return frame_get_shadow_margin(window->frame->frame); + else + return 0; } static void -handle_surface_change_state(void *data, struct xdg_surface *xdg_surface, - uint32_t state, - uint32_t value, - uint32_t serial) +handle_surface_configure(void *data, struct xdg_surface *xdg_surface, + int32_t width, int32_t height, + struct wl_array *states, uint32_t serial) { struct window *window = data; + uint32_t *p; - switch (state) { - case XDG_SURFACE_STATE_MAXIMIZED: - window->maximized = value; - break; - case XDG_SURFACE_STATE_FULLSCREEN: - window->fullscreen = value; - break; + window->maximized = 0; + window->fullscreen = 0; + window->resizing = 0; + window->focused = 0; + + wl_array_for_each(p, states) { + uint32_t state = *p; + switch (state) { + case XDG_SURFACE_STATE_MAXIMIZED: + window->maximized = 1; + break; + case XDG_SURFACE_STATE_FULLSCREEN: + window->fullscreen = 1; + break; + case XDG_SURFACE_STATE_RESIZING: + window->resizing = 1; + break; + case XDG_SURFACE_STATE_ACTIVATED: + window->focused = 1; + break; + default: + /* Unknown state */ + break; + } } - if (!window->fullscreen && !window->maximized) + if (width > 0 && height > 0) { + /* The width / height params are for window geometry, + * but window_schedule_resize takes allocation. Add + * on the shadow margin to get the difference. */ + int margin = window_get_shadow_margin(window); + window_schedule_resize(window, + width + margin * 2, + height + margin *2); + } else { window_schedule_resize(window, window->saved_allocation.width, window->saved_allocation.height); + } - xdg_surface_ack_change_state(xdg_surface, state, value, serial); - window_schedule_redraw(window); -} - -static void -handle_surface_activated(void *data, struct xdg_surface *xdg_surface) -{ - struct window *window = data; - window->focused = 1; -} - -static void -handle_surface_deactivated(void *data, struct xdg_surface *xdg_surface) -{ - struct window *window = data; - window->focused = 0; + xdg_surface_ack_configure(xdg_surface, serial); } static void @@ -3905,14 +3917,11 @@ handle_surface_delete(void *data, struct xdg_surface *xdg_surface) static const struct xdg_surface_listener xdg_surface_listener = { handle_surface_configure, - handle_surface_change_state, - handle_surface_activated, - handle_surface_deactivated, handle_surface_delete, }; static void -window_sync_transient_for(struct window *window) +window_sync_parent(struct window *window) { struct wl_surface *parent_surface; @@ -3924,28 +3933,42 @@ window_sync_transient_for(struct window *window) else parent_surface = NULL; - xdg_surface_set_transient_for(window->xdg_surface, parent_surface); + xdg_surface_set_parent(window->xdg_surface, parent_surface); +} + +window_get_geometry(struct window *window, struct rectangle *geometry) +{ + if (window->frame && !window->fullscreen) + frame_input_rect(window->frame->frame, + &geometry->x, + &geometry->y, + &geometry->width, + &geometry->height); + else + window_get_allocation(window, geometry); } static void -window_sync_margin(struct window *window) +window_sync_geometry(struct window *window) { - int margin; + struct rectangle geometry; if (!window->xdg_surface) return; - if (!window->frame) + window_get_geometry(window, &geometry); + if (geometry.x == window->last_geometry.x && + geometry.y == window->last_geometry.y && + geometry.width == window->last_geometry.width && + geometry.height == window->last_geometry.height) return; - margin = frame_get_shadow_margin(window->frame->frame); - - /* Shadow size is the same on every side. */ - xdg_surface_set_margin(window->xdg_surface, - margin, - margin, - margin, - margin); + xdg_surface_set_window_geometry(window->xdg_surface, + geometry.x, + geometry.y, + geometry.width, + geometry.height); + window->last_geometry = geometry; } static void @@ -3955,8 +3978,8 @@ window_flush(struct window *window) if (!window->custom) { if (window->xdg_surface) { - window_sync_transient_for(window); - window_sync_margin(window); + window_sync_parent(window); + window_sync_geometry(window); } } @@ -4145,10 +4168,10 @@ window_set_fullscreen(struct window *window, int fullscreen) if (window->fullscreen == fullscreen) return; - xdg_surface_request_change_state(window->xdg_surface, - XDG_SURFACE_STATE_FULLSCREEN, - fullscreen ? 1 : 0, - 0); + if (fullscreen) + xdg_surface_set_fullscreen(window->xdg_surface, NULL); + else + xdg_surface_unset_fullscreen(window->xdg_surface); } int @@ -4166,10 +4189,10 @@ window_set_maximized(struct window *window, int maximized) if (window->maximized == maximized) return; - xdg_surface_request_change_state(window->xdg_surface, - XDG_SURFACE_STATE_MAXIMIZED, - maximized ? 1 : 0, - 0); + if (maximized) + xdg_surface_set_maximized(window->xdg_surface); + else + xdg_surface_unset_maximized(window->xdg_surface); } void @@ -4432,7 +4455,7 @@ window_set_transient_for(struct window *window, struct window *parent_window) { window->transient_for = parent_window; - window_sync_transient_for(window); + window_sync_parent(window); } struct window * @@ -5041,7 +5064,7 @@ static const struct xdg_shell_listener xdg_shell_listener = { xdg_shell_ping, }; -#define XDG_VERSION 3 /* The version of xdg-shell that we implement */ +#define XDG_VERSION 4 /* The version of xdg-shell that we implement */ #ifdef static_assert static_assert(XDG_VERSION == XDG_SHELL_VERSION_CURRENT, "Interface version doesn't match implementation version"); diff --git a/src/toytoolkit/xdg-shell-client-protocol.h b/src/toytoolkit/xdg-shell-client-protocol.h index 6ae0d9d..66dc5d8 100644 --- a/src/toytoolkit/xdg-shell-client-protocol.h +++ b/src/toytoolkit/xdg-shell-client-protocol.h @@ -59,7 +59,7 @@ extern const struct wl_interface xdg_popup_interface; * static_assert to ensure the protocol and implementation versions match. */ enum xdg_shell_version { - XDG_SHELL_VERSION_CURRENT = 3, + XDG_SHELL_VERSION_CURRENT = 4, }; #endif /* XDG_SHELL_VERSION_ENUM */ @@ -195,11 +195,13 @@ enum xdg_surface_resize_edge { * xdg_surface_state - types of state on the surface * @XDG_SURFACE_STATE_MAXIMIZED: the surface is maximized * @XDG_SURFACE_STATE_FULLSCREEN: the surface is fullscreen + * @XDG_SURFACE_STATE_RESIZING: (none) + * @XDG_SURFACE_STATE_ACTIVATED: (none) * * The different state values used on the surface. This is designed for - * state values like maximized, fullscreen. It is paired with the - * request_change_state event to ensure that both the client and the - * compositor setting the state can be synchronized. + * state values like maximized, fullscreen. It is paired with the configure + * event to ensure that both the client and the compositor setting the + * state can be synchronized. * * States set in this way are double-buffered. They will get applied on the * next commit. @@ -218,15 +220,14 @@ enum xdg_surface_resize_edge { enum xdg_surface_state { XDG_SURFACE_STATE_MAXIMIZED = 1, XDG_SURFACE_STATE_FULLSCREEN = 2, + XDG_SURFACE_STATE_RESIZING = 3, + XDG_SURFACE_STATE_ACTIVATED = 4, }; #endif /* XDG_SURFACE_STATE_ENUM */ /** * xdg_surface - desktop-style metadata interface - * @configure: suggest resize - * @change_state: compositor wants to change a surface's state - * @activated: surface was activated - * @deactivated: surface was deactivated + * @configure: suggest a surface change * @close: surface wants to be closed * * An interface that may be implemented by a wl_surface, for @@ -242,66 +243,33 @@ enum xdg_surface_state { */ struct xdg_surface_listener { /** - * configure - suggest resize + * configure - suggest a surface change * @width: (none) * @height: (none) + * @states: (none) + * @serial: (none) * * 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 width and height arguments specify a hint to the window + * about how its surface should be resized in window geometry + * coordinates. The states listed in the event specify how the + * width/height arguments should be interpreted. * - * The client is free to dismiss all but the last configure event - * it received. + * 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. * - * The width and height arguments specify the size of the window in - * surface local coordinates. + * 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. */ void (*configure)(void *data, struct xdg_surface *xdg_surface, int32_t width, - int32_t height); - /** - * change_state - compositor wants to change a surface's state - * @state_type: the state to set - * @value: the value to change the state to - * @serial: a serial for the compositor's own tracking - * - * 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. - */ - void (*change_state)(void *data, - struct xdg_surface *xdg_surface, - uint32_t state_type, - uint32_t value, - uint32_t serial); - /** - * activated - surface was activated - * - * 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. - */ - void (*activated)(void *data, - struct xdg_surface *xdg_surface); - /** - * deactivated - surface was deactivated - * - * 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. - */ - void (*deactivated)(void *data, - struct xdg_surface *xdg_surface); + int32_t height, + struct wl_array *states, + uint32_t serial); /** * close - surface wants to be closed * @@ -327,16 +295,19 @@ xdg_surface_add_listener(struct xdg_surface *xdg_surface, } #define XDG_SURFACE_DESTROY 0 -#define XDG_SURFACE_SET_TRANSIENT_FOR 1 -#define XDG_SURFACE_SET_MARGIN 2 -#define XDG_SURFACE_SET_TITLE 3 -#define XDG_SURFACE_SET_APP_ID 4 +#define XDG_SURFACE_SET_PARENT 1 +#define XDG_SURFACE_SET_TITLE 2 +#define XDG_SURFACE_SET_APP_ID 3 +#define XDG_SURFACE_SHOW_WINDOW_MENU 4 #define XDG_SURFACE_MOVE 5 #define XDG_SURFACE_RESIZE 6 -#define XDG_SURFACE_SET_OUTPUT 7 -#define XDG_SURFACE_REQUEST_CHANGE_STATE 8 -#define XDG_SURFACE_ACK_CHANGE_STATE 9 -#define XDG_SURFACE_SET_MINIMIZED 10 +#define XDG_SURFACE_ACK_CONFIGURE 7 +#define XDG_SURFACE_SET_WINDOW_GEOMETRY 8 +#define XDG_SURFACE_SET_MAXIMIZED 9 +#define XDG_SURFACE_UNSET_MAXIMIZED 10 +#define XDG_SURFACE_SET_FULLSCREEN 11 +#define XDG_SURFACE_UNSET_FULLSCREEN 12 +#define XDG_SURFACE_SET_MINIMIZED 13 static inline void xdg_surface_set_user_data(struct xdg_surface *xdg_surface, void *user_data) @@ -360,31 +331,31 @@ xdg_surface_destroy(struct xdg_surface *xdg_surface) } static inline void -xdg_surface_set_transient_for(struct xdg_surface *xdg_surface, struct wl_surface *parent) +xdg_surface_set_parent(struct xdg_surface *xdg_surface, struct wl_surface *parent) { wl_proxy_marshal((struct wl_proxy *) xdg_surface, - XDG_SURFACE_SET_TRANSIENT_FOR, parent); + XDG_SURFACE_SET_PARENT, parent); } static inline void -xdg_surface_set_margin(struct xdg_surface *xdg_surface, int32_t left_margin, int32_t right_margin, int32_t top_margin, int32_t bottom_margin) +xdg_surface_set_title(struct xdg_surface *xdg_surface, const char *title) { wl_proxy_marshal((struct wl_proxy *) xdg_surface, - XDG_SURFACE_SET_MARGIN, left_margin, right_margin, top_margin, bottom_margin); + XDG_SURFACE_SET_TITLE, title); } static inline void -xdg_surface_set_title(struct xdg_surface *xdg_surface, const char *title) +xdg_surface_set_app_id(struct xdg_surface *xdg_surface, const char *app_id) { wl_proxy_marshal((struct wl_proxy *) xdg_surface, - XDG_SURFACE_SET_TITLE, title); + XDG_SURFACE_SET_APP_ID, app_id); } static inline void -xdg_surface_set_app_id(struct xdg_surface *xdg_surface, const char *app_id) +xdg_surface_show_window_menu(struct xdg_surface *xdg_surface, struct wl_seat *seat, uint32_t serial, int32_t x, int32_t y) { wl_proxy_marshal((struct wl_proxy *) xdg_surface, - XDG_SURFACE_SET_APP_ID, app_id); + XDG_SURFACE_SHOW_WINDOW_MENU, seat, serial, x, y); } static inline void @@ -402,24 +373,45 @@ xdg_surface_resize(struct xdg_surface *xdg_surface, struct wl_seat *seat, uint32 } static inline void -xdg_surface_set_output(struct xdg_surface *xdg_surface, struct wl_output *output) +xdg_surface_ack_configure(struct xdg_surface *xdg_surface, uint32_t serial) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_surface, + XDG_SURFACE_ACK_CONFIGURE, serial); +} + +static inline void +xdg_surface_set_window_geometry(struct xdg_surface *xdg_surface, int32_t x, int32_t y, int32_t width, int32_t height) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_surface, + XDG_SURFACE_SET_WINDOW_GEOMETRY, x, y, width, height); +} + +static inline void +xdg_surface_set_maximized(struct xdg_surface *xdg_surface) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_surface, + XDG_SURFACE_SET_MAXIMIZED); +} + +static inline void +xdg_surface_unset_maximized(struct xdg_surface *xdg_surface) { wl_proxy_marshal((struct wl_proxy *) xdg_surface, - XDG_SURFACE_SET_OUTPUT, output); + XDG_SURFACE_UNSET_MAXIMIZED); } static inline void -xdg_surface_request_change_state(struct xdg_surface *xdg_surface, uint32_t state_type, uint32_t value, uint32_t serial) +xdg_surface_set_fullscreen(struct xdg_surface *xdg_surface, struct wl_output *output) { wl_proxy_marshal((struct wl_proxy *) xdg_surface, - XDG_SURFACE_REQUEST_CHANGE_STATE, state_type, value, serial); + XDG_SURFACE_SET_FULLSCREEN, output); } static inline void -xdg_surface_ack_change_state(struct xdg_surface *xdg_surface, uint32_t state_type, uint32_t value, uint32_t serial) +xdg_surface_unset_fullscreen(struct xdg_surface *xdg_surface) { wl_proxy_marshal((struct wl_proxy *) xdg_surface, - XDG_SURFACE_ACK_CHANGE_STATE, state_type, value, serial); + XDG_SURFACE_UNSET_FULLSCREEN); } static inline void diff --git a/src/toytoolkit/xdg-shell-protocol.c b/src/toytoolkit/xdg-shell-protocol.c index 242e6c3..863f74e 100644 --- a/src/toytoolkit/xdg-shell-protocol.c +++ b/src/toytoolkit/xdg-shell-protocol.c @@ -54,6 +54,10 @@ static const struct wl_interface *types[] = { &wl_surface_interface, &wl_seat_interface, NULL, + NULL, + NULL, + &wl_seat_interface, + NULL, &wl_seat_interface, NULL, NULL, @@ -79,30 +83,30 @@ WL_EXPORT const struct wl_interface xdg_shell_interface = { static const struct wl_message xdg_surface_requests[] = { { "destroy", "", types + 0 }, - { "set_transient_for", "?o", types + 14 }, - { "set_margin", "iiii", types + 0 }, + { "set_parent", "?o", types + 14 }, { "set_title", "s", types + 0 }, { "set_app_id", "s", types + 0 }, - { "move", "ou", types + 15 }, - { "resize", "ouu", types + 17 }, - { "set_output", "?o", types + 20 }, - { "request_change_state", "uuu", types + 0 }, - { "ack_change_state", "uuu", types + 0 }, + { "show_window_menu", "ouii", types + 15 }, + { "move", "ou", types + 19 }, + { "resize", "ouu", types + 21 }, + { "ack_configure", "u", types + 0 }, + { "set_window_geometry", "iiii", types + 0 }, + { "set_maximized", "", types + 0 }, + { "unset_maximized", "", types + 0 }, + { "set_fullscreen", "?o", types + 24 }, + { "unset_fullscreen", "", types + 0 }, { "set_minimized", "", types + 0 }, }; static const struct wl_message xdg_surface_events[] = { - { "configure", "ii", types + 0 }, - { "change_state", "uuu", types + 0 }, - { "activated", "", types + 0 }, - { "deactivated", "", types + 0 }, + { "configure", "iiau", types + 0 }, { "close", "", types + 0 }, }; WL_EXPORT const struct wl_interface xdg_surface_interface = { "xdg_surface", 1, - 11, xdg_surface_requests, - 5, xdg_surface_events, + 14, xdg_surface_requests, + 2, xdg_surface_events, }; static const struct wl_message xdg_popup_requests[] = { |