mirror of
https://github.com/labwc/labwc.git
synced 2025-11-03 09:01:51 -05:00
Add xwayland-unmanaged.c
Handle xwayland override_direct surfaces separately from the view struct - in order to simplify code, particularly in view.c
This commit is contained in:
parent
d831743b25
commit
8e7f2e78cd
8 changed files with 162 additions and 24 deletions
|
|
@ -52,6 +52,7 @@ struct server {
|
||||||
struct wlr_xwayland *xwayland;
|
struct wlr_xwayland *xwayland;
|
||||||
struct wl_listener new_xwayland_surface;
|
struct wl_listener new_xwayland_surface;
|
||||||
struct wl_list views;
|
struct wl_list views;
|
||||||
|
struct wl_list unmanaged_surfaces;
|
||||||
|
|
||||||
struct wlr_cursor *cursor;
|
struct wlr_cursor *cursor;
|
||||||
struct wlr_xcursor_manager *cursor_mgr;
|
struct wlr_xcursor_manager *cursor_mgr;
|
||||||
|
|
@ -78,10 +79,12 @@ struct server {
|
||||||
struct wl_list outputs;
|
struct wl_list outputs;
|
||||||
struct wl_listener new_output;
|
struct wl_listener new_output;
|
||||||
|
|
||||||
/* For use in cycle (alt-tab) mode */
|
/* Set when in cycle (alt-tab) mode */
|
||||||
struct view *cycle_view;
|
struct view *cycle_view;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern struct server server;
|
||||||
|
|
||||||
struct output {
|
struct output {
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
struct server *server;
|
struct server *server;
|
||||||
|
|
@ -137,6 +140,18 @@ struct view {
|
||||||
struct wl_listener request_configure;
|
struct wl_listener request_configure;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct xwayland_unmanaged {
|
||||||
|
struct wlr_xwayland_surface *xwayland_surface;
|
||||||
|
struct wl_list link;
|
||||||
|
int lx, ly;
|
||||||
|
|
||||||
|
struct wl_listener request_configure;
|
||||||
|
struct wl_listener commit;
|
||||||
|
struct wl_listener map;
|
||||||
|
struct wl_listener unmap;
|
||||||
|
struct wl_listener destroy;
|
||||||
|
};
|
||||||
|
|
||||||
struct keyboard {
|
struct keyboard {
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
struct server *server;
|
struct server *server;
|
||||||
|
|
@ -150,6 +165,7 @@ void xdg_toplevel_decoration(struct wl_listener *listener, void *data);
|
||||||
void xdg_surface_new(struct wl_listener *listener, void *data);
|
void xdg_surface_new(struct wl_listener *listener, void *data);
|
||||||
|
|
||||||
void xwl_surface_new(struct wl_listener *listener, void *data);
|
void xwl_surface_new(struct wl_listener *listener, void *data);
|
||||||
|
void xwayland_unmanaged_create(struct wlr_xwayland_surface *xsurface);
|
||||||
|
|
||||||
void view_init_position(struct view *view);
|
void view_init_position(struct view *view);
|
||||||
/**
|
/**
|
||||||
|
|
@ -169,6 +185,8 @@ struct view *view_at(struct server *server, double lx, double ly,
|
||||||
struct wlr_surface **surface, double *sx, double *sy,
|
struct wlr_surface **surface, double *sx, double *sy,
|
||||||
int *view_area);
|
int *view_area);
|
||||||
|
|
||||||
|
void seat_focus_surface(struct wlr_surface *surface);
|
||||||
|
|
||||||
void interactive_begin(struct view *view, enum cursor_mode mode,
|
void interactive_begin(struct view *view, enum cursor_mode mode,
|
||||||
uint32_t edges);
|
uint32_t edges);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,11 @@ labwc_sources = files(
|
||||||
'keyboard.c',
|
'keyboard.c',
|
||||||
'main.c',
|
'main.c',
|
||||||
'output.c',
|
'output.c',
|
||||||
|
'seat.c',
|
||||||
'server.c',
|
'server.c',
|
||||||
'view.c',
|
'view.c',
|
||||||
'xdg.c',
|
'xdg.c',
|
||||||
|
'xwayland-unmanaged.c',
|
||||||
'xwl.c',
|
'xwl.c',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
36
src/output.c
36
src/output.c
|
|
@ -88,7 +88,7 @@ static void render_decorations(struct wlr_output *output, struct view *view)
|
||||||
struct render_data {
|
struct render_data {
|
||||||
struct wlr_output *output;
|
struct wlr_output *output;
|
||||||
struct wlr_renderer *renderer;
|
struct wlr_renderer *renderer;
|
||||||
struct view *view;
|
int lx, ly;
|
||||||
struct timespec *when;
|
struct timespec *when;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -98,7 +98,6 @@ static void render_surface(struct wlr_surface *surface, int sx, int sy,
|
||||||
/* This function is called for every surface that needs to be rendered.
|
/* This function is called for every surface that needs to be rendered.
|
||||||
*/
|
*/
|
||||||
struct render_data *rdata = data;
|
struct render_data *rdata = data;
|
||||||
struct view *view = rdata->view;
|
|
||||||
struct wlr_output *output = rdata->output;
|
struct wlr_output *output = rdata->output;
|
||||||
|
|
||||||
/* We first obtain a wlr_texture, which is a GPU resource. wlroots
|
/* We first obtain a wlr_texture, which is a GPU resource. wlroots
|
||||||
|
|
@ -117,10 +116,9 @@ static void render_surface(struct wlr_surface *surface, int sx, int sy,
|
||||||
* display might have layout coordinates of 2000,100. We need to
|
* display might have layout coordinates of 2000,100. We need to
|
||||||
* translate that to output-local coordinates, or (2000 - 1920). */
|
* translate that to output-local coordinates, or (2000 - 1920). */
|
||||||
double ox = 0, oy = 0;
|
double ox = 0, oy = 0;
|
||||||
wlr_output_layout_output_coords(view->server->output_layout, output,
|
wlr_output_layout_output_coords(server.output_layout, output, &ox, &oy);
|
||||||
&ox, &oy);
|
ox += rdata->lx + sx;
|
||||||
ox += view->x + sx;
|
oy += rdata->ly + sy;
|
||||||
oy += view->y + sy;
|
|
||||||
|
|
||||||
/* TODO: Support HiDPI */
|
/* TODO: Support HiDPI */
|
||||||
struct wlr_box box = {
|
struct wlr_box box = {
|
||||||
|
|
@ -188,22 +186,21 @@ void output_frame(struct wl_listener *listener, void *data)
|
||||||
* backwards. */
|
* backwards. */
|
||||||
struct view *view;
|
struct view *view;
|
||||||
wl_list_for_each_reverse (view, &output->server->views, link) {
|
wl_list_for_each_reverse (view, &output->server->views, link) {
|
||||||
if (!view->mapped) {
|
if (!view->mapped)
|
||||||
/* An unmapped view should not be rendered. */
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
struct render_data rdata = {
|
struct render_data rdata = {
|
||||||
.output = output->wlr_output,
|
.output = output->wlr_output,
|
||||||
.view = view,
|
.lx = view->x,
|
||||||
|
.ly = view->y,
|
||||||
.renderer = renderer,
|
.renderer = renderer,
|
||||||
.when = &now,
|
.when = &now,
|
||||||
};
|
};
|
||||||
|
|
||||||
render_decorations(output->wlr_output, view);
|
render_decorations(output->wlr_output, view);
|
||||||
|
|
||||||
/* This calls our render_surface function for each surface among
|
|
||||||
* the xdg_surface's toplevel and popups. */
|
|
||||||
if (view->type == LAB_XDG_SHELL_VIEW) {
|
if (view->type == LAB_XDG_SHELL_VIEW) {
|
||||||
|
/* render each xdg toplevel and popup surface */
|
||||||
wlr_xdg_surface_for_each_surface(
|
wlr_xdg_surface_for_each_surface(
|
||||||
view->xdg_surface, render_surface, &rdata);
|
view->xdg_surface, render_surface, &rdata);
|
||||||
} else if (view->type == LAB_XWAYLAND_VIEW) {
|
} else if (view->type == LAB_XWAYLAND_VIEW) {
|
||||||
|
|
@ -215,6 +212,21 @@ void output_frame(struct wl_listener *listener, void *data)
|
||||||
/* If in cycle (alt-tab) mode, highlight selected view */
|
/* If in cycle (alt-tab) mode, highlight selected view */
|
||||||
render_cycle_box(output);
|
render_cycle_box(output);
|
||||||
|
|
||||||
|
/* Render xwayland override_redirect surfaces */
|
||||||
|
struct xwayland_unmanaged *unmanaged;
|
||||||
|
wl_list_for_each_reverse (unmanaged, &server.unmanaged_surfaces, link) {
|
||||||
|
struct render_data rdata = {
|
||||||
|
.output = output->wlr_output,
|
||||||
|
.lx = unmanaged->lx,
|
||||||
|
.ly = unmanaged->ly,
|
||||||
|
.renderer = renderer,
|
||||||
|
.when = &now,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlr_surface *s = unmanaged->xwayland_surface->surface;
|
||||||
|
render_surface(s, 0, 0, &rdata);
|
||||||
|
}
|
||||||
|
|
||||||
/* Hardware cursors are rendered by the GPU on a separate plane, and can
|
/* Hardware cursors are rendered by the GPU on a separate plane, and can
|
||||||
* be moved around without re-rendering what's beneath them - which is
|
* be moved around without re-rendering what's beneath them - which is
|
||||||
* more efficient. However, not all hardware supports hardware cursors.
|
* more efficient. However, not all hardware supports hardware cursors.
|
||||||
|
|
|
||||||
11
src/seat.c
Normal file
11
src/seat.c
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#include "labwc.h"
|
||||||
|
|
||||||
|
void seat_focus_surface(struct wlr_surface *surface)
|
||||||
|
{
|
||||||
|
if (!surface) {
|
||||||
|
wlr_seat_keyboard_notify_clear_focus(server.seat);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* TODO: add keyboard stuff */
|
||||||
|
wlr_seat_keyboard_notify_enter(server.seat, surface, NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
|
@ -105,6 +105,7 @@ void server_init(struct server *server)
|
||||||
wlr_renderer_init_wl_display(server->renderer, server->wl_display);
|
wlr_renderer_init_wl_display(server->renderer, server->wl_display);
|
||||||
|
|
||||||
wl_list_init(&server->views);
|
wl_list_init(&server->views);
|
||||||
|
wl_list_init(&server->unmanaged_surfaces);
|
||||||
wl_list_init(&server->outputs);
|
wl_list_init(&server->outputs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,8 @@ void view_focus(struct view *view)
|
||||||
/* Note: this function only deals with keyboard focus. */
|
/* Note: this function only deals with keyboard focus. */
|
||||||
if (!view)
|
if (!view)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* TODO: messy - sort out */
|
||||||
if (!view->mapped) {
|
if (!view->mapped) {
|
||||||
view->impl->map(view);
|
view->impl->map(view);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
86
src/xwayland-unmanaged.c
Normal file
86
src/xwayland-unmanaged.c
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
#include "labwc.h"
|
||||||
|
|
||||||
|
static void unmanaged_handle_request_configure(struct wl_listener *listener,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct xwayland_unmanaged *unmanaged =
|
||||||
|
wl_container_of(listener, unmanaged, request_configure);
|
||||||
|
struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
|
||||||
|
struct wlr_xwayland_surface_configure_event *ev = data;
|
||||||
|
wlr_xwayland_surface_configure(xsurface, ev->x, ev->y, ev->width,
|
||||||
|
ev->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unmanaged_handle_commit(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
struct xwayland_unmanaged *unmanaged =
|
||||||
|
wl_container_of(listener, unmanaged, commit);
|
||||||
|
struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
|
||||||
|
unmanaged->lx = xsurface->x;
|
||||||
|
unmanaged->ly = xsurface->y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unmanaged_handle_map(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
struct xwayland_unmanaged *unmanaged =
|
||||||
|
wl_container_of(listener, unmanaged, map);
|
||||||
|
struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
|
||||||
|
|
||||||
|
wl_list_insert(server.unmanaged_surfaces.prev, &unmanaged->link);
|
||||||
|
|
||||||
|
wl_signal_add(&xsurface->surface->events.commit, &unmanaged->commit);
|
||||||
|
unmanaged->commit.notify = unmanaged_handle_commit;
|
||||||
|
|
||||||
|
unmanaged->lx = xsurface->x;
|
||||||
|
unmanaged->ly = xsurface->y;
|
||||||
|
|
||||||
|
if (wlr_xwayland_or_surface_wants_focus(xsurface))
|
||||||
|
seat_focus_surface(xsurface->surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unmanaged_handle_unmap(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
struct xwayland_unmanaged *unmanaged =
|
||||||
|
wl_container_of(listener, unmanaged, unmap);
|
||||||
|
struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
|
||||||
|
wl_list_remove(&unmanaged->link);
|
||||||
|
wl_list_remove(&unmanaged->commit.link);
|
||||||
|
|
||||||
|
if (server.seat->keyboard_state.focused_surface == xsurface->surface) {
|
||||||
|
struct xwayland_unmanaged *u;
|
||||||
|
wl_list_for_each (u, &server.unmanaged_surfaces, link) {
|
||||||
|
struct wlr_xwayland_surface *prev = u->xwayland_surface;
|
||||||
|
if (!wlr_xwayland_or_surface_wants_focus(prev))
|
||||||
|
continue;
|
||||||
|
seat_focus_surface(prev->surface);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unmanaged_handle_destroy(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
struct xwayland_unmanaged *unmanaged =
|
||||||
|
wl_container_of(listener, unmanaged, destroy);
|
||||||
|
wl_list_remove(&unmanaged->map.link);
|
||||||
|
wl_list_remove(&unmanaged->unmap.link);
|
||||||
|
wl_list_remove(&unmanaged->destroy.link);
|
||||||
|
free(unmanaged);
|
||||||
|
}
|
||||||
|
|
||||||
|
void xwayland_unmanaged_create(struct wlr_xwayland_surface *xsurface)
|
||||||
|
{
|
||||||
|
struct xwayland_unmanaged *unmanaged;
|
||||||
|
unmanaged = calloc(1, sizeof(struct xwayland_unmanaged));
|
||||||
|
unmanaged->xwayland_surface = xsurface;
|
||||||
|
wl_signal_add(&xsurface->events.request_configure,
|
||||||
|
&unmanaged->request_configure);
|
||||||
|
unmanaged->request_configure.notify =
|
||||||
|
unmanaged_handle_request_configure;
|
||||||
|
wl_signal_add(&xsurface->events.map, &unmanaged->map);
|
||||||
|
unmanaged->map.notify = unmanaged_handle_map;
|
||||||
|
wl_signal_add(&xsurface->events.unmap, &unmanaged->unmap);
|
||||||
|
unmanaged->unmap.notify = unmanaged_handle_unmap;
|
||||||
|
wl_signal_add(&xsurface->events.destroy, &unmanaged->destroy);
|
||||||
|
unmanaged->destroy.notify = unmanaged_handle_destroy;
|
||||||
|
}
|
||||||
28
src/xwl.c
28
src/xwl.c
|
|
@ -79,10 +79,7 @@ static void map(struct view *view)
|
||||||
}
|
}
|
||||||
view->been_mapped = true;
|
view->been_mapped = true;
|
||||||
|
|
||||||
/*
|
/* Add commit here, as xwayland map/unmap can change the wlr_surface */
|
||||||
* Add commit listener here, because xwayland map/unmap can change
|
|
||||||
* the wlr_surface
|
|
||||||
*/
|
|
||||||
wl_signal_add(&view->xwayland_surface->surface->events.commit,
|
wl_signal_add(&view->xwayland_surface->surface->events.commit,
|
||||||
&view->commit);
|
&view->commit);
|
||||||
view->commit.notify = handle_commit;
|
view->commit.notify = handle_commit;
|
||||||
|
|
@ -108,22 +105,31 @@ void xwl_surface_new(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
struct server *server =
|
struct server *server =
|
||||||
wl_container_of(listener, server, new_xwayland_surface);
|
wl_container_of(listener, server, new_xwayland_surface);
|
||||||
struct wlr_xwayland_surface *xwayland_surface = data;
|
struct wlr_xwayland_surface *xsurface = data;
|
||||||
wlr_xwayland_surface_ping(xwayland_surface);
|
wlr_xwayland_surface_ping(xsurface);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We do not create 'views' for xwayland override_redirect surfaces,
|
||||||
|
* but add them to server.unmanaged_surfaces so that we can render them
|
||||||
|
*/
|
||||||
|
if (xsurface->override_redirect) {
|
||||||
|
xwayland_unmanaged_create(xsurface);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
struct view *view = calloc(1, sizeof(struct view));
|
struct view *view = calloc(1, sizeof(struct view));
|
||||||
view->server = server;
|
view->server = server;
|
||||||
view->type = LAB_XWAYLAND_VIEW;
|
view->type = LAB_XWAYLAND_VIEW;
|
||||||
view->impl = &xwl_view_impl;
|
view->impl = &xwl_view_impl;
|
||||||
view->xwayland_surface = xwayland_surface;
|
view->xwayland_surface = xsurface;
|
||||||
|
|
||||||
view->map.notify = handle_map;
|
view->map.notify = handle_map;
|
||||||
wl_signal_add(&xwayland_surface->events.map, &view->map);
|
wl_signal_add(&xsurface->events.map, &view->map);
|
||||||
view->unmap.notify = handle_unmap;
|
view->unmap.notify = handle_unmap;
|
||||||
wl_signal_add(&xwayland_surface->events.unmap, &view->unmap);
|
wl_signal_add(&xsurface->events.unmap, &view->unmap);
|
||||||
view->destroy.notify = handle_destroy;
|
view->destroy.notify = handle_destroy;
|
||||||
wl_signal_add(&xwayland_surface->events.destroy, &view->destroy);
|
wl_signal_add(&xsurface->events.destroy, &view->destroy);
|
||||||
view->request_configure.notify = handle_request_configure;
|
view->request_configure.notify = handle_request_configure;
|
||||||
wl_signal_add(&xwayland_surface->events.request_configure,
|
wl_signal_add(&xsurface->events.request_configure,
|
||||||
&view->request_configure);
|
&view->request_configure);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue