47 Commits

Author SHA1 Message Date
Devin J. Pohly 7c3c5ffcc2 Merge branch 'main' into push 2023-07-03 22:06:26 -05:00
Devin J. Pohly 81c8ebf677 Merge branch 'push' of github:Abanoub8/dwl into push 2023-07-03 22:05:05 -05:00
Devin J. Pohly a89872f02e Merge branch 'push' of github:djpohly/dwl into push 2023-07-03 22:04:38 -05:00
Devin J. Pohly eda0613cc4 Separate drag icon from layers array and Lyr enum
If we treat the drag icon as distinct from other layers (it doesn't have
contents that are interactive, focusable, etc.), then we can iterate
over layers meaningfully with a simple for loop.

ΔSLOC: -8
2023-06-25 17:44:00 -05:00
Abanoub a41d817979 Use focustop(selmon) instead of selclient() in the push patch 2023-06-21 18:11:09 +03:00
Devin J. Pohly 68a17f962e Don't bother with ignoring SIGCHLD
It added complexity, especially with the differences in behavior between
handled and ignored signals across an exec().
2023-06-16 00:24:17 -06:00
Devin J. Pohly 9c592da01f Reset ignored signal handler in spawn() as well 2023-06-16 00:24:17 -06:00
Devin J. Pohly df11b7a786 fix startup_cmd SIGCHLD handler
Ignored handlers are not reset by exec() calls
2023-06-16 00:24:17 -06:00
A Frederick Christensen 5215712cab Stray whitespace fixes 2023-06-07 17:47:36 -06:00
Leonardo Hernández Hernández 9b9b79b35e activate lock surface in updatemons
Fixes an issue when swaylock does not receive input after turn off and then
turn on the outputs
2023-06-02 21:56:09 -06:00
Leonardo Hernández Hernández 3d98907b98 send frame done even if output commit fails
Bug: https://github.com/djpohly/dwl/issues/420
Fixes: https://github.com/djpohly/dwl/issues/353
2023-06-02 21:51:47 -06:00
Nikita Ivanov f8884ffc2b Set XCURSOR_SIZE 2023-06-01 19:11:33 -06:00
Leonardo Hernández Hernández a5e45924ed remove note about contact me for patch issues
I am no longer able to spend much time developing dwl let alone maintaining
other's patches :)
2023-05-28 00:20:20 -06:00
Leonardo Hernández Hernández 72adab621f destroy old client popups when focusing another client
Closes: https://github.com/djpohly/dwl/issues/408
2023-05-27 23:29:05 -06:00
Micah Gorrell 0729f18dce Prevent using a wlr_layer_surface after destroying it, due to no available outputs 2023-05-25 21:21:56 -06:00
Leonardo Hernández Hernández 797e0c74b2 correctly check if a scene node is enabled
checking only wlr_scene_node.enabled may result in a false positive because it
does not consider if its ancestors are enabled as well.
2023-04-13 13:12:27 -06:00
Leonardo Hernández Hernández 3c760bcd4a remove unneeded check of m in arrange()
arrange must never be called with a NULL argument
2023-04-13 13:12:27 -06:00
Ben Collerson da77e34ee5 Use uint32_t for ui Arg 2023-04-09 17:09:35 -06:00
Leonardo Hernández Hernández 20f61a59af use fixed-size type for client tags
while the size of `int` in most compilers is 32-bits, the size of int and all
other integer types are implementation defined, so make sure we can use up to
32-bits
2023-04-08 11:29:18 -06:00
Ben Collerson 9d68554c59 remove tag labels from dwl
Tag labels are not used in dwl. Only the number of tags is important.
Tag labels should be defined for each tag in whatever status bar is
used.
2023-04-08 11:27:49 -06:00
Yves Zoundi bbdf2a913b display clients count in monocle symbol
- Replicate missing functionality from dwl to display the client count in monocle mode
  - Add ltsymbol field to Monitor struct
  - Display client count in monocle mode when greater than zero
