From 7a99bb83b4bba927424eea136466b77803d549b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Wed, 15 Aug 2018 08:50:15 +0200 Subject: [PATCH 1/3] Rename phosh to phosh_private This makes it better match the protocol name. Also name the variables consistently "phosh" instead of the overused "shell". --- include/rootston/desktop.h | 2 +- include/rootston/phosh.h | 14 ++++---- rootston/phosh.c | 68 ++++++++++++++++++++++---------------- 3 files changed, 47 insertions(+), 37 deletions(-) diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h index 768c3e20c..740f2643f 100644 --- a/include/rootston/desktop.h +++ b/include/rootston/desktop.h @@ -74,7 +74,7 @@ struct roots_desktop { struct wlr_xwayland *xwayland; struct wl_listener xwayland_surface; #endif - struct phosh *phosh; + struct phosh_private *phosh; }; struct roots_server; diff --git a/include/rootston/phosh.h b/include/rootston/phosh.h index cb0d546b1..f6e658a38 100644 --- a/include/rootston/phosh.h +++ b/include/rootston/phosh.h @@ -1,11 +1,10 @@ -#ifndef _ROOTSTON_PHOSH_H -#define _ROOTSTON_PHOSH_H - +#pragma once #include -struct phosh { +struct phosh_private { struct wl_resource* resource; struct wl_global *global; + struct roots_desktop *desktop; struct { struct wl_listener layer_shell_new_surface; @@ -14,6 +13,7 @@ struct phosh { struct wlr_layer_surface *panel; }; -struct phosh* phosh_create(struct roots_desktop *desktop, struct wl_display *display); -void phosh_destroy(struct phosh *shell); -#endif + +struct phosh_private* phosh_create(struct roots_desktop *desktop, struct wl_display *display); +void phosh_destroy(struct phosh_private *shell); +struct phosh_private *phosh_private_from_resource(struct wl_resource *resource); diff --git a/rootston/phosh.c b/rootston/phosh.c index f31c7b9a2..794c50c44 100644 --- a/rootston/phosh.c +++ b/rootston/phosh.c @@ -12,12 +12,14 @@ #include "rootston/desktop.h" #include "rootston/phosh.h" -static void phosh_rotate_output(struct wl_client *client, +#define PHOSH_PRIVATE_VERSION 1 + +static void phosh_rotate_display(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface_resource, uint32_t degrees) { - struct phosh *shell = wl_resource_get_user_data(resource); + struct phosh_private *phosh = wl_resource_get_user_data(resource); enum wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; wlr_log(WLR_DEBUG, "rotation: %d", degrees); @@ -43,17 +45,17 @@ static void phosh_rotate_output(struct wl_client *client, break; } - if (!shell->panel) { + if (!phosh->panel) { wlr_log(WLR_ERROR, "Tried to rotate inexistent panel"); return; } - wlr_output_set_transform(shell->panel->output, transform); + wlr_output_set_transform(phosh->panel->output, transform); } static void handle_phosh_panel_surface_destroy (struct wl_listener *listener, void *data) { - struct phosh *phosh = + struct phosh_private *phosh = wl_container_of(listener, phosh, listeners.panel_surface_destroy); if (phosh->panel) { @@ -65,7 +67,7 @@ static void handle_phosh_panel_surface_destroy (struct wl_listener *listener, vo static void handle_phosh_layer_shell_new_surface(struct wl_listener *listener, void *data) { struct wlr_layer_surface *surface = data; - struct phosh *phosh = + struct phosh_private *phosh = wl_container_of(listener, phosh, listeners.layer_shell_new_surface); /* We're only interested in the panel */ @@ -79,36 +81,37 @@ static void handle_phosh_layer_shell_new_surface(struct wl_listener *listener, v } -static void phosh_resource_destroy(struct wl_resource *resource) { - struct phosh *phosh = wl_resource_get_user_data(resource); +static void phosh_handle_resource_destroy(struct wl_resource *resource) { + struct phosh_private *phosh = wl_resource_get_user_data(resource); phosh->resource = NULL; phosh->panel = NULL; + wlr_log(WLR_DEBUG, "Destroying phosh %p (res %p)", phosh, resource); } -static const struct phosh_private_interface phosh_impl = { - phosh_rotate_output, +static const struct phosh_private_interface phosh_private_impl = { + phosh_rotate_display, }; static void -bind_phosh(struct wl_client *client, void *data, uint32_t version, uint32_t id) { - struct phosh *phosh = data; +phosh_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) { + struct phosh_private *phosh = data; struct wl_resource *resource = wl_resource_create(client, &phosh_private_interface, - 1, id); + version, id); if (phosh->resource) { wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "Only a single client can bind to phosh's private protocol"); } - /* FIXME: unsafe needs client == shell->child.client */ + /* FIXME: unsafe, needs client == shell->child.client */ if (true) { wlr_log(WLR_ERROR, "FIXME: allowing every client to bind as phosh"); wl_resource_set_implementation(resource, - &phosh_impl, - phosh, phosh_resource_destroy); + &phosh_private_impl, + phosh, phosh_handle_resource_destroy); phosh->resource = resource; return; } @@ -118,29 +121,36 @@ bind_phosh(struct wl_client *client, void *data, uint32_t version, uint32_t id) } -struct phosh* +struct phosh_private* phosh_create(struct roots_desktop *desktop, struct wl_display *display) { - struct phosh *shell = calloc(1, sizeof (struct phosh)); - if (!shell) + struct phosh_private *phosh = calloc(1, sizeof (struct phosh_private)); + if (!phosh) return NULL; - shell->desktop = desktop; + phosh->desktop = desktop; wl_signal_add(&desktop->layer_shell->events.new_surface, - &shell->listeners.layer_shell_new_surface); - shell->listeners.layer_shell_new_surface.notify = handle_phosh_layer_shell_new_surface; + &phosh->listeners.layer_shell_new_surface); + phosh->listeners.layer_shell_new_surface.notify = handle_phosh_layer_shell_new_surface; - wlr_log(WLR_INFO, "Initializing phosh private inrerface"); - shell->global = wl_global_create(display, &phosh_private_interface, 1, shell, bind_phosh); - if (!shell->global) { + wlr_log(WLR_INFO, "Initializing phosh private interface"); + phosh->global = wl_global_create(display, &phosh_private_interface, PHOSH_PRIVATE_VERSION, phosh, phosh_bind); + if (!phosh->global) { return NULL; } - return shell; + return phosh; } -void phosh_destroy(struct phosh *shell) { - wl_list_remove(&shell->listeners.layer_shell_new_surface.link); - wl_global_destroy(shell->global); +void phosh_destroy(struct phosh_private *phosh) { + wl_list_remove(&phosh->listeners.layer_shell_new_surface.link); + wl_global_destroy(phosh->global); +} + +struct phosh_private *phosh_private_from_resource( + struct wl_resource *resource) { + assert(wl_resource_instance_of(resource, &phosh_private_interface, + &phosh_private_impl)); + return wl_resource_get_user_data(resource); } -- GitLab From b188071e6d0523fa47d112376b5abf34ed0c682d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Thu, 30 Aug 2018 13:06:59 +0200 Subject: [PATCH 2/3] phosh-private: Use output instead of display We don't rename the request itself since we don't want to change the protocol. --- protocol/phosh-private.xml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/protocol/phosh-private.xml b/protocol/phosh-private.xml index 79b9b9b0d..bedc82cc3 100644 --- a/protocol/phosh-private.xml +++ b/protocol/phosh-private.xml @@ -9,10 +9,12 @@ summary="an invalid argument was provided in a request"/> - + + + - - Rotate the display clockwise 0, 90, 180 or 270 degree. + + Rotate the output clockwise 0, 90, 180 or 270 degree. -- GitLab From 95b605a9d7988fe95c56286e78daefe4a925d7a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Wed, 18 Jul 2018 22:15:56 +0200 Subject: [PATCH 3/3] Add phosh_private_xdg_switcher protocol Simple private protocoll to list and raise toplevels by app_id and title. We wanted a minimal set of objects, requests and events. Since this is only meant for the app overview page in the shell we can take many shortcuts and leave out e.g. XWayland for the moment. This will be replaced by wlr_foreign_toplevel_unstable_v1 later on. --- include/rootston/phosh.h | 17 ++++ protocol/phosh-private.xml | 54 ++++++++++++- rootston/phosh.c | 157 ++++++++++++++++++++++++++++++++++++- 3 files changed, 221 insertions(+), 7 deletions(-) diff --git a/include/rootston/phosh.h b/include/rootston/phosh.h index f6e658a38..aa885ad6a 100644 --- a/include/rootston/phosh.h +++ b/include/rootston/phosh.h @@ -1,9 +1,12 @@ #pragma once #include +#define PHOSH_PRIVATE_XDG_SWITCHER_SINCE_VERSION 2 + struct phosh_private { struct wl_resource* resource; struct wl_global *global; + struct wl_list xdg_switchers; // phosh_private_xdg_switchers::link struct roots_desktop *desktop; struct { @@ -11,9 +14,23 @@ struct phosh_private { struct wl_listener panel_surface_destroy; } listeners; struct wlr_layer_surface *panel; + struct wl_list apps; +}; + + +struct phosh_private_xdg_switcher { + struct wl_list link; + struct wl_resource *resource; + struct phosh_private *phosh; + + struct { + struct wl_signal destroy; + } events; }; struct phosh_private* phosh_create(struct roots_desktop *desktop, struct wl_display *display); void phosh_destroy(struct phosh_private *shell); struct phosh_private *phosh_private_from_resource(struct wl_resource *resource); +struct phosh_private_xdg_switcher *phosh_private_xdg_switcher_from_resource( + struct wl_resource *resource); diff --git a/protocol/phosh-private.xml b/protocol/phosh-private.xml index bedc82cc3..4eede1e58 100644 --- a/protocol/phosh-private.xml +++ b/protocol/phosh-private.xml @@ -1,5 +1,5 @@ - + Private protocol between phosh and the compositor. @@ -10,14 +10,60 @@ - - - + Rotate the output clockwise 0, 90, 180 or 270 degree. + + + + + + + + + + The interface is meant to list xdg surfaces (see the xdg-shell + stable wayland protocol) and to raise these surfaces to the top + of the window stack. + + It's up to the compositor if it only lists surfaces of the + xdg-shell stable protocol or also surfaces using unstable versions of + the xdg-shell protocol. + + + + + + + + Request to list xdg shell toplevels. + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rootston/phosh.c b/rootston/phosh.c index 794c50c44..16bfcf67e 100644 --- a/rootston/phosh.c +++ b/rootston/phosh.c @@ -12,13 +12,118 @@ #include "rootston/desktop.h" #include "rootston/phosh.h" -#define PHOSH_PRIVATE_VERSION 1 +#define PHOSH_PRIVATE_VERSION 2 + +static void xdg_switcher_handle_list_xdg_surfaces(struct wl_client *client, + struct wl_resource *resource) { + struct phosh_private_xdg_switcher *xdg_switcher = + phosh_private_xdg_switcher_from_resource(resource); + struct phosh_private *phosh = xdg_switcher->phosh; + struct roots_desktop *desktop = phosh->desktop; + struct roots_view *view; + + wl_list_for_each(view, &desktop->views, link) { + const char *app_id = NULL; + const char *title = NULL; + + switch (view->type) { + case ROOTS_XDG_SHELL_VIEW: + if (view->xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) + continue; + app_id = view->xdg_surface->toplevel->app_id; + title = view->xdg_surface->toplevel->title; + break; + case ROOTS_XDG_SHELL_V6_VIEW: + if (view->xdg_surface_v6->role != WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) + continue; + app_id = view->xdg_surface_v6->toplevel->app_id; + title = view->xdg_surface_v6->toplevel->title; + break; + default: + /* other surface types would go here */ + break; + } + + if (app_id) { + phosh_private_xdg_switcher_send_xdg_surface (resource, app_id, title); + app_id = NULL; + title = NULL; + } + } + phosh_private_xdg_switcher_send_list_xdg_surfaces_done (resource); +} + + +static void xdg_switcher_handle_raise_xdg_surfaces(struct wl_client *client, + struct wl_resource *resource, + const char *app_id, + const char *title) { + struct phosh_private_xdg_switcher *xdg_switcher = + phosh_private_xdg_switcher_from_resource(resource); + struct phosh_private *phosh = xdg_switcher->phosh; + struct roots_desktop *desktop = phosh->desktop; + struct roots_view *view, *found_view; + struct roots_input *input = desktop->server->input; + struct roots_seat *seat = input_last_active_seat(input); + + wlr_log(WLR_DEBUG, "will raise view %s", app_id); + wl_list_for_each(view, &desktop->views, link) { + switch (view->type) { + case ROOTS_XDG_SHELL_VIEW: + if (view->xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) + continue; + if (!strcmp(app_id, view->xdg_surface->toplevel->app_id) && + !strcmp(title, view->xdg_surface->toplevel->title)) + found_view = view; + break; + case ROOTS_XDG_SHELL_V6_VIEW: + if (view->xdg_surface_v6->role != WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) + continue; + if (!strcmp(app_id, view->xdg_surface_v6->toplevel->app_id) && + !strcmp(title, view->xdg_surface_v6->toplevel->title)) + found_view = view; + break; + default: + /* other surface types would go here */ + break; + } + } + + /* TODO: check if view belongs to this seat */ + if (found_view) { + roots_seat_set_focus(seat, found_view); + } +} + + +static void xdg_switcher_handle_destroy(struct wl_client *client, + struct wl_resource *resource) { + wl_resource_destroy(resource); +} + + +static void xdg_switcher_handle_resource_destroy(struct wl_resource *resource) { + struct phosh_private_xdg_switcher *xdg_switcher = + phosh_private_xdg_switcher_from_resource(resource); + + wlr_log(WLR_DEBUG, "Destroying xdg_switcher %p (res %p)", xdg_switcher, + xdg_switcher->resource); + wl_list_remove(&xdg_switcher->link); + free(xdg_switcher); +} + + +static const struct phosh_private_xdg_switcher_interface phosh_private_xdg_switcher_impl = { + .destroy = xdg_switcher_handle_destroy, + .list_xdg_surfaces = xdg_switcher_handle_list_xdg_surfaces, + .raise_xdg_surface = xdg_switcher_handle_raise_xdg_surfaces, +}; + static void phosh_rotate_display(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface_resource, - uint32_t degrees) -{ + uint32_t degrees) { struct phosh_private *phosh = wl_resource_get_user_data(resource); enum wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; @@ -81,6 +186,40 @@ static void handle_phosh_layer_shell_new_surface(struct wl_listener *listener, v } +void handle_get_xdg_switcher(struct wl_client *client, + struct wl_resource *phosh_private_resource, + uint32_t id) { + struct phosh_private *phosh = + phosh_private_from_resource(phosh_private_resource); + + struct phosh_private_xdg_switcher *xdg_switcher = + calloc(1, sizeof(struct wlr_gamma_control)); + if (xdg_switcher == NULL) { + wl_client_post_no_memory(client); + return; + } + + int version = wl_resource_get_version(phosh_private_resource); + xdg_switcher->resource = wl_resource_create(client, + &phosh_private_xdg_switcher_interface, version, id); + if (xdg_switcher->resource == NULL) { + free(xdg_switcher); + wl_client_post_no_memory(client); + return; + } + + wlr_log(WLR_DEBUG, "new phosh_private_xdg_switcher %p (res %p)", xdg_switcher, + xdg_switcher->resource); + wl_resource_set_implementation(xdg_switcher->resource, + &phosh_private_xdg_switcher_impl, xdg_switcher, xdg_switcher_handle_resource_destroy); + + xdg_switcher->phosh = phosh; + wl_signal_init(&xdg_switcher->events.destroy); + wl_list_insert(&phosh->xdg_switchers, &xdg_switcher->link); +} + + + static void phosh_handle_resource_destroy(struct wl_resource *resource) { struct phosh_private *phosh = wl_resource_get_user_data(resource); @@ -92,6 +231,7 @@ static void phosh_handle_resource_destroy(struct wl_resource *resource) { static const struct phosh_private_interface phosh_private_impl = { phosh_rotate_display, + handle_get_xdg_switcher, }; @@ -132,9 +272,11 @@ phosh_create(struct roots_desktop *desktop, struct wl_display *display) { wl_signal_add(&desktop->layer_shell->events.new_surface, &phosh->listeners.layer_shell_new_surface); phosh->listeners.layer_shell_new_surface.notify = handle_phosh_layer_shell_new_surface; + wl_list_init(&phosh->xdg_switchers); wlr_log(WLR_INFO, "Initializing phosh private interface"); phosh->global = wl_global_create(display, &phosh_private_interface, PHOSH_PRIVATE_VERSION, phosh, phosh_bind); + if (!phosh->global) { return NULL; } @@ -148,9 +290,18 @@ void phosh_destroy(struct phosh_private *phosh) { wl_global_destroy(phosh->global); } + struct phosh_private *phosh_private_from_resource( struct wl_resource *resource) { assert(wl_resource_instance_of(resource, &phosh_private_interface, &phosh_private_impl)); return wl_resource_get_user_data(resource); } + + +struct phosh_private_xdg_switcher *phosh_private_xdg_switcher_from_resource( + struct wl_resource *resource) { + assert(wl_resource_instance_of(resource, &phosh_private_xdg_switcher_interface, + &phosh_private_xdg_switcher_impl)); + return wl_resource_get_user_data(resource); +} -- GitLab