Merge branch 'master' into 31-independents-mouse-focus
commit
4788baee8d
7
Makefile
7
Makefile
|
@ -1,9 +1,10 @@
|
||||||
|
include config.mk
|
||||||
|
|
||||||
|
CFLAGS += -I. -DWLR_USE_UNSTABLE -std=c99 -Werror=declaration-after-statement
|
||||||
|
|
||||||
WAYLAND_PROTOCOLS=$(shell pkg-config --variable=pkgdatadir wayland-protocols)
|
WAYLAND_PROTOCOLS=$(shell pkg-config --variable=pkgdatadir wayland-protocols)
|
||||||
WAYLAND_SCANNER=$(shell pkg-config --variable=wayland_scanner wayland-scanner)
|
WAYLAND_SCANNER=$(shell pkg-config --variable=wayland_scanner wayland-scanner)
|
||||||
|
|
||||||
CFLAGS ?= -g -Wall -Wextra -Werror -Wno-unused-parameter -Wno-sign-compare -Wno-error=unused-function
|
|
||||||
CFLAGS += -I. -DWLR_USE_UNSTABLE -std=c99 -Werror=declaration-after-statement
|
|
||||||
|
|
||||||
PKGS = wlroots wayland-server xcb xkbcommon
|
PKGS = wlroots wayland-server xcb xkbcommon
|
||||||
CFLAGS += $(foreach p,$(PKGS),$(shell pkg-config --cflags $(p)))
|
CFLAGS += $(foreach p,$(PKGS),$(shell pkg-config --cflags $(p)))
|
||||||
LDLIBS += $(foreach p,$(PKGS),$(shell pkg-config --libs $(p)))
|
LDLIBS += $(foreach p,$(PKGS),$(shell pkg-config --libs $(p)))
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
# Default compile flags (overridable by environment)
|
||||||
|
CFLAGS ?= -g -Wall -Wextra -Werror -Wno-unused-parameter -Wno-sign-compare -Wno-error=unused-function
|
||||||
|
|
||||||
|
# Uncomment to build XWayland support
|
||||||
|
#CFLAGS += -DXWAYLAND
|
368
dwl.c
368
dwl.c
|
@ -33,9 +33,11 @@
|
||||||
#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 <X11/Xlib.h>
|
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <wlr/xwayland.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* macros */
|
/* macros */
|
||||||
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||||
|
@ -45,13 +47,19 @@
|
||||||
#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)
|
||||||
|
#ifdef XWAYLAND
|
||||||
#define WLR_SURFACE(C) ((C)->type != XDGShell ? (C)->surface.xwayland->surface : (C)->surface.xdg->surface)
|
#define WLR_SURFACE(C) ((C)->type != XDGShell ? (C)->surface.xwayland->surface : (C)->surface.xdg->surface)
|
||||||
|
#else
|
||||||
|
#define WLR_SURFACE(C) ((C)->surface.xdg->surface)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* enums */
|
/* enums */
|
||||||
enum { CurNormal, CurMove, CurResize }; /* cursor */
|
enum { CurNormal, CurMove, CurResize }; /* cursor */
|
||||||
enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar,
|
enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar,
|
||||||
NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */
|
NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */
|
||||||
|
#ifdef XWAYLAND
|
||||||
enum { XDGShell, X11Managed, X11Unmanaged }; /* client types */
|
enum { XDGShell, X11Managed, X11Unmanaged }; /* client types */
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
int i;
|
int i;
|
||||||
|
@ -74,16 +82,22 @@ typedef struct {
|
||||||
struct wl_list slink;
|
struct wl_list slink;
|
||||||
union {
|
union {
|
||||||
struct wlr_xdg_surface *xdg;
|
struct wlr_xdg_surface *xdg;
|
||||||
|
#ifdef XWAYLAND
|
||||||
struct wlr_xwayland_surface *xwayland;
|
struct wlr_xwayland_surface *xwayland;
|
||||||
|
#endif
|
||||||
} surface;
|
} surface;
|
||||||
|
#ifdef XWAYLAND
|
||||||
struct wl_listener activate;
|
struct wl_listener activate;
|
||||||
|
#endif
|
||||||
struct wl_listener commit;
|
struct wl_listener commit;
|
||||||
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 */
|
||||||
Monitor *mon;
|
Monitor *mon;
|
||||||
|
#ifdef XWAYLAND
|
||||||
unsigned int type;
|
unsigned int type;
|
||||||
|
#endif
|
||||||
int bw;
|
int bw;
|
||||||
unsigned int tags;
|
unsigned int tags;
|
||||||
int isfloating;
|
int isfloating;
|
||||||
|
@ -157,7 +171,6 @@ struct render_data {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* function declarations */
|
/* function declarations */
|
||||||
static void activatex11(struct wl_listener *listener, void *data);
|
|
||||||
static void applybounds(Client *c, struct wlr_box *bbox);
|
static void applybounds(Client *c, struct wlr_box *bbox);
|
||||||
static void applyrules(Client *c);
|
static void applyrules(Client *c);
|
||||||
static void arrange(Monitor *m);
|
static void arrange(Monitor *m);
|
||||||
|
@ -169,7 +182,6 @@ static void cleanupmon(struct wl_listener *listener, void *data);
|
||||||
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 createnotify(struct wl_listener *listener, void *data);
|
||||||
static void createnotifyx11(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);
|
||||||
|
@ -180,7 +192,6 @@ static void focusclient(Client *old, Client *c, int lift);
|
||||||
static void focusmon(const Arg *arg);
|
static void focusmon(const Arg *arg);
|
||||||
static void focusstack(const Arg *arg);
|
static void focusstack(const Arg *arg);
|
||||||
static Client *focustop(Monitor *m);
|
static Client *focustop(Monitor *m);
|
||||||
static Atom getatom(xcb_connection_t *xc, const char *name);
|
|
||||||
static void getxdecomode(struct wl_listener *listener, void *data);
|
static void getxdecomode(struct wl_listener *listener, void *data);
|
||||||
static void incnmaster(const Arg *arg);
|
static void incnmaster(const Arg *arg);
|
||||||
static void inputdevice(struct wl_listener *listener, void *data);
|
static void inputdevice(struct wl_listener *listener, void *data);
|
||||||
|
@ -219,12 +230,9 @@ static void tile(Monitor *m);
|
||||||
static void togglefloating(const Arg *arg);
|
static void togglefloating(const Arg *arg);
|
||||||
static void toggletag(const Arg *arg);
|
static void toggletag(const Arg *arg);
|
||||||
static void toggleview(const Arg *arg);
|
static void toggleview(const Arg *arg);
|
||||||
static void updatewindowtype(Client *c);
|
|
||||||
static void unmapnotify(struct wl_listener *listener, void *data);
|
static void unmapnotify(struct wl_listener *listener, void *data);
|
||||||
static void xwaylandready(struct wl_listener *listener, void *data);
|
|
||||||
static void view(const Arg *arg);
|
static void view(const Arg *arg);
|
||||||
static Client *xytoclient(double x, double y);
|
static Client *xytoclient(double x, double y);
|
||||||
static Client *xytoindependent(double x, double y);
|
|
||||||
static Monitor *xytomon(double x, double y);
|
static Monitor *xytomon(double x, double y);
|
||||||
static void zoom(const Arg *arg);
|
static void zoom(const Arg *arg);
|
||||||
|
|
||||||
|
@ -234,7 +242,6 @@ 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_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 */
|
||||||
|
@ -257,8 +264,6 @@ static struct wlr_box sgeom;
|
||||||
static struct wl_list mons;
|
static struct wl_list mons;
|
||||||
static Monitor *selmon;
|
static Monitor *selmon;
|
||||||
|
|
||||||
static Atom netatom[NetLast];
|
|
||||||
|
|
||||||
/* global event handlers */
|
/* global event handlers */
|
||||||
static struct wl_listener cursor_axis = {.notify = axisnotify};
|
static struct wl_listener cursor_axis = {.notify = axisnotify};
|
||||||
static struct wl_listener cursor_button = {.notify = buttonpress};
|
static struct wl_listener cursor_button = {.notify = buttonpress};
|
||||||
|
@ -269,11 +274,23 @@ 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 = createnotify};
|
||||||
static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11};
|
|
||||||
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};
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
static void activatex11(struct wl_listener *listener, void *data);
|
||||||
|
static void createnotifyx11(struct wl_listener *listener, void *data);
|
||||||
|
static Atom getatom(xcb_connection_t *xc, const char *name);
|
||||||
|
static void renderindependents(struct wlr_output *output, struct timespec *now);
|
||||||
|
static void updatewindowtype(Client *c);
|
||||||
|
static void xwaylandready(struct wl_listener *listener, void *data);
|
||||||
|
static Client *xytoindependent(double x, double y);
|
||||||
|
static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11};
|
||||||
static struct wl_listener xwayland_ready = {.notify = xwaylandready};
|
static struct wl_listener xwayland_ready = {.notify = xwaylandready};
|
||||||
|
static struct wlr_xwayland *xwayland;
|
||||||
|
static Atom netatom[NetLast];
|
||||||
|
#endif
|
||||||
|
|
||||||
/* configuration, allows nested code to access above variables */
|
/* configuration, allows nested code to access above variables */
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -282,16 +299,6 @@ static struct wl_listener xwayland_ready = {.notify = xwaylandready};
|
||||||
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
|
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
|
||||||
|
|
||||||
/* function implementations */
|
/* function implementations */
|
||||||
void
|
|
||||||
activatex11(struct wl_listener *listener, void *data)
|
|
||||||
{
|
|
||||||
Client *c = wl_container_of(listener, c, activate);
|
|
||||||
|
|
||||||
/* Only "managed" windows can be activated */
|
|
||||||
if (c->type == X11Managed)
|
|
||||||
wlr_xwayland_surface_activate(c->surface.xwayland, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
applybounds(Client *c, struct wlr_box *bbox)
|
applybounds(Client *c, struct wlr_box *bbox)
|
||||||
{
|
{
|
||||||
|
@ -319,10 +326,17 @@ applyrules(Client *c)
|
||||||
|
|
||||||
/* rule matching */
|
/* rule matching */
|
||||||
c->isfloating = 0;
|
c->isfloating = 0;
|
||||||
appid = c->type != XDGShell ? c->surface.xwayland->class :
|
#ifdef XWAYLAND
|
||||||
c->surface.xdg->toplevel->app_id;
|
updatewindowtype(c);
|
||||||
title = c->type != XDGShell ? c->surface.xwayland->title :
|
if (c->type != XDGShell) {
|
||||||
c->surface.xdg->toplevel->title;
|
appid = c->surface.xwayland->class;
|
||||||
|
title = c->surface.xwayland->title;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
appid = c->surface.xdg->toplevel->app_id;
|
||||||
|
title = c->surface.xdg->toplevel->title;
|
||||||
|
}
|
||||||
if (!appid)
|
if (!appid)
|
||||||
appid = broken;
|
appid = broken;
|
||||||
if (!title)
|
if (!title)
|
||||||
|
@ -339,7 +353,6 @@ applyrules(Client *c)
|
||||||
mon = m;
|
mon = m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updatewindowtype(c);
|
|
||||||
setmon(c, mon, newtags);
|
setmon(c, mon, newtags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -553,7 +566,6 @@ 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->surface.xdg = xdg_surface;
|
c->surface.xdg = xdg_surface;
|
||||||
c->type = XDGShell;
|
|
||||||
c->bw = borderpx;
|
c->bw = borderpx;
|
||||||
|
|
||||||
/* Tell the client not to try anything fancy */
|
/* Tell the client not to try anything fancy */
|
||||||
|
@ -571,29 +583,6 @@ 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
|
|
||||||
createnotifyx11(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->surface.xwayland = xwayland_surface;
|
|
||||||
c->type = xwayland_surface->override_redirect ? X11Unmanaged : X11Managed;
|
|
||||||
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->activate.notify = activatex11;
|
|
||||||
wl_signal_add(&xwayland_surface->events.request_activate, &c->activate);
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
@ -638,10 +627,12 @@ destroynotify(struct wl_listener *listener, void *data)
|
||||||
wl_list_remove(&c->map.link);
|
wl_list_remove(&c->map.link);
|
||||||
wl_list_remove(&c->unmap.link);
|
wl_list_remove(&c->unmap.link);
|
||||||
wl_list_remove(&c->destroy.link);
|
wl_list_remove(&c->destroy.link);
|
||||||
if (c->type == XDGShell)
|
#ifdef XWAYLAND
|
||||||
wl_list_remove(&c->commit.link);
|
|
||||||
if (c->type == X11Managed)
|
if (c->type == X11Managed)
|
||||||
wl_list_remove(&c->activate.link);
|
wl_list_remove(&c->activate.link);
|
||||||
|
else if (c->type == XDGShell)
|
||||||
|
#endif
|
||||||
|
wl_list_remove(&c->commit.link);
|
||||||
free(c);
|
free(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -689,9 +680,11 @@ focusclient(Client *old, Client *c, int lift)
|
||||||
|
|
||||||
/* Deactivate old client if focus is changing */
|
/* Deactivate old client if focus is changing */
|
||||||
if (c != old && old) {
|
if (c != old && old) {
|
||||||
|
#ifdef XWAYLAND
|
||||||
if (old->type != XDGShell)
|
if (old->type != XDGShell)
|
||||||
wlr_xwayland_surface_activate(old->surface.xwayland, 0);
|
wlr_xwayland_surface_activate(old->surface.xwayland, 0);
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
wlr_xdg_toplevel_set_activated(old->surface.xdg, 0);
|
wlr_xdg_toplevel_set_activated(old->surface.xdg, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -712,9 +705,11 @@ focusclient(Client *old, Client *c, int lift)
|
||||||
selmon = c->mon;
|
selmon = c->mon;
|
||||||
|
|
||||||
/* Activate the new client */
|
/* Activate the new client */
|
||||||
|
#ifdef XWAYLAND
|
||||||
if (c->type != XDGShell)
|
if (c->type != XDGShell)
|
||||||
wlr_xwayland_surface_activate(c->surface.xwayland, 1);
|
wlr_xwayland_surface_activate(c->surface.xwayland, 1);
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
wlr_xdg_toplevel_set_activated(c->surface.xdg, 1);
|
wlr_xdg_toplevel_set_activated(c->surface.xdg, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -763,21 +758,6 @@ focustop(Monitor *m)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Atom
|
|
||||||
getatom(xcb_connection_t *xc, const char *name)
|
|
||||||
{
|
|
||||||
Atom atom = 0;
|
|
||||||
xcb_intern_atom_cookie_t cookie;
|
|
||||||
xcb_intern_atom_reply_t *reply;
|
|
||||||
|
|
||||||
cookie = xcb_intern_atom(xc, 0, strlen(name), name);
|
|
||||||
if ((reply = xcb_intern_atom_reply(xc, cookie, NULL)))
|
|
||||||
atom = reply->atom;
|
|
||||||
free(reply);
|
|
||||||
|
|
||||||
return atom;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
getxdecomode(struct wl_listener *listener, void *data)
|
getxdecomode(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
|
@ -896,9 +876,11 @@ killclient(const Arg *arg)
|
||||||
if (!sel)
|
if (!sel)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
if (sel->type != XDGShell)
|
if (sel->type != XDGShell)
|
||||||
wlr_xwayland_surface_close(sel->surface.xwayland);
|
wlr_xwayland_surface_close(sel->surface.xwayland);
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
wlr_xdg_toplevel_send_close(sel->surface.xdg);
|
wlr_xdg_toplevel_send_close(sel->surface.xdg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -908,23 +890,28 @@ maprequest(struct wl_listener *listener, void *data)
|
||||||
/* Called when the surface is mapped, or ready to display on-screen. */
|
/* Called when the surface is mapped, or ready to display on-screen. */
|
||||||
Client *c = wl_container_of(listener, c, map);
|
Client *c = wl_container_of(listener, c, map);
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
if (c->type == X11Unmanaged) {
|
if (c->type == X11Unmanaged) {
|
||||||
/* Insert this independent into independents lists. */
|
/* Insert this independent into independents lists. */
|
||||||
wl_list_insert(&independents, &c->link);
|
wl_list_insert(&independents, &c->link);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Insert this client into client lists. */
|
/* Insert this client into client lists. */
|
||||||
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);
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
if (c->type != XDGShell) {
|
if (c->type != XDGShell) {
|
||||||
c->geom.x = c->surface.xwayland->x;
|
c->geom.x = c->surface.xwayland->x;
|
||||||
c->geom.y = c->surface.xwayland->y;
|
c->geom.y = c->surface.xwayland->y;
|
||||||
c->geom.width = c->surface.xwayland->width + 2 * c->bw;
|
c->geom.width = c->surface.xwayland->width + 2 * c->bw;
|
||||||
c->geom.height = c->surface.xwayland->height + 2 * c->bw;
|
c->geom.height = c->surface.xwayland->height + 2 * c->bw;
|
||||||
} else {
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
wlr_xdg_surface_get_geometry(c->surface.xdg, &c->geom);
|
wlr_xdg_surface_get_geometry(c->surface.xdg, &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;
|
||||||
|
@ -984,6 +971,7 @@ motionnotify(uint32_t time)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
/* Find an independent under the pointer and send the event along. */
|
/* Find an independent under the pointer and send the event along. */
|
||||||
if ((c = xytoindependent(cursor->x, cursor->y))) {
|
if ((c = xytoindependent(cursor->x, cursor->y))) {
|
||||||
surface = wlr_surface_surface_at(c->surface.xwayland->surface,
|
surface = wlr_surface_surface_at(c->surface.xwayland->surface,
|
||||||
|
@ -992,11 +980,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. */
|
||||||
} else if ((c = xytoclient(cursor->x, cursor->y))) {
|
} else if ((c = xytoclient(cursor->x, cursor->y))) {
|
||||||
|
#else
|
||||||
|
if ((c = xytoclient(cursor->x, cursor->y))) {
|
||||||
|
#endif
|
||||||
|
#ifdef XWAYLAND
|
||||||
if (c->type != XDGShell)
|
if (c->type != XDGShell)
|
||||||
surface = wlr_surface_surface_at(c->surface.xwayland->surface,
|
surface = wlr_surface_surface_at(c->surface.xwayland->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
|
else
|
||||||
|
#endif
|
||||||
surface = wlr_xdg_surface_surface_at(c->surface.xdg,
|
surface = wlr_xdg_surface_surface_at(c->surface.xdg,
|
||||||
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);
|
||||||
|
@ -1077,7 +1070,13 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
|
||||||
/* Otherwise, let the client know that the mouse cursor has entered one
|
/* Otherwise, let the client know that the mouse cursor has entered one
|
||||||
* of its surfaces, and make keyboard focus follow if desired. */
|
* of its surfaces, and make keyboard focus follow if desired. */
|
||||||
wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
|
wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
|
||||||
if (sloppyfocus && c->type != X11Unmanaged)
|
|
||||||
|
#if XWAYLAND
|
||||||
|
if (c->type == X11Unmanaged)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (sloppyfocus)
|
||||||
focusclient(selclient(), c, 0);
|
focusclient(selclient(), c, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1190,39 +1189,15 @@ renderclients(Monitor *m, struct timespec *now)
|
||||||
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;
|
||||||
|
#ifdef XWAYLAND
|
||||||
if (c->type != XDGShell)
|
if (c->type != XDGShell)
|
||||||
wlr_surface_for_each_surface(c->surface.xwayland->surface, render, &rdata);
|
wlr_surface_for_each_surface(c->surface.xwayland->surface, render, &rdata);
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
wlr_xdg_surface_for_each_surface(c->surface.xdg, render, &rdata);
|
wlr_xdg_surface_for_each_surface(c->surface.xdg, render, &rdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
renderindependents(struct wlr_output *output, struct timespec *now)
|
|
||||||
{
|
|
||||||
Client *c;
|
|
||||||
struct render_data rdata;
|
|
||||||
struct wlr_box geom;
|
|
||||||
|
|
||||||
wl_list_for_each_reverse(c, &independents, link) {
|
|
||||||
geom.x = c->surface.xwayland->x;
|
|
||||||
geom.y = c->surface.xwayland->y;
|
|
||||||
geom.width = c->surface.xwayland->width;
|
|
||||||
geom.height = c->surface.xwayland->height;
|
|
||||||
|
|
||||||
/* Only render visible clients which show on this output */
|
|
||||||
if (!wlr_output_layout_intersects(output_layout, output, &geom))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
rdata.output = output;
|
|
||||||
rdata.when = now;
|
|
||||||
rdata.x = c->surface.xwayland->x;
|
|
||||||
rdata.y = c->surface.xwayland->y;
|
|
||||||
|
|
||||||
wlr_surface_for_each_surface(c->surface.xwayland->surface, render, &rdata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
rendermon(struct wl_listener *listener, void *data)
|
rendermon(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
|
@ -1254,7 +1229,9 @@ rendermon(struct wl_listener *listener, void *data)
|
||||||
wlr_renderer_clear(drw, rootcolor);
|
wlr_renderer_clear(drw, rootcolor);
|
||||||
|
|
||||||
renderclients(m, &now);
|
renderclients(m, &now);
|
||||||
|
#ifdef XWAYLAND
|
||||||
renderindependents(m->wlr_output, &now);
|
renderindependents(m->wlr_output, &now);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Hardware cursors are rendered by the GPU on a separate plane, and can be
|
/* 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
|
* moved around without re-rendering what's beneath them - which is more
|
||||||
|
@ -1287,11 +1264,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 */
|
||||||
|
#ifdef XWAYLAND
|
||||||
if (c->type != XDGShell)
|
if (c->type != XDGShell)
|
||||||
wlr_xwayland_surface_configure(c->surface.xwayland,
|
wlr_xwayland_surface_configure(c->surface.xwayland,
|
||||||
c->geom.x, c->geom.y,
|
c->geom.x, c->geom.y,
|
||||||
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
|
else
|
||||||
|
#endif
|
||||||
c->resize = wlr_xdg_toplevel_set_size(c->surface.xdg,
|
c->resize = wlr_xdg_toplevel_set_size(c->surface.xdg,
|
||||||
c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw);
|
c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw);
|
||||||
}
|
}
|
||||||
|
@ -1586,6 +1565,7 @@ setup(void)
|
||||||
wl_signal_add(&seat->events.request_set_primary_selection,
|
wl_signal_add(&seat->events.request_set_primary_selection,
|
||||||
&request_set_psel);
|
&request_set_psel);
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
/*
|
/*
|
||||||
* Initialise the XWayland X server.
|
* Initialise the XWayland X server.
|
||||||
* It will be started when the first X client is started.
|
* It will be started when the first X client is started.
|
||||||
|
@ -1599,6 +1579,7 @@ setup(void)
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "failed to setup XWayland X server, continuing without it\n");
|
fprintf(stderr, "failed to setup XWayland X server, continuing without it\n");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1710,49 +1691,15 @@ unmapnotify(struct wl_listener *listener, void *data)
|
||||||
/* Called when the surface is unmapped, and should no longer be shown. */
|
/* Called when the surface is unmapped, and should no longer be shown. */
|
||||||
Client *c = wl_container_of(listener, c, unmap);
|
Client *c = wl_container_of(listener, c, unmap);
|
||||||
wl_list_remove(&c->link);
|
wl_list_remove(&c->link);
|
||||||
|
#ifdef XWAYLAND
|
||||||
if (c->type == X11Unmanaged)
|
if (c->type == X11Unmanaged)
|
||||||
return;
|
return;
|
||||||
|
#endif
|
||||||
setmon(c, NULL, 0);
|
setmon(c, NULL, 0);
|
||||||
wl_list_remove(&c->flink);
|
wl_list_remove(&c->flink);
|
||||||
wl_list_remove(&c->slink);
|
wl_list_remove(&c->slink);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
updatewindowtype(Client *c)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (c->type != XDGShell)
|
|
||||||
for (i = 0; i < c->surface.xwayland->window_type_len; i++)
|
|
||||||
if (c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeDialog] ||
|
|
||||||
c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeSplash] ||
|
|
||||||
c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeToolbar] ||
|
|
||||||
c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeUtility])
|
|
||||||
c->isfloating = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
xwaylandready(struct wl_listener *listener, void *data) {
|
|
||||||
xcb_connection_t *xc = xcb_connect(xwayland->display_name, NULL);
|
|
||||||
int err = xcb_connection_has_error(xc);
|
|
||||||
if (err) {
|
|
||||||
fprintf(stderr, "xcb_connect to X server failed with code %d\n. Continuing with degraded functionality.\n", err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Collect atoms we are interested in. If getatom returns 0, we will
|
|
||||||
* not detect that window type. */
|
|
||||||
netatom[NetWMWindowTypeDialog] = getatom(xc, "_NET_WM_WINDOW_TYPE_DIALOG");
|
|
||||||
netatom[NetWMWindowTypeSplash] = getatom(xc, "_NET_WM_WINDOW_TYPE_SPLASH");
|
|
||||||
netatom[NetWMWindowTypeUtility] = getatom(xc, "_NET_WM_WINDOW_TYPE_TOOLBAR");
|
|
||||||
netatom[NetWMWindowTypeToolbar] = getatom(xc, "_NET_WM_WINDOW_TYPE_UTILITY");
|
|
||||||
|
|
||||||
/* assign the one and only seat */
|
|
||||||
wlr_xwayland_set_seat(xwayland, seat);
|
|
||||||
|
|
||||||
xcb_disconnect(xc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
view(const Arg *arg)
|
view(const Arg *arg)
|
||||||
{
|
{
|
||||||
|
@ -1778,27 +1725,6 @@ xytoclient(double x, double y)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Client *
|
|
||||||
xytoindependent(double x, double y)
|
|
||||||
{
|
|
||||||
/* Find the topmost visible independent at point (x, y).
|
|
||||||
* For independents, the most recently created can be used as the "top".
|
|
||||||
* We rely on the X11 convention of unmapping unmanaged when the "owning"
|
|
||||||
* client loses focus, which ensures that unmanaged are only visible on
|
|
||||||
* the current tag. */
|
|
||||||
Client *c;
|
|
||||||
struct wlr_box geom;
|
|
||||||
wl_list_for_each_reverse(c, &independents, link) {
|
|
||||||
geom.x = c->surface.xwayland->x;
|
|
||||||
geom.y = c->surface.xwayland->y;
|
|
||||||
geom.width = c->surface.xwayland->width;
|
|
||||||
geom.height = c->surface.xwayland->height;
|
|
||||||
if (wlr_box_contains_point(&geom, x, y))
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Monitor *
|
Monitor *
|
||||||
xytomon(double x, double y)
|
xytomon(double x, double y)
|
||||||
{
|
{
|
||||||
|
@ -1838,6 +1764,140 @@ zoom(const Arg *arg)
|
||||||
arrange(selmon);
|
arrange(selmon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
void
|
||||||
|
activatex11(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
Client *c = wl_container_of(listener, c, activate);
|
||||||
|
|
||||||
|
/* Only "managed" windows can be activated */
|
||||||
|
if (c->type == X11Managed)
|
||||||
|
wlr_xwayland_surface_activate(c->surface.xwayland, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
createnotifyx11(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->surface.xwayland = xwayland_surface;
|
||||||
|
c->type = xwayland_surface->override_redirect ? X11Unmanaged : X11Managed;
|
||||||
|
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->activate.notify = activatex11;
|
||||||
|
wl_signal_add(&xwayland_surface->events.request_activate, &c->activate);
|
||||||
|
c->destroy.notify = destroynotify;
|
||||||
|
wl_signal_add(&xwayland_surface->events.destroy, &c->destroy);
|
||||||
|
}
|
||||||
|
|
||||||
|
Atom
|
||||||
|
getatom(xcb_connection_t *xc, const char *name)
|
||||||
|
{
|
||||||
|
Atom atom = 0;
|
||||||
|
xcb_intern_atom_cookie_t cookie;
|
||||||
|
xcb_intern_atom_reply_t *reply;
|
||||||
|
|
||||||
|
cookie = xcb_intern_atom(xc, 0, strlen(name), name);
|
||||||
|
if ((reply = xcb_intern_atom_reply(xc, cookie, NULL)))
|
||||||
|
atom = reply->atom;
|
||||||
|
free(reply);
|
||||||
|
|
||||||
|
return atom;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
renderindependents(struct wlr_output *output, struct timespec *now)
|
||||||
|
{
|
||||||
|
Client *c;
|
||||||
|
struct render_data rdata;
|
||||||
|
struct wlr_box geom;
|
||||||
|
|
||||||
|
wl_list_for_each_reverse(c, &independents, link) {
|
||||||
|
geom.x = c->surface.xwayland->x;
|
||||||
|
geom.y = c->surface.xwayland->y;
|
||||||
|
geom.width = c->surface.xwayland->width;
|
||||||
|
geom.height = c->surface.xwayland->height;
|
||||||
|
|
||||||
|
/* Only render visible clients which show on this output */
|
||||||
|
if (!wlr_output_layout_intersects(output_layout, output, &geom))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rdata.output = output;
|
||||||
|
rdata.when = now;
|
||||||
|
rdata.x = c->surface.xwayland->x;
|
||||||
|
rdata.y = c->surface.xwayland->y;
|
||||||
|
|
||||||
|
wlr_surface_for_each_surface(c->surface.xwayland->surface, render, &rdata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
updatewindowtype(Client *c)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (c->type != XDGShell)
|
||||||
|
for (i = 0; i < c->surface.xwayland->window_type_len; i++)
|
||||||
|
if (c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeDialog] ||
|
||||||
|
c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeSplash] ||
|
||||||
|
c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeToolbar] ||
|
||||||
|
c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeUtility])
|
||||||
|
c->isfloating = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xwaylandready(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
xcb_connection_t *xc = xcb_connect(xwayland->display_name, NULL);
|
||||||
|
int err = xcb_connection_has_error(xc);
|
||||||
|
if (err) {
|
||||||
|
fprintf(stderr, "xcb_connect to X server failed with code %d\n. Continuing with degraded functionality.\n", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Collect atoms we are interested in. If getatom returns 0, we will
|
||||||
|
* not detect that window type. */
|
||||||
|
netatom[NetWMWindowTypeDialog] = getatom(xc, "_NET_WM_WINDOW_TYPE_DIALOG");
|
||||||
|
netatom[NetWMWindowTypeSplash] = getatom(xc, "_NET_WM_WINDOW_TYPE_SPLASH");
|
||||||
|
netatom[NetWMWindowTypeUtility] = getatom(xc, "_NET_WM_WINDOW_TYPE_TOOLBAR");
|
||||||
|
netatom[NetWMWindowTypeToolbar] = getatom(xc, "_NET_WM_WINDOW_TYPE_UTILITY");
|
||||||
|
|
||||||
|
/* assign the one and only seat */
|
||||||
|
wlr_xwayland_set_seat(xwayland, seat);
|
||||||
|
|
||||||
|
xcb_disconnect(xc);
|
||||||
|
}
|
||||||
|
|
||||||
|
Client *
|
||||||
|
xytoindependent(double x, double y)
|
||||||
|
{
|
||||||
|
/* Find the topmost visible independent at point (x, y).
|
||||||
|
* For independents, the most recently created can be used as the "top".
|
||||||
|
* We rely on the X11 convention of unmapping unmanaged when the "owning"
|
||||||
|
* client loses focus, which ensures that unmanaged are only visible on
|
||||||
|
* the current tag. */
|
||||||
|
Client *c;
|
||||||
|
struct wlr_box geom;
|
||||||
|
wl_list_for_each_reverse(c, &independents, link) {
|
||||||
|
geom.x = c->surface.xwayland->x;
|
||||||
|
geom.y = c->surface.xwayland->y;
|
||||||
|
geom.width = c->surface.xwayland->width;
|
||||||
|
geom.height = c->surface.xwayland->height;
|
||||||
|
if (wlr_box_contains_point(&geom, x, y))
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
@ -1882,7 +1942,9 @@ 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. */
|
||||||
|
#ifdef XWAYLAND
|
||||||
wlr_xwayland_destroy(xwayland);
|
wlr_xwayland_destroy(xwayland);
|
||||||
|
#endif
|
||||||
wl_display_destroy_clients(dpy);
|
wl_display_destroy_clients(dpy);
|
||||||
wl_display_destroy(dpy);
|
wl_display_destroy(dpy);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue