xwm: improve activation and dont send focus twice

This commit is contained in:
Tony Crisci 2017-10-25 08:39:28 -04:00
parent 1be650d78a
commit 0d1dd84a48
3 changed files with 69 additions and 55 deletions

View File

@ -125,7 +125,7 @@ void wlr_xwayland_destroy(struct wlr_xwayland *wlr_xwayland);
struct wlr_xwayland *wlr_xwayland_create(struct wl_display *wl_display, struct wlr_xwayland *wlr_xwayland_create(struct wl_display *wl_display,
struct wlr_compositor *compositor); struct wlr_compositor *compositor);
void wlr_xwayland_surface_activate(struct wlr_xwayland *wlr_xwayland, void wlr_xwayland_surface_activate(struct wlr_xwayland *wlr_xwayland,
struct wlr_xwayland_surface *surface); struct wlr_xwayland_surface *surface, bool activated);
void wlr_xwayland_surface_configure(struct wlr_xwayland *wlr_xwayland, void wlr_xwayland_surface_configure(struct wlr_xwayland *wlr_xwayland,
struct wlr_xwayland_surface *surface, int16_t x, int16_t y, struct wlr_xwayland_surface *surface, int16_t x, int16_t y,
uint16_t width, uint16_t height); uint16_t width, uint16_t height);

View File

@ -11,12 +11,8 @@
static void activate(struct roots_view *view, bool active) { static void activate(struct roots_view *view, bool active) {
assert(view->type == ROOTS_XWAYLAND_VIEW); assert(view->type == ROOTS_XWAYLAND_VIEW);
if (active) { struct wlr_xwayland *xwayland = view->desktop->xwayland;
wlr_xwayland_surface_activate(view->desktop->xwayland, wlr_xwayland_surface_activate(xwayland, view->xwayland_surface, active);
view->xwayland_surface);
} else {
wlr_xwayland_surface_activate(view->desktop->xwayland, NULL);
}
} }
static void resize(struct roots_view *view, uint32_t width, uint32_t height) { static void resize(struct roots_view *view, uint32_t width, uint32_t height) {

View File

@ -86,9 +86,69 @@ static struct wlr_xwayland_surface *wlr_xwayland_surface_create(
return surface; return surface;
} }
static void xwm_set_net_active_window(struct wlr_xwm *xwm,
xcb_window_t window) {
xcb_change_property(xwm->xcb_conn, XCB_PROP_MODE_REPLACE,
xwm->screen->root, xwm->atoms[_NET_ACTIVE_WINDOW],
xwm->atoms[WINDOW], 32, 1, &window);
}
static void xwm_send_focus_window(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *surface) {
if (surface) {
xcb_client_message_event_t client_message;
client_message.response_type = XCB_CLIENT_MESSAGE;
client_message.format = 32;
client_message.window = surface->window_id;
client_message.type = xwm->atoms[WM_PROTOCOLS];
client_message.data.data32[0] = xwm->atoms[WM_TAKE_FOCUS];
client_message.data.data32[1] = XCB_TIME_CURRENT_TIME;
xcb_send_event(xwm->xcb_conn, 0, surface->window_id,
XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (char*)&client_message);
xcb_set_input_focus(xwm->xcb_conn, XCB_INPUT_FOCUS_POINTER_ROOT,
surface->window_id, XCB_CURRENT_TIME);
uint32_t values[1];
values[0] = XCB_STACK_MODE_ABOVE;
xcb_configure_window_checked(xwm->xcb_conn, surface->window_id,
XCB_CONFIG_WINDOW_STACK_MODE, values);
} else {
xcb_set_input_focus_checked(xwm->xcb_conn,
XCB_INPUT_FOCUS_POINTER_ROOT,
XCB_NONE, XCB_CURRENT_TIME);
}
}
void xwm_surface_activate(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *xsurface) {
if (xwm->focus_surface == xsurface) {
return;
}
if (xsurface) {
xwm_set_net_active_window(xwm, xsurface->window_id);
} else {
xwm_set_net_active_window(xwm, XCB_WINDOW_NONE);
}
xwm_send_focus_window(xwm, xsurface);
xwm->focus_surface = xsurface;
xcb_flush(xwm->xcb_conn);
}
static void wlr_xwayland_surface_destroy(struct wlr_xwayland_surface *surface) { static void wlr_xwayland_surface_destroy(struct wlr_xwayland_surface *surface) {
wl_signal_emit(&surface->events.destroy, surface); wl_signal_emit(&surface->events.destroy, surface);
if (surface == surface->xwm->focus_surface) {
xwm_surface_activate(surface->xwm, NULL);
}
wl_list_remove(&surface->link); wl_list_remove(&surface->link);
if (surface->surface_id) { if (surface->surface_id) {
@ -707,56 +767,14 @@ static void handle_compositor_surface_create(struct wl_listener *listener,
} }
} }
static void xwm_set_net_active_window(struct wlr_xwm *xwm,
xcb_window_t window) {
xcb_change_property(xwm->xcb_conn, XCB_PROP_MODE_REPLACE,
xwm->screen->root, xwm->atoms[_NET_ACTIVE_WINDOW],
xwm->atoms[WINDOW], 32, 1, &window);
}
static void xwm_send_focus_window(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *surface) {
if (surface) {
xcb_client_message_event_t client_message;
client_message.response_type = XCB_CLIENT_MESSAGE;
client_message.format = 32;
client_message.window = surface->window_id;
client_message.type = xwm->atoms[WM_PROTOCOLS];
client_message.data.data32[0] = xwm->atoms[WM_TAKE_FOCUS];
client_message.data.data32[1] = XCB_TIME_CURRENT_TIME;
xcb_send_event(xwm->xcb_conn, 0, surface->window_id,
XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (char*)&client_message);
xcb_set_input_focus(xwm->xcb_conn, XCB_INPUT_FOCUS_POINTER_ROOT,
surface->window_id, XCB_CURRENT_TIME);
uint32_t values[1];
values[0] = XCB_STACK_MODE_ABOVE;
xcb_configure_window_checked(xwm->xcb_conn, surface->window_id,
XCB_CONFIG_WINDOW_STACK_MODE, values);
} else {
xcb_set_input_focus_checked(xwm->xcb_conn,
XCB_INPUT_FOCUS_POINTER_ROOT,
XCB_NONE, XCB_CURRENT_TIME);
}
}
void wlr_xwayland_surface_activate(struct wlr_xwayland *wlr_xwayland, void wlr_xwayland_surface_activate(struct wlr_xwayland *wlr_xwayland,
struct wlr_xwayland_surface *surface) { struct wlr_xwayland_surface *surface, bool activated) {
struct wlr_xwm *xwm = wlr_xwayland->xwm; struct wlr_xwayland_surface *focused = wlr_xwayland->xwm->focus_surface;
if (activated) {
if (surface) { xwm_surface_activate(wlr_xwayland->xwm, surface);
xwm_set_net_active_window(xwm, surface->window_id); } else if (focused == surface) {
} else { xwm_surface_activate(wlr_xwayland->xwm, NULL);
xwm_set_net_active_window(xwm, XCB_WINDOW_NONE);
} }
xwm_send_focus_window(xwm, surface);
xwm->focus_surface = surface;
xcb_flush(xwm->xcb_conn);
} }
void wlr_xwayland_surface_configure(struct wlr_xwayland *wlr_xwayland, void wlr_xwayland_surface_configure(struct wlr_xwayland *wlr_xwayland,