add xwayland unmanaged tests to support dmenu

This adds `wlr_xwayland_surface_is_unamanged`, to allow compositors more
fine grained control over XWayland focus.
A surface that is unmanaged should not receive focus, while other
windows that are just override redirect may want it (dmenu).
The way unamanged is determined is taken from wlc.
This commit is contained in:
Markus Ongyerth 2018-02-25 09:57:30 +01:00
parent 3bce37f99a
commit bb676013ed
8 changed files with 60 additions and 2 deletions

View file

@ -78,6 +78,7 @@ void view_apply_damage(struct roots_view *view);
void view_damage_whole(struct roots_view *view);
void view_update_position(struct roots_view *view, double x, double y);
void view_update_size(struct roots_view *view, uint32_t width, uint32_t height);
void view_initial_focus(struct roots_view *view);
void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data);
void handle_xdg_shell_surface(struct wl_listener *listener, void *data);

View file

@ -186,4 +186,5 @@ void wlr_xwayland_surface_set_fullscreen(struct wlr_xwayland_surface *surface,
void wlr_xwayland_set_seat(struct wlr_xwayland *xwayland,
struct wlr_seat *seat);
bool wlr_xwayland_surface_is_unmanaged(const struct wlr_xwayland_surface *surface);
#endif

View file

@ -39,6 +39,12 @@ enum atom_name {
INCR,
TEXT,
TIMESTAMP,
NET_WM_WINDOW_TYPE_UTILITY,
NET_WM_WINDOW_TYPE_TOOLTIP,
NET_WM_WINDOW_TYPE_DND,
NET_WM_WINDOW_TYPE_DROPDOWN_MENU,
NET_WM_WINDOW_TYPE_POPUP_MENU,
NET_WM_WINDOW_TYPE_COMBO,
ATOM_LAST,
};
@ -113,4 +119,7 @@ void xwm_selection_finish(struct wlr_xwm *xwm);
void xwm_set_seat(struct wlr_xwm *xwm, struct wlr_seat *seat);
bool wlr_xwm_atoms_contains(struct wlr_xwm *xwm, xcb_atom_t *atoms,
size_t num_atoms, enum atom_name needle);
#endif

View file

@ -426,13 +426,17 @@ void view_init(struct roots_view *view, struct roots_desktop *desktop) {
view_damage_whole(view);
}
void view_setup(struct roots_view *view) {
void view_initial_focus(struct roots_view *view) {
struct roots_input *input = view->desktop->server->input;
// TODO what seat gets focus? the one with the last input event?
struct roots_seat *seat;
wl_list_for_each(seat, &input->seats, link) {
roots_seat_set_focus(seat, view);
}
}
void view_setup(struct roots_view *view) {
view_initial_focus(view);
view_center(view);
view_update_output(view, NULL);

View file

@ -721,7 +721,7 @@ 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_surface_is_unmanaged(view->xwayland_surface)) {
return;
}
#endif

View file

@ -350,5 +350,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
}
view_setup(view);
} else {
view_initial_focus(view);
}
}

View file

@ -405,3 +405,24 @@ void wlr_xwayland_set_seat(struct wlr_xwayland *xwayland,
xwayland->seat_destroy.notify = wlr_xwayland_handle_seat_destroy;
wl_signal_add(&seat->events.destroy, &xwayland->seat_destroy);
}
bool wlr_xwayland_surface_is_unmanaged(const struct wlr_xwayland_surface *surface) {
static enum atom_name needles[] = {
NET_WM_WINDOW_TYPE_UTILITY,
NET_WM_WINDOW_TYPE_TOOLTIP,
NET_WM_WINDOW_TYPE_DND,
NET_WM_WINDOW_TYPE_DROPDOWN_MENU,
NET_WM_WINDOW_TYPE_POPUP_MENU,
NET_WM_WINDOW_TYPE_COMBO,
};
for (size_t i = 0; i < sizeof(needles) / sizeof(needles[0]); ++i) {
if (wlr_xwm_atoms_contains(surface->xwm, surface->window_type,
surface->window_type_len, needles[i])) {
return true;
}
}
return false;
}

View file

@ -54,6 +54,12 @@ const char *atom_map[ATOM_LAST] = {
"INCR",
"TEXT",
"TIMESTAMP",
"_NET_WM_WINDOW_TYPE_UTILITY",
"_NET_WM_WINDOW_TYPE_TOOLTIP",
"_NET_WM_WINDOW_TYPE_DND",
"_NET_WM_WINDOW_TYPE_DROPDOWN_MENU",
"_NET_WM_WINDOW_TYPE_POPUP_MENU",
"_NET_WM_WINDOW_TYPE_COMBO",
};
/* General helpers */
@ -1446,3 +1452,17 @@ void wlr_xwayland_surface_set_fullscreen(struct wlr_xwayland_surface *surface,
xsurface_set_net_wm_state(surface);
xcb_flush(surface->xwm->xcb_conn);
}
bool wlr_xwm_atoms_contains(struct wlr_xwm *xwm, xcb_atom_t *atoms,
size_t num_atoms, enum atom_name needle) {
xcb_atom_t atom = xwm->atoms[needle];
for (size_t i = 0; i < num_atoms; ++i) {
if (atom == atoms[i]) {
return true;
}
}
return false;
}