aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/simple.c35
-rw-r--r--include/wlr/xwayland.h25
-rw-r--r--rootston/seat.c3
-rw-r--r--xwayland/xwm.c24
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;
+}