- Tested with somebar and dwlb
2023-03-16 00:02:14 -06:00
Palanix 21930621ee Remove rootcolor 2023-03-13 09:40:40 -06:00
A Frederick Christensen 6722a89532 Missing apostrophe 2023-03-07 22:17:05 -06:00
gan-of-culture e4921fad28 add missing comma in "MonitorRule"
add a missing comma for the example
2023-02-25 15:59:23 -06:00
godalming123 c69a2bec3f Fix spacing and replace it with tabs 2023-02-18 18:47:44 -06:00
godalming123 737688a6b1 fix spelling 2023-02-18 18:47:44 -06:00
pino-desktop f8373ccf25 Fixed 'unused variable' compiler warning. 2023-02-13 13:43:28 -06:00
Ben Collerson 7f9a212476 Add appid field to printstatus() output
Adds an appid field to printstatus which can be used to monitor the
currently active application.
2023-02-13 13:30:27 -06:00
Leonardo Hernández Hernández ab8334bd8a implement repeatable keybindings 2023-02-13 13:18:43 -06:00
Leonardo Hernández Hernández 23ede80f74 allow configure x and y of outputs 2023-02-13 13:14:29 -06:00
Leonardo Hernández Hernández f7d6a34cd9 use sigaction(2) for signal handling
References: http://git.suckless.org/dwm/commit/712d6639ff8e863560328131bbb92b248dc9cde7.html
2023-01-30 23:26:32 -06:00
Leonardo Hernández Hernández 8653b27692 bump version to 0.4 2022-12-30 14:46:52 -06:00
Leonardo Hernández Hernández 932c1d45f2 remove --long from git-describe command 2022-12-30 14:46:34 -06:00
Leonardo Hernández Hernández dbe44e48c8 return early if selmon is not part of the output layout in dirtomon()
instead of checking twice
2022-12-30 14:31:56 -06:00
Leonardo Hernández Hernández 0b2c33248c simplify check in urgent()
we only care if it returned a client or not
2022-12-30 14:29:19 -06:00
Leonardo Hernández Hernández 56114f700f arrange monitor after updating fullscreen background and lock surfaces 2022-12-30 14:26:53 -06:00
Leonardo Hernández Hernández 71c7e4e1e5 also update locked_bg node position in updatemons() 2022-12-30 14:25:19 -06:00
Leonardo Hernández Hernández 72d29f1654 add blank lines to make updatemons() more readable 2022-12-30 14:21:46 -06:00
Leonardo Hernández Hernández e523c2b82b update comment about client_set_size() as no-op 2022-12-30 14:19:47 -06:00
Leonardo Hernández Hernández 6d0e3a5198 check if a client is resizing before checking if it's visible
It's not like it's noticeable, but theoretically this is faster
2022-12-30 14:15:21 -06:00
Leonardo Hernández Hernández 5347ed663d only mark pending resizes as completed checking the configure serial 2022-12-30 14:14:06 -06:00
Devin J. Pohly a4e4fd3d25 add missing header 2022-12-05 22:58:26 -06:00
Devin J. Pohly 0259e9a8ab port dwm "push" patch to dwl 2022-12-05 22:58:26 -06:00
Devin J. Pohly 04079a0946 Merge branch 'wlroots-next' into push 2021-04-26 07:34:59 -05:00
Devin J. Pohly daf5ee475f Merge branch 'main' into push 2021-03-10 15:37:57 -06:00
Devin J. Pohly 156a13d9f9 add missing header 2021-03-04 13:52:58 -06:00
Devin J. Pohly dcb7a4d910 port dwm "push" patch to dwl 2021-03-04 00:45:50 -06:00
7 changed files with 280 additions and 150 deletions
-5
View File
@@ -14,9 +14,4 @@ wlroots version:
<!-- <!--
Only report bugs that can be reproduced on the main line Only report bugs that can be reproduced on the main line
Report patch issues to their respective authors Report patch issues to their respective authors
If the patch author doesn't respond within a reasonable time, email me:
Leonardo Hernández Hernández <leohdz172@protonmail.com>
but note that I'm NOT making any promises
--> -->
+1 -1
View File
@@ -16,7 +16,7 @@ LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(LIBS)
all: dwl all: dwl
dwl: dwl.o util.o dwl: dwl.o util.o
$(CC) dwl.o util.o $(LDLIBS) $(LDFLAGS) $(DWLCFLAGS) -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 push.c config.mk config.h client.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h
util.o: util.c util.h util.o: util.c util.h
# wayland-scanner is a tool which generates C headers and rigging for Wayland # wayland-scanner is a tool which generates C headers and rigging for Wayland
+8 -9
View File
@@ -2,14 +2,13 @@
static const int sloppyfocus = 1; /* focus follows mouse */ static const int sloppyfocus = 1; /* focus follows mouse */
static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */
static const unsigned int borderpx = 1; /* border pixel of windows */ static const unsigned int borderpx = 1; /* border pixel of windows */
static const float rootcolor[] = {0.3, 0.3, 0.3, 1.0};
static const float bordercolor[] = {0.5, 0.5, 0.5, 1.0}; static const float bordercolor[] = {0.5, 0.5, 0.5, 1.0};
static const float focuscolor[] = {1.0, 0.0, 0.0, 1.0}; static const float focuscolor[] = {1.0, 0.0, 0.0, 1.0};
/* To conform the xdg-protocol, set the alpha to zero to restore the old behavior */ /* To conform the xdg-protocol, set the alpha to zero to restore the old behavior */
static const float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0}; static const float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0};
/* tagging */ /* tagging - tagcount must be no greater than 31 */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; static const int tagcount = 9;
static const Rule rules[] = { static const Rule rules[] = {
/* app_id title tags mask isfloating monitor */ /* app_id title tags mask isfloating monitor */
@@ -29,12 +28,12 @@ static const Layout layouts[] = {
/* monitors */ /* monitors */
static const MonitorRule monrules[] = { static const MonitorRule monrules[] = {
/* name mfact nmaster scale layout rotate/reflect */ /* name mfact nmaster scale layout rotate/reflect x y */
/* example of a HiDPI laptop monitor: /* example of a HiDPI laptop monitor:
{ "eDP-1", 0.5, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL }, { "eDP-1", 0.5, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 },
*/ */
/* defaults */ /* defaults */
{ NULL, 0.55, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL }, { NULL, 0.55, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 },
}; };
/* keyboard */ /* keyboard */
@@ -66,9 +65,9 @@ LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN
static const enum libinput_config_scroll_method scroll_method = LIBINPUT_CONFIG_SCROLL_2FG; static const enum libinput_config_scroll_method scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;
/* You can choose between: /* You can choose between:
LIBINPUT_CONFIG_CLICK_METHOD_NONE LIBINPUT_CONFIG_CLICK_METHOD_NONE
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER
*/ */
static const enum libinput_config_click_method click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; static const enum libinput_config_click_method click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
+2 -2
View File
@@ -1,5 +1,5 @@
_VERSION = 0.4-rc3 _VERSION = 0.4
VERSION = `git describe --long --tags --dirty 2>/dev/null || echo $(_VERSION)` VERSION = `git describe --tags --dirty 2>/dev/null || echo $(_VERSION)`
PKG_CONFIG = pkg-config PKG_CONFIG = pkg-config
+202 -133
View File
@@ -67,14 +67,14 @@
#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags])) #define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags]))
#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 ((1u << tagcount) - 1)
#define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) #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 IDLE_NOTIFY_ACTIVITY wlr_idle_notify_activity(idle, seat), wlr_idle_notifier_v1_notify_activity(idle_notifier, seat)
/* enums */ /* enums */
enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
enum { XDGShell, LayerShell, X11Managed, X11Unmanaged }; /* client types */ enum { XDGShell, LayerShell, X11Managed, X11Unmanaged }; /* client types */
enum { LyrBg, LyrBottom, LyrTop, LyrOverlay, LyrTile, LyrFloat, LyrFS, LyrDragIcon, LyrBlock, NUM_LAYERS }; /* scene layers */ enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrFS, LyrTop, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */
#ifdef XWAYLAND #ifdef XWAYLAND
enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar,
NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */
@@ -82,7 +82,7 @@ enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar,
typedef union { typedef union {
int i; int i;
unsigned int ui; uint32_t ui;
float f; float f;
const void *v; const void *v;
} Arg; } Arg;
@@ -98,7 +98,7 @@ typedef struct Monitor Monitor;
typedef struct { typedef struct {
/* Must keep these three elements in this order */ /* Must keep these three elements in this order */
unsigned int type; /* XDGShell or X11* */ unsigned int type; /* XDGShell or X11* */
struct wlr_box geom; /* layout-relative, includes border */ struct wlr_box geom; /* layout-relative, includes border */
Monitor *mon; Monitor *mon;
struct wlr_scene_tree *scene; struct wlr_scene_tree *scene;
struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ struct wlr_scene_rect *border[4]; /* top, bottom, left, right */
@@ -116,14 +116,14 @@ typedef struct {
struct wl_listener destroy; struct wl_listener destroy;
struct wl_listener set_title; struct wl_listener set_title;
struct wl_listener fullscreen; struct wl_listener fullscreen;
struct wlr_box prev; /* layout-relative, includes border */ struct wlr_box prev; /* layout-relative, includes border */
#ifdef XWAYLAND #ifdef XWAYLAND
struct wl_listener activate; struct wl_listener activate;
struct wl_listener configure; struct wl_listener configure;
struct wl_listener set_hints; struct wl_listener set_hints;
#endif #endif
unsigned int bw; unsigned int bw;
unsigned int tags; uint32_t tags;
int isfloating, isurgent, isfullscreen; int isfloating, isurgent, isfullscreen;
uint32_t resize; /* configure serial of a pending resize */ uint32_t resize; /* configure serial of a pending resize */
} Client; } Client;
@@ -139,6 +139,11 @@ typedef struct {
struct wl_list link; struct wl_list link;
struct wlr_keyboard *wlr_keyboard; struct wlr_keyboard *wlr_keyboard;
int nsyms;
const xkb_keysym_t *keysyms; /* invalid if nsyms == 0 */
uint32_t mods; /* invalid if nsyms == 0 */
struct wl_event_source *key_repeat_source;
struct wl_listener modifiers; struct wl_listener modifiers;
struct wl_listener key; struct wl_listener key;
struct wl_listener destroy; struct wl_listener destroy;
@@ -176,15 +181,16 @@ struct Monitor {
struct wl_listener destroy; struct wl_listener destroy;
struct wl_listener destroy_lock_surface; struct wl_listener destroy_lock_surface;
struct wlr_session_lock_surface_v1 *lock_surface; struct wlr_session_lock_surface_v1 *lock_surface;
struct wlr_box m; /* monitor area, layout-relative */ struct wlr_box m; /* monitor area, layout-relative */
struct wlr_box w; /* window area, layout-relative */ struct wlr_box w; /* window area, layout-relative */
struct wl_list layers[4]; /* LayerSurface::link */ struct wl_list layers[4]; /* LayerSurface::link */
const Layout *lt[2]; const Layout *lt[2];
unsigned int seltags; unsigned int seltags;
unsigned int sellt; unsigned int sellt;
unsigned int tagset[2]; uint32_t tagset[2];
double mfact; double mfact;
int nmaster; int nmaster;
char ltsymbol[16];
}; };
typedef struct { typedef struct {
@@ -194,12 +200,13 @@ typedef struct {
float scale; float scale;
const Layout *lt; const Layout *lt;
enum wl_output_transform rr; enum wl_output_transform rr;
int x, y;
} MonitorRule; } MonitorRule;
typedef struct { typedef struct {
const char *id; const char *id;
const char *title; const char *title;
unsigned int tags; uint32_t tags;
int isfloating; int isfloating;
int monitor; int monitor;
} Rule; } Rule;
@@ -258,6 +265,7 @@ static void inputdevice(struct wl_listener *listener, void *data);
static int keybinding(uint32_t mods, xkb_keysym_t sym); static int keybinding(uint32_t mods, xkb_keysym_t sym);
static void keypress(struct wl_listener *listener, void *data); static void keypress(struct wl_listener *listener, void *data);
static void keypressmod(struct wl_listener *listener, void *data); static void keypressmod(struct wl_listener *listener, void *data);
static int keyrepeat(void *data);
static void killclient(const Arg *arg); static void killclient(const Arg *arg);
static void locksession(struct wl_listener *listener, void *data); static void locksession(struct wl_listener *listener, void *data);
static void maplayersurfacenotify(struct wl_listener *listener, void *data); static void maplayersurfacenotify(struct wl_listener *listener, void *data);
@@ -285,10 +293,11 @@ static void setfloating(Client *c, int floating);
static void setfullscreen(Client *c, int fullscreen); static void setfullscreen(Client *c, int fullscreen);
static void setlayout(const Arg *arg); static void setlayout(const Arg *arg);
static void setmfact(const Arg *arg); static void setmfact(const Arg *arg);
static void setmon(Client *c, Monitor *m, unsigned int newtags); static void setmon(Client *c, Monitor *m, uint32_t newtags);
static void setpsel(struct wl_listener *listener, void *data); static void setpsel(struct wl_listener *listener, void *data);
static void setsel(struct wl_listener *listener, void *data); static void setsel(struct wl_listener *listener, void *data);
static void setup(void); static void setup(void);
static void sigchld(int unused);
static void spawn(const Arg *arg); static void spawn(const Arg *arg);
static void startdrag(struct wl_listener *listener, void *data); static void startdrag(struct wl_listener *listener, void *data);
static void tag(const Arg *arg); static void tag(const Arg *arg);
@@ -321,6 +330,8 @@ static struct wl_display *dpy;
static struct wlr_backend *backend; static struct wlr_backend *backend;
static struct wlr_scene *scene; static struct wlr_scene *scene;
static struct wlr_scene_tree *layers[NUM_LAYERS]; static struct wlr_scene_tree *layers[NUM_LAYERS];
/* Map from ZWLR_LAYER_SHELL_* constants to Lyr* enum */
static const int layermap[] = { LyrBg, LyrBottom, LyrTop, LyrOverlay };
static struct wlr_renderer *drw; static struct wlr_renderer *drw;
static struct wlr_allocator *alloc; static struct wlr_allocator *alloc;
static struct wlr_compositor *compositor; static struct wlr_compositor *compositor;
@@ -389,7 +400,6 @@ static void configurex11(struct wl_listener *listener, void *data);
static void createnotifyx11(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 Atom getatom(xcb_connection_t *xc, const char *name);
static void sethints(struct wl_listener *listener, void *data); static void sethints(struct wl_listener *listener, void *data);
static void sigchld(int unused);
static void xwaylandready(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 new_xwayland_surface = {.notify = createnotifyx11};
static struct wl_listener xwayland_ready = {.notify = xwaylandready}; static struct wl_listener xwayland_ready = {.notify = xwaylandready};
@@ -398,14 +408,13 @@ static Atom netatom[NetLast];
#endif #endif
/* configuration, allows nested code to access above variables */ /* configuration, allows nested code to access above variables */
#include "push.h"
#include "config.h" #include "config.h"
#include "push.c"
/* attempt to encapsulate suck into one file */ /* attempt to encapsulate suck into one file */
#include "client.h" #include "client.h"
/* compile-time check if all tags fit into an unsigned int bit array. */
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
/* function implementations */ /* function implementations */
void void
applybounds(Client *c, struct wlr_box *bbox) applybounds(Client *c, struct wlr_box *bbox)
@@ -416,8 +425,8 @@ applybounds(Client *c, struct wlr_box *bbox)
/* try to set size hints */ /* try to set size hints */
c->geom.width = MAX(min.width + (2 * (int)c->bw), c->geom.width); 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); c->geom.height = MAX(min.height + (2 * (int)c->bw), c->geom.height);
/* Some clients set them max size to INT_MAX, which does not violates /* Some clients set their max size to INT_MAX, which does not violate the
* the protocol but its innecesary, they can set them max size to zero. */ * 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 */ 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); 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 */ if (max.height > 0 && !(2 * c->bw > INT_MAX - max.height)) /* Checks for overflow */
@@ -439,7 +448,7 @@ applyrules(Client *c)
{ {
/* rule matching */ /* rule matching */
const char *appid, *title; const char *appid, *title;
unsigned int i, newtags = 0; uint32_t i, newtags = 0;
const Rule *r; const Rule *r;
Monitor *mon = selmon, *m; Monitor *mon = selmon, *m;
@@ -475,7 +484,9 @@ arrange(Monitor *m)
wlr_scene_node_set_enabled(&m->fullscreen_bg->node, wlr_scene_node_set_enabled(&m->fullscreen_bg->node,
(c = focustop(m)) && c->isfullscreen); (c = focustop(m)) && c->isfullscreen);
if (m && m->lt[m->sellt]->arrange) strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol));
if (m->lt[m->sellt]->arrange)
m->lt[m->sellt]->arrange(m); m->lt[m->sellt]->arrange(m);
motionnotify(0); motionnotify(0);
checkidleinhibitor(NULL); checkidleinhibitor(NULL);
@@ -624,13 +635,13 @@ chvt(const Arg *arg)
void void
checkidleinhibitor(struct wlr_surface *exclude) checkidleinhibitor(struct wlr_surface *exclude)
{ {
int inhibited = 0; int inhibited = 0, unused_lx, unused_ly;
struct wlr_idle_inhibitor_v1 *inhibitor; struct wlr_idle_inhibitor_v1 *inhibitor;
wl_list_for_each(inhibitor, &idle_inhibit_mgr->inhibitors, link) { wl_list_for_each(inhibitor, &idle_inhibit_mgr->inhibitors, link) {
struct wlr_surface *surface = wlr_surface_get_root_surface(inhibitor->surface); struct wlr_surface *surface = wlr_surface_get_root_surface(inhibitor->surface);
struct wlr_scene_tree *tree = surface->data; struct wlr_scene_tree *tree = surface->data;
if (exclude != surface && (bypass_surface_visibility || (!tree if (exclude != surface && (bypass_surface_visibility || (!tree
|| tree->node.enabled))) { || wlr_scene_node_coords(&tree->node, &unused_lx, &unused_ly)))) {
inhibited = 1; inhibited = 1;
break; break;
} }
@@ -666,6 +677,7 @@ cleanupkeyboard(struct wl_listener *listener, void *data)
{ {
Keyboard *kb = wl_container_of(listener, kb, destroy); Keyboard *kb = wl_container_of(listener, kb, destroy);
wl_event_source_remove(kb->key_repeat_source);
wl_list_remove(&kb->link); wl_list_remove(&kb->link);
wl_list_remove(&kb->modifiers.link); wl_list_remove(&kb->modifiers.link);
wl_list_remove(&kb->key.link); wl_list_remove(&kb->key.link);
@@ -728,17 +740,16 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data)
LayerSurface *layersurface = wl_container_of(listener, layersurface, surface_commit); LayerSurface *layersurface = wl_container_of(listener, layersurface, surface_commit);
struct wlr_layer_surface_v1 *wlr_layer_surface = layersurface->layer_surface; struct wlr_layer_surface_v1 *wlr_layer_surface = layersurface->layer_surface;
struct wlr_output *wlr_output = wlr_layer_surface->output; struct wlr_output *wlr_output = wlr_layer_surface->output;
struct wlr_scene_tree *layer = layers[layermap[wlr_layer_surface->current.layer]];
/* For some reason this layersurface have no monitor, this can be because /* For some reason this layersurface have no monitor, this can be because
* its monitor has just been destroyed */ * its monitor has just been destroyed */
if (!wlr_output || !(layersurface->mon = wlr_output->data)) if (!wlr_output || !(layersurface->mon = wlr_output->data))
return; return;
if (layers[wlr_layer_surface->current.layer] != layersurface->scene->node.parent) { if (layer != layersurface->scene->node.parent) {
wlr_scene_node_reparent(&layersurface->scene->node, wlr_scene_node_reparent(&layersurface->scene->node, layer);
layers[wlr_layer_surface->current.layer]); wlr_scene_node_reparent(&layersurface->popups->node, layer);
wlr_scene_node_reparent(&layersurface->popups->node,
layers[wlr_layer_surface->current.layer]);
wl_list_remove(&layersurface->link); wl_list_remove(&layersurface->link);
wl_list_insert(&layersurface->mon->layers[wlr_layer_surface->current.layer], wl_list_insert(&layersurface->mon->layers[wlr_layer_surface->current.layer],
&layersurface->link); &layersurface->link);
@@ -766,9 +777,7 @@ commitnotify(struct wl_listener *listener, void *data)
c->isfloating ? resize(c, c->geom, 1) : arrange(c->mon); c->isfloating ? resize(c, c->geom, 1) : arrange(c->mon);
/* mark a pending resize as completed */ /* mark a pending resize as completed */
if (c->resize && (c->resize <= c->surface.xdg->current.configure_serial if (c->resize && c->resize <= c->surface.xdg->current.configure_serial)
|| (c->surface.xdg->current.geometry.width == c->surface.xdg->pending.geometry.width
&& c->surface.xdg->current.geometry.height == c->surface.xdg->pending.geometry.height)))
c->resize = 0; c->resize = 0;
} }
@@ -813,6 +822,9 @@ createkeyboard(struct wlr_keyboard *keyboard)
wlr_seat_set_keyboard(seat, keyboard); wlr_seat_set_keyboard(seat, keyboard);
kb->key_repeat_source = wl_event_loop_add_timer(
wl_display_get_event_loop(dpy), keyrepeat, kb);
/* And add the keyboard to our list of keyboards */ /* And add the keyboard to our list of keyboards */
wl_list_insert(&keyboards, &kb->link); wl_list_insert(&keyboards, &kb->link);
} }
@@ -823,12 +835,15 @@ createlayersurface(struct wl_listener *listener, void *data)
struct wlr_layer_surface_v1 *wlr_layer_surface = data; struct wlr_layer_surface_v1 *wlr_layer_surface = data;
LayerSurface *layersurface; LayerSurface *layersurface;
struct wlr_layer_surface_v1_state old_state; struct wlr_layer_surface_v1_state old_state;
struct wlr_scene_tree *l = layers[layermap[wlr_layer_surface->pending.layer]];
if (!wlr_layer_surface->output) if (!wlr_layer_surface->output)
wlr_layer_surface->output = selmon ? selmon->wlr_output : NULL; wlr_layer_surface->output = selmon ? selmon->wlr_output : NULL;
if (!wlr_layer_surface->output) if (!wlr_layer_surface->output) {
wlr_layer_surface_v1_destroy(wlr_layer_surface); wlr_layer_surface_v1_destroy(wlr_layer_surface);
return;
}
layersurface = ecalloc(1, sizeof(LayerSurface)); layersurface = ecalloc(1, sizeof(LayerSurface));
layersurface->type = LayerShell; layersurface->type = LayerShell;
@@ -845,11 +860,9 @@ createlayersurface(struct wl_listener *listener, void *data)
layersurface->mon = wlr_layer_surface->output->data; layersurface->mon = wlr_layer_surface->output->data;
wlr_layer_surface->data = layersurface; wlr_layer_surface->data = layersurface;
layersurface->scene_layer = wlr_scene_layer_surface_v1_create( layersurface->scene_layer = wlr_scene_layer_surface_v1_create(l, wlr_layer_surface);
layers[wlr_layer_surface->pending.layer], wlr_layer_surface);
layersurface->scene = layersurface->scene_layer->tree; layersurface->scene = layersurface->scene_layer->tree;
layersurface->popups = wlr_layer_surface->surface->data = layersurface->popups = wlr_layer_surface->surface->data = wlr_scene_tree_create(l);
wlr_scene_tree_create(layers[wlr_layer_surface->pending.layer]);
layersurface->scene->node.data = layersurface; layersurface->scene->node.data = layersurface;
@@ -910,6 +923,8 @@ createmon(struct wl_listener *listener, void *data)
wlr_xcursor_manager_load(cursor_mgr, r->scale); wlr_xcursor_manager_load(cursor_mgr, r->scale);
m->lt[0] = m->lt[1] = r->lt; m->lt[0] = m->lt[1] = r->lt;
wlr_output_set_transform(wlr_output, r->rr); wlr_output_set_transform(wlr_output, r->rr);
m->m.x = r->x;
m->m.y = r->y;
break; break;
} }
} }
@@ -955,7 +970,11 @@ createmon(struct wl_listener *listener, void *data)
* output (such as DPI, scale factor, manufacturer, etc). * output (such as DPI, scale factor, manufacturer, etc).
*/ */
m->scene_output = wlr_scene_output_create(scene, wlr_output); m->scene_output = wlr_scene_output_create(scene, wlr_output);
wlr_output_layout_add_auto(output_layout, wlr_output); if (m->m.x < 0 || m->m.y < 0)
wlr_output_layout_add_auto(output_layout, wlr_output);
else
wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y);
strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol));
} }
void void
@@ -1006,7 +1025,7 @@ void
createpointer(struct wlr_pointer *pointer) createpointer(struct wlr_pointer *pointer)
{ {
if (wlr_input_device_is_libinput(&pointer->base)) { if (wlr_input_device_is_libinput(&pointer->base)) {
struct libinput_device *libinput_device = (struct libinput_device*) struct libinput_device *libinput_device = (struct libinput_device*)
wlr_libinput_get_device_handle(&pointer->base); wlr_libinput_get_device_handle(&pointer->base);
if (libinput_device_config_tap_get_finger_count(libinput_device)) { if (libinput_device_config_tap_get_finger_count(libinput_device)) {
@@ -1030,7 +1049,7 @@ createpointer(struct wlr_pointer *pointer)
if (libinput_device_config_scroll_get_methods(libinput_device) != LIBINPUT_CONFIG_SCROLL_NO_SCROLL) if (libinput_device_config_scroll_get_methods(libinput_device) != LIBINPUT_CONFIG_SCROLL_NO_SCROLL)
libinput_device_config_scroll_set_method (libinput_device, scroll_method); libinput_device_config_scroll_set_method (libinput_device, scroll_method);
if (libinput_device_config_click_get_methods(libinput_device) != LIBINPUT_CONFIG_CLICK_METHOD_NONE) if (libinput_device_config_click_get_methods(libinput_device) != LIBINPUT_CONFIG_CLICK_METHOD_NONE)
libinput_device_config_click_set_method (libinput_device, click_method); libinput_device_config_click_set_method (libinput_device, click_method);
@@ -1170,12 +1189,12 @@ Monitor *
dirtomon(enum wlr_direction dir) dirtomon(enum wlr_direction dir)
{ {
struct wlr_output *next; struct wlr_output *next;
if (wlr_output_layout_get(output_layout, selmon->wlr_output) if (!wlr_output_layout_get(output_layout, selmon->wlr_output))
&& (next = wlr_output_layout_adjacent_output(output_layout, return selmon;
if ((next = wlr_output_layout_adjacent_output(output_layout,
dir, selmon->wlr_output, selmon->m.x, selmon->m.y))) dir, selmon->wlr_output, selmon->m.x, selmon->m.y)))
return next->data; return next->data;
if (wlr_output_layout_get(output_layout, selmon->wlr_output) if ((next = wlr_output_layout_farthest_output(output_layout,
&& (next = wlr_output_layout_farthest_output(output_layout,
dir ^ (WLR_DIRECTION_LEFT|WLR_DIRECTION_RIGHT), dir ^ (WLR_DIRECTION_LEFT|WLR_DIRECTION_RIGHT),
selmon->wlr_output, selmon->m.x, selmon->m.y))) selmon->wlr_output, selmon->m.x, selmon->m.y)))
return next->data; return next->data;
@@ -1186,7 +1205,9 @@ void
focusclient(Client *c, int lift) focusclient(Client *c, int lift)
{ {
struct wlr_surface *old = seat->keyboard_state.focused_surface; struct wlr_surface *old = seat->keyboard_state.focused_surface;
int i; int i, unused_lx, unused_ly, old_client_type;
Client *old_c = NULL;
LayerSurface *old_l = NULL;
if (locked) if (locked)
return; return;
@@ -1198,6 +1219,12 @@ focusclient(Client *c, int lift)
if (c && client_surface(c) == old) if (c && client_surface(c) == old)
return; return;
if ((old_client_type = toplevel_from_wlr_surface(old, &old_c, &old_l)) == XDGShell) {
struct wlr_xdg_popup *popup, *tmp;
wl_list_for_each_safe(popup, tmp, &old_c->surface.xdg->popups, link)
wlr_xdg_popup_destroy(popup);
}
/* Put the new client atop the focus stack and select its monitor */ /* Put the new client atop the focus stack and select its monitor */
if (c && !client_is_unmanaged(c)) { if (c && !client_is_unmanaged(c)) {
wl_list_remove(&c->flink); wl_list_remove(&c->flink);
@@ -1218,19 +1245,17 @@ focusclient(Client *c, int lift)
/* If an overlay is focused, don't focus or activate the client, /* If an overlay is focused, don't focus or activate the client,
* but only update its position in fstack to render its border with focuscolor * but only update its position in fstack to render its border with focuscolor
* and focus it after the overlay is closed. */ * and focus it after the overlay is closed. */
Client *w = NULL; if (old_client_type == LayerShell && wlr_scene_node_coords(
LayerSurface *l = NULL; &old_l->scene->node, &unused_lx, &unused_ly)
int type = toplevel_from_wlr_surface(old, &w, &l); && old_l->layer_surface->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) {
if (type == LayerShell && l->scene->node.enabled
&& l->layer_surface->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) {
return; return;
} else if (w && w == exclusive_focus && client_wants_focus(w)) { } else if (old_c && old_c == exclusive_focus && client_wants_focus(old_c)) {
return; return;
/* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg /* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg
* and probably other clients */ * and probably other clients */
} else if (w && !client_is_unmanaged(w) && (!c || !client_wants_focus(c))) { } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) {
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
wlr_scene_rect_set_color(w->border[i], bordercolor); wlr_scene_rect_set_color(old_c->border[i], bordercolor);
client_activate_surface(old, 0); client_activate_surface(old, 0);
} }
@@ -1274,16 +1299,16 @@ focusstack(const Arg *arg)
if (arg->i > 0) { if (arg->i > 0) {
wl_list_for_each(c, &sel->link, link) { wl_list_for_each(c, &sel->link, link) {
if (&c->link == &clients) if (&c->link == &clients)
continue; /* wrap past the sentinel node */ continue; /* wrap past the sentinel node */
if (VISIBLEON(c, selmon)) if (VISIBLEON(c, selmon))
break; /* found it */ break; /* found it */
} }
} else { } else {
wl_list_for_each_reverse(c, &sel->link, link) { wl_list_for_each_reverse(c, &sel->link, link) {
if (&c->link == &clients) if (&c->link == &clients)
continue; /* wrap past the sentinel node */ continue; /* wrap past the sentinel node */
if (VISIBLEON(c, selmon)) if (VISIBLEON(c, selmon))
break; /* found it */ break; /* found it */
} }
} }
/* If only one client is visible on selmon, then c == sel */ /* If only one client is visible on selmon, then c == sel */
@@ -1396,6 +1421,17 @@ keypress(struct wl_listener *listener, void *data)
for (i = 0; i < nsyms; i++) for (i = 0; i < nsyms; i++)
handled = keybinding(mods, syms[i]) || handled; handled = keybinding(mods, syms[i]) || handled;
if (handled && kb->wlr_keyboard->repeat_info.delay > 0) {
kb->mods = mods;
kb->keysyms = syms;
kb->nsyms = nsyms;
wl_event_source_timer_update(kb->key_repeat_source,
kb->wlr_keyboard->repeat_info.delay);
} else {
kb->nsyms = 0;
wl_event_source_timer_update(kb->key_repeat_source, 0);
}
if (!handled) { if (!handled) {
/* Pass unhandled keycodes along to the client. */ /* Pass unhandled keycodes along to the client. */
wlr_seat_set_keyboard(seat, kb->wlr_keyboard); wlr_seat_set_keyboard(seat, kb->wlr_keyboard);
@@ -1422,6 +1458,22 @@ keypressmod(struct wl_listener *listener, void *data)
&kb->wlr_keyboard->modifiers); &kb->wlr_keyboard->modifiers);
} }
int
keyrepeat(void *data)
{
Keyboard *kb = data;
int i;
if (kb->nsyms && kb->wlr_keyboard->repeat_info.rate > 0) {
wl_event_source_timer_update(kb->key_repeat_source,
1000 / kb->wlr_keyboard->repeat_info.rate);
for (i = 0; i < kb->nsyms; i++)
keybinding(kb->mods, kb->keysyms[i]);
}
return 0;
}
void void
killclient(const Arg *arg) killclient(const Arg *arg)
{ {
@@ -1485,7 +1537,6 @@ mapnotify(struct wl_listener *listener, void *data)
} }
c->scene->node.data = c->scene_surface->node.data = c; c->scene->node.data = c->scene_surface->node.data = c;
#ifdef XWAYLAND
/* Handle unmanaged clients first so we can return prior create borders */ /* Handle unmanaged clients first so we can return prior create borders */
if (client_is_unmanaged(c)) { if (client_is_unmanaged(c)) {
client_get_geometry(c, &c->geom); client_get_geometry(c, &c->geom);
@@ -1499,7 +1550,6 @@ mapnotify(struct wl_listener *listener, void *data)
} }
goto unset_fullscreen; goto unset_fullscreen;
} }
#endif
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
c->border[i] = wlr_scene_rect_create(c->scene, 0, 0, bordercolor); c->border[i] = wlr_scene_rect_create(c->scene, 0, 0, bordercolor);
@@ -1553,12 +1603,16 @@ void
monocle(Monitor *m) monocle(Monitor *m)
{ {
Client *c; Client *c;
int n = 0;
wl_list_for_each(c, &clients, link) { wl_list_for_each(c, &clients, link) {
if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
continue; continue;
resize(c, m->w, 0); resize(c, m->w, 0);
n++;
} }
if (n)
snprintf(m->ltsymbol, LENGTH(m->ltsymbol), "[%d]", n);
if ((c = focustop(m))) if ((c = focustop(m)))
wlr_scene_node_raise_to_top(&c->scene->node); wlr_scene_node_raise_to_top(&c->scene->node);
} }
@@ -1690,7 +1744,7 @@ outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test)
{ {
/* /*
* Called when a client such as wlr-randr requests a change in output * Called when a client such as wlr-randr requests a change in output
* configuration. This is only one way that the layout can be changed, * configuration. This is only one way that the layout can be changed,
* so any Monitor information should be updated by updatemons() after an * so any Monitor information should be updated by updatemons() after an
* output_layout.change event, not here. * output_layout.change event, not here.
*/ */
@@ -1781,7 +1835,8 @@ printstatus(void)
{ {
Monitor *m = NULL; Monitor *m = NULL;
Client *c; Client *c;
unsigned int occ, urg, sel; uint32_t occ, urg, sel;
const char *appid, *title;
wl_list_for_each(m, &mons, link) { wl_list_for_each(m, &mons, link) {
occ = urg = 0; occ = urg = 0;
@@ -1793,12 +1848,16 @@ printstatus(void)
urg |= c->tags; urg |= c->tags;
} }
if ((c = focustop(m))) { if ((c = focustop(m))) {
printf("%s title %s\n", m->wlr_output->name, client_get_title(c)); title = client_get_title(c);
appid = client_get_appid(c);
printf("%s title %s\n", m->wlr_output->name, title ? title : broken);
printf("%s appid %s\n", m->wlr_output->name, appid ? appid : broken);
printf("%s fullscreen %u\n", m->wlr_output->name, c->isfullscreen); printf("%s fullscreen %u\n", m->wlr_output->name, c->isfullscreen);
printf("%s floating %u\n", m->wlr_output->name, c->isfloating); printf("%s floating %u\n", m->wlr_output->name, c->isfloating);
sel = c->tags; sel = c->tags;
} else { } else {
printf("%s title \n", m->wlr_output->name); printf("%s title \n", m->wlr_output->name);
printf("%s appid \n", m->wlr_output->name);
printf("%s fullscreen \n", m->wlr_output->name); printf("%s fullscreen \n", m->wlr_output->name);
printf("%s floating \n", m->wlr_output->name); printf("%s floating \n", m->wlr_output->name);
sel = 0; sel = 0;
@@ -1807,7 +1866,7 @@ printstatus(void)
printf("%s selmon %u\n", m->wlr_output->name, m == selmon); printf("%s selmon %u\n", m->wlr_output->name, m == selmon);
printf("%s tags %u %u %u %u\n", m->wlr_output->name, occ, m->tagset[m->seltags], printf("%s tags %u %u %u %u\n", m->wlr_output->name, occ, m->tagset[m->seltags],
sel, urg); sel, urg);
printf("%s layout %s\n", m->wlr_output->name, m->lt[m->sellt]->symbol); printf("%s layout %s\n", m->wlr_output->name, m->ltsymbol);
} }
fflush(stdout); fflush(stdout);
} }
@@ -1836,10 +1895,10 @@ rendermon(struct wl_listener *listener, void *data)
/* Render if no XDG clients have an outstanding resize and are visible on /* Render if no XDG clients have an outstanding resize and are visible on
* this monitor. */ * this monitor. */
wl_list_for_each(c, &clients, link) wl_list_for_each(c, &clients, link)
if (client_is_rendered_on_mon(c, m) && (!c->isfloating && c->resize) && !client_is_stopped(c)) if (c->resize && !c->isfloating && client_is_rendered_on_mon(c, m) && !client_is_stopped(c))
goto skip; goto skip;
if (!wlr_scene_output_commit(m->scene_output)) wlr_scene_output_commit(m->scene_output);
return;
skip: skip:
/* Let clients know a frame has been rendered */ /* Let clients know a frame has been rendered */
clock_gettime(CLOCK_MONOTONIC, &now); clock_gettime(CLOCK_MONOTONIC, &now);
@@ -1877,7 +1936,7 @@ resize(Client *c, struct wlr_box geo, int interact)
wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw); wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw); wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw);
/* wlroots makes this a no-op if size hasn't changed */ /* this is a no-op if size hasn't changed */
c->resize = client_set_size(c, c->geom.width - 2 * c->bw, c->resize = client_set_size(c, c->geom.width - 2 * c->bw,
c->geom.height - 2 * c->bw); c->geom.height - 2 * c->bw);
} }
@@ -1887,6 +1946,8 @@ run(char *startup_cmd)
{ {
/* Add a Unix socket to the Wayland display. */ /* Add a Unix socket to the Wayland display. */
const char *socket = wl_display_add_socket_auto(dpy); const char *socket = wl_display_add_socket_auto(dpy);
struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = SIG_IGN};
sigemptyset(&sa.sa_mask);
if (!socket) if (!socket)
die("startup: display_add_socket_auto"); die("startup: display_add_socket_auto");
setenv("WAYLAND_DISPLAY", socket, 1); setenv("WAYLAND_DISPLAY", socket, 1);
@@ -1915,7 +1976,7 @@ run(char *startup_cmd)
close(piperw[0]); close(piperw[0]);
} }
/* If nobody is reading the status output, don't terminate */ /* If nobody is reading the status output, don't terminate */
signal(SIGPIPE, SIG_IGN); sigaction(SIGPIPE, &sa, NULL);
printstatus(); printstatus();
/* At this point the outputs are initialized, choose initial selmon based on /* At this point the outputs are initialized, choose initial selmon based on
@@ -1923,7 +1984,7 @@ run(char *startup_cmd)
selmon = xytomon(cursor->x, cursor->y); selmon = xytomon(cursor->x, cursor->y);
/* TODO hack to get cursor to display in its initial location (100, 100) /* TODO hack to get cursor to display in its initial location (100, 100)
* instead of (0, 0) and then jumping. still may not be fully * instead of (0, 0) and then jumping. still may not be fully
* initialized, as the image/coordinates are not transformed for the * initialized, as the image/coordinates are not transformed for the
* monitor when displayed here */ * monitor when displayed here */
wlr_cursor_warp_closest(cursor, NULL, cursor->x, cursor->y); wlr_cursor_warp_closest(cursor, NULL, cursor->x, cursor->y);
@@ -1998,7 +2059,7 @@ setlayout(const Arg *arg)
selmon->sellt ^= 1; selmon->sellt ^= 1;
if (arg && arg->v) if (arg && arg->v)
selmon->lt[selmon->sellt] = (Layout *)arg->v; selmon->lt[selmon->sellt] = (Layout *)arg->v;
/* TODO change layout symbol? */ strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol));
arrange(selmon); arrange(selmon);
printstatus(); printstatus();
} }
@@ -2019,7 +2080,7 @@ setmfact(const Arg *arg)
} }
void void
setmon(Client *c, Monitor *m, unsigned int newtags) setmon(Client *c, Monitor *m, uint32_t newtags)
{ {
Monitor *oldmon = c->mon; Monitor *oldmon = c->mon;
@@ -2068,19 +2129,21 @@ setsel(struct wl_listener *listener, void *data)
void void
setup(void) setup(void)
{ {
int layer;
/* Set up signal handlers */
struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = sigchld};
sigemptyset(&sa.sa_mask);
sigaction(SIGCHLD, &sa, NULL);
sa.sa_handler = quitsignal;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
/* The Wayland display is managed by libwayland. It handles accepting /* The Wayland display is managed by libwayland. It handles accepting
* clients from the Unix socket, manging Wayland globals, and so on. */ * clients from the Unix socket, manging Wayland globals, and so on. */
dpy = wl_display_create(); dpy = wl_display_create();
/* Set up signal handlers */
#ifdef XWAYLAND
sigchld(0);
#else
signal(SIGCHLD, SIG_IGN);
#endif
signal(SIGINT, quitsignal);
signal(SIGTERM, quitsignal);
/* The backend is a wlroots feature which abstracts the underlying input and /* The backend is a wlroots feature which abstracts the underlying input and
* output hardware. The autocreate option will choose the most suitable * output hardware. The autocreate option will choose the most suitable
* backend based on the current environment, such as opening an X11 window * backend based on the current environment, such as opening an X11 window
@@ -2094,15 +2157,8 @@ setup(void)
/* Initialize the scene graph used to lay out windows */ /* Initialize the scene graph used to lay out windows */
scene = wlr_scene_create(); scene = wlr_scene_create();
layers[LyrBg] = wlr_scene_tree_create(&scene->tree); for (layer = 0; layer < NUM_LAYERS; layer++)
layers[LyrBottom] = wlr_scene_tree_create(&scene->tree); layers[layer] = wlr_scene_tree_create(&scene->tree);
layers[LyrTile] = wlr_scene_tree_create(&scene->tree);
layers[LyrFloat] = wlr_scene_tree_create(&scene->tree);
layers[LyrFS] = wlr_scene_tree_create(&scene->tree);
layers[LyrTop] = wlr_scene_tree_create(&scene->tree);
layers[LyrOverlay] = wlr_scene_tree_create(&scene->tree);
layers[LyrDragIcon] = wlr_scene_tree_create(&scene->tree);
layers[LyrBlock] = wlr_scene_tree_create(&scene->tree);
/* Create a renderer with the default implementation */ /* Create a renderer with the default implementation */
if (!(drw = wlr_renderer_autocreate(backend))) if (!(drw = wlr_renderer_autocreate(backend)))
@@ -2193,6 +2249,7 @@ setup(void)
* images are available at all scale factors on the screen (necessary for * images are available at all scale factors on the screen (necessary for
* HiDPI support). Scaled cursors will be loaded with each output. */ * HiDPI support). Scaled cursors will be loaded with each output. */
cursor_mgr = wlr_xcursor_manager_create(NULL, 24); cursor_mgr = wlr_xcursor_manager_create(NULL, 24);
setenv("XCURSOR_SIZE", "24", 1);
/* /*
* wlr_cursor *only* displays an image on screen. It does not move around * wlr_cursor *only* displays an image on screen. It does not move around
@@ -2253,6 +2310,28 @@ setup(void)
#endif #endif
} }
void
sigchld(int unused)
{
#ifdef XWAYLAND
siginfo_t in;
/* We should be able to remove this function in favor of a simple
* struct sigaction sa = {.sa_handler = SIG_IGN};
* sigaction(SIGCHLD, &sa, NULL);
* but the Xwayland implementation in wlroots currently prevents us from
* setting our own disposition for SIGCHLD.
*/
/* WNOWAIT leaves the child in a waitable state, in case this is the
* XWayland process
*/
while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid
&& (!xwayland || in.si_pid != xwayland->server->pid))
waitpid(in.si_pid, NULL, 0);
#else
while (waitpid(-1, NULL, WNOHANG) > 0);
#endif
}
void void
spawn(const Arg *arg) spawn(const Arg *arg)
{ {
@@ -2268,11 +2347,13 @@ void
startdrag(struct wl_listener *listener, void *data) startdrag(struct wl_listener *listener, void *data)
{ {
struct wlr_drag *drag = data; struct wlr_drag *drag = data;
struct wlr_scene_tree *icon;
if (!drag->icon) if (!drag->icon)
return; return;
drag->icon->data = wlr_scene_subsurface_tree_create(layers[LyrDragIcon], drag->icon->surface); drag->icon->data = icon = wlr_scene_subsurface_tree_create(&scene->tree, drag->icon->surface);
wlr_scene_node_place_below(&icon->node, &layers[LyrBlock]->node);
motionnotify(0); motionnotify(0);
wl_signal_add(&drag->icon->events.destroy, &drag_icon_destroy); wl_signal_add(&drag->icon->events.destroy, &drag_icon_destroy);
} }
@@ -2350,7 +2431,7 @@ togglefullscreen(const Arg *arg)
void void
toggletag(const Arg *arg) toggletag(const Arg *arg)
{ {
unsigned int newtags; uint32_t newtags;
Client *sel = focustop(selmon); Client *sel = focustop(selmon);
if (!sel) if (!sel)
return; return;
@@ -2366,7 +2447,7 @@ toggletag(const Arg *arg)
void void
toggleview(const Arg *arg) toggleview(const Arg *arg)
{ {
unsigned int newtagset = selmon ? selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK) : 0; uint32_t newtagset = selmon ? selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK) : 0;
if (newtagset) { if (newtagset) {
selmon->tagset[selmon->seltags] = newtagset; selmon->tagset[selmon->seltags] = newtagset;
@@ -2433,7 +2514,7 @@ updatemons(struct wl_listener *listener, void *data)
{ {
/* /*
* Called whenever the output layout changes: adding or removing a * Called whenever the output layout changes: adding or removing a
* monitor, changing an output's mode or position, etc. This is where * monitor, changing an output's mode or position, etc. This is where
* the change officially happens and we update geometry, window * the change officially happens and we update geometry, window
* positions, focus, and the stored configuration in wlroots' * positions, focus, and the stored configuration in wlroots'
* output-manager implementation. * output-manager implementation.
@@ -2461,9 +2542,14 @@ updatemons(struct wl_listener *listener, void *data)
if (m->wlr_output->enabled if (m->wlr_output->enabled
&& !wlr_output_layout_get(output_layout, m->wlr_output)) && !wlr_output_layout_get(output_layout, m->wlr_output))
wlr_output_layout_add_auto(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 */ /* Now that we update the output layout we can get its box */
wlr_output_layout_get_box(output_layout, NULL, &sgeom); wlr_output_layout_get_box(output_layout, NULL, &sgeom);
/* Make sure the clients are hidden when dwl is locked */
wlr_scene_node_set_position(&locked_bg->node, sgeom.x, sgeom.y);
wlr_scene_rect_set_size(locked_bg, sgeom.width, sgeom.height); wlr_scene_rect_set_size(locked_bg, sgeom.width, sgeom.height);
wl_list_for_each(m, &mons, link) { wl_list_for_each(m, &mons, link) {
if (!m->wlr_output->enabled) if (!m->wlr_output->enabled)
continue; continue;
@@ -2473,10 +2559,6 @@ updatemons(struct wl_listener *listener, void *data)
wlr_output_layout_get_box(output_layout, m->wlr_output, &(m->m)); 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->w));
wlr_scene_output_set_position(m->scene_output, m->m.x, m->m.y); wlr_scene_output_set_position(m->scene_output, m->m.x, m->m.y);
/* Calculate the effective monitor geometry to use for clients */
arrangelayers(m);
/* Don't move clients to the left output when plugging monitors */
arrange(m);
wlr_scene_node_set_position(&m->fullscreen_bg->node, m->m.x, m->m.y); wlr_scene_node_set_position(&m->fullscreen_bg->node, m->m.x, m->m.y);
wlr_scene_rect_set_size(m->fullscreen_bg, m->m.width, m->m.height); wlr_scene_rect_set_size(m->fullscreen_bg, m->m.width, m->m.height);
@@ -2488,6 +2570,11 @@ updatemons(struct wl_listener *listener, void *data)
m->m.height); m->m.height);
} }
/* Calculate the effective monitor geometry to use for clients */
arrangelayers(m);
/* Don't move clients to the left output when plugging monitors */
arrange(m);
config_head->state.enabled = 1; config_head->state.enabled = 1;
config_head->state.mode = m->wlr_output->current_mode; config_head->state.mode = m->wlr_output->current_mode;
config_head->state.x = m->m.x; config_head->state.x = m->m.x;
@@ -2498,9 +2585,12 @@ updatemons(struct wl_listener *listener, void *data)
wl_list_for_each(c, &clients, link) wl_list_for_each(c, &clients, link)
if (!c->mon && client_is_mapped(c)) if (!c->mon && client_is_mapped(c))
setmon(c, selmon, c->tags); setmon(c, selmon, c->tags);
if (selmon->lock_surface) focusclient(focustop(selmon), 1);
if (selmon->lock_surface) {
client_notify_enter(selmon->lock_surface->surface, client_notify_enter(selmon->lock_surface->surface,
wlr_seat_get_keyboard(seat)); wlr_seat_get_keyboard(seat));
client_activate_surface(selmon->lock_surface->surface, 1);
}
} }
wlr_output_manager_v1_set_configuration(output_mgr, config); wlr_output_manager_v1_set_configuration(output_mgr, config);
@@ -2519,8 +2609,8 @@ urgent(struct wl_listener *listener, void *data)
{ {
struct wlr_xdg_activation_v1_request_activate_event *event = data; struct wlr_xdg_activation_v1_request_activate_event *event = data;
Client *c = NULL; Client *c = NULL;
int type = toplevel_from_wlr_surface(event->surface, &c, NULL); toplevel_from_wlr_surface(event->surface, &c, NULL);
if (type >= 0 && type != LayerShell && c != focustop(selmon)) { if (c && c != focustop(selmon)) {
c->isurgent = 1; c->isurgent = 1;
printstatus(); printstatus();
} }
@@ -2561,24 +2651,22 @@ xytonode(double x, double y, struct wlr_surface **psurface,
struct wlr_surface *surface = NULL; struct wlr_surface *surface = NULL;
Client *c = NULL; Client *c = NULL;
LayerSurface *l = NULL; LayerSurface *l = NULL;
const int *layer; int layer;
int focus_order[] = { LyrBlock, LyrOverlay, LyrTop, LyrFS, LyrFloat, LyrTile, LyrBottom, LyrBg };
for (layer = focus_order; layer < END(focus_order); layer++) { for (layer = NUM_LAYERS - 1; !surface && layer >= 0; layer--) {
if ((node = wlr_scene_node_at(&layers[*layer]->node, x, y, nx, ny))) { if (!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny)))
if (node->type == WLR_SCENE_NODE_BUFFER) continue;
surface = wlr_scene_surface_from_buffer(
wlr_scene_buffer_from_node(node))->surface; if (node->type == WLR_SCENE_NODE_BUFFER)
/* Walk the tree to find a node that knows the client */ surface = wlr_scene_surface_from_buffer(
for (pnode = node; pnode && !c; pnode = &pnode->parent->node) wlr_scene_buffer_from_node(node))->surface;
c = pnode->data; /* Walk the tree to find a node that knows the client */
if (c && c->type == LayerShell) { for (pnode = node; pnode && !c; pnode = &pnode->parent->node)
c = NULL; c = pnode->data;
l = pnode->data; if (c && c->type == LayerShell) {
} c = NULL;
l = pnode->data;
} }
if (surface)
break;
} }
if (psurface) *psurface = surface; if (psurface) *psurface = surface;
@@ -2690,25 +2778,6 @@ sethints(struct wl_listener *listener, void *data)
} }
} }
void
sigchld(int unused)
{
siginfo_t in;
/* We should be able to remove this function in favor of a simple
* signal(SIGCHLD, SIG_IGN);
* but the Xwayland implementation in wlroots currently prevents us from
* setting our own disposition for SIGCHLD.
*/
if (signal(SIGCHLD, sigchld) == SIG_ERR)
die("can't install SIGCHLD handler:");
/* WNOWAIT leaves the child in a waitable state, in case this is the
* XWayland process
*/
while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid
&& (!xwayland || in.si_pid != xwayland->server->pid))
waitpid(in.si_pid, NULL, 0);
}
void void
xwaylandready(struct wl_listener *listener, void *data) xwaylandready(struct wl_listener *listener, void *data)
{ {
@@ -2720,7 +2789,7 @@ xwaylandready(struct wl_listener *listener, void *data)
return; return;
} }
/* Collect atoms we are interested in. If getatom returns 0, we will /* Collect atoms we are interested in. If getatom returns 0, we will
* not detect that window type. */ * not detect that window type. */
netatom[NetWMWindowTypeDialog] = getatom(xc, "_NET_WM_WINDOW_TYPE_DIALOG"); netatom[NetWMWindowTypeDialog] = getatom(xc, "_NET_WM_WINDOW_TYPE_DIALOG");
netatom[NetWMWindowTypeSplash] = getatom(xc, "_NET_WM_WINDOW_TYPE_SPLASH"); netatom[NetWMWindowTypeSplash] = getatom(xc, "_NET_WM_WINDOW_TYPE_SPLASH");
+63
View File
@@ -0,0 +1,63 @@
static Client *
nexttiled(Client *sel) {
Client *c;
wl_list_for_each(c, &sel->link, link) {
if (&c->link == &clients)
break; /* don't wrap */
if (!c->isfloating && VISIBLEON(c, selmon))
return c;
}
return NULL;
}
static Client *
prevtiled(Client *sel) {
Client *c;
wl_list_for_each_reverse(c, &sel->link, link) {
if (&c->link == &clients)
break; /* don't wrap */
if (!c->isfloating && VISIBLEON(c, selmon))
return c;
}
return NULL;
}
static void
pushup(const Arg *arg) {
Client *sel = focustop(selmon);
Client *c;
if(!sel || sel->isfloating)
return;
if((c = prevtiled(sel))) {
/* attach before c */
wl_list_remove(&sel->link);
wl_list_insert(c->link.prev, &sel->link);
} else {
/* move to the end */
wl_list_remove(&sel->link);
wl_list_insert(clients.prev, &sel->link);
}
focusclient(sel, 1);
arrange(selmon);
}
static void
pushdown(const Arg *arg) {
Client *sel = focustop(selmon);
Client *c;
if(!sel || sel->isfloating)
return;
if((c = nexttiled(sel))) {
/* attach after c */
wl_list_remove(&sel->link);
wl_list_insert(&c->link, &sel->link);
} else {
/* move to the front */
wl_list_remove(&sel->link);
wl_list_insert(&clients, &sel->link);
}
focusclient(sel, 1);
arrange(selmon);
}
+4
View File
@@ -0,0 +1,4 @@
static Client *nexttiled(Client *sel);
static Client *prevtiled(Client *sel);
static void pushdown(const Arg *arg);
static void pushup(const Arg *arg);