aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/xwayland/xwm.h1
-rw-r--r--xwayland/xwm.c33
2 files changed, 26 insertions, 8 deletions
diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h
index 1085cb14..a3e7132d 100644
--- a/include/xwayland/xwm.h
+++ b/include/xwayland/xwm.h
@@ -40,6 +40,7 @@ enum atom_name {
NET_ACTIVE_WINDOW,
NET_WM_MOVERESIZE,
NET_SUPPORTING_WM_CHECK,
+ NET_WM_STATE_FOCUSED,
NET_WM_STATE_MODAL,
NET_WM_STATE_FULLSCREEN,
NET_WM_STATE_MAXIMIZED_VERT,
diff --git a/xwayland/xwm.c b/xwayland/xwm.c
index 692c0f8b..88f4c3c5 100644
--- a/xwayland/xwm.c
+++ b/xwayland/xwm.c
@@ -38,6 +38,7 @@ const char *atom_map[ATOM_LAST] = {
[NET_ACTIVE_WINDOW] = "_NET_ACTIVE_WINDOW",
[NET_WM_MOVERESIZE] = "_NET_WM_MOVERESIZE",
[NET_SUPPORTING_WM_CHECK] = "_NET_SUPPORTING_WM_CHECK",
+ [NET_WM_STATE_FOCUSED] = "_NET_WM_STATE_FOCUSED",
[NET_WM_STATE_MODAL] = "_NET_WM_STATE_MODAL",
[NET_WM_STATE_FULLSCREEN] = "_NET_WM_STATE_FULLSCREEN",
[NET_WM_STATE_MAXIMIZED_VERT] = "_NET_WM_STATE_MAXIMIZED_VERT",
@@ -238,8 +239,20 @@ static void xwm_set_net_client_list(struct wlr_xwm *xwm) {
XCB_ATOM_WINDOW, 32, mapped_surfaces, windows);
}
-static void xwm_send_focus_window(struct wlr_xwm *xwm,
+static void xsurface_set_net_wm_state(struct wlr_xwayland_surface *xsurface);
+
+static void xwm_set_focus_window(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *xsurface) {
+ struct wlr_xwayland_surface *unfocus_surface = xwm->focus_surface;
+
+ // We handle cases where focus_surface == xsurface because we
+ // want to be able to deny FocusIn events.
+ xwm->focus_surface = xsurface;
+
+ if (unfocus_surface) {
+ xsurface_set_net_wm_state(unfocus_surface);
+ }
+
if (!xsurface) {
xcb_set_input_focus_checked(xwm->xcb_conn,
XCB_INPUT_FOCUS_POINTER_ROOT,
@@ -270,6 +283,8 @@ static void xwm_send_focus_window(struct wlr_xwm *xwm,
values[0] = XCB_STACK_MODE_ABOVE;
xcb_configure_window(xwm->xcb_conn, xsurface->window_id,
XCB_CONFIG_WINDOW_STACK_MODE, values);
+
+ xsurface_set_net_wm_state(xsurface);
}
static void xwm_surface_activate(struct wlr_xwm *xwm,
@@ -285,9 +300,7 @@ static void xwm_surface_activate(struct wlr_xwm *xwm,
xwm_set_net_active_window(xwm, XCB_WINDOW_NONE);
}
- xwm_send_focus_window(xwm, xsurface);
-
- xwm->focus_surface = xsurface;
+ xwm_set_focus_window(xwm, xsurface);
xcb_flush(xwm->xcb_conn);
}
@@ -295,7 +308,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[5];
+ uint32_t property[6];
size_t i = 0;
if (xsurface->modal) {
property[i++] = xwm->atoms[NET_WM_STATE_MODAL];
@@ -312,6 +325,9 @@ static void xsurface_set_net_wm_state(struct wlr_xwayland_surface *xsurface) {
if (xsurface->minimized) {
property[i++] = xwm->atoms[NET_WM_STATE_HIDDEN];
}
+ if (xsurface == xwm->focus_surface) {
+ property[i++] = xwm->atoms[NET_WM_STATE_FOCUSED];
+ }
assert(i <= sizeof(property) / sizeof(property[0]));
xcb_change_property(xwm->xcb_conn,
@@ -1299,10 +1315,10 @@ static void xwm_handle_focus_in(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *requested_focus = lookup_surface(xwm, ev->event);
if (xwm->focus_surface && requested_focus &&
requested_focus->pid == xwm->focus_surface->pid) {
- xwm->focus_surface = requested_focus;
+ xwm_set_focus_window(xwm, requested_focus);
+ } else {
+ xwm_set_focus_window(xwm, xwm->focus_surface);
}
-
- xwm_send_focus_window(xwm, xwm->focus_surface);
}
static void xwm_handle_xcb_error(struct wlr_xwm *xwm, xcb_value_error_t *ev) {
@@ -1817,6 +1833,7 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) {
xwm->atoms[NET_WM_STATE],
xwm->atoms[NET_ACTIVE_WINDOW],
xwm->atoms[NET_WM_MOVERESIZE],
+ xwm->atoms[NET_WM_STATE_FOCUSED],
xwm->atoms[NET_WM_STATE_MODAL],
xwm->atoms[NET_WM_STATE_FULLSCREEN],
xwm->atoms[NET_WM_STATE_MAXIMIZED_VERT],