wlserver: create one wl_output global per Xwayland server
Closes: https://github.com/Plagman/gamescope/issues/571
This commit is contained in:
parent
9aada10be3
commit
5b7f70a9e5
2 changed files with 88 additions and 33 deletions
107
src/wlserver.cpp
107
src/wlserver.cpp
|
@ -440,6 +440,11 @@ struct wl_client *gamescope_xwayland_server_t::get_client()
|
||||||
return xwayland_server->client;
|
return xwayland_server->client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct wlr_output *gamescope_xwayland_server_t::get_output()
|
||||||
|
{
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
static void gamescope_xwayland_handle_override_window_content( struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface_resource, uint32_t x11_window )
|
static void gamescope_xwayland_handle_override_window_content( struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface_resource, uint32_t x11_window )
|
||||||
{
|
{
|
||||||
// This should ideally use the surface's xwayland, but we don't know it.
|
// This should ideally use the surface's xwayland, but we don't know it.
|
||||||
|
@ -536,14 +541,37 @@ static void handle_wlr_log(enum wlr_log_importance importance, const char *fmt,
|
||||||
|
|
||||||
void wlserver_set_output_info( const wlserver_output_info *info )
|
void wlserver_set_output_info( const wlserver_output_info *info )
|
||||||
{
|
{
|
||||||
wlr_output_destroy_global(wlserver.wlr.output);
|
free(wlserver.output_info.name);
|
||||||
|
free(wlserver.output_info.description);
|
||||||
|
wlserver.output_info.name = strdup(info->name);
|
||||||
|
wlserver.output_info.description = strdup(info->description);
|
||||||
|
wlserver.output_info.phys_width = info->phys_width;
|
||||||
|
wlserver.output_info.phys_height = info->phys_height;
|
||||||
|
|
||||||
wlr_output_set_name(wlserver.wlr.output, info->name);
|
for (size_t i = 0; i < wlserver.wlr.xwayland_servers.size(); i++) {
|
||||||
wlr_output_set_description(wlserver.wlr.output, info->description);
|
gamescope_xwayland_server_t *server = wlserver.wlr.xwayland_servers[i].get();
|
||||||
wlserver.wlr.output->phys_width = info->phys_width;
|
server->update_output_info();
|
||||||
wlserver.wlr.output->phys_height = info->phys_height;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wlr_output_create_global(wlserver.wlr.output);
|
static bool filter_global(const struct wl_client *client, const struct wl_global *global, void *data)
|
||||||
|
{
|
||||||
|
const struct wl_interface *iface = wl_global_get_interface(global);
|
||||||
|
if (strcmp(iface->name, "wl_output") != 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
struct wlr_output *output = (struct wlr_output *) wl_global_get_user_data(global);
|
||||||
|
assert(output);
|
||||||
|
|
||||||
|
/* We create one wl_output global per Xwayland server, to easily have
|
||||||
|
* per-server output configuration. Only expose the wl_output belonging to
|
||||||
|
* the server. */
|
||||||
|
for (size_t i = 0; i < wlserver.wlr.xwayland_servers.size(); i++) {
|
||||||
|
gamescope_xwayland_server_t *server = wlserver.wlr.xwayland_servers[i].get();
|
||||||
|
if (server->get_client() == client)
|
||||||
|
return server->get_output() == output;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wlsession_init( void ) {
|
bool wlsession_init( void ) {
|
||||||
|
@ -552,9 +580,7 @@ bool wlsession_init( void ) {
|
||||||
wlserver.display = wl_display_create();
|
wlserver.display = wl_display_create();
|
||||||
wlserver.wlr.headless_backend = wlr_headless_backend_create( wlserver.display );
|
wlserver.wlr.headless_backend = wlr_headless_backend_create( wlserver.display );
|
||||||
|
|
||||||
wlserver.wlr.output = wlr_headless_add_output( wlserver.wlr.headless_backend, 1280, 720 );
|
wl_display_set_global_filter(wlserver.display, filter_global, nullptr);
|
||||||
strncpy(wlserver.wlr.output->make, "gamescope", sizeof(wlserver.wlr.output->make));
|
|
||||||
strncpy(wlserver.wlr.output->model, "gamescope", sizeof(wlserver.wlr.output->model));
|
|
||||||
|
|
||||||
const struct wlserver_output_info output_info = {
|
const struct wlserver_output_info output_info = {
|
||||||
.name = "Virtual-1",
|
.name = "Virtual-1",
|
||||||
|
@ -631,11 +657,45 @@ gamescope_xwayland_server_t::gamescope_xwayland_server_t(wl_display *display)
|
||||||
};
|
};
|
||||||
xwayland_server = wlr_xwayland_server_create(display, &xwayland_options);
|
xwayland_server = wlr_xwayland_server_create(display, &xwayland_options);
|
||||||
wl_signal_add(&xwayland_server->events.ready, &xwayland_ready_listener);
|
wl_signal_add(&xwayland_server->events.ready, &xwayland_ready_listener);
|
||||||
|
|
||||||
|
output = wlr_headless_add_output(wlserver.wlr.headless_backend, 1280, 720);
|
||||||
|
strncpy(output->make, "gamescope", sizeof(output->make));
|
||||||
|
strncpy(output->model, "gamescope", sizeof(output->model));
|
||||||
|
|
||||||
|
int refresh = g_nNestedRefresh;
|
||||||
|
if (refresh == 0) {
|
||||||
|
refresh = g_nOutputRefresh;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_output_enable(output, true);
|
||||||
|
wlr_output_set_custom_mode(output, g_nNestedWidth, g_nNestedHeight, refresh * 1000);
|
||||||
|
if (!wlr_output_commit(output))
|
||||||
|
{
|
||||||
|
wl_log.errorf("Failed to commit headless output");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
update_output_info();
|
||||||
}
|
}
|
||||||
|
|
||||||
gamescope_xwayland_server_t::~gamescope_xwayland_server_t()
|
gamescope_xwayland_server_t::~gamescope_xwayland_server_t()
|
||||||
{
|
{
|
||||||
wlr_xwayland_server_destroy(xwayland_server);
|
wlr_xwayland_server_destroy(xwayland_server);
|
||||||
|
wlr_output_destroy(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gamescope_xwayland_server_t::update_output_info()
|
||||||
|
{
|
||||||
|
const auto *info = &wlserver.output_info;
|
||||||
|
|
||||||
|
wlr_output_destroy_global(output);
|
||||||
|
|
||||||
|
wlr_output_set_name(output, info->name);
|
||||||
|
wlr_output_set_description(output, info->description);
|
||||||
|
output->phys_width = info->phys_width;
|
||||||
|
output->phys_height = info->phys_height;
|
||||||
|
|
||||||
|
wlr_output_create_global(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wlserver_init( void ) {
|
bool wlserver_init( void ) {
|
||||||
|
@ -723,19 +783,6 @@ bool wlserver_init( void ) {
|
||||||
|
|
||||||
wl_signal_emit( &wlserver.wlr.multi_backend->events.new_input, kbd_dev );
|
wl_signal_emit( &wlserver.wlr.multi_backend->events.new_input, kbd_dev );
|
||||||
|
|
||||||
int refresh = g_nNestedRefresh;
|
|
||||||
if (refresh == 0) {
|
|
||||||
refresh = g_nOutputRefresh;
|
|
||||||
}
|
|
||||||
|
|
||||||
wlr_output_enable( wlserver.wlr.output, true );
|
|
||||||
wlr_output_set_custom_mode( wlserver.wlr.output, g_nNestedWidth, g_nNestedHeight, refresh * 1000 );
|
|
||||||
if ( !wlr_output_commit( wlserver.wlr.output ) )
|
|
||||||
{
|
|
||||||
wl_log.errorf("Failed to commit noop output");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < g_nXWaylandCount; i++)
|
for (int i = 0; i < g_nXWaylandCount; i++)
|
||||||
{
|
{
|
||||||
auto server = std::make_unique<gamescope_xwayland_server_t>(wlserver.display);
|
auto server = std::make_unique<gamescope_xwayland_server_t>(wlserver.display);
|
||||||
|
@ -1134,16 +1181,14 @@ void wlserver_set_xwayland_server_mode( size_t idx, int w, int h, int refresh )
|
||||||
gamescope_xwayland_server_t *server = wlserver_get_xwayland_server( idx );
|
gamescope_xwayland_server_t *server = wlserver_get_xwayland_server( idx );
|
||||||
if ( !server )
|
if ( !server )
|
||||||
return;
|
return;
|
||||||
wl_client *client = server->get_client();
|
|
||||||
|
|
||||||
struct wl_resource *resource;
|
struct wlr_output *output = server->get_output();
|
||||||
wl_resource_for_each( resource, &wlserver.wlr.output->resources )
|
wlr_output_set_custom_mode(output, w, h, refresh * 1000);
|
||||||
|
if (!wlr_output_commit(output))
|
||||||
{
|
{
|
||||||
if ( wl_resource_get_client( resource ) == client )
|
wl_log.errorf("Failed to commit headless output");
|
||||||
{
|
abort();
|
||||||
wl_output_send_mode( resource, WL_OUTPUT_MODE_CURRENT, w, h, refresh * 1000 );
|
|
||||||
wl_output_send_done( resource );
|
|
||||||
wl_log.infof( "Updating mode for xwayland server %zu %dx%d@%d - client %p - resource %p", idx, w, h, refresh, client, resource );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wl_log.infof("Updating mode for xwayland server #%zu: %dx%d@%d", idx, w, h, refresh);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,11 +48,16 @@ public:
|
||||||
void destroy_content_override(struct wlserver_content_override *co);
|
void destroy_content_override(struct wlserver_content_override *co);
|
||||||
|
|
||||||
struct wl_client *get_client();
|
struct wl_client *get_client();
|
||||||
|
struct wlr_output *get_output();
|
||||||
|
|
||||||
|
void update_output_info();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct wlr_xwayland_server *xwayland_server = NULL;
|
struct wlr_xwayland_server *xwayland_server = NULL;
|
||||||
struct wl_listener xwayland_ready_listener = { .notify = xwayland_ready_callback };
|
struct wl_listener xwayland_ready_listener = { .notify = xwayland_ready_callback };
|
||||||
|
|
||||||
|
struct wlr_output *output;
|
||||||
|
|
||||||
std::map<uint32_t, wlserver_content_override *> content_overrides;
|
std::map<uint32_t, wlserver_content_override *> content_overrides;
|
||||||
|
|
||||||
bool xwayland_ready = false;
|
bool xwayland_ready = false;
|
||||||
|
@ -74,9 +79,8 @@ struct wlserver_t {
|
||||||
|
|
||||||
struct wlr_renderer *renderer;
|
struct wlr_renderer *renderer;
|
||||||
struct wlr_compositor *compositor;
|
struct wlr_compositor *compositor;
|
||||||
struct wlr_session *session;
|
struct wlr_session *session;
|
||||||
struct wlr_seat *seat;
|
struct wlr_seat *seat;
|
||||||
struct wlr_output *output;
|
|
||||||
|
|
||||||
// Used to simulate key events and set the keymap
|
// Used to simulate key events and set the keymap
|
||||||
struct wlr_input_device *virtual_keyboard_device;
|
struct wlr_input_device *virtual_keyboard_device;
|
||||||
|
@ -92,6 +96,12 @@ struct wlserver_t {
|
||||||
bool button_held[ WLSERVER_BUTTON_COUNT ];
|
bool button_held[ WLSERVER_BUTTON_COUNT ];
|
||||||
bool touch_down[ WLSERVER_TOUCH_COUNT ];
|
bool touch_down[ WLSERVER_TOUCH_COUNT ];
|
||||||
|
|
||||||
|
struct {
|
||||||
|
char *name;
|
||||||
|
char *description;
|
||||||
|
int phys_width, phys_height; // millimeters
|
||||||
|
} output_info;
|
||||||
|
|
||||||
struct wl_listener session_active;
|
struct wl_listener session_active;
|
||||||
struct wl_listener new_input_method;
|
struct wl_listener new_input_method;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue