Merge branch 'wlroots-next'
This commit is contained in:
commit
7ac76219df
3 changed files with 341 additions and 273 deletions
7
Makefile
7
Makefile
|
@ -5,7 +5,7 @@ include config.mk
|
|||
|
||||
# flags for compiling
|
||||
DWLCPPFLAGS = -I. -DWLR_USE_UNSTABLE -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XWAYLAND)
|
||||
DWLDEVCFLAGS = -pedantic -Wall -Wextra -Wdeclaration-after-statement -Wno-unused-parameter -Wno-sign-compare -Wshadow -Wunused-macros\
|
||||
DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement -Wno-unused-parameter -Wno-sign-compare -Wshadow -Wunused-macros\
|
||||
-Werror=strict-prototypes -Werror=implicit -Werror=return-type -Werror=incompatible-pointer-types
|
||||
|
||||
# CFLAGS / LDFLAGS
|
||||
|
@ -16,7 +16,7 @@ LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(LIBS)
|
|||
all: dwl
|
||||
dwl: dwl.o util.o
|
||||
$(CC) dwl.o util.o $(LDLIBS) $(LDFLAGS) $(DWLCFLAGS) -o $@
|
||||
dwl.o: dwl.c config.mk config.h client.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h
|
||||
dwl.o: dwl.c config.mk config.h client.h cursor-shape-v1-protocol.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h
|
||||
util.o: util.c util.h
|
||||
|
||||
# wayland-scanner is a tool which generates C headers and rigging for Wayland
|
||||
|
@ -31,6 +31,9 @@ xdg-shell-protocol.h:
|
|||
wlr-layer-shell-unstable-v1-protocol.h:
|
||||
$(WAYLAND_SCANNER) server-header \
|
||||
protocols/wlr-layer-shell-unstable-v1.xml $@
|
||||
cursor-shape-v1-protocol.h:
|
||||
$(WAYLAND_SCANNER) server-header \
|
||||
$(WAYLAND_PROTOCOLS)/staging/cursor-shape/cursor-shape-v1.xml $@
|
||||
|
||||
config.h:
|
||||
cp config.def.h $@
|
||||
|
|
180
client.h
180
client.h
|
@ -11,34 +11,8 @@ client_is_x11(Client *c)
|
|||
{
|
||||
#ifdef XWAYLAND
|
||||
return c->type == X11Managed || c->type == X11Unmanaged;
|
||||
#else
|
||||
#endif
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
client_get_size_hints(Client *c, struct wlr_box *max, struct wlr_box *min)
|
||||
{
|
||||
struct wlr_xdg_toplevel *toplevel;
|
||||
struct wlr_xdg_toplevel_state *state;
|
||||
#ifdef XWAYLAND
|
||||
if (client_is_x11(c)) {
|
||||
xcb_size_hints_t *size_hints = c->surface.xwayland->size_hints;
|
||||
if (size_hints) {
|
||||
max->width = size_hints->max_width;
|
||||
max->height = size_hints->max_height;
|
||||
min->width = size_hints->min_width;
|
||||
min->height = size_hints->min_height;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
toplevel = c->surface.xdg->toplevel;
|
||||
state = &toplevel->current;
|
||||
max->width = state->max_width;
|
||||
max->height = state->max_height;
|
||||
min->width = state->min_width;
|
||||
min->height = state->min_height;
|
||||
}
|
||||
|
||||
static inline struct wlr_surface *
|
||||
|
@ -54,7 +28,7 @@ client_surface(Client *c)
|
|||
static inline int
|
||||
toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc, LayerSurface **pl)
|
||||
{
|
||||
struct wlr_xdg_surface *xdg_surface;
|
||||
struct wlr_xdg_surface *xdg_surface, *tmp_xdg_surface;
|
||||
struct wlr_surface *root_surface;
|
||||
struct wlr_layer_surface_v1 *layer_surface;
|
||||
Client *c = NULL;
|
||||
|
@ -65,44 +39,44 @@ toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc, LayerSurface **pl)
|
|||
#endif
|
||||
|
||||
if (!s)
|
||||
return type;
|
||||
return -1;
|
||||
root_surface = wlr_surface_get_root_surface(s);
|
||||
|
||||
#ifdef XWAYLAND
|
||||
if (wlr_surface_is_xwayland_surface(root_surface)
|
||||
&& (xsurface = wlr_xwayland_surface_from_wlr_surface(root_surface))) {
|
||||
if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(root_surface))) {
|
||||
c = xsurface->data;
|
||||
type = c->type;
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (wlr_surface_is_layer_surface(root_surface)
|
||||
&& (layer_surface = wlr_layer_surface_v1_from_wlr_surface(root_surface))) {
|
||||
if ((layer_surface = wlr_layer_surface_v1_try_from_wlr_surface(root_surface))) {
|
||||
l = layer_surface->data;
|
||||
type = LayerShell;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (wlr_surface_is_xdg_surface(root_surface)
|
||||
&& (xdg_surface = wlr_xdg_surface_from_wlr_surface(root_surface))) {
|
||||
while (1) {
|
||||
switch (xdg_surface->role) {
|
||||
case WLR_XDG_SURFACE_ROLE_POPUP:
|
||||
if (!xdg_surface->popup->parent)
|
||||
return -1;
|
||||
else if (!wlr_surface_is_xdg_surface(xdg_surface->popup->parent))
|
||||
return toplevel_from_wlr_surface(xdg_surface->popup->parent, pc, pl);
|
||||
|
||||
xdg_surface = wlr_xdg_surface_from_wlr_surface(xdg_surface->popup->parent);
|
||||
break;
|
||||
case WLR_XDG_SURFACE_ROLE_TOPLEVEL:
|
||||
c = xdg_surface->data;
|
||||
type = c->type;
|
||||
goto end;
|
||||
case WLR_XDG_SURFACE_ROLE_NONE:
|
||||
xdg_surface = wlr_xdg_surface_try_from_wlr_surface(root_surface);
|
||||
while (xdg_surface) {
|
||||
tmp_xdg_surface = NULL;
|
||||
switch (xdg_surface->role) {
|
||||
case WLR_XDG_SURFACE_ROLE_POPUP:
|
||||
if (!xdg_surface->popup || !xdg_surface->popup->parent)
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp_xdg_surface = wlr_xdg_surface_try_from_wlr_surface(xdg_surface->popup->parent);
|
||||
|
||||
if (!tmp_xdg_surface)
|
||||
return toplevel_from_wlr_surface(xdg_surface->popup->parent, pc, pl);
|
||||
|
||||
xdg_surface = tmp_xdg_surface;
|
||||
break;
|
||||
case WLR_XDG_SURFACE_ROLE_TOPLEVEL:
|
||||
c = xdg_surface->data;
|
||||
type = c->type;
|
||||
goto end;
|
||||
case WLR_XDG_SURFACE_ROLE_NONE:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,19 +92,16 @@ end:
|
|||
static inline void
|
||||
client_activate_surface(struct wlr_surface *s, int activated)
|
||||
{
|
||||
struct wlr_xdg_surface *surface;
|
||||
struct wlr_xdg_toplevel *toplevel;
|
||||
#ifdef XWAYLAND
|
||||
struct wlr_xwayland_surface *xsurface;
|
||||
if (wlr_surface_is_xwayland_surface(s)
|
||||
&& (xsurface = wlr_xwayland_surface_from_wlr_surface(s))) {
|
||||
if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(s))) {
|
||||
wlr_xwayland_surface_activate(xsurface, activated);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (wlr_surface_is_xdg_surface(s)
|
||||
&& (surface = wlr_xdg_surface_from_wlr_surface(s))
|
||||
&& surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL)
|
||||
wlr_xdg_toplevel_set_activated(surface->toplevel, activated);
|
||||
if ((toplevel = wlr_xdg_toplevel_try_from_wlr_surface(s)))
|
||||
wlr_xdg_toplevel_set_activated(toplevel, activated);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
|
@ -140,23 +111,16 @@ client_set_bounds(Client *c, int32_t width, int32_t height)
|
|||
if (client_is_x11(c))
|
||||
return 0;
|
||||
#endif
|
||||
if (c->surface.xdg->client->shell->version >=
|
||||
XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION && width >= 0 && height >= 0)
|
||||
if (wl_resource_get_version(c->surface.xdg->toplevel->resource) >=
|
||||
XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION && width >= 0 && height >= 0
|
||||
&& (c->bounds.width != width || c->bounds.height != height)) {
|
||||
c->bounds.width = width;
|
||||
c->bounds.height = height;
|
||||
return wlr_xdg_toplevel_set_bounds(c->surface.xdg->toplevel, width, height);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
client_for_each_surface(Client *c, wlr_surface_iterator_func_t fn, void *data)
|
||||
{
|
||||
wlr_surface_for_each_surface(client_surface(c), fn, data);
|
||||
#ifdef XWAYLAND
|
||||
if (client_is_x11(c))
|
||||
return;
|
||||
#endif
|
||||
wlr_xdg_surface_for_each_popup_surface(c->surface.xdg, fn, data);
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
client_get_appid(Client *c)
|
||||
{
|
||||
|
@ -167,6 +131,27 @@ client_get_appid(Client *c)
|
|||
return c->surface.xdg->toplevel->app_id;
|
||||
}
|
||||
|
||||
static inline void
|
||||
client_get_clip(Client *c, struct wlr_box *clip)
|
||||
{
|
||||
struct wlr_box xdg_geom = {0};
|
||||
*clip = (struct wlr_box){
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = c->geom.width - c->bw,
|
||||
.height = c->geom.height - c->bw,
|
||||
};
|
||||
|
||||
#ifdef XWAYLAND
|
||||
if (client_is_x11(c))
|
||||
return;
|
||||
#endif
|
||||
|
||||
wlr_xdg_surface_get_geometry(c->surface.xdg, &xdg_geom);
|
||||
clip->x = xdg_geom.x;
|
||||
clip->y = xdg_geom.y;
|
||||
}
|
||||
|
||||
static inline void
|
||||
client_get_geometry(Client *c, struct wlr_box *geom)
|
||||
{
|
||||
|
@ -192,7 +177,6 @@ client_get_parent(Client *c)
|
|||
#endif
|
||||
if (c->surface.xdg->toplevel->parent)
|
||||
toplevel_from_wlr_surface(c->surface.xdg->toplevel->parent->base->surface, &p, NULL);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
@ -209,35 +193,35 @@ client_get_title(Client *c)
|
|||
static inline int
|
||||
client_is_float_type(Client *c)
|
||||
{
|
||||
struct wlr_box min = {0}, max = {0};
|
||||
client_get_size_hints(c, &max, &min);
|
||||
struct wlr_xdg_toplevel *toplevel;
|
||||
struct wlr_xdg_toplevel_state state;
|
||||
|
||||
#ifdef XWAYLAND
|
||||
if (client_is_x11(c)) {
|
||||
struct wlr_xwayland_surface *surface = c->surface.xwayland;
|
||||
xcb_size_hints_t *size_hints = surface->size_hints;
|
||||
size_t i;
|
||||
if (surface->modal)
|
||||
return 1;
|
||||
|
||||
for (size_t i = 0; i < surface->window_type_len; i++)
|
||||
for (i = 0; i < surface->window_type_len; i++)
|
||||
if (surface->window_type[i] == netatom[NetWMWindowTypeDialog]
|
||||
|| surface->window_type[i] == netatom[NetWMWindowTypeSplash]
|
||||
|| surface->window_type[i] == netatom[NetWMWindowTypeToolbar]
|
||||
|| surface->window_type[i] == netatom[NetWMWindowTypeUtility])
|
||||
return 1;
|
||||
|
||||
return size_hints && size_hints->min_width > 0 && size_hints->min_height > 0
|
||||
&& (size_hints->max_width == size_hints->min_width
|
||||
|| size_hints->max_height == size_hints->min_height);
|
||||
}
|
||||
#endif
|
||||
return ((min.width > 0 || min.height > 0 || max.width > 0 || max.height > 0)
|
||||
&& (min.width == max.width || min.height == max.height));
|
||||
}
|
||||
|
||||
static inline int
|
||||
client_is_mapped(Client *c)
|
||||
{
|
||||
#ifdef XWAYLAND
|
||||
if (client_is_x11(c))
|
||||
return c->surface.xwayland->mapped;
|
||||
#endif
|
||||
return c->surface.xdg->mapped;
|
||||
toplevel = c->surface.xdg->toplevel;
|
||||
state = toplevel->current;
|
||||
return toplevel->parent || (state.min_width != 0 && state.min_height != 0
|
||||
&& (state.min_width == state.max_width
|
||||
|| state.min_height == state.max_height));
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
@ -247,7 +231,8 @@ client_is_rendered_on_mon(Client *c, Monitor *m)
|
|||
* but rather actual displaying of the pixels.
|
||||
* Usually VISIBLEON suffices and is also faster. */
|
||||
struct wlr_surface_output *s;
|
||||
if (!c->scene->node.enabled)
|
||||
int unused_lx, unused_ly;
|
||||
if (!wlr_scene_node_coords(&c->scene->node, &unused_lx, &unused_ly))
|
||||
return 0;
|
||||
wl_list_for_each(s, &client_surface(c)->current_outputs, link)
|
||||
if (s->output == m->wlr_output)
|
||||
|
@ -366,18 +351,25 @@ client_set_tiled(Client *c, uint32_t edges)
|
|||
if (client_is_x11(c))
|
||||
return;
|
||||
#endif
|
||||
wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, edges);
|
||||
if (wl_resource_get_version(c->surface.xdg->resource)
|
||||
>= XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) {
|
||||
wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, edges);
|
||||
} else {
|
||||
wlr_xdg_toplevel_set_maximized(c->surface.xdg->toplevel, edges != WLR_EDGE_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
static inline struct wlr_surface *
|
||||
client_surface_at(Client *c, double cx, double cy, double *sx, double *sy)
|
||||
static inline void
|
||||
client_set_suspended(Client *c, int suspended)
|
||||
{
|
||||
#ifdef XWAYLAND
|
||||
if (client_is_x11(c))
|
||||
return wlr_surface_surface_at(c->surface.xwayland->surface,
|
||||
cx, cy, sx, sy);
|
||||
if (client_is_x11(c)) {
|
||||
wlr_xwayland_surface_set_withdrawn(c->surface.xwayland, suspended);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
return wlr_xdg_surface_surface_at(c->surface.xdg, cx, cy, sx, sy);
|
||||
|
||||
wlr_xdg_toplevel_set_suspended(c->surface.xdg->toplevel, suspended);
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
|
427
dwl.c
427
dwl.c
|
@ -3,7 +3,6 @@
|
|||
*/
|
||||
#include <getopt.h>
|
||||
#include <libinput.h>
|
||||
#include <limits.h>
|
||||
#include <linux/input-event-codes.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
|
@ -18,15 +17,17 @@
|
|||
#include <wlr/render/wlr_renderer.h>
|
||||
#include <wlr/types/wlr_compositor.h>
|
||||
#include <wlr/types/wlr_cursor.h>
|
||||
#include <wlr/types/wlr_cursor_shape_v1.h>
|
||||
#include <wlr/types/wlr_data_control_v1.h>
|
||||
#include <wlr/types/wlr_data_device.h>
|
||||
#include <wlr/types/wlr_drm.h>
|
||||
#include <wlr/types/wlr_linux_dmabuf_v1.h>
|
||||
#include <wlr/types/wlr_export_dmabuf_v1.h>
|
||||
#include <wlr/types/wlr_fractional_scale_v1.h>
|
||||
#include <wlr/types/wlr_gamma_control_v1.h>
|
||||
#include <wlr/types/wlr_idle.h>
|
||||
#include <wlr/types/wlr_idle_inhibit_v1.h>
|
||||
#include <wlr/types/wlr_idle_notify_v1.h>
|
||||
#include <wlr/types/wlr_input_device.h>
|
||||
#include <wlr/types/wlr_input_inhibitor.h>
|
||||
#include <wlr/types/wlr_keyboard.h>
|
||||
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
|
@ -69,7 +70,7 @@
|
|||
#define END(A) ((A) + LENGTH(A))
|
||||
#define TAGMASK ((1u << TAGCOUNT) - 1)
|
||||
#define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L)))
|
||||
#define IDLE_NOTIFY_ACTIVITY wlr_idle_notify_activity(idle, seat), wlr_idle_notifier_v1_notify_activity(idle_notifier, seat)
|
||||
#define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0)
|
||||
|
||||
/* enums */
|
||||
enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
|
||||
|
@ -117,8 +118,11 @@ typedef struct {
|
|||
struct wl_listener set_title;
|
||||
struct wl_listener fullscreen;
|
||||
struct wlr_box prev; /* layout-relative, includes border */
|
||||
struct wlr_box bounds;
|
||||
#ifdef XWAYLAND
|
||||
struct wl_listener activate;
|
||||
struct wl_listener associate;
|
||||
struct wl_listener dissociate;
|
||||
struct wl_listener configure;
|
||||
struct wl_listener set_hints;
|
||||
#endif
|
||||
|
@ -179,6 +183,7 @@ struct Monitor {
|
|||
struct wlr_scene_rect *fullscreen_bg; /* See createmon() for info */
|
||||
struct wl_listener frame;
|
||||
struct wl_listener destroy;
|
||||
struct wl_listener request_state;
|
||||
struct wl_listener destroy_lock_surface;
|
||||
struct wlr_session_lock_surface_v1 *lock_surface;
|
||||
struct wlr_box m; /* monitor area, layout-relative */
|
||||
|
@ -189,6 +194,7 @@ struct Monitor {
|
|||
unsigned int sellt;
|
||||
uint32_t tagset[2];
|
||||
double mfact;
|
||||
int gamma_lut_changed;
|
||||
int nmaster;
|
||||
char ltsymbol[16];
|
||||
};
|
||||
|
@ -286,11 +292,14 @@ static void printstatus(void);
|
|||
static void quit(const Arg *arg);
|
||||
static void rendermon(struct wl_listener *listener, void *data);
|
||||
static void requeststartdrag(struct wl_listener *listener, void *data);
|
||||
static void requestmonstate(struct wl_listener *listener, void *data);
|
||||
static void resize(Client *c, struct wlr_box geo, int interact);
|
||||
static void run(char *startup_cmd);
|
||||
static void setcursor(struct wl_listener *listener, void *data);
|
||||
static void setcursorshape(struct wl_listener *listener, void *data);
|
||||
static void setfloating(Client *c, int floating);
|
||||
static void setfullscreen(Client *c, int fullscreen);
|
||||
static void setgamma(struct wl_listener *listener, void *data);
|
||||
static void setlayout(const Arg *arg);
|
||||
static void setmfact(const Arg *arg);
|
||||
static void setmon(Client *c, Monitor *m, uint32_t newtags);
|
||||
|
@ -321,7 +330,6 @@ static void zoom(const Arg *arg);
|
|||
|
||||
/* variables */
|
||||
static const char broken[] = "broken";
|
||||
static const char *cursor_image = "left_ptr";
|
||||
static pid_t child_pid = -1;
|
||||
static int locked;
|
||||
static void *exclusive_focus;
|
||||
|
@ -335,19 +343,20 @@ static const int layermap[] = { LyrBg, LyrBottom, LyrTop, LyrOverlay };
|
|||
static struct wlr_renderer *drw;
|
||||
static struct wlr_allocator *alloc;
|
||||
static struct wlr_compositor *compositor;
|
||||
static struct wlr_session *session;
|
||||
|
||||
static struct wlr_xdg_shell *xdg_shell;
|
||||
static struct wlr_xdg_activation_v1 *activation;
|
||||
static struct wlr_xdg_decoration_manager_v1 *xdg_decoration_mgr;
|
||||
static struct wl_list clients; /* tiling order */
|
||||
static struct wl_list fstack; /* focus order */
|
||||
static struct wlr_idle *idle;
|
||||
static struct wlr_idle_notifier_v1 *idle_notifier;
|
||||
static struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr;
|
||||
static struct wlr_input_inhibit_manager *input_inhibit_mgr;
|
||||
static struct wlr_layer_shell_v1 *layer_shell;
|
||||
static struct wlr_output_manager_v1 *output_mgr;
|
||||
static struct wlr_gamma_control_manager_v1 *gamma_control_mgr;
|
||||
static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr;
|
||||
static struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr;
|
||||
|
||||
static struct wlr_cursor *cursor;
|
||||
static struct wlr_xcursor_manager *cursor_mgr;
|
||||
|
@ -355,6 +364,7 @@ static struct wlr_xcursor_manager *cursor_mgr;
|
|||
static struct wlr_session_lock_manager_v1 *session_lock_mgr;
|
||||
static struct wlr_scene_rect *locked_bg;
|
||||
static struct wlr_session_lock_v1 *cur_lock;
|
||||
static struct wl_listener lock_listener = {.notify = locksession};
|
||||
|
||||
static struct wlr_seat *seat;
|
||||
static struct wl_list keyboards;
|
||||
|
@ -367,42 +377,15 @@ static struct wlr_box sgeom;
|
|||
static struct wl_list mons;
|
||||
static Monitor *selmon;
|
||||
|
||||
/* global event handlers */
|
||||
static struct wl_listener cursor_axis = {.notify = axisnotify};
|
||||
static struct wl_listener cursor_button = {.notify = buttonpress};
|
||||
static struct wl_listener cursor_frame = {.notify = cursorframe};
|
||||
static struct wl_listener cursor_motion = {.notify = motionrelative};
|
||||
static struct wl_listener cursor_motion_absolute = {.notify = motionabsolute};
|
||||
static struct wl_listener drag_icon_destroy = {.notify = destroydragicon};
|
||||
static struct wl_listener idle_inhibitor_create = {.notify = createidleinhibitor};
|
||||
static struct wl_listener idle_inhibitor_destroy = {.notify = destroyidleinhibitor};
|
||||
static struct wl_listener layout_change = {.notify = updatemons};
|
||||
static struct wl_listener new_input = {.notify = inputdevice};
|
||||
static struct wl_listener new_virtual_keyboard = {.notify = virtualkeyboard};
|
||||
static struct wl_listener new_output = {.notify = createmon};
|
||||
static struct wl_listener new_xdg_surface = {.notify = createnotify};
|
||||
static struct wl_listener new_xdg_decoration = {.notify = createdecoration};
|
||||
static struct wl_listener new_layer_shell_surface = {.notify = createlayersurface};
|
||||
static struct wl_listener output_mgr_apply = {.notify = outputmgrapply};
|
||||
static struct wl_listener output_mgr_test = {.notify = outputmgrtest};
|
||||
static struct wl_listener request_activate = {.notify = urgent};
|
||||
static struct wl_listener request_cursor = {.notify = setcursor};
|
||||
static struct wl_listener request_set_psel = {.notify = setpsel};
|
||||
static struct wl_listener request_set_sel = {.notify = setsel};
|
||||
static struct wl_listener request_start_drag = {.notify = requeststartdrag};
|
||||
static struct wl_listener start_drag = {.notify = startdrag};
|
||||
static struct wl_listener session_lock_create_lock = {.notify = locksession};
|
||||
static struct wl_listener session_lock_mgr_destroy = {.notify = destroysessionmgr};
|
||||
|
||||
#ifdef XWAYLAND
|
||||
static void activatex11(struct wl_listener *listener, void *data);
|
||||
static void associatex11(struct wl_listener *listener, void *data);
|
||||
static void configurex11(struct wl_listener *listener, void *data);
|
||||
static void createnotifyx11(struct wl_listener *listener, void *data);
|
||||
static void dissociatex11(struct wl_listener *listener, void *data);
|
||||
static xcb_atom_t getatom(xcb_connection_t *xc, const char *name);
|
||||
static void sethints(struct wl_listener *listener, void *data);
|
||||
static void xwaylandready(struct wl_listener *listener, void *data);
|
||||
static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11};
|
||||
static struct wl_listener xwayland_ready = {.notify = xwaylandready};
|
||||
static struct wlr_xwayland *xwayland;
|
||||
static xcb_atom_t netatom[NetLast];
|
||||
#endif
|
||||
|
@ -417,19 +400,9 @@ static xcb_atom_t netatom[NetLast];
|
|||
void
|
||||
applybounds(Client *c, struct wlr_box *bbox)
|
||||
{
|
||||
if (!c->isfullscreen) {
|
||||
struct wlr_box min = {0}, max = {0};
|
||||
client_get_size_hints(c, &max, &min);
|
||||
/* try to set size hints */
|
||||
c->geom.width = MAX(min.width + (2 * (int)c->bw), c->geom.width);
|
||||
c->geom.height = MAX(min.height + (2 * (int)c->bw), c->geom.height);
|
||||
/* Some clients set their max size to INT_MAX, which does not violate the
|
||||
* protocol but it's unnecesary, as they can set their max size to zero. */
|
||||
if (max.width > 0 && !(2 * c->bw > INT_MAX - max.width)) /* Checks for overflow */
|
||||
c->geom.width = MIN(max.width + (2 * c->bw), c->geom.width);
|
||||
if (max.height > 0 && !(2 * c->bw > INT_MAX - max.height)) /* Checks for overflow */
|
||||
c->geom.height = MIN(max.height + (2 * c->bw), c->geom.height);
|
||||
}
|
||||
/* set minimum possible */
|
||||
c->geom.width = MAX(1, c->geom.width);
|
||||
c->geom.height = MAX(1, c->geom.height);
|
||||
|
||||
if (c->geom.x >= bbox->x + bbox->width)
|
||||
c->geom.x = bbox->x + bbox->width - c->geom.width;
|
||||
|
@ -475,9 +448,12 @@ void
|
|||
arrange(Monitor *m)
|
||||
{
|
||||
Client *c;
|
||||
wl_list_for_each(c, &clients, link)
|
||||
if (c->mon == m)
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (c->mon == m) {
|
||||
wlr_scene_node_set_enabled(&c->scene->node, VISIBLEON(c, m));
|
||||
client_set_suspended(c, !VISIBLEON(c, m));
|
||||
}
|
||||
}
|
||||
|
||||
wlr_scene_node_set_enabled(&m->fullscreen_bg->node,
|
||||
(c = focustop(m)) && c->isfullscreen);
|
||||
|
@ -559,7 +535,7 @@ axisnotify(struct wl_listener *listener, void *data)
|
|||
/* This event is forwarded by the cursor when a pointer emits an axis event,
|
||||
* for example when you move the scroll wheel. */
|
||||
struct wlr_pointer_axis_event *event = data;
|
||||
IDLE_NOTIFY_ACTIVITY;
|
||||
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
||||
/* TODO: allow usage of scroll whell for mousebindings, it can be implemented
|
||||
* checking the event's orientation and the delta of the event */
|
||||
/* Notify the client with pointer focus of the axis event. */
|
||||
|
@ -577,7 +553,7 @@ buttonpress(struct wl_listener *listener, void *data)
|
|||
Client *c;
|
||||
const Button *b;
|
||||
|
||||
IDLE_NOTIFY_ACTIVITY;
|
||||
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
||||
|
||||
switch (event->state) {
|
||||
case WLR_BUTTON_PRESSED:
|
||||
|
@ -602,13 +578,10 @@ buttonpress(struct wl_listener *listener, void *data)
|
|||
break;
|
||||
case WLR_BUTTON_RELEASED:
|
||||
/* If you released any buttons, we exit interactive move/resize mode. */
|
||||
/* TODO should reset to the pointer focus's current setcursor */
|
||||
if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) {
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
|
||||
cursor_mode = CurNormal;
|
||||
/* Clear the pointer focus, this way if the cursor is over a surface
|
||||
* we will send an enter event after which the client will provide us
|
||||
* a cursor surface */
|
||||
wlr_seat_pointer_clear_focus(seat);
|
||||
motionnotify(0);
|
||||
/* Drop the window off on its new monitor */
|
||||
selmon = xytomon(cursor->x, cursor->y);
|
||||
setmon(grabc, selmon, 0);
|
||||
|
@ -627,7 +600,7 @@ buttonpress(struct wl_listener *listener, void *data)
|
|||
void
|
||||
chvt(const Arg *arg)
|
||||
{
|
||||
wlr_session_change_vt(wlr_backend_get_session(backend), arg->ui);
|
||||
wlr_session_change_vt(session, arg->ui);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -645,7 +618,6 @@ checkidleinhibitor(struct wlr_surface *exclude)
|
|||
}
|
||||
}
|
||||
|
||||
wlr_idle_set_enabled(idle, NULL, !inhibited);
|
||||
wlr_idle_notifier_v1_set_inhibited(idle_notifier, inhibited);
|
||||
}
|
||||
|
||||
|
@ -654,21 +626,19 @@ cleanup(void)
|
|||
{
|
||||
#ifdef XWAYLAND
|
||||
wlr_xwayland_destroy(xwayland);
|
||||
xwayland = NULL;
|
||||
#endif
|
||||
wl_display_destroy_clients(dpy);
|
||||
if (child_pid > 0) {
|
||||
kill(child_pid, SIGTERM);
|
||||
waitpid(child_pid, NULL, 0);
|
||||
}
|
||||
wlr_backend_destroy(backend);
|
||||
wlr_scene_node_destroy(&scene->tree.node);
|
||||
wlr_renderer_destroy(drw);
|
||||
wlr_allocator_destroy(alloc);
|
||||
wlr_xcursor_manager_destroy(cursor_mgr);
|
||||
wlr_cursor_destroy(cursor);
|
||||
wlr_output_layout_destroy(output_layout);
|
||||
wlr_seat_destroy(seat);
|
||||
wl_display_destroy(dpy);
|
||||
/* Destroy after the wayland display (when the monitors are already destroyed)
|
||||
to avoid destroying them with an invalid scene output. */
|
||||
wlr_scene_node_destroy(&scene->tree.node);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -757,9 +727,9 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data)
|
|||
wlr_scene_node_reparent(&layersurface->popups->node, layers[LyrTop]);
|
||||
|
||||
if (wlr_layer_surface->current.committed == 0
|
||||
&& layersurface->mapped == wlr_layer_surface->mapped)
|
||||
&& layersurface->mapped == wlr_layer_surface->surface->mapped)
|
||||
return;
|
||||
layersurface->mapped = wlr_layer_surface->mapped;
|
||||
layersurface->mapped = wlr_layer_surface->surface->mapped;
|
||||
|
||||
arrangelayers(layersurface->mon);
|
||||
}
|
||||
|
@ -769,6 +739,9 @@ commitnotify(struct wl_listener *listener, void *data)
|
|||
{
|
||||
Client *c = wl_container_of(listener, c, commit);
|
||||
|
||||
if (client_surface(c)->mapped)
|
||||
resize(c, c->geom, (c->isfloating && !c->isfullscreen));
|
||||
|
||||
/* mark a pending resize as completed */
|
||||
if (c->resize && c->resize <= c->surface.xdg->current.configure_serial)
|
||||
c->resize = 0;
|
||||
|
@ -785,7 +758,7 @@ void
|
|||
createidleinhibitor(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct wlr_idle_inhibitor_v1 *idle_inhibitor = data;
|
||||
wl_signal_add(&idle_inhibitor->events.destroy, &idle_inhibitor_destroy);
|
||||
LISTEN_STATIC(&idle_inhibitor->events.destroy, destroyidleinhibitor);
|
||||
|
||||
checkidleinhibitor(NULL);
|
||||
}
|
||||
|
@ -840,21 +813,19 @@ createlayersurface(struct wl_listener *listener, void *data)
|
|||
return;
|
||||
}
|
||||
|
||||
layersurface = ecalloc(1, sizeof(LayerSurface));
|
||||
layersurface = wlr_layer_surface->data = ecalloc(1, sizeof(LayerSurface));
|
||||
layersurface->type = LayerShell;
|
||||
LISTEN(&wlr_layer_surface->surface->events.commit,
|
||||
&layersurface->surface_commit, commitlayersurfacenotify);
|
||||
LISTEN(&wlr_layer_surface->events.destroy, &layersurface->destroy,
|
||||
destroylayersurfacenotify);
|
||||
LISTEN(&wlr_layer_surface->events.map, &layersurface->map,
|
||||
LISTEN(&wlr_layer_surface->surface->events.map, &layersurface->map,
|
||||
maplayersurfacenotify);
|
||||
LISTEN(&wlr_layer_surface->events.unmap, &layersurface->unmap,
|
||||
LISTEN(&wlr_layer_surface->surface->events.unmap, &layersurface->unmap,
|
||||
unmaplayersurfacenotify);
|
||||
|
||||
layersurface->layer_surface = wlr_layer_surface;
|
||||
layersurface->mon = wlr_layer_surface->output->data;
|
||||
wlr_layer_surface->data = layersurface;
|
||||
|
||||
layersurface->scene_layer = wlr_scene_layer_surface_v1_create(l, wlr_layer_surface);
|
||||
layersurface->scene = layersurface->scene_layer->tree;
|
||||
layersurface->popups = wlr_layer_surface->surface->data = wlr_scene_tree_create(l);
|
||||
|
@ -915,7 +886,6 @@ createmon(struct wl_listener *listener, void *data)
|
|||
m->mfact = r->mfact;
|
||||
m->nmaster = r->nmaster;
|
||||
wlr_output_set_scale(wlr_output, r->scale);
|
||||
wlr_xcursor_manager_load(cursor_mgr, r->scale);
|
||||
m->lt[0] = m->lt[1] = r->lt;
|
||||
wlr_output_set_transform(wlr_output, r->rr);
|
||||
m->m.x = r->x;
|
||||
|
@ -933,16 +903,12 @@ createmon(struct wl_listener *listener, void *data)
|
|||
/* Set up event listeners */
|
||||
LISTEN(&wlr_output->events.frame, &m->frame, rendermon);
|
||||
LISTEN(&wlr_output->events.destroy, &m->destroy, cleanupmon);
|
||||
LISTEN(&wlr_output->events.request_state, &m->request_state, requestmonstate);
|
||||
|
||||
wlr_output_enable(wlr_output, 1);
|
||||
if (!wlr_output_commit(wlr_output))
|
||||
return;
|
||||
|
||||
/* Try to enable adaptive sync, note that not all monitors support it.
|
||||
* wlr_output_commit() will deactivate it in case it cannot be enabled */
|
||||
wlr_output_enable_adaptive_sync(wlr_output, 1);
|
||||
wlr_output_commit(wlr_output);
|
||||
|
||||
wl_list_insert(&mons, &m->link);
|
||||
printstatus();
|
||||
|
||||
|
@ -1006,8 +972,12 @@ createnotify(struct wl_listener *listener, void *data)
|
|||
c->surface.xdg = xdg_surface;
|
||||
c->bw = borderpx;
|
||||
|
||||
LISTEN(&xdg_surface->events.map, &c->map, mapnotify);
|
||||
LISTEN(&xdg_surface->events.unmap, &c->unmap, unmapnotify);
|
||||
wlr_xdg_toplevel_set_wm_capabilities(xdg_surface->toplevel,
|
||||
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
|
||||
|
||||
LISTEN(&xdg_surface->surface->events.commit, &c->commit, commitnotify);
|
||||
LISTEN(&xdg_surface->surface->events.map, &c->map, mapnotify);
|
||||
LISTEN(&xdg_surface->surface->events.unmap, &c->unmap, unmapnotify);
|
||||
LISTEN(&xdg_surface->events.destroy, &c->destroy, destroynotify);
|
||||
LISTEN(&xdg_surface->toplevel->events.set_title, &c->set_title, updatetitle);
|
||||
LISTEN(&xdg_surface->toplevel->events.request_fullscreen, &c->fullscreen,
|
||||
|
@ -1074,8 +1044,6 @@ cursorframe(struct wl_listener *listener, void *data)
|
|||
void
|
||||
destroydragicon(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct wlr_drag_icon *icon = data;
|
||||
wlr_scene_node_destroy(icon->data);
|
||||
/* Focus enter isn't sent during drag, so refocus the focused node. */
|
||||
focusclient(focustop(selmon), 1);
|
||||
motionnotify(0);
|
||||
|
@ -1150,20 +1118,25 @@ destroylocksurface(struct wl_listener *listener, void *data)
|
|||
void
|
||||
destroynotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Called when the surface is destroyed and should never be shown again. */
|
||||
/* Called when the xdg_toplevel is destroyed. */
|
||||
Client *c = wl_container_of(listener, c, destroy);
|
||||
wl_list_remove(&c->map.link);
|
||||
wl_list_remove(&c->unmap.link);
|
||||
wl_list_remove(&c->destroy.link);
|
||||
wl_list_remove(&c->set_title.link);
|
||||
wl_list_remove(&c->fullscreen.link);
|
||||
#ifdef XWAYLAND
|
||||
if (c->type != XDGShell) {
|
||||
wl_list_remove(&c->configure.link);
|
||||
wl_list_remove(&c->set_hints.link);
|
||||
wl_list_remove(&c->activate.link);
|
||||
}
|
||||
wl_list_remove(&c->associate.link);
|
||||
wl_list_remove(&c->configure.link);
|
||||
wl_list_remove(&c->dissociate.link);
|
||||
wl_list_remove(&c->set_hints.link);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
wl_list_remove(&c->commit.link);
|
||||
wl_list_remove(&c->map.link);
|
||||
wl_list_remove(&c->unmap.link);
|
||||
}
|
||||
free(c);
|
||||
}
|
||||
|
||||
|
@ -1177,8 +1150,8 @@ destroysessionlock(struct wl_listener *listener, void *data)
|
|||
void
|
||||
destroysessionmgr(struct wl_listener *listener, void *data)
|
||||
{
|
||||
wl_list_remove(&session_lock_create_lock.link);
|
||||
wl_list_remove(&session_lock_mgr_destroy.link);
|
||||
wl_list_remove(&lock_listener.link);
|
||||
wl_list_remove(&listener->link);
|
||||
}
|
||||
|
||||
Monitor *
|
||||
|
@ -1427,12 +1400,11 @@ keypress(struct wl_listener *listener, void *data)
|
|||
int handled = 0;
|
||||
uint32_t mods = wlr_keyboard_get_modifiers(kb->wlr_keyboard);
|
||||
|
||||
IDLE_NOTIFY_ACTIVITY;
|
||||
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
||||
|
||||
/* On _press_ if there is no active screen locker,
|
||||
* attempt to process a compositor keybinding. */
|
||||
if (!locked && !input_inhibit_mgr->active_inhibitor
|
||||
&& event->state == WL_KEYBOARD_KEY_STATE_PRESSED)
|
||||
if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED)
|
||||
for (i = 0; i < nsyms; i++)
|
||||
handled = keybinding(mods, syms[i]) || handled;
|
||||
|
||||
|
@ -1509,13 +1481,12 @@ locksession(struct wl_listener *listener, void *data)
|
|||
wlr_session_lock_v1_destroy(session_lock);
|
||||
return;
|
||||
}
|
||||
lock = ecalloc(1, sizeof(*lock));
|
||||
lock = session_lock->data = ecalloc(1, sizeof(*lock));
|
||||
focusclient(NULL, 0);
|
||||
|
||||
lock->scene = wlr_scene_tree_create(layers[LyrBlock]);
|
||||
cur_lock = lock->lock = session_lock;
|
||||
locked = 1;
|
||||
session_lock->data = lock;
|
||||
|
||||
LISTEN(&session_lock->events.new_surface, &lock->new_surface, createlocksurface);
|
||||
LISTEN(&session_lock->events.destroy, &lock->destroy, destroysessionlock);
|
||||
|
@ -1540,17 +1511,11 @@ mapnotify(struct wl_listener *listener, void *data)
|
|||
int i;
|
||||
|
||||
/* Create scene tree for this client and its border */
|
||||
c->scene = wlr_scene_tree_create(layers[LyrTile]);
|
||||
c->scene = client_surface(c)->data = wlr_scene_tree_create(layers[LyrTile]);
|
||||
wlr_scene_node_set_enabled(&c->scene->node, c->type != XDGShell);
|
||||
c->scene_surface = c->type == XDGShell
|
||||
? wlr_scene_xdg_surface_create(c->scene, c->surface.xdg)
|
||||
: wlr_scene_subsurface_tree_create(c->scene, client_surface(c));
|
||||
if (client_surface(c)) {
|
||||
client_surface(c)->data = c->scene;
|
||||
/* Ideally we should do this in createnotify{,x11} but at that moment
|
||||
* wlr_xwayland_surface doesn't have wlr_surface yet. */
|
||||
LISTEN(&client_surface(c)->events.commit, &c->commit, commitnotify);
|
||||
}
|
||||
c->scene->node.data = c->scene_surface->node.data = c;
|
||||
|
||||
/* Handle unmanaged clients first so we can return prior create borders */
|
||||
|
@ -1610,9 +1575,14 @@ maximizenotify(struct wl_listener *listener, void *data)
|
|||
* typically because the user clicked on the maximize button on
|
||||
* client-side decorations. dwl doesn't support maximization, but
|
||||
* to conform to xdg-shell protocol we still must send a configure.
|
||||
* Since xdg-shell protocol v5 we should ignore request of unsupported
|
||||
* capabilities, just schedule a empty configure when the client uses <5
|
||||
* protocol version
|
||||
* wlr_xdg_surface_schedule_configure() is used to send an empty reply. */
|
||||
Client *c = wl_container_of(listener, c, maximize);
|
||||
wlr_xdg_surface_schedule_configure(c->surface.xdg);
|
||||
if (wl_resource_get_version(c->surface.xdg->resource)
|
||||
< XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION)
|
||||
wlr_xdg_surface_schedule_configure(c->surface.xdg);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1658,7 +1628,7 @@ motionnotify(uint32_t time)
|
|||
|
||||
/* time is 0 in internal calls meant to restore pointer focus. */
|
||||
if (time) {
|
||||
IDLE_NOTIFY_ACTIVITY;
|
||||
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
||||
|
||||
/* Update selmon (even while dragging a window) */
|
||||
if (sloppyfocus)
|
||||
|
@ -1696,8 +1666,8 @@ motionnotify(uint32_t time)
|
|||
/* 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
|
||||
* off of a client or over its border. */
|
||||
if (!surface && !seat->drag && (!cursor_image || strcmp(cursor_image, "left_ptr")))
|
||||
wlr_xcursor_manager_set_cursor_image(cursor_mgr, (cursor_image = "left_ptr"), cursor);
|
||||
if (!surface && !seat->drag)
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
|
||||
|
||||
pointerfocus(c, surface, sx, sy, time);
|
||||
}
|
||||
|
@ -1732,7 +1702,7 @@ moveresize(const Arg *arg)
|
|||
case CurMove:
|
||||
grabcx = cursor->x - grabc->geom.x;
|
||||
grabcy = cursor->y - grabc->geom.y;
|
||||
wlr_xcursor_manager_set_cursor_image(cursor_mgr, (cursor_image = "fleur"), cursor);
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur");
|
||||
break;
|
||||
case CurResize:
|
||||
/* Doesn't work for X11 output - the next absolute motion event
|
||||
|
@ -1740,8 +1710,7 @@ moveresize(const Arg *arg)
|
|||
wlr_cursor_warp_closest(cursor, NULL,
|
||||
grabc->geom.x + grabc->geom.width,
|
||||
grabc->geom.y + grabc->geom.height);
|
||||
wlr_xcursor_manager_set_cursor_image(cursor_mgr,
|
||||
(cursor_image = "bottom_right_corner"), cursor);
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1783,7 +1752,7 @@ outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test)
|
|||
/* Don't move monitors if position wouldn't change, this to avoid
|
||||
* wlroots marking the output as manually configured */
|
||||
if (m->m.x != config_head->state.x || m->m.y != config_head->state.y)
|
||||
wlr_output_layout_move(output_layout, wlr_output,
|
||||
wlr_output_layout_add(output_layout, wlr_output,
|
||||
config_head->state.x, config_head->state.y);
|
||||
wlr_output_set_transform(wlr_output, config_head->state.transform);
|
||||
wlr_output_set_scale(wlr_output, config_head->state.scale);
|
||||
|
@ -1842,6 +1811,7 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
|
|||
* wlroots makes this a no-op if surface is already focused */
|
||||
wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
|
||||
wlr_seat_pointer_notify_motion(seat, time, sx, sy);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1898,6 +1868,8 @@ rendermon(struct wl_listener *listener, void *data)
|
|||
* generally at the output's refresh rate (e.g. 60Hz). */
|
||||
Monitor *m = wl_container_of(listener, m, frame);
|
||||
Client *c;
|
||||
struct wlr_output_state pending = {0};
|
||||
struct wlr_gamma_control_v1 *gamma_control;
|
||||
struct timespec now;
|
||||
|
||||
/* Render if no XDG clients have an outstanding resize and are visible on
|
||||
|
@ -1905,12 +1877,38 @@ rendermon(struct wl_listener *listener, void *data)
|
|||
wl_list_for_each(c, &clients, link)
|
||||
if (c->resize && !c->isfloating && client_is_rendered_on_mon(c, m) && !client_is_stopped(c))
|
||||
goto skip;
|
||||
wlr_scene_output_commit(m->scene_output);
|
||||
|
||||
/*
|
||||
* HACK: The "correct" way to set the gamma is to commit it together with
|
||||
* the rest of the state in one go, but to do that we would need to rewrite
|
||||
* wlr_scene_output_commit() in order to add the gamma to the pending
|
||||
* state before committing, instead try to commit the gamma in one frame,
|
||||
* and commit the rest of the state in the next one (or in the same frame if
|
||||
* the gamma can not be committed).
|
||||
*/
|
||||
if (m->gamma_lut_changed) {
|
||||
gamma_control = wlr_gamma_control_manager_v1_get_control(gamma_control_mgr, m->wlr_output);
|
||||
m->gamma_lut_changed = 0;
|
||||
|
||||
if (!wlr_gamma_control_v1_apply(gamma_control, &pending))
|
||||
goto commit;
|
||||
|
||||
if (!wlr_output_test_state(m->wlr_output, &pending)) {
|
||||
wlr_gamma_control_v1_send_failed_and_destroy(gamma_control);
|
||||
goto commit;
|
||||
}
|
||||
wlr_output_commit_state(m->wlr_output, &pending);
|
||||
wlr_output_schedule_frame(m->wlr_output);
|
||||
} else {
|
||||
commit:
|
||||
wlr_scene_output_commit(m->scene_output, NULL);
|
||||
}
|
||||
|
||||
skip:
|
||||
/* Let clients know a frame has been rendered */
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
wlr_scene_output_send_frame_done(m->scene_output, &now);
|
||||
wlr_output_state_finish(&pending);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1925,10 +1923,19 @@ requeststartdrag(struct wl_listener *listener, void *data)
|
|||
wlr_data_source_destroy(event->drag->source);
|
||||
}
|
||||
|
||||
void
|
||||
requestmonstate(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct wlr_output_event_request_state *event = data;
|
||||
wlr_output_commit_state(event->output, event->state);
|
||||
updatemons(NULL, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
resize(Client *c, struct wlr_box geo, int interact)
|
||||
{
|
||||
struct wlr_box *bbox = interact ? &sgeom : &c->mon->w;
|
||||
struct wlr_box clip;
|
||||
client_set_bounds(c, geo.width, geo.height);
|
||||
c->geom = geo;
|
||||
applybounds(c, bbox);
|
||||
|
@ -1947,6 +1954,8 @@ resize(Client *c, struct wlr_box geo, int interact)
|
|||
/* this is a no-op if size hasn't changed */
|
||||
c->resize = client_set_size(c, c->geom.width - 2 * c->bw,
|
||||
c->geom.height - 2 * c->bw);
|
||||
client_get_clip(c, &clip);
|
||||
wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1992,7 +2001,7 @@ run(char *startup_cmd)
|
|||
* initialized, as the image/coordinates are not transformed for the
|
||||
* monitor when displayed here */
|
||||
wlr_cursor_warp_closest(cursor, NULL, cursor->x, cursor->y);
|
||||
wlr_xcursor_manager_set_cursor_image(cursor_mgr, cursor_image, cursor);
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
|
||||
|
||||
/* Run the Wayland event loop. This does not return until you exit the
|
||||
* compositor. Starting the backend rigged up all of the necessary event
|
||||
|
@ -2011,7 +2020,6 @@ setcursor(struct wl_listener *listener, void *data)
|
|||
* event, which will result in the client requesting set the cursor surface */
|
||||
if (cursor_mode != CurNormal && cursor_mode != CurPressed)
|
||||
return;
|
||||
cursor_image = NULL;
|
||||
/* This can be sent by any client, so we check to make sure this one is
|
||||
* actually has pointer focus first. If so, we can tell the cursor to
|
||||
* use the provided surface as the cursor image. It will set the
|
||||
|
@ -2022,6 +2030,20 @@ setcursor(struct wl_listener *listener, void *data)
|
|||
event->hotspot_x, event->hotspot_y);
|
||||
}
|
||||
|
||||
void
|
||||
setcursorshape(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data;
|
||||
if (cursor_mode != CurNormal && cursor_mode != CurPressed)
|
||||
return;
|
||||
/* This can be sent by any client, so we check to make sure this one is
|
||||
* actually has pointer focus first. If so, we can tell the cursor to
|
||||
* use the provided cursor shape. */
|
||||
if (event->seat_client == seat->pointer_state.focused_client)
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr,
|
||||
wlr_cursor_shape_v1_name(event->shape));
|
||||
}
|
||||
|
||||
void
|
||||
setfloating(Client *c, int floating)
|
||||
{
|
||||
|
@ -2057,6 +2079,15 @@ setfullscreen(Client *c, int fullscreen)
|
|||
printstatus();
|
||||
}
|
||||
|
||||
void
|
||||
setgamma(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct wlr_gamma_control_manager_v1_set_gamma_event *event = data;
|
||||
Monitor *m = event->output->data;
|
||||
m->gamma_lut_changed = 1;
|
||||
wlr_output_schedule_frame(m->wlr_output);
|
||||
}
|
||||
|
||||
void
|
||||
setlayout(const Arg *arg)
|
||||
{
|
||||
|
@ -2150,12 +2181,8 @@ setup(void)
|
|||
/* The backend is a wlroots feature which abstracts the underlying input and
|
||||
* output hardware. The autocreate option will choose the most suitable
|
||||
* backend based on the current environment, such as opening an X11 window
|
||||
* if an X11 server is running. The NULL argument here optionally allows you
|
||||
* to pass in a custom renderer if wlr_renderer doesn't meet your needs. The
|
||||
* backend uses the renderer, for example, to fall back to software cursors
|
||||
* if the backend does not support hardware cursors (some older GPUs
|
||||
* don't). */
|
||||
if (!(backend = wlr_backend_autocreate(dpy)))
|
||||
* if an X11 server is running. */
|
||||
if (!(backend = wlr_backend_autocreate(dpy, &session)))
|
||||
die("couldn't create backend");
|
||||
|
||||
/* Initialize the scene graph used to lay out windows */
|
||||
|
@ -2165,12 +2192,30 @@ setup(void)
|
|||
drag_icon = wlr_scene_tree_create(&scene->tree);
|
||||
wlr_scene_node_place_below(&drag_icon->node, &layers[LyrBlock]->node);
|
||||
|
||||
/* Create a renderer with the default implementation */
|
||||
/* Autocreates a renderer, either Pixman, GLES2 or Vulkan for us. The user
|
||||
* can also specify a renderer using the WLR_RENDERER env var.
|
||||
* The renderer is responsible for defining the various pixel formats it
|
||||
* supports for shared memory, this configures that for clients. */
|
||||
if (!(drw = wlr_renderer_autocreate(backend)))
|
||||
die("couldn't create renderer");
|
||||
wlr_renderer_init_wl_display(drw, dpy);
|
||||
|
||||
/* Create a default allocator */
|
||||
/* Create shm, drm and linux_dmabuf interfaces by ourselves.
|
||||
* The simplest way is call:
|
||||
* wlr_renderer_init_wl_display(drw);
|
||||
* but we need to create manually the linux_dmabuf interface to integrate it
|
||||
* with wlr_scene. */
|
||||
wlr_renderer_init_wl_shm(drw, dpy);
|
||||
|
||||
if (wlr_renderer_get_dmabuf_texture_formats(drw)) {
|
||||
wlr_drm_create(dpy, drw);
|
||||
wlr_scene_set_linux_dmabuf_v1(scene,
|
||||
wlr_linux_dmabuf_v1_create_with_renderer(dpy, 4, drw));
|
||||
}
|
||||
|
||||
/* Autocreates an allocator for us.
|
||||
* The allocator is the bridge between the renderer and the backend. It
|
||||
* handles the buffer creation, allowing wlroots to render onto the
|
||||
* screen */
|
||||
if (!(alloc = wlr_allocator_autocreate(backend, drw)))
|
||||
die("couldn't create allocator");
|
||||
|
||||
|
@ -2180,33 +2225,36 @@ setup(void)
|
|||
* 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,
|
||||
* see the setsel() function. */
|
||||
compositor = wlr_compositor_create(dpy, drw);
|
||||
compositor = wlr_compositor_create(dpy, 6, drw);
|
||||
wlr_subcompositor_create(dpy);
|
||||
wlr_data_device_manager_create(dpy);
|
||||
wlr_export_dmabuf_manager_v1_create(dpy);
|
||||
wlr_screencopy_manager_v1_create(dpy);
|
||||
wlr_data_control_manager_v1_create(dpy);
|
||||
wlr_data_device_manager_create(dpy);
|
||||
wlr_gamma_control_manager_v1_create(dpy);
|
||||
wlr_primary_selection_v1_device_manager_create(dpy);
|
||||
wlr_viewporter_create(dpy);
|
||||
wlr_single_pixel_buffer_manager_v1_create(dpy);
|
||||
wlr_subcompositor_create(dpy);
|
||||
wlr_fractional_scale_manager_v1_create(dpy, 1);
|
||||
|
||||
/* Initializes the interface used to implement urgency hints */
|
||||
activation = wlr_xdg_activation_v1_create(dpy);
|
||||
wl_signal_add(&activation->events.request_activate, &request_activate);
|
||||
LISTEN_STATIC(&activation->events.request_activate, urgent);
|
||||
|
||||
gamma_control_mgr = wlr_gamma_control_manager_v1_create(dpy);
|
||||
LISTEN_STATIC(&gamma_control_mgr->events.set_gamma, setgamma);
|
||||
|
||||
/* Creates an output layout, which a wlroots utility for working with an
|
||||
* arrangement of screens in a physical layout. */
|
||||
output_layout = wlr_output_layout_create();
|
||||
wl_signal_add(&output_layout->events.change, &layout_change);
|
||||
LISTEN_STATIC(&output_layout->events.change, updatemons);
|
||||
wlr_xdg_output_manager_v1_create(dpy, output_layout);
|
||||
|
||||
/* Configure a listener to be notified when new outputs are available on the
|
||||
* backend. */
|
||||
wl_list_init(&mons);
|
||||
wl_signal_add(&backend->events.new_output, &new_output);
|
||||
LISTEN_STATIC(&backend->events.new_output, createmon);
|
||||
|
||||
/* Set up our client lists and the xdg-shell. The xdg-shell is a
|
||||
/* Set up our client lists, the xdg-shell and the layer-shell. The xdg-shell is a
|
||||
* Wayland protocol which is used for application windows. For more
|
||||
* detail on shells, refer to the article:
|
||||
*
|
||||
|
@ -2215,22 +2263,20 @@ setup(void)
|
|||
wl_list_init(&clients);
|
||||
wl_list_init(&fstack);
|
||||
|
||||
idle = wlr_idle_create(dpy);
|
||||
xdg_shell = wlr_xdg_shell_create(dpy, 6);
|
||||
LISTEN_STATIC(&xdg_shell->events.new_surface, createnotify);
|
||||
|
||||
layer_shell = wlr_layer_shell_v1_create(dpy, 3);
|
||||
LISTEN_STATIC(&layer_shell->events.new_surface, createlayersurface);
|
||||
|
||||
idle_notifier = wlr_idle_notifier_v1_create(dpy);
|
||||
|
||||
idle_inhibit_mgr = wlr_idle_inhibit_v1_create(dpy);
|
||||
wl_signal_add(&idle_inhibit_mgr->events.new_inhibitor, &idle_inhibitor_create);
|
||||
LISTEN_STATIC(&idle_inhibit_mgr->events.new_inhibitor, createidleinhibitor);
|
||||
|
||||
layer_shell = wlr_layer_shell_v1_create(dpy);
|
||||
wl_signal_add(&layer_shell->events.new_surface, &new_layer_shell_surface);
|
||||
|
||||
xdg_shell = wlr_xdg_shell_create(dpy, 4);
|
||||
wl_signal_add(&xdg_shell->events.new_surface, &new_xdg_surface);
|
||||
|
||||
input_inhibit_mgr = wlr_input_inhibit_manager_create(dpy);
|
||||
session_lock_mgr = wlr_session_lock_manager_v1_create(dpy);
|
||||
wl_signal_add(&session_lock_mgr->events.new_lock, &session_lock_create_lock);
|
||||
wl_signal_add(&session_lock_mgr->events.destroy, &session_lock_mgr_destroy);
|
||||
wl_signal_add(&session_lock_mgr->events.new_lock, &lock_listener);
|
||||
LISTEN_STATIC(&session_lock_mgr->events.destroy, destroysessionmgr);
|
||||
locked_bg = wlr_scene_rect_create(layers[LyrBlock], sgeom.width, sgeom.height,
|
||||
(float [4]){0.1, 0.1, 0.1, 1.0});
|
||||
wlr_scene_node_set_enabled(&locked_bg->node, 0);
|
||||
|
@ -2240,7 +2286,7 @@ setup(void)
|
|||
wlr_server_decoration_manager_create(dpy),
|
||||
WLR_SERVER_DECORATION_MANAGER_MODE_SERVER);
|
||||
xdg_decoration_mgr = wlr_xdg_decoration_manager_v1_create(dpy);
|
||||
wl_signal_add(&xdg_decoration_mgr->events.new_toplevel_decoration, &new_xdg_decoration);
|
||||
LISTEN_STATIC(&xdg_decoration_mgr->events.new_toplevel_decoration, createdecoration);
|
||||
|
||||
/*
|
||||
* Creates a cursor, which is a wlroots utility for tracking the cursor
|
||||
|
@ -2261,18 +2307,19 @@ setup(void)
|
|||
* when the pointer moves. However, we can attach input devices to it, and
|
||||
* it will generate aggregate events for all of them. In these events, we
|
||||
* can choose how we want to process them, forwarding them to clients and
|
||||
* moving the cursor around. More detail on this process is described in my
|
||||
* input handling blog post:
|
||||
*
|
||||
* moving the cursor around. More detail on this process is described in
|
||||
* https://drewdevault.com/2018/07/17/Input-handling-in-wlroots.html
|
||||
*
|
||||
* And more comments are sprinkled throughout the notify functions above.
|
||||
*/
|
||||
wl_signal_add(&cursor->events.motion, &cursor_motion);
|
||||
wl_signal_add(&cursor->events.motion_absolute, &cursor_motion_absolute);
|
||||
wl_signal_add(&cursor->events.button, &cursor_button);
|
||||
wl_signal_add(&cursor->events.axis, &cursor_axis);
|
||||
wl_signal_add(&cursor->events.frame, &cursor_frame);
|
||||
LISTEN_STATIC(&cursor->events.motion, motionrelative);
|
||||
LISTEN_STATIC(&cursor->events.motion_absolute, motionabsolute);
|
||||
LISTEN_STATIC(&cursor->events.button, buttonpress);
|
||||
LISTEN_STATIC(&cursor->events.axis, axisnotify);
|
||||
LISTEN_STATIC(&cursor->events.frame, cursorframe);
|
||||
|
||||
cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1);
|
||||
LISTEN_STATIC(&cursor_shape_mgr->events.request_set_shape, setcursorshape);
|
||||
|
||||
/*
|
||||
* Configures a seat, which is a single "seat" at which a user sits and
|
||||
|
@ -2281,20 +2328,19 @@ setup(void)
|
|||
* let us know when new input devices are available on the backend.
|
||||
*/
|
||||
wl_list_init(&keyboards);
|
||||
wl_signal_add(&backend->events.new_input, &new_input);
|
||||
LISTEN_STATIC(&backend->events.new_input, inputdevice);
|
||||
virtual_keyboard_mgr = wlr_virtual_keyboard_manager_v1_create(dpy);
|
||||
wl_signal_add(&virtual_keyboard_mgr->events.new_virtual_keyboard,
|
||||
&new_virtual_keyboard);
|
||||
LISTEN_STATIC(&virtual_keyboard_mgr->events.new_virtual_keyboard, virtualkeyboard);
|
||||
seat = wlr_seat_create(dpy, "seat0");
|
||||
wl_signal_add(&seat->events.request_set_cursor, &request_cursor);
|
||||
wl_signal_add(&seat->events.request_set_selection, &request_set_sel);
|
||||
wl_signal_add(&seat->events.request_set_primary_selection, &request_set_psel);
|
||||
wl_signal_add(&seat->events.request_start_drag, &request_start_drag);
|
||||
wl_signal_add(&seat->events.start_drag, &start_drag);
|
||||
LISTEN_STATIC(&seat->events.request_set_cursor, setcursor);
|
||||
LISTEN_STATIC(&seat->events.request_set_selection, setsel);
|
||||
LISTEN_STATIC(&seat->events.request_set_primary_selection, setpsel);
|
||||
LISTEN_STATIC(&seat->events.request_start_drag, requeststartdrag);
|
||||
LISTEN_STATIC(&seat->events.start_drag, startdrag);
|
||||
|
||||
output_mgr = wlr_output_manager_v1_create(dpy);
|
||||
wl_signal_add(&output_mgr->events.apply, &output_mgr_apply);
|
||||
wl_signal_add(&output_mgr->events.test, &output_mgr_test);
|
||||
LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply);
|
||||
LISTEN_STATIC(&output_mgr->events.test, outputmgrtest);
|
||||
|
||||
wlr_scene_set_presentation(scene, wlr_presentation_create(dpy, backend));
|
||||
|
||||
|
@ -2305,8 +2351,8 @@ setup(void)
|
|||
*/
|
||||
xwayland = wlr_xwayland_create(dpy, compositor, 1);
|
||||
if (xwayland) {
|
||||
wl_signal_add(&xwayland->events.ready, &xwayland_ready);
|
||||
wl_signal_add(&xwayland->events.new_surface, &new_xwayland_surface);
|
||||
LISTEN_STATIC(&xwayland->events.ready, xwaylandready);
|
||||
LISTEN_STATIC(&xwayland->events.new_surface, createnotifyx11);
|
||||
|
||||
setenv("DISPLAY", xwayland->display_name, 1);
|
||||
} else {
|
||||
|
@ -2333,8 +2379,8 @@ startdrag(struct wl_listener *listener, void *data)
|
|||
if (!drag->icon)
|
||||
return;
|
||||
|
||||
drag->icon->data = &wlr_scene_subsurface_tree_create(drag_icon, drag->icon->surface)->node;
|
||||
wl_signal_add(&drag->icon->events.destroy, &drag_icon_destroy);
|
||||
drag->icon->data = &wlr_scene_drag_icon_create(drag_icon, drag->icon)->node;
|
||||
LISTEN_STATIC(&drag->icon->events.destroy, destroydragicon);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2485,7 +2531,6 @@ unmapnotify(struct wl_listener *listener, void *data)
|
|||
wl_list_remove(&c->flink);
|
||||
}
|
||||
|
||||
wl_list_remove(&c->commit.link);
|
||||
wlr_scene_node_destroy(&c->scene->node);
|
||||
printstatus();
|
||||
motionnotify(0);
|
||||
|
@ -2524,7 +2569,6 @@ updatemons(struct wl_listener *listener, void *data)
|
|||
if (m->wlr_output->enabled
|
||||
&& !wlr_output_layout_get(output_layout, m->wlr_output))
|
||||
wlr_output_layout_add_auto(output_layout, m->wlr_output);
|
||||
|
||||
/* Now that we update the output layout we can get its box */
|
||||
wlr_output_layout_get_box(output_layout, NULL, &sgeom);
|
||||
|
||||
|
@ -2538,8 +2582,8 @@ updatemons(struct wl_listener *listener, void *data)
|
|||
config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output);
|
||||
|
||||
/* Get the effective monitor geometry to use for surfaces */
|
||||
wlr_output_layout_get_box(output_layout, m->wlr_output, &(m->m));
|
||||
wlr_output_layout_get_box(output_layout, m->wlr_output, &(m->w));
|
||||
wlr_output_layout_get_box(output_layout, m->wlr_output, &m->m);
|
||||
m->w = m->m;
|
||||
wlr_scene_output_set_position(m->scene_output, m->m.x, m->m.y);
|
||||
|
||||
wlr_scene_node_set_position(&m->fullscreen_bg->node, m->m.x, m->m.y);
|
||||
|
@ -2556,7 +2600,11 @@ updatemons(struct wl_listener *listener, void *data)
|
|||
arrangelayers(m);
|
||||
/* Don't move clients to the left output when plugging monitors */
|
||||
arrange(m);
|
||||
/* make sure fullscreen clients have the right size */
|
||||
if ((c = focustop(m)) && c->isfullscreen)
|
||||
resize(c, m->m, 0);
|
||||
|
||||
m->gamma_lut_changed = 1;
|
||||
config_head->state.enabled = 1;
|
||||
config_head->state.mode = m->wlr_output->current_mode;
|
||||
config_head->state.x = m->m.x;
|
||||
|
@ -2565,7 +2613,7 @@ updatemons(struct wl_listener *listener, void *data)
|
|||
|
||||
if (selmon && selmon->wlr_output->enabled) {
|
||||
wl_list_for_each(c, &clients, link)
|
||||
if (!c->mon && client_is_mapped(c))
|
||||
if (!c->mon && client_surface(c)->mapped)
|
||||
setmon(c, selmon, c->tags);
|
||||
focusclient(focustop(selmon), 1);
|
||||
if (selmon->lock_surface) {
|
||||
|
@ -2575,6 +2623,13 @@ updatemons(struct wl_listener *listener, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
/* FIXME: figure out why the cursor image is at 0,0 after turning all
|
||||
* the monitors on.
|
||||
* Move the cursor image where it used to be. It does not generate a
|
||||
* wl_pointer.motion event for the clients, it's only the image what it's
|
||||
* at the wrong position after all. */
|
||||
wlr_cursor_move(cursor, NULL, 0, 0);
|
||||
|
||||
wlr_output_manager_v1_set_configuration(output_mgr, config);
|
||||
}
|
||||
|
||||
|
@ -2595,7 +2650,7 @@ urgent(struct wl_listener *listener, void *data)
|
|||
if (!c || c == focustop(selmon))
|
||||
return;
|
||||
|
||||
if (client_is_mapped(c))
|
||||
if (client_surface(c)->mapped)
|
||||
client_set_border_color(c, urgentcolor);
|
||||
c->isurgent = 1;
|
||||
printstatus();
|
||||
|
@ -2643,7 +2698,7 @@ xytonode(double x, double y, struct wlr_surface **psurface,
|
|||
continue;
|
||||
|
||||
if (node->type == WLR_SCENE_NODE_BUFFER)
|
||||
surface = wlr_scene_surface_from_buffer(
|
||||
surface = wlr_scene_surface_try_from_buffer(
|
||||
wlr_scene_buffer_from_node(node))->surface;
|
||||
/* Walk the tree to find a node that knows the client */
|
||||
for (pnode = node; pnode && !c; pnode = &pnode->parent->node)
|
||||
|
@ -2702,6 +2757,15 @@ activatex11(struct wl_listener *listener, void *data)
|
|||
wlr_xwayland_surface_activate(c->surface.xwayland, 1);
|
||||
}
|
||||
|
||||
void
|
||||
associatex11(struct wl_listener *listener, void *data)
|
||||
{
|
||||
Client *c = wl_container_of(listener, c, associate);
|
||||
|
||||
LISTEN(&client_surface(c)->events.map, &c->map, mapnotify);
|
||||
LISTEN(&client_surface(c)->events.unmap, &c->unmap, unmapnotify);
|
||||
}
|
||||
|
||||
void
|
||||
configurex11(struct wl_listener *listener, void *data)
|
||||
{
|
||||
|
@ -2729,8 +2793,8 @@ createnotifyx11(struct wl_listener *listener, void *data)
|
|||
c->bw = borderpx;
|
||||
|
||||
/* Listen to the various events it can emit */
|
||||
LISTEN(&xsurface->events.map, &c->map, mapnotify);
|
||||
LISTEN(&xsurface->events.unmap, &c->unmap, unmapnotify);
|
||||
LISTEN(&xsurface->events.associate, &c->associate, associatex11);
|
||||
LISTEN(&xsurface->events.dissociate, &c->dissociate, dissociatex11);
|
||||
LISTEN(&xsurface->events.request_activate, &c->activate, activatex11);
|
||||
LISTEN(&xsurface->events.request_configure, &c->configure, configurex11);
|
||||
LISTEN(&xsurface->events.set_hints, &c->set_hints, sethints);
|
||||
|
@ -2739,6 +2803,14 @@ createnotifyx11(struct wl_listener *listener, void *data)
|
|||
LISTEN(&xsurface->events.request_fullscreen, &c->fullscreen, fullscreennotify);
|
||||
}
|
||||
|
||||
void
|
||||
dissociatex11(struct wl_listener *listener, void *data)
|
||||
{
|
||||
Client *c = wl_container_of(listener, c, dissociate);
|
||||
wl_list_remove(&c->map.link);
|
||||
wl_list_remove(&c->unmap.link);
|
||||
}
|
||||
|
||||
xcb_atom_t
|
||||
getatom(xcb_connection_t *xc, const char *name)
|
||||
{
|
||||
|
@ -2756,12 +2828,13 @@ void
|
|||
sethints(struct wl_listener *listener, void *data)
|
||||
{
|
||||
Client *c = wl_container_of(listener, c, set_hints);
|
||||
struct wlr_surface *surface = client_surface(c);
|
||||
if (c == focustop(selmon))
|
||||
return;
|
||||
|
||||
c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints);
|
||||
|
||||
if (c->isurgent && client_is_mapped(c))
|
||||
if (c->isurgent && surface && surface->mapped)
|
||||
client_set_border_color(c, urgentcolor);
|
||||
|
||||
printstatus();
|
||||
|
@ -2789,7 +2862,7 @@ xwaylandready(struct wl_listener *listener, void *data)
|
|||
wlr_xwayland_set_seat(xwayland, seat);
|
||||
|
||||
/* Set the default XWayland cursor to match the rest of dwl. */
|
||||
if ((xcursor = wlr_xcursor_manager_get_xcursor(cursor_mgr, "left_ptr", 1)))
|
||||
if ((xcursor = wlr_xcursor_manager_get_xcursor(cursor_mgr, "default", 1)))
|
||||
wlr_xwayland_set_cursor(xwayland,
|
||||
xcursor->images[0]->buffer, xcursor->images[0]->width * 4,
|
||||
xcursor->images[0]->width, xcursor->images[0]->height,
|
||||
|
|
Loading…
Reference in a new issue