aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Langendorf <junglerobba@jngl.one>2020-07-18 21:37:02 +0200
committerSimon Ser <contact@emersion.fr>2020-07-21 13:20:17 +0200
commitbd387da62d78f25027f1f80d25d85970fd09c235 (patch)
tree6e3c6b02521bb20b5a22234c58624078484031bc
parent751a21d94f1b4f0345d040ddfd54b723631d5991 (diff)
xwm: add support for xwayland minimize
-rw-r--r--include/wlr/xwayland.h10
-rw-r--r--include/xwayland/xwm.h2
-rw-r--r--xwayland/xwm.c70
3 files changed, 81 insertions, 1 deletions
diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h
index 03201718..26a14aea 100644
--- a/include/wlr/xwayland.h
+++ b/include/wlr/xwayland.h
@@ -173,6 +173,7 @@ struct wlr_xwayland_surface {
bool modal;
bool fullscreen;
bool maximized_vert, maximized_horz;
+ bool minimized;
bool has_alpha;
@@ -181,6 +182,7 @@ struct wlr_xwayland_surface {
struct wl_signal request_configure;
struct wl_signal request_move;
struct wl_signal request_resize;
+ struct wl_signal request_minimize;
struct wl_signal request_maximize;
struct wl_signal request_fullscreen;
struct wl_signal request_activate;
@@ -221,6 +223,11 @@ struct wlr_xwayland_resize_event {
uint32_t edges;
};
+struct wlr_xwayland_minimize_event {
+ struct wlr_xwayland_surface *surface;
+ bool minimize;
+};
+
struct wlr_xwayland_server *wlr_xwayland_server_create(
struct wl_display *display, struct wlr_xwayland_server_options *options);
void wlr_xwayland_server_destroy(struct wlr_xwayland_server *server);
@@ -250,6 +257,9 @@ void wlr_xwayland_surface_configure(struct wlr_xwayland_surface *surface,
void wlr_xwayland_surface_close(struct wlr_xwayland_surface *surface);
+void wlr_xwayland_surface_set_minimized(struct wlr_xwayland_surface *surface,
+ bool minimized);
+
void wlr_xwayland_surface_set_maximized(struct wlr_xwayland_surface *surface,
bool maximized);
diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h
index 2569092f..1085cb14 100644
--- a/include/xwayland/xwm.h
+++ b/include/xwayland/xwm.h
@@ -44,7 +44,9 @@ enum atom_name {
NET_WM_STATE_FULLSCREEN,
NET_WM_STATE_MAXIMIZED_VERT,
NET_WM_STATE_MAXIMIZED_HORZ,
+ NET_WM_STATE_HIDDEN,
NET_WM_PING,
+ WM_CHANGE_STATE,
WM_STATE,
CLIPBOARD,
PRIMARY,
diff --git a/xwayland/xwm.c b/xwayland/xwm.c
index 28e329f3..a3fb61b4 100644
--- a/xwayland/xwm.c
+++ b/xwayland/xwm.c
@@ -42,7 +42,9 @@ const char *atom_map[ATOM_LAST] = {
[NET_WM_STATE_FULLSCREEN] = "_NET_WM_STATE_FULLSCREEN",
[NET_WM_STATE_MAXIMIZED_VERT] = "_NET_WM_STATE_MAXIMIZED_VERT",
[NET_WM_STATE_MAXIMIZED_HORZ] = "_NET_WM_STATE_MAXIMIZED_HORZ",
+ [NET_WM_STATE_HIDDEN] = "_NET_WM_STATE_HIDDEN",
[NET_WM_PING] = "_NET_WM_PING",
+ [WM_CHANGE_STATE] = "WM_CHANGE_STATE",
[WM_STATE] = "WM_STATE",
[CLIPBOARD] = "CLIPBOARD",
[PRIMARY] = "PRIMARY",
@@ -146,6 +148,7 @@ static struct wlr_xwayland_surface *xwayland_surface_create(
wl_signal_init(&surface->events.request_configure);
wl_signal_init(&surface->events.request_move);
wl_signal_init(&surface->events.request_resize);
+ wl_signal_init(&surface->events.request_minimize);
wl_signal_init(&surface->events.request_maximize);
wl_signal_init(&surface->events.request_fullscreen);
wl_signal_init(&surface->events.request_activate);
@@ -290,7 +293,7 @@ static void xwm_surface_activate(struct wlr_xwm *xwm,
static void xsurface_set_net_wm_state(struct wlr_xwayland_surface *xsurface) {
struct wlr_xwm *xwm = xsurface->xwm;
- uint32_t property[4];
+ uint32_t property[5];
int i;
i = 0;
@@ -306,6 +309,9 @@ static void xsurface_set_net_wm_state(struct wlr_xwayland_surface *xsurface) {
if (xsurface->maximized_horz) {
property[i++] = xwm->atoms[NET_WM_STATE_MAXIMIZED_HORZ];
}
+ if (xsurface->minimized) {
+ property[i++] = xwm->atoms[NET_WM_STATE_HIDDEN];
+ }
xcb_change_property(xwm->xcb_conn,
XCB_PROP_MODE_REPLACE,
@@ -664,6 +670,8 @@ static void read_surface_net_wm_state(struct wlr_xwm *xwm,
xsurface->maximized_vert = true;
} else if (atom[i] == xwm->atoms[NET_WM_STATE_MAXIMIZED_HORZ]) {
xsurface->maximized_horz = true;
+ } else if (atom[i] == xwm->atoms[NET_WM_STATE_HIDDEN]) {
+ xsurface->minimized = true;
}
}
}
@@ -1126,6 +1134,7 @@ static void xwm_handle_net_wm_state_message(struct wlr_xwm *xwm,
bool fullscreen = xsurface->fullscreen;
bool maximized = xsurface_is_maximized(xsurface);
+ bool minimized = xsurface->minimized;
uint32_t action = client_message->data.data32[0];
for (size_t i = 0; i < 2; ++i) {
@@ -1143,6 +1152,9 @@ static void xwm_handle_net_wm_state_message(struct wlr_xwm *xwm,
} else if (property == xwm->atoms[NET_WM_STATE_MAXIMIZED_HORZ] &&
update_state(action, &xsurface->maximized_horz)) {
xsurface_set_net_wm_state(xsurface);
+ } else if (property == xwm->atoms[NET_WM_STATE_HIDDEN] &&
+ update_state(action, &xsurface->minimized)) {
+ xsurface_set_net_wm_state(xsurface);
}
}
// client_message->data.data32[3] is the source indication
@@ -1165,6 +1177,19 @@ static void xwm_handle_net_wm_state_message(struct wlr_xwm *xwm,
wlr_signal_emit_safe(&xsurface->events.request_maximize, xsurface);
}
+
+ if (minimized != xsurface->minimized) {
+ if (xsurface->minimized) {
+ xsurface->saved_width = xsurface->width;
+ xsurface->saved_height = xsurface->height;
+ }
+
+ struct wlr_xwayland_minimize_event minimize_event = {
+ .surface = xsurface,
+ .minimize = xsurface->minimized,
+ };
+ wlr_signal_emit_safe(&xsurface->events.request_minimize, &minimize_event);
+ }
}
static void xwm_handle_wm_protocols_message(struct wlr_xwm *xwm,
@@ -1202,6 +1227,32 @@ static void xwm_handle_net_active_window_message(struct wlr_xwm *xwm,
wlr_signal_emit_safe(&surface->events.request_activate, surface);
}
+static void xwm_handle_wm_change_state_message(struct wlr_xwm *xwm,
+ xcb_client_message_event_t *ev) {
+ struct wlr_xwayland_surface *xsurface = lookup_surface(xwm, ev->window);
+ uint32_t detail = ev->data.data32[0];
+
+ if (xsurface == NULL) {
+ return;
+ }
+
+ bool minimize;
+ if (detail == ICCCM_ICONIC_STATE) {
+ minimize = true;
+ } else if (detail == ICCCM_NORMAL_STATE) {
+ minimize = false;
+ } else {
+ wlr_log(WLR_DEBUG, "unhandled wm_change_state event %u", detail);
+ return;
+ }
+
+ struct wlr_xwayland_minimize_event minimize_event = {
+ .surface = xsurface,
+ .minimize = minimize,
+ };
+ wlr_signal_emit_safe(&xsurface->events.request_minimize, &minimize_event);
+}
+
static void xwm_handle_client_message(struct wlr_xwm *xwm,
xcb_client_message_event_t *ev) {
wlr_log(WLR_DEBUG, "XCB_CLIENT_MESSAGE (%u)", ev->window);
@@ -1216,6 +1267,8 @@ static void xwm_handle_client_message(struct wlr_xwm *xwm,
xwm_handle_wm_protocols_message(xwm, ev);
} else if (ev->type == xwm->atoms[NET_ACTIVE_WINDOW]) {
xwm_handle_net_active_window_message(xwm, ev);
+ } else if (ev->type == xwm->atoms[WM_CHANGE_STATE]) {
+ xwm_handle_wm_change_state_message(xwm, ev);
} else if (!xwm_handle_selection_client_message(xwm, ev)) {
char *type_name = xwm_get_atom_name(xwm, ev->type);
wlr_log(WLR_DEBUG, "unhandled x11 client message %u (%s)", ev->type,
@@ -1768,6 +1821,7 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) {
xwm->atoms[NET_WM_STATE_FULLSCREEN],
xwm->atoms[NET_WM_STATE_MAXIMIZED_VERT],
xwm->atoms[NET_WM_STATE_MAXIMIZED_HORZ],
+ xwm->atoms[NET_WM_STATE_HIDDEN],
xwm->atoms[NET_CLIENT_LIST],
};
xcb_change_property(xwm->xcb_conn,
@@ -1799,6 +1853,20 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) {
return xwm;
}
+void wlr_xwayland_surface_set_minimized(struct wlr_xwayland_surface *surface,
+ bool minimized) {
+ surface->minimized = minimized;
+
+ if (minimized) {
+ xsurface_set_wm_state(surface, ICCCM_ICONIC_STATE);
+ } else {
+ xsurface_set_wm_state(surface, ICCCM_NORMAL_STATE);
+ }
+
+ xsurface_set_net_wm_state(surface);
+ xcb_flush(surface->xwm->xcb_conn);
+}
+
void wlr_xwayland_surface_set_maximized(struct wlr_xwayland_surface *surface,
bool maximized) {
surface->maximized_horz = maximized;