diff options
-rw-r--r-- | examples/simple.c | 35 | ||||
-rw-r--r-- | include/wlr/xwayland.h | 25 | ||||
-rw-r--r-- | rootston/seat.c | 3 | ||||
-rw-r--r-- | xwayland/xwm.c | 24 |
4 files changed, 72 insertions, 15 deletions
diff --git a/examples/simple.c b/examples/simple.c index f161dc22..1125bd2a 100644 --- a/examples/simple.c +++ b/examples/simple.c @@ -37,8 +37,8 @@ struct sample_keyboard { }; void output_frame_notify(struct wl_listener *listener, void *data) { - wlr_log(WLR_DEBUG, "Output removed"); - struct sample_output *sample_output = wl_container_of(listener, sample_output, frame); + struct sample_output *sample_output = + wl_container_of(listener, sample_output, frame); struct sample_state *sample = sample_output->sample; struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -66,7 +66,9 @@ void output_frame_notify(struct wl_listener *listener, void *data) { } void output_remove_notify(struct wl_listener *listener, void *data) { - struct sample_output *sample_output = wl_container_of(listener, sample_output, destroy); + struct sample_output *sample_output = + wl_container_of(listener, sample_output, destroy); + wlr_log(WLR_DEBUG, "Output removed"); wl_list_remove(&sample_output->frame.link); wl_list_remove(&sample_output->destroy.link); free(sample_output); @@ -74,10 +76,13 @@ void output_remove_notify(struct wl_listener *listener, void *data) { void new_output_notify(struct wl_listener *listener, void *data) { struct wlr_output *output = data; - struct sample_state *sample = wl_container_of(listener, sample, new_output); - struct sample_output *sample_output = calloc(1, sizeof(struct sample_output)); + struct sample_state *sample = + wl_container_of(listener, sample, new_output); + struct sample_output *sample_output = + calloc(1, sizeof(struct sample_output)); if (!wl_list_empty(&output->modes)) { - struct wlr_output_mode *mode = wl_container_of(output->modes.prev, mode, link); + struct wlr_output_mode *mode = + wl_container_of(output->modes.prev, mode, link); wlr_output_set_mode(output, mode); } sample_output->output = output; @@ -105,7 +110,8 @@ void keyboard_key_notify(struct wl_listener *listener, void *data) { } void keyboard_destroy_notify(struct wl_listener *listener, void *data) { - struct sample_keyboard *keyboard = wl_container_of(listener, keyboard, destroy); + struct sample_keyboard *keyboard = + wl_container_of(listener, keyboard, destroy); wl_list_remove(&keyboard->destroy.link); wl_list_remove(&keyboard->key.link); free(keyboard); @@ -116,7 +122,8 @@ void new_input_notify(struct wl_listener *listener, void *data) { struct sample_state *sample = wl_container_of(listener, sample, new_input); switch (device->type) { case WLR_INPUT_DEVICE_KEYBOARD:; - struct sample_keyboard *keyboard = calloc(1, sizeof(struct sample_keyboard)); + struct sample_keyboard *keyboard = + calloc(1, sizeof(struct sample_keyboard)); keyboard->device = device; keyboard->sample = sample; wl_signal_add(&device->events.destroy, &keyboard->destroy); @@ -152,19 +159,19 @@ int main(void) { .last_frame = { 0 }, .display = display }; - struct wlr_backend *wlr = wlr_backend_autocreate(display, NULL); - if (!wlr) { + struct wlr_backend *backend = wlr_backend_autocreate(display, NULL); + if (!backend) { exit(1); } - wl_signal_add(&wlr->events.new_output, &state.new_output); + wl_signal_add(&backend->events.new_output, &state.new_output); state.new_output.notify = new_output_notify; - wl_signal_add(&wlr->events.new_input, &state.new_input); + wl_signal_add(&backend->events.new_input, &state.new_input); state.new_input.notify = new_input_notify; clock_gettime(CLOCK_MONOTONIC, &state.last_frame); - if (!wlr_backend_start(wlr)) { + if (!wlr_backend_start(backend)) { wlr_log(WLR_ERROR, "Failed to start backend"); - wlr_backend_destroy(wlr); + wlr_backend_destroy(backend); exit(1); } wl_display_run(display); diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h index 2b643ec9..e7f7a467 100644 --- a/include/wlr/xwayland.h +++ b/include/wlr/xwayland.h @@ -209,4 +209,29 @@ struct wlr_xwayland_surface *wlr_xwayland_surface_from_wlr_surface( void wlr_xwayland_surface_ping(struct wlr_xwayland_surface *surface); +/** Metric to guess if an OR window should "receive" focus + * + * In the pure X setups, window managers usually straight up ignore override + * redirect windows, and never touch them. (we have to handle them for mapping) + * + * When such a window wants to receive keyboard input (e.g. rofi/dzen) it will + * use mechanics we don't support (sniffing/grabbing input). + * [Sadly this is unrelated to xwayland-keyboard-grab] + * + * To still support these windows, while keeping general OR semantics as is, we + * need to hand a subset of windows focus. + * The dirty truth is, we need to hand focus to any Xwayland window, though + * pretending this window has focus makes it easier to handle unmap. + * + * This function provides a handy metric based on the window type to guess if + * the OR window wants focus. + * It's probably not perfect, nor exactly intended but works in practice. + * + * Returns: true if the window should receive focus + * false if it should be ignored + */ +bool wlr_xwayland_or_surface_wants_focus( + const struct wlr_xwayland_surface *surface); + + #endif diff --git a/rootston/seat.c b/rootston/seat.c index cae548d3..27363d8e 100644 --- a/rootston/seat.c +++ b/rootston/seat.c @@ -1124,7 +1124,8 @@ void roots_seat_set_focus(struct roots_seat *seat, struct roots_view *view) { #ifdef WLR_HAS_XWAYLAND if (view && view->type == ROOTS_XWAYLAND_VIEW && - view->xwayland_surface->override_redirect) { + !wlr_xwayland_or_surface_wants_focus( + view->xwayland_surface)) { return; } #endif diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 7999480a..c939d8ea 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -1703,3 +1703,27 @@ void wlr_xwayland_surface_ping(struct wlr_xwayland_surface *surface) { surface->xwm->ping_timeout); surface->pinging = true; } + +bool wlr_xwayland_or_surface_wants_focus( + const struct wlr_xwayland_surface *surface) { + bool ret = true; + static enum atom_name needles[] = { + NET_WM_WINDOW_TYPE_COMBO, + NET_WM_WINDOW_TYPE_DND, + NET_WM_WINDOW_TYPE_DROPDOWN_MENU, + NET_WM_WINDOW_TYPE_MENU, + NET_WM_WINDOW_TYPE_NOTIFICATION, + NET_WM_WINDOW_TYPE_POPUP_MENU, + NET_WM_WINDOW_TYPE_SPLASH, + NET_WM_WINDOW_TYPE_TOOLTIP, + NET_WM_WINDOW_TYPE_UTILITY, + }; + for (size_t i = 0; i < sizeof(needles) / sizeof(needles[0]); ++i) { + if (xwm_atoms_contains(surface->xwm, surface->window_type, + surface->window_type_len, needles[i])) { + ret = false; + } + } + + return ret; +} |