diff --git a/include/labwc.h b/include/labwc.h index b8d839e6..c95b1810 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -226,6 +227,9 @@ struct server { struct wl_listener input_inhibit_activate; struct wl_listener input_inhibit_deactivate; + struct wlr_xdg_activation_v1 *xdg_activation; + struct wl_listener xdg_activation_request; + struct wl_list views; struct wl_list unmanaged_surfaces; @@ -342,6 +346,8 @@ void xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup); void xdg_toplevel_decoration(struct wl_listener *listener, void *data); +void xdg_activation_handle_request(struct wl_listener *listener, void *data); + void xdg_surface_new(struct wl_listener *listener, void *data); void foreign_toplevel_handle_create(struct view *view); diff --git a/src/server.c b/src/server.c index 3d36526c..bf74b871 100644 --- a/src/server.c +++ b/src/server.c @@ -331,6 +331,15 @@ server_init(struct server *server) ? WLR_SERVER_DECORATION_MANAGER_MODE_SERVER : WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT); + server->xdg_activation = wlr_xdg_activation_v1_create(server->wl_display); + if (!server->xdg_activation) { + wlr_log(WLR_ERROR, "unable to create xdg_activation interface"); + exit(EXIT_FAILURE); + } + server->xdg_activation_request.notify = xdg_activation_handle_request; + wl_signal_add(&server->xdg_activation->events.request_activate, + &server->xdg_activation_request); + struct wlr_presentation *presentation = wlr_presentation_create(server->wl_display, server->backend); if (!presentation) { diff --git a/src/xdg.c b/src/xdg.c index dcf41b6e..ee2e50a7 100644 --- a/src/xdg.c +++ b/src/xdg.c @@ -390,6 +390,46 @@ static const struct view_impl xdg_toplevel_view_impl = { .maximize = xdg_toplevel_view_maximize, }; +void +xdg_activation_handle_request(struct wl_listener *listener, void *data) +{ + const struct wlr_xdg_activation_v1_request_activate_event *event = data; + + if (!wlr_surface_is_xdg_surface(event->surface)) { + return; + } + struct wlr_xdg_surface *xdg_surface = + wlr_xdg_surface_from_wlr_surface(event->surface); + struct view *view = xdg_surface ? xdg_surface->data : NULL; + + if (!view) { + wlr_log(WLR_INFO, "Not activating surface - no view attached to surface"); + return; + } + if (!event->token->seat) { + wlr_log(WLR_INFO, "Denying focus request, seat wasn't supplied"); + return; + } + /* + * We do not check for event->token->surface here because it may already + * be destroyed and thus being NULL. With wlroots 0.17 we can hook into + * the `new_token` signal, attach further information to the token and + * then react to that information here instead. For now we just check + * for the seat / serial being correct and then allow the request. + */ + + /* + * TODO: This is the exact same code as used in foreign.c. + * Refactor it into a public helper function somewhere. + */ + wlr_log(WLR_DEBUG, "Activating surface"); + if (view->workspace != view->server->workspace_current) { + workspaces_switch_to(view->workspace); + } + desktop_focus_and_activate_view(&view->server->seat, view); + desktop_move_to_front(view); +} + /* * We use the following struct user_data pointers: * - wlr_xdg_surface->data = view