mirror of
https://codeberg.org/dwl/dwl.git
synced 2024-12-27 03:36:31 +00:00
xwayland: add server and basic window functionality (#10)
* xwayland: add server and basic window functionality * xwayland: add server and basic window functionality * xwayland: add server and basic window functionality * xwayland: add server and basic window functionality
This commit is contained in:
parent
91b18d4d4d
commit
57fef50310
1 changed files with 125 additions and 35 deletions
126
dwl.c
126
dwl.c
|
@ -31,6 +31,7 @@
|
||||||
#include <wlr/types/wlr_xdg_output_v1.h>
|
#include <wlr/types/wlr_xdg_output_v1.h>
|
||||||
#include <wlr/types/wlr_xdg_shell.h>
|
#include <wlr/types/wlr_xdg_shell.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
|
#include <wlr/xwayland.h>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
/* macros */
|
/* macros */
|
||||||
|
@ -41,6 +42,7 @@
|
||||||
#define LENGTH(X) (sizeof X / sizeof X[0])
|
#define LENGTH(X) (sizeof X / sizeof X[0])
|
||||||
#define END(A) ((A) + LENGTH(A))
|
#define END(A) ((A) + LENGTH(A))
|
||||||
#define TAGMASK ((1 << LENGTH(tags)) - 1)
|
#define TAGMASK ((1 << LENGTH(tags)) - 1)
|
||||||
|
#define WLR_SURFACE(C) (c->isxdg ? c->xdg_surface->surface : c->xwayland_surface->surface)
|
||||||
|
|
||||||
/* enums */
|
/* enums */
|
||||||
enum { CurNormal, CurMove, CurResize }; /* cursor */
|
enum { CurNormal, CurMove, CurResize }; /* cursor */
|
||||||
|
@ -64,11 +66,15 @@ typedef struct {
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
struct wl_list flink;
|
struct wl_list flink;
|
||||||
struct wl_list slink;
|
struct wl_list slink;
|
||||||
|
union {
|
||||||
struct wlr_xdg_surface *xdg_surface;
|
struct wlr_xdg_surface *xdg_surface;
|
||||||
|
struct wlr_xwayland_surface *xwayland_surface;
|
||||||
|
};
|
||||||
struct wl_listener map;
|
struct wl_listener map;
|
||||||
struct wl_listener unmap;
|
struct wl_listener unmap;
|
||||||
struct wl_listener destroy;
|
struct wl_listener destroy;
|
||||||
struct wlr_box geom; /* layout-relative, includes border */
|
struct wlr_box geom; /* layout-relative, includes border */
|
||||||
|
int isxdg;
|
||||||
Monitor *mon;
|
Monitor *mon;
|
||||||
int bw;
|
int bw;
|
||||||
unsigned int tags;
|
unsigned int tags;
|
||||||
|
@ -148,7 +154,8 @@ static void buttonpress(struct wl_listener *listener, void *data);
|
||||||
static void chvt(const Arg *arg);
|
static void chvt(const Arg *arg);
|
||||||
static void createkeyboard(struct wlr_input_device *device);
|
static void createkeyboard(struct wlr_input_device *device);
|
||||||
static void createmon(struct wl_listener *listener, void *data);
|
static void createmon(struct wl_listener *listener, void *data);
|
||||||
static void createnotify(struct wl_listener *listener, void *data);
|
static void createnotifyxdg(struct wl_listener *listener, void *data);
|
||||||
|
static void createnotifyxwayland(struct wl_listener *listener, void *data);
|
||||||
static void createpointer(struct wlr_input_device *device);
|
static void createpointer(struct wlr_input_device *device);
|
||||||
static void createxdeco(struct wl_listener *listener, void *data);
|
static void createxdeco(struct wl_listener *listener, void *data);
|
||||||
static void cursorframe(struct wl_listener *listener, void *data);
|
static void cursorframe(struct wl_listener *listener, void *data);
|
||||||
|
@ -205,6 +212,8 @@ static const char broken[] = "broken";
|
||||||
static struct wl_display *dpy;
|
static struct wl_display *dpy;
|
||||||
static struct wlr_backend *backend;
|
static struct wlr_backend *backend;
|
||||||
static struct wlr_renderer *drw;
|
static struct wlr_renderer *drw;
|
||||||
|
static struct wlr_compositor *compositor;
|
||||||
|
static struct wlr_xwayland *xwayland;
|
||||||
|
|
||||||
static struct wlr_xdg_shell *xdg_shell;
|
static struct wlr_xdg_shell *xdg_shell;
|
||||||
static struct wl_list clients; /* tiling order */
|
static struct wl_list clients; /* tiling order */
|
||||||
|
@ -235,7 +244,8 @@ static struct wl_listener cursor_motion_absolute = {.notify = motionabsolute};
|
||||||
static struct wl_listener new_input = {.notify = inputdevice};
|
static struct wl_listener new_input = {.notify = inputdevice};
|
||||||
static struct wl_listener new_output = {.notify = createmon};
|
static struct wl_listener new_output = {.notify = createmon};
|
||||||
static struct wl_listener new_xdeco = {.notify = createxdeco};
|
static struct wl_listener new_xdeco = {.notify = createxdeco};
|
||||||
static struct wl_listener new_xdg_surface = {.notify = createnotify};
|
static struct wl_listener new_xdg_surface = {.notify = createnotifyxdg};
|
||||||
|
static struct wl_listener new_xwayland_surface = {.notify = createnotifyxwayland};
|
||||||
static struct wl_listener request_cursor = {.notify = setcursor};
|
static struct wl_listener request_cursor = {.notify = setcursor};
|
||||||
static struct wl_listener request_set_psel = {.notify = setpsel};
|
static struct wl_listener request_set_psel = {.notify = setpsel};
|
||||||
static struct wl_listener request_set_sel = {.notify = setsel};
|
static struct wl_listener request_set_sel = {.notify = setsel};
|
||||||
|
@ -271,10 +281,15 @@ applyrules(Client *c)
|
||||||
|
|
||||||
/* rule matching */
|
/* rule matching */
|
||||||
c->isfloating = 0;
|
c->isfloating = 0;
|
||||||
|
if (c->isxdg) {
|
||||||
if (!(appid = c->xdg_surface->toplevel->app_id))
|
if (!(appid = c->xdg_surface->toplevel->app_id))
|
||||||
appid = broken;
|
appid = broken;
|
||||||
if (!(title = c->xdg_surface->toplevel->title))
|
if (!(title = c->xdg_surface->toplevel->title))
|
||||||
title = broken;
|
title = broken;
|
||||||
|
} else {
|
||||||
|
if (!(title = c->xwayland_surface->title))
|
||||||
|
title = broken;
|
||||||
|
}
|
||||||
|
|
||||||
for (r = rules; r < END(rules); r++) {
|
for (r = rules; r < END(rules); r++) {
|
||||||
if ((!r->title || strstr(title, r->title))
|
if ((!r->title || strstr(title, r->title))
|
||||||
|
@ -328,9 +343,14 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||||
case WLR_BUTTON_PRESSED:;
|
case WLR_BUTTON_PRESSED:;
|
||||||
/* Change focus if the button was _pressed_ over a client */
|
/* Change focus if the button was _pressed_ over a client */
|
||||||
if ((c = xytoclient(cursor->x, cursor->y))) {
|
if ((c = xytoclient(cursor->x, cursor->y))) {
|
||||||
|
if (c->isxdg)
|
||||||
surface = wlr_xdg_surface_surface_at(c->xdg_surface,
|
surface = wlr_xdg_surface_surface_at(c->xdg_surface,
|
||||||
cursor->x - c->geom.x - c->bw,
|
cursor->x - c->geom.x - c->bw,
|
||||||
cursor->y - c->geom.y - c->bw, NULL, NULL);
|
cursor->y - c->geom.y - c->bw, NULL, NULL);
|
||||||
|
else
|
||||||
|
surface = wlr_surface_surface_at(c->xwayland_surface->surface,
|
||||||
|
cursor->x - c->geom.x - c->bw,
|
||||||
|
cursor->y - c->geom.y - c->bw, NULL, NULL);
|
||||||
focusclient(c, surface, 1);
|
focusclient(c, surface, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,7 +478,7 @@ createmon(struct wl_listener *listener, void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
createnotify(struct wl_listener *listener, void *data)
|
createnotifyxdg(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
/* This event is raised when wlr_xdg_shell receives a new xdg surface from a
|
/* This event is raised when wlr_xdg_shell receives a new xdg surface from a
|
||||||
* client, either a toplevel (application window) or popup. */
|
* client, either a toplevel (application window) or popup. */
|
||||||
|
@ -471,6 +491,7 @@ createnotify(struct wl_listener *listener, void *data)
|
||||||
/* Allocate a Client for this surface */
|
/* Allocate a Client for this surface */
|
||||||
c = xdg_surface->data = calloc(1, sizeof(*c));
|
c = xdg_surface->data = calloc(1, sizeof(*c));
|
||||||
c->xdg_surface = xdg_surface;
|
c->xdg_surface = xdg_surface;
|
||||||
|
c->isxdg = 1;
|
||||||
c->bw = borderpx;
|
c->bw = borderpx;
|
||||||
|
|
||||||
/* Tell the client not to try anything fancy */
|
/* Tell the client not to try anything fancy */
|
||||||
|
@ -486,6 +507,27 @@ createnotify(struct wl_listener *listener, void *data)
|
||||||
wl_signal_add(&xdg_surface->events.destroy, &c->destroy);
|
wl_signal_add(&xdg_surface->events.destroy, &c->destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
createnotifyxwayland(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
struct wlr_xwayland_surface *xwayland_surface = data;
|
||||||
|
Client *c;
|
||||||
|
|
||||||
|
/* Allocate a Client for this surface */
|
||||||
|
c = xwayland_surface->data = calloc(1, sizeof(*c));
|
||||||
|
c->xwayland_surface = xwayland_surface;
|
||||||
|
c->isxdg = 0;
|
||||||
|
c->bw = borderpx;
|
||||||
|
|
||||||
|
/* Listen to the various events it can emit */
|
||||||
|
c->map.notify = maprequest;
|
||||||
|
wl_signal_add(&xwayland_surface->events.map, &c->map);
|
||||||
|
c->unmap.notify = unmapnotify;
|
||||||
|
wl_signal_add(&xwayland_surface->events.unmap, &c->unmap);
|
||||||
|
c->destroy.notify = destroynotify;
|
||||||
|
wl_signal_add(&xwayland_surface->events.destroy, &c->destroy);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
createpointer(struct wlr_input_device *device)
|
createpointer(struct wlr_input_device *device)
|
||||||
{
|
{
|
||||||
|
@ -566,8 +608,8 @@ focusclient(Client *c, struct wlr_surface *surface, int lift)
|
||||||
Client *sel = selclient();
|
Client *sel = selclient();
|
||||||
struct wlr_keyboard *kb;
|
struct wlr_keyboard *kb;
|
||||||
/* Previous and new xdg toplevel surfaces */
|
/* Previous and new xdg toplevel surfaces */
|
||||||
struct wlr_xdg_surface *ptl = sel ? sel->xdg_surface : NULL;
|
Client *ptl = sel;
|
||||||
struct wlr_xdg_surface *tl = c ? c->xdg_surface : NULL;
|
Client *tl = c;
|
||||||
/* Previously focused surface */
|
/* Previously focused surface */
|
||||||
struct wlr_surface *psurface = seat->keyboard_state.focused_surface;
|
struct wlr_surface *psurface = seat->keyboard_state.focused_surface;
|
||||||
|
|
||||||
|
@ -575,7 +617,7 @@ focusclient(Client *c, struct wlr_surface *surface, int lift)
|
||||||
/* assert(VISIBLEON(c, c->mon)); ? */
|
/* assert(VISIBLEON(c, c->mon)); ? */
|
||||||
/* Use top-level wlr_surface if nothing more specific given */
|
/* Use top-level wlr_surface if nothing more specific given */
|
||||||
if (!surface)
|
if (!surface)
|
||||||
surface = c->xdg_surface->surface;
|
surface = WLR_SURFACE(c);
|
||||||
|
|
||||||
/* Focus the correct monitor (must come after selclient!) */
|
/* Focus the correct monitor (must come after selclient!) */
|
||||||
selmon = c->mon;
|
selmon = c->mon;
|
||||||
|
@ -610,10 +652,18 @@ focusclient(Client *c, struct wlr_surface *surface, int lift)
|
||||||
* activate the new one. This lets the clients know to repaint
|
* activate the new one. This lets the clients know to repaint
|
||||||
* accordingly, e.g. show/hide a caret.
|
* accordingly, e.g. show/hide a caret.
|
||||||
*/
|
*/
|
||||||
if (tl != ptl && ptl)
|
if (tl != ptl && ptl) {
|
||||||
wlr_xdg_toplevel_set_activated(ptl, 0);
|
if (ptl->isxdg)
|
||||||
if (tl != ptl && tl)
|
wlr_xdg_toplevel_set_activated(ptl->xdg_surface, 0);
|
||||||
wlr_xdg_toplevel_set_activated(tl, 1);
|
else
|
||||||
|
wlr_xwayland_surface_activate(ptl->xwayland_surface, 0);
|
||||||
|
}
|
||||||
|
if (tl != ptl && tl) {
|
||||||
|
if (tl->isxdg)
|
||||||
|
wlr_xdg_toplevel_set_activated(tl->xdg_surface, 1);
|
||||||
|
else
|
||||||
|
wlr_xwayland_surface_activate(tl->xwayland_surface, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -783,9 +833,17 @@ maprequest(struct wl_listener *listener, void *data)
|
||||||
wl_list_insert(&clients, &c->link);
|
wl_list_insert(&clients, &c->link);
|
||||||
wl_list_insert(&fstack, &c->flink);
|
wl_list_insert(&fstack, &c->flink);
|
||||||
wl_list_insert(&stack, &c->slink);
|
wl_list_insert(&stack, &c->slink);
|
||||||
|
|
||||||
|
if (c->isxdg) {
|
||||||
wlr_xdg_surface_get_geometry(c->xdg_surface, &c->geom);
|
wlr_xdg_surface_get_geometry(c->xdg_surface, &c->geom);
|
||||||
c->geom.width += 2 * c->bw;
|
c->geom.width += 2 * c->bw;
|
||||||
c->geom.height += 2 * c->bw;
|
c->geom.height += 2 * c->bw;
|
||||||
|
} else {
|
||||||
|
c->geom.x = c->xwayland_surface->x;
|
||||||
|
c->geom.y = c->xwayland_surface->y;
|
||||||
|
c->geom.width = c->xwayland_surface->width + 2 * c->bw;
|
||||||
|
c->geom.height = c->xwayland_surface->height + 2 * c->bw;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set initial monitor, tags, floating status, and focus */
|
/* Set initial monitor, tags, floating status, and focus */
|
||||||
applyrules(c);
|
applyrules(c);
|
||||||
|
@ -830,10 +888,16 @@ motionnotify(uint32_t time)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise, find the client under the pointer and send the event along. */
|
/* Otherwise, find the client under the pointer and send the event along. */
|
||||||
if ((c = xytoclient(cursor->x, cursor->y)))
|
if ((c = xytoclient(cursor->x, cursor->y))) {
|
||||||
|
if (c->isxdg)
|
||||||
surface = wlr_xdg_surface_surface_at(c->xdg_surface,
|
surface = wlr_xdg_surface_surface_at(c->xdg_surface,
|
||||||
cursor->x - c->geom.x - c->bw,
|
cursor->x - c->geom.x - c->bw,
|
||||||
cursor->y - c->geom.y - c->bw, &sx, &sy);
|
cursor->y - c->geom.y - c->bw, &sx, &sy);
|
||||||
|
else
|
||||||
|
surface = wlr_surface_surface_at(c->xwayland_surface->surface,
|
||||||
|
cursor->x - c->geom.x - c->bw,
|
||||||
|
cursor->y - c->geom.y - c->bw, &sx, &sy);
|
||||||
|
}
|
||||||
/* If there's no client surface under the cursor, set the cursor image to a
|
/* If there's no client surface under the cursor, set the cursor image to a
|
||||||
* default. This is what makes the cursor image appear when you move it
|
* default. This is what makes the cursor image appear when you move it
|
||||||
* off of a client or over its border. */
|
* off of a client or over its border. */
|
||||||
|
@ -893,7 +957,8 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
|
||||||
{
|
{
|
||||||
/* Use top level surface if nothing more specific given */
|
/* Use top level surface if nothing more specific given */
|
||||||
if (c && !surface)
|
if (c && !surface)
|
||||||
surface = c->xdg_surface->surface;
|
surface = WLR_SURFACE(c);
|
||||||
|
|
||||||
/* If surface is already focused, only notify of motion */
|
/* If surface is already focused, only notify of motion */
|
||||||
if (surface && surface == seat->pointer_state.focused_surface) {
|
if (surface && surface == seat->pointer_state.focused_surface) {
|
||||||
wlr_seat_pointer_notify_motion(seat, time, sx, sy);
|
wlr_seat_pointer_notify_motion(seat, time, sx, sy);
|
||||||
|
@ -985,6 +1050,7 @@ renderclients(Monitor *m, struct timespec *now)
|
||||||
int i, w, h;
|
int i, w, h;
|
||||||
struct render_data rdata;
|
struct render_data rdata;
|
||||||
struct wlr_box *borders;
|
struct wlr_box *borders;
|
||||||
|
struct wlr_surface *surface;
|
||||||
/* Each subsequent window we render is rendered on top of the last. Because
|
/* Each subsequent window we render is rendered on top of the last. Because
|
||||||
* our stacking list is ordered front-to-back, we iterate over it backwards. */
|
* our stacking list is ordered front-to-back, we iterate over it backwards. */
|
||||||
wl_list_for_each_reverse(c, &stack, slink) {
|
wl_list_for_each_reverse(c, &stack, slink) {
|
||||||
|
@ -993,11 +1059,12 @@ renderclients(Monitor *m, struct timespec *now)
|
||||||
output_layout, m->wlr_output, &c->geom))
|
output_layout, m->wlr_output, &c->geom))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
surface = WLR_SURFACE(c);
|
||||||
ox = c->geom.x, oy = c->geom.y;
|
ox = c->geom.x, oy = c->geom.y;
|
||||||
wlr_output_layout_output_coords(output_layout, m->wlr_output,
|
wlr_output_layout_output_coords(output_layout, m->wlr_output,
|
||||||
&ox, &oy);
|
&ox, &oy);
|
||||||
w = c->xdg_surface->surface->current.width;
|
w = surface->current.width;
|
||||||
h = c->xdg_surface->surface->current.height;
|
h = surface->current.height;
|
||||||
borders = (struct wlr_box[4]) {
|
borders = (struct wlr_box[4]) {
|
||||||
{ox, oy, w + 2 * c->bw, c->bw}, /* top */
|
{ox, oy, w + 2 * c->bw, c->bw}, /* top */
|
||||||
{ox, oy + c->bw, c->bw, h}, /* left */
|
{ox, oy + c->bw, c->bw, h}, /* left */
|
||||||
|
@ -1015,8 +1082,11 @@ renderclients(Monitor *m, struct timespec *now)
|
||||||
rdata.output = m->wlr_output,
|
rdata.output = m->wlr_output,
|
||||||
rdata.when = now,
|
rdata.when = now,
|
||||||
rdata.x = c->geom.x + c->bw,
|
rdata.x = c->geom.x + c->bw,
|
||||||
rdata.y = c->geom.y + c->bw,
|
rdata.y = c->geom.y + c->bw;
|
||||||
|
if (c->isxdg)
|
||||||
wlr_xdg_surface_for_each_surface(c->xdg_surface, render, &rdata);
|
wlr_xdg_surface_for_each_surface(c->xdg_surface, render, &rdata);
|
||||||
|
else
|
||||||
|
wlr_surface_for_each_surface(c->xwayland_surface->surface, render, &rdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1069,8 +1139,13 @@ resize(Client *c, int x, int y, int w, int h, int interact)
|
||||||
c->geom.height = h;
|
c->geom.height = h;
|
||||||
applybounds(c, bbox);
|
applybounds(c, bbox);
|
||||||
/* wlroots makes this a no-op if size hasn't changed */
|
/* wlroots makes this a no-op if size hasn't changed */
|
||||||
|
if (c->isxdg)
|
||||||
wlr_xdg_toplevel_set_size(c->xdg_surface,
|
wlr_xdg_toplevel_set_size(c->xdg_surface,
|
||||||
c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw);
|
c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw);
|
||||||
|
else
|
||||||
|
wlr_xwayland_surface_configure(c->xwayland_surface,
|
||||||
|
c->geom.x, c->geom.y,
|
||||||
|
c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1214,19 +1289,20 @@ setmon(Client *c, Monitor *m, unsigned int newtags)
|
||||||
{
|
{
|
||||||
int hadfocus;
|
int hadfocus;
|
||||||
Monitor *oldmon = c->mon;
|
Monitor *oldmon = c->mon;
|
||||||
|
struct wlr_surface *surface = WLR_SURFACE(c);
|
||||||
if (oldmon == m)
|
if (oldmon == m)
|
||||||
return;
|
return;
|
||||||
hadfocus = (c == selclient());
|
hadfocus = (c == selclient());
|
||||||
c->mon = m;
|
c->mon = m;
|
||||||
/* XXX leave/enter is not optimal but works */
|
/* XXX leave/enter is not optimal but works */
|
||||||
if (oldmon) {
|
if (oldmon) {
|
||||||
wlr_surface_send_leave(c->xdg_surface->surface, oldmon->wlr_output);
|
wlr_surface_send_leave(surface, oldmon->wlr_output);
|
||||||
arrange(oldmon);
|
arrange(oldmon);
|
||||||
}
|
}
|
||||||
if (m) {
|
if (m) {
|
||||||
/* Make sure window actually overlaps with the monitor */
|
/* Make sure window actually overlaps with the monitor */
|
||||||
applybounds(c, &m->m);
|
applybounds(c, &m->m);
|
||||||
wlr_surface_send_enter(c->xdg_surface->surface, m->wlr_output);
|
wlr_surface_send_enter(surface, m->wlr_output);
|
||||||
c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */
|
c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */
|
||||||
arrange(m);
|
arrange(m);
|
||||||
}
|
}
|
||||||
|
@ -1282,7 +1358,7 @@ setup(void)
|
||||||
* to dig your fingers in and play with their behavior if you want. Note that
|
* to dig your fingers in and play with their behavior if you want. Note that
|
||||||
* the clients cannot set the selection directly without compositor approval,
|
* the clients cannot set the selection directly without compositor approval,
|
||||||
* see the setsel() function. */
|
* see the setsel() function. */
|
||||||
wlr_compositor_create(dpy, drw);
|
compositor = wlr_compositor_create(dpy, drw);
|
||||||
wlr_screencopy_manager_v1_create(dpy);
|
wlr_screencopy_manager_v1_create(dpy);
|
||||||
wlr_data_device_manager_create(dpy);
|
wlr_data_device_manager_create(dpy);
|
||||||
wlr_primary_selection_v1_device_manager_create(dpy);
|
wlr_primary_selection_v1_device_manager_create(dpy);
|
||||||
|
@ -1360,6 +1436,19 @@ setup(void)
|
||||||
&request_set_sel);
|
&request_set_sel);
|
||||||
wl_signal_add(&seat->events.request_set_primary_selection,
|
wl_signal_add(&seat->events.request_set_primary_selection,
|
||||||
&request_set_psel);
|
&request_set_psel);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialise the XWayland X server.
|
||||||
|
* It will be started when the first X client is started.
|
||||||
|
*/
|
||||||
|
xwayland = wlr_xwayland_create(dpy, compositor, true);
|
||||||
|
if (xwayland) {
|
||||||
|
wl_signal_add(&xwayland->events.new_surface, &new_xwayland_surface);
|
||||||
|
|
||||||
|
setenv("DISPLAY", xwayland->display_name, true);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "failed to setup XWayland X server, continuing without it\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1550,6 +1639,7 @@ main(int argc, char *argv[])
|
||||||
run(startup_cmd);
|
run(startup_cmd);
|
||||||
|
|
||||||
/* Once wl_display_run returns, we shut down the server. */
|
/* Once wl_display_run returns, we shut down the server. */
|
||||||
|
wlr_xwayland_destroy(xwayland);
|
||||||
wl_display_destroy_clients(dpy);
|
wl_display_destroy_clients(dpy);
|
||||||
wl_display_destroy(dpy);
|
wl_display_destroy(dpy);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|
Loading…
Reference in a new issue