struct wlr_xwayland *xwayland;
struct wl_listener new_xwayland_surface;
struct wl_list views;
+ struct wl_list unmanaged_surfaces;
struct wlr_cursor *cursor;
struct wlr_xcursor_manager *cursor_mgr;
struct wl_list outputs;
struct wl_listener new_output;
- /* For use in cycle (alt-tab) mode */
+ /* Set when in cycle (alt-tab) mode */
struct view *cycle_view;
};
+extern struct server server;
+
struct output {
struct wl_list link;
struct server *server;
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 wl_list link;
struct server *server;
void xdg_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);
/**
struct wlr_surface **surface, double *sx, double *sy,
int *view_area);
+void seat_focus_surface(struct wlr_surface *surface);
+
void interactive_begin(struct view *view, enum cursor_mode mode,
uint32_t edges);
'keyboard.c',
'main.c',
'output.c',
+ 'seat.c',
'server.c',
'view.c',
'xdg.c',
+ 'xwayland-unmanaged.c',
'xwl.c',
)
struct render_data {
struct wlr_output *output;
struct wlr_renderer *renderer;
- struct view *view;
+ int lx, ly;
struct timespec *when;
};
/* This function is called for every surface that needs to be rendered.
*/
struct render_data *rdata = data;
- struct view *view = rdata->view;
struct wlr_output *output = rdata->output;
/* We first obtain a wlr_texture, which is a GPU resource. wlroots
* display might have layout coordinates of 2000,100. We need to
* translate that to output-local coordinates, or (2000 - 1920). */
double ox = 0, oy = 0;
- wlr_output_layout_output_coords(view->server->output_layout, output,
- &ox, &oy);
- ox += view->x + sx;
- oy += view->y + sy;
+ wlr_output_layout_output_coords(server.output_layout, output, &ox, &oy);
+ ox += rdata->lx + sx;
+ oy += rdata->ly + sy;
/* TODO: Support HiDPI */
struct wlr_box box = {
* backwards. */
struct view *view;
wl_list_for_each_reverse (view, &output->server->views, link) {
- if (!view->mapped) {
- /* An unmapped view should not be rendered. */
+ if (!view->mapped)
continue;
- }
+
struct render_data rdata = {
.output = output->wlr_output,
- .view = view,
+ .lx = view->x,
+ .ly = view->y,
.renderer = renderer,
.when = &now,
};
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) {
+ /* render each xdg toplevel and popup surface */
wlr_xdg_surface_for_each_surface(
view->xdg_surface, render_surface, &rdata);
} else if (view->type == LAB_XWAYLAND_VIEW) {
/* If in cycle (alt-tab) mode, highlight selected view */
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
* be moved around without re-rendering what's beneath them - which is
* more efficient. However, not all hardware supports hardware cursors.
--- /dev/null
+#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);
+}
wlr_renderer_init_wl_display(server->renderer, server->wl_display);
wl_list_init(&server->views);
+ wl_list_init(&server->unmanaged_surfaces);
wl_list_init(&server->outputs);
/*
/* Note: this function only deals with keyboard focus. */
if (!view)
return;
+
+ /* TODO: messy - sort out */
if (!view->mapped) {
view->impl->map(view);
return;
--- /dev/null
+#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;
+}
}
view->been_mapped = true;
- /*
- * Add commit listener here, because xwayland map/unmap can change
- * the wlr_surface
- */
+ /* Add commit here, as xwayland map/unmap can change the wlr_surface */
wl_signal_add(&view->xwayland_surface->surface->events.commit,
&view->commit);
view->commit.notify = handle_commit;
{
struct server *server =
wl_container_of(listener, server, new_xwayland_surface);
- struct wlr_xwayland_surface *xwayland_surface = data;
- wlr_xwayland_surface_ping(xwayland_surface);
+ struct wlr_xwayland_surface *xsurface = data;
+ 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));
view->server = server;
view->type = LAB_XWAYLAND_VIEW;
view->impl = &xwl_view_impl;
- view->xwayland_surface = xwayland_surface;
+ view->xwayland_surface = xsurface;
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;
- wl_signal_add(&xwayland_surface->events.unmap, &view->unmap);
+ wl_signal_add(&xsurface->events.unmap, &view->unmap);
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;
- wl_signal_add(&xwayland_surface->events.request_configure,
+ wl_signal_add(&xsurface->events.request_configure,
&view->request_configure);
}