wlserver: Split out xwayland_server from global wlserver state

This commit is contained in:
Joshua Ashton 2022-01-06 06:59:58 +00:00 committed by Joshie
parent 582da1d967
commit 26f9942e6c
4 changed files with 80 additions and 34 deletions

View file

@ -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

View file

@ -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;
}

View file

@ -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<gamescope_xwayland_server_t>(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 )

View file

@ -4,10 +4,33 @@
#include <wayland-server-core.h>
#include <atomic>
#include <vector>
#include <memory>
#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<std::unique_ptr<gamescope_xwayland_server_t>> 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 );