summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/toytoolkit/window.c147
-rw-r--r--src/toytoolkit/xdg-shell-client-protocol.h150
-rw-r--r--src/toytoolkit/xdg-shell-protocol.c30
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[] = {