From 26f9942e6c94fc89520abde31f9bd0fcafeee42b Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Thu, 6 Jan 2022 06:59:58 +0000 Subject: [PATCH] wlserver: Split out xwayland_server from global wlserver state --- src/main.cpp | 4 ++- src/steamcompmgr.cpp | 8 +++-- src/wlserver.cpp | 73 ++++++++++++++++++++++++++++---------------- src/wlserver.hpp | 29 ++++++++++++++++-- 4 files changed, 80 insertions(+), 34 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 3c4afcb..1592a23 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -392,8 +392,10 @@ int main(int argc, char **argv) fprintf( stderr, "Failed to initialize wlserver\n" ); return 1; } + + gamescope_xwayland_server_t *base_server = wlserver_get_xwayland_server(0); - setenv("DISPLAY", wlserver_get_nested_display_name(), 1); + setenv("DISPLAY", base_server->get_nested_display_name(), 1); setenv("GAMESCOPE_WAYLAND_DISPLAY", wlserver_get_wl_display_name(), 1); #if HAVE_PIPEWIRE diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index ffae882..8857bc6 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -215,6 +215,7 @@ struct xwayland_ctx_t ignore_tail = &ignore_head; } + gamescope_xwayland_server_t *xwayland_server; Display *dpy; win *list; @@ -2903,7 +2904,7 @@ handle_wl_surface_id(xwayland_ctx_t *ctx, win *w, long surfaceID) wlserver_lock(); - wlserver_surface_set_wl_id( &w->surface, surfaceID ); + ctx->xwayland_server->set_wl_id( &w->surface, surfaceID ); surface = w->surface.wlr; if ( surface == NULL ) @@ -4036,7 +4037,8 @@ steamcompmgr_main(int argc, char **argv) alwaysComposite = true; } - ctx->dpy = XOpenDisplay( wlserver_get_nested_display_name() ); + ctx->xwayland_server = wlserver_get_xwayland_server(0); + ctx->dpy = XOpenDisplay( ctx->xwayland_server->get_nested_display_name() ); if (!ctx->dpy) { xwm_log.errorf("Can't open display"); @@ -4199,7 +4201,7 @@ steamcompmgr_main(int argc, char **argv) if ( readyPipeFD != -1 ) { - dprintf( readyPipeFD, "%s %s\n", wlserver_get_nested_display_name(), wlserver_get_wl_display_name() ); + dprintf( readyPipeFD, "%s %s\n", ctx->xwayland_server->get_nested_display_name(), wlserver_get_wl_display_name() ); close( readyPipeFD ); readyPipeFD = -1; } diff --git a/src/wlserver.cpp b/src/wlserver.cpp index bc249ad..841598e 100644 --- a/src/wlserver.cpp +++ b/src/wlserver.cpp @@ -55,8 +55,6 @@ static LogScope wl_log("wlserver"); static struct wlserver_t wlserver = {}; -static Display *g_XWLDpy = nullptr; - struct wlserver_content_override { struct wlr_surface *surface; uint32_t x11_window; @@ -70,8 +68,6 @@ enum wlserver_touch_click_mode g_nTouchClickMode = g_nDefaultTouchClickMode; static struct wl_list pending_surfaces = {0}; -static bool bXwaylandReady = false; - static void wlserver_surface_set_wlr( struct wlserver_surface *surf, struct wlr_surface *wlr_surf ); extern const struct wlr_surface_role xwayland_surface_role; @@ -106,15 +102,19 @@ const struct wlr_surface_role xwayland_surface_role = { .precommit = xwayland_surface_role_precommit, }; -static void xwayland_ready(struct wl_listener *listener, void *data) +void gamescope_xwayland_server_t::on_xwayland_ready(void *data) { - bXwaylandReady = true; + xwayland_ready = true; - if (!wlserver.wlr.xwayland_server->options.no_touch_pointer_emulation) + if (!xwayland_server->options.no_touch_pointer_emulation) wl_log.infof("Xwayland doesn't support -noTouchPointerEmulation, touch events might get duplicated"); } -struct wl_listener xwayland_ready_listener = { .notify = xwayland_ready }; +void gamescope_xwayland_server_t::xwayland_ready_callback(struct wl_listener *listener, void *data) +{ + gamescope_xwayland_server_t *server = wl_container_of( listener, server, xwayland_ready_listener ); + server->on_xwayland_ready(data); +} static void bump_input_counter() { @@ -629,6 +629,22 @@ int wlsession_open_kms( const char *device_name ) { return device->fd; } +gamescope_xwayland_server_t::gamescope_xwayland_server_t(wl_display *display) +{ + struct wlr_xwayland_server_options xwayland_options = { + .lazy = false, + .enable_wm = false, + .no_touch_pointer_emulation = true, + }; + xwayland_server = wlr_xwayland_server_create(display, &xwayland_options); + wl_signal_add(&xwayland_server->events.ready, &xwayland_ready_listener); +} + +gamescope_xwayland_server_t::~gamescope_xwayland_server_t() +{ + wlr_xwayland_server_destroy(xwayland_server); +} + bool wlserver_init( void ) { assert( wlserver.display != nullptr ); @@ -733,15 +749,9 @@ bool wlserver_init( void ) { wlr_output_create_global( wlserver.wlr.output ); - struct wlr_xwayland_server_options xwayland_options = { - .lazy = false, - .enable_wm = false, - .no_touch_pointer_emulation = true, - }; - wlserver.wlr.xwayland_server = wlr_xwayland_server_create(wlserver.display, &xwayland_options); - wl_signal_add(&wlserver.wlr.xwayland_server->events.ready, &xwayland_ready_listener); + auto server = std::make_unique(wlserver.display); - while (!bXwaylandReady) { + while (!server->is_xwayland_ready()) { wl_display_flush_clients(wlserver.display); if (wl_event_loop_dispatch(wlserver.event_loop, -1) < 0) { wl_log.errorf("wl_event_loop_dispatch failed\n"); @@ -749,12 +759,7 @@ bool wlserver_init( void ) { } } - g_XWLDpy = XOpenDisplay( wlserver.wlr.xwayland_server->display_name ); - if ( g_XWLDpy == nullptr ) - { - wl_log.errorf( "Failed to connect to X11 server" ); - return false; - } + wlserver.wlr.xwayland_servers.emplace_back(std::move(server)); return true; } @@ -808,7 +813,7 @@ void wlserver_run(void) // We need to shutdown Xwayland before disconnecting all clients, otherwise // wlroots will restart it automatically. - wlr_xwayland_server_destroy(wlserver.wlr.xwayland_server); + wlserver.wlr.xwayland_servers.clear(); wl_display_destroy_clients(wlserver.display); wl_display_destroy(wlserver.display); } @@ -850,11 +855,14 @@ void wlserver_mousefocus( struct wlr_surface *wlrsurface, int x /* = 0 */, int y void wlserver_mousemotion( int x, int y, uint32_t time ) { + // TODO: Josh: Fix me for multiple xwaylands +#if 0 if ( g_XWLDpy != NULL ) { XTestFakeRelativeMotionEvent( g_XWLDpy, x, y, CurrentTime ); XFlush( g_XWLDpy ); } +#endif } void wlserver_mousebutton( int button, bool press, uint32_t time ) @@ -881,9 +889,10 @@ void wlserver_send_frame_done( struct wlr_surface *surf, const struct timespec * wlr_surface_send_frame_done( surf, when ); } -const char *wlserver_get_nested_display_name( void ) +gamescope_xwayland_server_t *wlserver_get_xwayland_server( size_t index ) { - return wlserver.wlr.xwayland_server->display_name; + assert(index < wlserver.wlr.xwayland_servers.size()); + return wlserver.wlr.xwayland_servers[index].get(); } const char *wlserver_get_wl_display_name( void ) @@ -925,7 +934,7 @@ void wlserver_surface_init( struct wlserver_surface *surf, long x11_id ) wl_list_init( &surf->destroy.link ); } -void wlserver_surface_set_wl_id( struct wlserver_surface *surf, long id ) +void gamescope_xwayland_server_t::set_wl_id( struct wlserver_surface *surf, long id ) { if ( surf->wl_id != 0 ) { @@ -946,7 +955,7 @@ void wlserver_surface_set_wl_id( struct wlserver_surface *surf, long id ) } else { - struct wl_resource *resource = wl_client_get_object( wlserver.wlr.xwayland_server->client, id ); + struct wl_resource *resource = wl_client_get_object( xwayland_server->client, id ); if ( resource != nullptr ) wlr_surf = wlr_surface_from_resource( resource ); } @@ -955,6 +964,16 @@ void wlserver_surface_set_wl_id( struct wlserver_surface *surf, long id ) wlserver_surface_set_wlr( surf, wlr_surf ); } +bool gamescope_xwayland_server_t::is_xwayland_ready() const +{ + return xwayland_ready; +} + +const char *gamescope_xwayland_server_t::get_nested_display_name() const +{ + return xwayland_server->display_name; +} + void wlserver_surface_finish( struct wlserver_surface *surf ) { if ( surf->wlr == wlserver.mouse_focus_surface ) diff --git a/src/wlserver.hpp b/src/wlserver.hpp index c46946a..272336f 100644 --- a/src/wlserver.hpp +++ b/src/wlserver.hpp @@ -4,10 +4,33 @@ #include #include +#include +#include #define WLSERVER_BUTTON_COUNT 4 #define WLSERVER_TOUCH_COUNT 11 // Ten fingers + nose ought to be enough for anyone +class gamescope_xwayland_server_t +{ +public: + gamescope_xwayland_server_t(wl_display *display); + ~gamescope_xwayland_server_t(); + + void on_xwayland_ready(void *data); + static void xwayland_ready_callback(struct wl_listener *listener, void *data); + + bool is_xwayland_ready() const; + const char *get_nested_display_name() const; + + void set_wl_id( struct wlserver_surface *surf, long id ); + +private: + struct wlr_xwayland_server *xwayland_server = NULL; + struct wl_listener xwayland_ready_listener = { .notify = xwayland_ready_callback }; + + bool xwayland_ready = false; +}; + struct wlserver_t { struct wl_display *display; struct wl_event_loop *event_loop; @@ -20,13 +43,14 @@ struct wlserver_t { struct wlr_renderer *renderer; struct wlr_compositor *compositor; - struct wlr_xwayland_server *xwayland_server; struct wlr_session *session; struct wlr_seat *seat; struct wlr_output *output; // Used to simulate key events and set the keymap struct wlr_input_device *virtual_keyboard_device; + + std::vector> xwayland_servers; } wlr; struct wlr_surface *mouse_focus_surface; @@ -97,7 +121,7 @@ void wlserver_mousewheel( int x, int y, uint32_t time ); void wlserver_send_frame_done( struct wlr_surface *surf, const struct timespec *when ); -const char *wlserver_get_nested_display_name( void ); +gamescope_xwayland_server_t *wlserver_get_xwayland_server( size_t index ); const char *wlserver_get_wl_display_name( void ); struct wlserver_surface @@ -112,5 +136,4 @@ struct wlserver_surface }; void wlserver_surface_init( struct wlserver_surface *surf, long x11_id ); -void wlserver_surface_set_wl_id( struct wlserver_surface *surf, long id ); void wlserver_surface_finish( struct wlserver_surface *surf );