diff --git a/dwl/alwayscenter.patch b/dwl/alwayscenter.patch deleted file mode 100644 index 962745de..00000000 --- a/dwl/alwayscenter.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 48110f0443c8e1ddcd56b6fed5da46535024919c Mon Sep 17 00:00:00 2001 -From: Guido Cella -Date: Tue, 13 Jan 2026 21:17:22 +0100 -Subject: [PATCH] center floating windows - ---- - dwl.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/dwl.c b/dwl.c -index 44f3ad9..72714f8 100644 ---- a/dwl.c -+++ b/dwl.c -@@ -2414,6 +2414,8 @@ setmon(Client *c, Monitor *m, uint32_t newtags) - /* Make sure window actually overlaps with the monitor */ - resize(c, c->geom, 0); - c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */ -+ c->prev.x = (m->w.width - c->prev.width) / 2 + m->m.x; -+ c->prev.y = (m->w.height - c->prev.height) / 2 + m->m.y; - setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */ - setfloating(c, c->isfloating); - } --- -2.52.0 - diff --git a/dwl/autostart-0.8.patch b/dwl/autostart-0.8.patch deleted file mode 100644 index a1ce9ac9..00000000 --- a/dwl/autostart-0.8.patch +++ /dev/null @@ -1,141 +0,0 @@ -From d2e2e61aeb25ad71c2c559994968ba64e0974503 Mon Sep 17 00:00:00 2001 -From: A Frederick Christensen -Date: Fri, 27 Feb 2026 12:23:04 -0600 -Subject: [PATCH] Applied autostart patch - ---- - config.def.h | 6 ++++++ - dwl.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++--- - 2 files changed, 61 insertions(+), 3 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 8a6eda0..6eb0db4 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -20,6 +20,12 @@ static const float fullscreen_bg[] = {0.0f, 0.0f, 0.0f, 1.0f}; /* You ca - /* logging */ - static int log_level = WLR_ERROR; - -+/* Autostart */ -+static const char *const autostart[] = { -+ "wbg", "/path/to/your/image", NULL, -+ NULL /* terminate */ -+}; -+ - static const Rule rules[] = { - /* app_id title tags mask isfloating monitor */ - { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ -diff --git a/dwl.c b/dwl.c -index 44f3ad9..e7b6199 100644 ---- a/dwl.c -+++ b/dwl.c -@@ -246,6 +246,7 @@ static void arrange(Monitor *m); - static void arrangelayer(Monitor *m, struct wl_list *list, - struct wlr_box *usable_area, int exclusive); - static void arrangelayers(Monitor *m); -+static void autostartexec(void); - static void axisnotify(struct wl_listener *listener, void *data); - static void buttonpress(struct wl_listener *listener, void *data); - static void chvt(const Arg *arg); -@@ -449,6 +450,9 @@ static struct wl_listener xwayland_ready = {.notify = xwaylandready}; - static struct wlr_xwayland *xwayland; - #endif - -+static pid_t *autostart_pids; -+static size_t autostart_len; -+ - /* configuration, allows nested code to access above variables */ - #include "config.h" - -@@ -603,6 +607,27 @@ arrangelayers(Monitor *m) - } - } - -+void -+autostartexec(void) { -+ const char *const *p; -+ size_t i = 0; -+ -+ /* count entries */ -+ for (p = autostart; *p; autostart_len++, p++) -+ while (*++p); -+ -+ autostart_pids = calloc(autostart_len, sizeof(pid_t)); -+ for (p = autostart; *p; i++, p++) { -+ if ((autostart_pids[i] = fork()) == 0) { -+ setsid(); -+ execvp(*p, (char *const *)p); -+ die("dwl: execvp %s:", *p); -+ } -+ /* skip arguments */ -+ while (*++p); -+ } -+} -+ - void - axisnotify(struct wl_listener *listener, void *data) - { -@@ -699,12 +724,23 @@ checkidleinhibitor(struct wlr_surface *exclude) - void - cleanup(void) - { -+ size_t i; -+ - cleanuplisteners(); - #ifdef XWAYLAND - wlr_xwayland_destroy(xwayland); - xwayland = NULL; - #endif - wl_display_destroy_clients(dpy); -+ -+ /* kill child processes */ -+ for (i = 0; i < autostart_len; i++) { -+ if (0 < autostart_pids[i]) { -+ kill(autostart_pids[i], SIGTERM); -+ waitpid(autostart_pids[i], NULL, 0); -+ } -+ } -+ - if (child_pid > 0) { - kill(-child_pid, SIGTERM); - waitpid(child_pid, NULL, 0); -@@ -1560,10 +1596,25 @@ gpureset(struct wl_listener *listener, void *data) - void - handlesig(int signo) - { -- if (signo == SIGCHLD) -- while (waitpid(-1, NULL, WNOHANG) > 0); -- else if (signo == SIGINT || signo == SIGTERM) -+ if (signo == SIGCHLD) { -+ pid_t pid, *p, *lim; -+ while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) { -+ if (pid == child_pid) -+ child_pid = -1; -+ if (!(p = autostart_pids)) -+ continue; -+ lim = &p[autostart_len]; -+ -+ for (; p < lim; p++) { -+ if (*p == pid) { -+ *p = -1; -+ break; -+ } -+ } -+ } -+ } else if (signo == SIGINT || signo == SIGTERM) { - quit(NULL); -+ } - } - - void -@@ -2250,6 +2301,7 @@ run(char *startup_cmd) - die("startup: backend_start"); - - /* Now that the socket exists and the backend is started, run the startup command */ -+ autostartexec(); - if (startup_cmd) { - int piperw[2]; - if (pipe(piperw) < 0) --- -2.52.0 - diff --git a/dwl/config.h b/dwl/config.h deleted file mode 100644 index 69bca091..00000000 --- a/dwl/config.h +++ /dev/null @@ -1,263 +0,0 @@ -/* Taken from https://github.com/djpohly/dwl/issues/466 */ -#define COLOR(hex) \ - {((hex >> 24) & 0xFF) / 255.0f, ((hex >> 16) & 0xFF) / 255.0f, \ - ((hex >> 8) & 0xFF) / 255.0f, (hex & 0xFF) / 255.0f} -/* appearance */ -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 unsigned int borderpx = 1; /* border pixel of windows */ -static const float rootcolor[] = COLOR(0x222222ff); -static const float bordercolor[] = COLOR(0x444444ff); -static const float focuscolor[] = COLOR(0x005577ff); -static const float urgentcolor[] = COLOR(0xff0000ff); -/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old - * behavior */ -static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, - 1.0f}; /* You can also use glsl colors */ -static int enableautoswallow = - 1; /* enables autoswallowing newly spawned clients */ - -/* tagging - TAGCOUNT must be no greater than 31 */ -#define TAGCOUNT (9) - -/* logging */ -static int log_level = WLR_ERROR; - -/* Autostart */ -static const char *const autostart[] = { - "swaybg", - "-i", - "/home/brian/Pictures/leaves.jpg", - "-m", - "fill", - NULL, - "gammastep", - "-b", - "0.95", - "-O", - "5500K", - NULL, - "foot", - "-c", - "/home/brian/.config/foot/bfoot.ini", - "/usr/bin/btop", - NULL, - - NULL /* terminate */ -}; - -/* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at - * least one example) */ -static const Rule rules[] = { - /* app_id title tags mask isfloating isterm - noswallow monitor */ - /* examples: */ - {"foot", NULL, 0, 0, 1, 1, -1}, - {"Gimp_EXAMPLE", NULL, 0, 1, 0, 0, - -1}, /* Start on currently visible tags floating, not tiled */ - {"firefox_EXAMPLE", NULL, 1 << 8, 0, 0, 0, -1}, /* Start on ONLY tag "9" */ -}; - -/* layout(s) */ -static const Layout layouts[] = { - /* symbol arrange function */ - {"[]=", tile}, - {"><>", NULL}, /* no layout function means floating behavior */ - {"[M]", monocle}, -}; - -/* monitors */ -/* (x=-1, y=-1) is reserved as an "autoconfigure" monitor position indicator - * WARNING: negative values other than (-1, -1) cause problems with Xwayland - * clients https://gitlab.freedesktop.org/xorg/xserver/-/issues/899 - */ -/* NOTE: ALWAYS add a fallback rule, even if you are completely sure it won't be - * used */ -static const MonitorRule monrules[] = { - /* name mfact nmaster scale layout rotate/reflect x y */ - /* example of a HiDPI laptop monitor: - { "eDP-1", 0.5f, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, - -1, -1 }, - */ - /* defaults */ - {NULL, 0.50f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1}, -}; - -/* keyboard */ -static const struct xkb_rule_names xkb_rules = { - /* can specify fields: rules, model, layout, variant, options */ - /* example: - .options = "ctrl:nocaps", - */ - .options = NULL, -}; - -static const int repeat_rate = 25; -static const int repeat_delay = 600; - -/* Trackpad */ -static const int tap_to_click = 1; -static const int tap_and_drag = 1; -static const int drag_lock = 1; -static const int natural_scrolling = 0; -static const int disable_while_typing = 1; -static const int left_handed = 0; -static const int middle_button_emulation = 0; -/* You can choose between: -LIBINPUT_CONFIG_SCROLL_NO_SCROLL -LIBINPUT_CONFIG_SCROLL_2FG -LIBINPUT_CONFIG_SCROLL_EDGE -LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN -*/ -static const enum libinput_config_scroll_method scroll_method = - LIBINPUT_CONFIG_SCROLL_2FG; - -/* You can choose between: -LIBINPUT_CONFIG_CLICK_METHOD_NONE -LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS -LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER -*/ -static const enum libinput_config_click_method click_method = - LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; - -/* You can choose between: -LIBINPUT_CONFIG_SEND_EVENTS_ENABLED -LIBINPUT_CONFIG_SEND_EVENTS_DISABLED -LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE -*/ -static const uint32_t send_events_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; - -/* You can choose between: -LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT -LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE -*/ -static const enum libinput_config_accel_profile accel_profile = - LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; -static const double accel_speed = 0.0; - -/* You can choose between: -LIBINPUT_CONFIG_TAP_MAP_LRM -- 1/2/3 finger tap maps to left/right/middle -LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right -*/ -static const enum libinput_config_tap_button_map button_map = - LIBINPUT_CONFIG_TAP_MAP_LRM; - -/* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */ -#define MODKEY WLR_MODIFIER_LOGO - -#define TAGKEYS(KEY, SKEY, TAG) \ - {MODKEY, KEY, view, {.ui = 1 << TAG}}, \ - {MODKEY | WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG}}, \ - {MODKEY | WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG}}, { \ - MODKEY | WLR_MODIFIER_CTRL | WLR_MODIFIER_SHIFT, SKEY, toggletag, { \ - .ui = 1 << TAG \ - } \ - } - -/* helper for spawning shell commands in the pre dwm-5.0 fashion */ -#define SHCMD(cmd) \ - { \ - .v = (const char *[]) { "/bin/sh", "-c", cmd, NULL } \ - } - -/* commands */ -static const char *termcmd[] = {"foot", NULL}; -static const char *menucmd[] = {"wmenu-run", NULL}; -static const char *librewolfcmd[] = {"librewolf-bin", NULL}; -static const char *chromiumcmd[] = {"chromium-bin", NULL}; -static const char *inkscapecmd[] = {"inkscape", NULL}; -static const char *gimpcmd[] = {"gimp", NULL}; -static const char *pcmanfmcmd[] = {"pcmanfm", NULL}; -static const char *keepassxccmd[] = {"keepassxc", NULL}; -static const char *libreofficecmd[] = {"libreoffice-bin", NULL}; -static const char *mousepadcmd[] = {"mousepad", NULL}; -static const char *virtmanagercmd[] = {"virt-manager", NULL}; -static const char *qalculatecmd[] = {"qalculate-qt", NULL}; - -static const Key keys[] = { - /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ - /* modifier key function argument */ - {MODKEY, XKB_KEY_Return, spawn, {.v = termcmd}}, - {MODKEY, XKB_KEY_d, spawn, {.v = menucmd}}, - {MODKEY, XKB_KEY_f, spawn, {.v = librewolfcmd}}, - {MODKEY, XKB_KEY_c, spawn, {.v = chromiumcmd}}, - {MODKEY, XKB_KEY_i, spawn, {.v = inkscapecmd}}, - {MODKEY, XKB_KEY_g, spawn, {.v = gimpcmd}}, - {MODKEY, XKB_KEY_p, spawn, {.v = pcmanfmcmd}}, - {MODKEY, XKB_KEY_k, spawn, {.v = keepassxccmd}}, - {MODKEY, XKB_KEY_n, spawn, {.v = libreofficecmd}}, - {MODKEY, XKB_KEY_m, spawn, {.v = mousepadcmd}}, - {MODKEY, XKB_KEY_v, spawn, {.v = virtmanagercmd}}, - {MODKEY, XKB_KEY_u, spawn, {.v = qalculatecmd}}, - {MODKEY, XKB_KEY_Left, setmfact, {.f = -0.05f}}, - {MODKEY, XKB_KEY_Right, setmfact, {.f = +0.05f}}, - {MODKEY | WLR_MODIFIER_SHIFT, XKB_KEY_Q, killclient, {0}}, - {MODKEY | WLR_MODIFIER_SHIFT, XKB_KEY_Escape, quit, {0}}, - {MODKEY, XKB_KEY_o, togglefloating, {0}}, - {MODKEY, XKB_KEY_j, focusstack, {.i = +1}}, - {MODKEY, XKB_KEY_k, focusstack, {.i = -1}}, - {MODKEY, XKB_KEY_i, incnmaster, {.i = +1}}, - {MODKEY, XKB_KEY_d, incnmaster, {.i = -1}}, - {MODKEY, XKB_KEY_Return, zoom, {0}}, - {MODKEY, XKB_KEY_Tab, view, {0}}, - // {MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]}}, - // {MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]}}, - // {MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]}}, - {MODKEY, XKB_KEY_space, setlayout, {0}}, - {MODKEY | WLR_MODIFIER_SHIFT, XKB_KEY_f, togglefullscreen, {0}}, - {MODKEY, XKB_KEY_a, toggleswallow, {0}}, - {MODKEY | WLR_MODIFIER_SHIFT, XKB_KEY_A, toggleautoswallow, {0}}, - {MODKEY, XKB_KEY_0, view, {.ui = ~0}}, - {MODKEY | WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0}}, - {MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT}}, - {MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT}}, - {MODKEY | WLR_MODIFIER_SHIFT, - XKB_KEY_less, - tagmon, - {.i = WLR_DIRECTION_LEFT}}, - {MODKEY | WLR_MODIFIER_SHIFT, - XKB_KEY_greater, - tagmon, - {.i = WLR_DIRECTION_RIGHT}}, - TAGKEYS(XKB_KEY_1, XKB_KEY_exclam, 0), - TAGKEYS(XKB_KEY_2, XKB_KEY_at, 1), - TAGKEYS(XKB_KEY_3, XKB_KEY_numbersign, 2), - TAGKEYS(XKB_KEY_4, XKB_KEY_dollar, 3), - TAGKEYS(XKB_KEY_5, XKB_KEY_percent, 4), - TAGKEYS(XKB_KEY_6, XKB_KEY_asciicircum, 5), - TAGKEYS(XKB_KEY_7, XKB_KEY_ampersand, 6), - TAGKEYS(XKB_KEY_8, XKB_KEY_asterisk, 7), - TAGKEYS(XKB_KEY_9, XKB_KEY_parenleft, 8), - - /* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */ - {WLR_MODIFIER_CTRL | WLR_MODIFIER_ALT, XKB_KEY_Terminate_Server, quit, {0}}, -/* Ctrl-Alt-Fx is used to switch to another VT, if you don't know what a VT is - * do not remove them. - */ -#define CHVT(n) \ - { \ - WLR_MODIFIER_CTRL | WLR_MODIFIER_ALT, XKB_KEY_XF86Switch_VT_##n, chvt, { \ - .ui = (n) \ - } \ - } - CHVT(1), - CHVT(2), - CHVT(3), - CHVT(4), - CHVT(5), - CHVT(6), - CHVT(7), - CHVT(8), - CHVT(9), - CHVT(10), - CHVT(11), - CHVT(12), -}; - -static const Button buttons[] = { - {MODKEY, BTN_LEFT, moveresize, {.ui = CurMove}}, - {MODKEY, BTN_MIDDLE, togglefloating, {0}}, - {MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize}}, -}; diff --git a/dwl/customfloat-0.8.patch b/dwl/customfloat-0.8.patch deleted file mode 100644 index 6f760d14..00000000 --- a/dwl/customfloat-0.8.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 96125a70b7525740a42803f1faa666ca37b9433f Mon Sep 17 00:00:00 2001 -From: A Frederick Christensen -Date: Mon, 23 Feb 2026 09:06:33 -0600 -Subject: [PATCH] Apply customfloat patch - ---- - config.def.h | 7 ++++--- - dwl.c | 26 ++++++++++++++++++++++++++ - 2 files changed, 30 insertions(+), 3 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 8a6eda0..16afbb3 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -13,6 +13,7 @@ static const float focuscolor[] = COLOR(0x005577ff); - static const float urgentcolor[] = COLOR(0xff0000ff); - /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ - static const float fullscreen_bg[] = {0.0f, 0.0f, 0.0f, 1.0f}; /* You can also use glsl colors */ -+static const int respect_monitor_reserved_area = 0; /* 1 to monitor center while respecting the monitor's reserved area, 0 to monitor center */ - - /* tagging - TAGCOUNT must be no greater than 31 */ - #define TAGCOUNT (9) -@@ -21,9 +22,9 @@ static const float fullscreen_bg[] = {0.0f, 0.0f, 0.0f, 1.0f}; /* You ca - static int log_level = WLR_ERROR; - - static const Rule rules[] = { -- /* app_id title tags mask isfloating monitor */ -- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ -- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ -+ /* app_id title tags mask isfloating monitor x y width height */ -+ { "Gimp_EXAMPLE", NULL, 0, 1, -1, -1, -1, 1000, 0.75 }, /* Start on currently visible tags floating, not tiled */ -+ { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1, -1, -1, -1, -1 }, /* Start on ONLY tag "9" */ - /* default/example rule: can be changed but cannot be eliminated; at least one rule must exist */ - }; - -diff --git a/dwl.c b/dwl.c -index 44f3ad9..801696a 100644 ---- a/dwl.c -+++ b/dwl.c -@@ -228,6 +228,10 @@ typedef struct { - uint32_t tags; - int isfloating; - int monitor; -+ int x; -+ int y; -+ float w; -+ float h; - } Rule; - - typedef struct { -@@ -482,6 +486,11 @@ applyrules(Client *c) - int i; - const Rule *r; - Monitor *mon = selmon, *m; -+ int newwidth; -+ int newheight; -+ int newx; -+ int newy; -+ int apply_resize = 0; - - appid = client_get_appid(c); - title = client_get_title(c); -@@ -495,12 +504,29 @@ applyrules(Client *c) - wl_list_for_each(m, &mons, link) { - if (r->monitor == i++) - mon = m; -+ if (c->isfloating || !mon->lt[mon->sellt]->arrange) { -+ /* client is floating or in floating layout */ -+ struct wlr_box b = respect_monitor_reserved_area ? mon->w : mon->m; -+ newwidth = (int)round((r->w >= 0) ? (r->w <= 1 ? b.width * r->w : r->w) : c->geom.width); -+ newheight = (int)round((r->h >= 0) ? (r->h <= 1 ? b.height * r->h : r->h) : c->geom.height); -+ newx = (int)round((r->x >= 0) ? (r->x <= 1 ? b.width * r->x + b.x : r->x + b.x) : c->geom.x); -+ newy = (int)round((r->y >= 0) ? (r->y <= 1 ? b.height * r->y + b.y : r->y + b.y) : c->geom.y); -+ apply_resize = 1; -+ } - } - } - } - - c->isfloating |= client_is_float_type(c); - setmon(c, mon, newtags); -+ if (apply_resize) { -+ resize(c, (struct wlr_box){ -+ .x = newx, -+ .y = newy, -+ .width = newwidth, -+ .height = newheight, -+ }, 1); -+ } - } - - void --- -2.52.0 - diff --git a/dwl/dragresize.patch b/dwl/dragresize.patch deleted file mode 100644 index 1e4cfe01..00000000 --- a/dwl/dragresize.patch +++ /dev/null @@ -1,210 +0,0 @@ -From 83ae7d4816a49f46063ab16ffecd32b2e7e61784 Mon Sep 17 00:00:00 2001 -From: choc -Date: Fri, 15 Sep 2023 11:45:16 +0800 -Subject: [PATCH] dragresize: implement rio-like window resizing - -select window to resize then drag out an area for it to occupy ---- - dwl.c | 132 +++++++++++++++++++++++++++++++++++++++++++--------------- - 1 file changed, 98 insertions(+), 34 deletions(-) - -diff --git a/dwl.c b/dwl.c -index dc0437e..843aa7a 100644 ---- a/dwl.c -+++ b/dwl.c -@@ -80,7 +80,7 @@ - #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 */ -+enum { CurNormal, CurPressed, CurSelect, CurMove, CurResize, CurBind }; /* cursor */ - enum { XDGShell, LayerShell, X11 }; /* client types */ - enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ - #ifdef XWAYLAND -@@ -603,15 +603,21 @@ buttonpress(struct wl_listener *listener, void *data) - - switch (event->state) { - case WLR_BUTTON_PRESSED: -- cursor_mode = CurPressed; - selmon = xytomon(cursor->x, cursor->y); -- if (locked) -+ if (locked) { -+ cursor_mode = CurPressed; - break; -+ } - -- /* Change focus if the button was _pressed_ over a client */ -- xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); -- if (c && (!client_is_unmanaged(c) || client_wants_focus(c))) -- focusclient(c, 1); -+ if (cursor_mode == CurNormal) -+ cursor_mode = CurPressed; -+ -+ if (cursor_mode != CurResize) { -+ /* Change focus if the button was _pressed_ over a client */ -+ xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); -+ if (c && (!client_is_unmanaged(c) || client_wants_focus(c))) -+ focusclient(c, 1); -+ } - - keyboard = wlr_seat_get_keyboard(seat); - mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; -@@ -624,17 +630,42 @@ buttonpress(struct wl_listener *listener, void *data) - } - break; - case WLR_BUTTON_RELEASED: -+ if (locked) { -+ cursor_mode = CurNormal; -+ break; -+ } - /* 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"); -+ switch (cursor_mode) { -+ case CurPressed: - cursor_mode = CurNormal; -- /* Drop the window off on its new monitor */ -- selmon = xytomon(cursor->x, cursor->y); -- setmon(grabc, selmon, 0); -+ case CurNormal: -+ break; -+ case CurSelect: - return; -- } else { -+ case CurResize: -+ /* a label can only be part of a statement - Wpedantic */ -+ { -+ int nw = abs((int) cursor->x - grabcx); -+ int nh = abs((int) cursor->y - grabcy); -+ if (nw > 1 && nh > 1) { -+ setfloating(grabc, 1); -+ resize(grabc, (struct wlr_box){.x = MIN(ROUND(cursor->x), grabcx), -+ .y = MIN(ROUND(cursor->y), grabcy), -+ .width = nw, .height = nh}, 1); -+ } -+ } -+ /* fallthrough */ -+ default: -+ /* TODO should reset to the pointer focus's current setcursor */ -+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); -+ /* Drop the window off on its new monitor */ -+ if (grabc && cursor_mode != CurBind) { -+ selmon = xytomon(cursor->x, cursor->y); -+ setmon(grabc, selmon, 0); -+ grabc = NULL; -+ } - cursor_mode = CurNormal; -+ return; - } - break; - } -@@ -1815,15 +1846,33 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d - wlr_scene_node_set_position(&drag_icon->node, (int)round(cursor->x), (int)round(cursor->y)); - - /* If we are currently grabbing the mouse, handle and return */ -- if (cursor_mode == CurMove) { -+ switch (cursor_mode) { -+ case CurSelect: -+ return; -+ case CurMove: - /* Move the grabbed client to the new position. */ - resize(grabc, (struct wlr_box){.x = (int)round(cursor->x) - grabcx, .y = (int)round(cursor->y) - grabcy, - .width = grabc->geom.width, .height = grabc->geom.height}, 1); - return; -- } else if (cursor_mode == CurResize) { -- resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y, -- .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1); -- return; -+ case CurResize: -+ { -+ int w, h, x, y; -+ if (!grabc) -+ return; -+ w = abs(grabcx - (int)round(cursor->x)); -+ h = abs(grabcy - (int)round(cursor->y)); -+ x = MIN(grabcx, (int)round(cursor->x)) - grabc->geom.x; -+ y = MIN(grabcy, (int)round(cursor->y)) - grabc->geom.y; -+ wlr_scene_rect_set_size(grabc->border[0], w, grabc->bw); -+ wlr_scene_rect_set_size(grabc->border[1], w, grabc->bw); -+ wlr_scene_rect_set_size(grabc->border[2], grabc->bw, h - 2 * grabc->bw); -+ wlr_scene_rect_set_size(grabc->border[3], grabc->bw, h - 2 * grabc->bw); -+ wlr_scene_node_set_position(&grabc->border[0]->node, x, y); -+ wlr_scene_node_set_position(&grabc->border[1]->node, x, y + h - grabc->bw); -+ wlr_scene_node_set_position(&grabc->border[2]->node, x, y + grabc->bw); -+ wlr_scene_node_set_position(&grabc->border[3]->node, x + w - grabc->bw, y + grabc->bw); -+ return; -+ } - } - - /* If there's no client surface under the cursor, set the cursor image to a -@@ -1853,29 +1902,43 @@ motionrelative(struct wl_listener *listener, void *data) - void - moveresize(const Arg *arg) - { -- if (cursor_mode != CurNormal && cursor_mode != CurPressed) -- return; -- xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL); -- if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen) -+ /* Consider global select bool instead of this + CurSelect enum */ -+ bool selected = (cursor_mode == CurSelect); -+ if (!selected) { -+ if (cursor_mode != CurNormal && cursor_mode != CurPressed) -+ return; -+ xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL); -+ } -+ -+ if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen) { -+ grabc = NULL; -+ cursor_mode = CurNormal; - return; -+ } - -- /* Float the window and tell motionnotify to grab it */ -- setfloating(grabc, 1); -+ /* TODO: factor out selected bool */ - switch (cursor_mode = arg->ui) { -+ case CurResize: -+ if (!selected) break; -+ grabcx = ROUND(cursor->x); -+ grabcy = ROUND(cursor->y); -+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "tcross"); -+ return; - case CurMove: - grabcx = (int)round(cursor->x) - grabc->geom.x; - grabcy = (int)round(cursor->y) - grabc->geom.y; -+ setfloating(grabc, 1); - wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur"); -- break; -- case CurResize: -- /* Doesn't work for X11 output - the next absolute motion event -- * returns the cursor to where it started */ -- wlr_cursor_warp_closest(cursor, NULL, -- grabc->geom.x + grabc->geom.width, -- grabc->geom.y + grabc->geom.height); -- wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); -- break; -+ return; -+ default: -+ grabc = NULL; -+ cursor_mode = CurNormal; -+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); -+ return; - } -+ -+ cursor_mode = CurSelect; -+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "crosshair"); - } - - void -@@ -2149,6 +2212,7 @@ resize(Client *c, struct wlr_box geo, int interact) - wlr_scene_rect_set_size(c->border[1], c->geom.width, c->bw); - wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - 2 * c->bw); - wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - 2 * c->bw); -+ wlr_scene_node_set_position(&c->border[0]->node, 0, 0); - wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - 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); --- -2.43.0 - diff --git a/dwl/dwl-v0.7/CHANGELOG.md b/dwl/dwl-v0.7/CHANGELOG.md deleted file mode 100644 index 3a299c46..00000000 --- a/dwl/dwl-v0.7/CHANGELOG.md +++ /dev/null @@ -1,200 +0,0 @@ -# Changelog - -* [0.7](#0.7) -* [0.6](#0.6) -* [0.5](#0.5) - - -## 0.7 - -See also [0.6](#0.6) release notes. 0.7 builds against wlroots 0.18.x. - -### Added - -* Add support for the alpha-modifier-v1 protocol ([wlroots!4616][wlroots!4616]). -* dwl now will survive GPU resets ([#601][601]). - -[wlroots!4616]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4616 -[601]: https://codeberg.org/dwl/dwl/issues/601 - - -### Fixed - -* Crash when re-mapping unmapped clients. - - -### Contributors - -Guido Cella -Lennart Jablonka - - -## 0.6 - -### Added - -* Add `rootcolor` to change the default background color ([#544][544]). -* Implement the wlr-virtual-pointer-unstable-v1 protocol ([#574][574]). -* Implement the pointer-constraints and relative-pointer protocols ([#317][317]) -* Implement the wlr-output-power-management protocol ([#599][599]) - -[544]: https://codeberg.org/dwl/dwl/pulls/544 -[574]: https://codeberg.org/dwl/dwl/pulls/574 -[317]: https://codeberg.org/dwl/dwl/issues/317 -[599]: https://codeberg.org/dwl/dwl/issues/559 - - -### Changed - -* Keyboards are now managed through keyboard groups ([#549][549]). -* Only the first matched keybinding is executed. -* Allow toggling the layout before selecting a different one ([#570][570]). -* Fullscreen clients are now rendered above wlr_layer_surfaces in the top layer - ([#609][609]). -* The default menu was changed from `bemenu-run` to `wmenu-run` ([#553][553]). -* The option `sloppyfocus` now replicates the dwm behavior ([#599][599]). -* Allow configure position of monitors with negative values. (-1, -1) is - used to auto-configure them ([#635][635]). -* dwl now kills the entire process group of `startup_cmd` -* The O_NONBLOCK flag is set for stdout. - -[549]: https://codeberg.org/dwl/dwl/pulls/549 -[570]: https://codeberg.org/dwl/dwl/pulls/570 -[609]: https://codeberg.org/dwl/dwl/pulls/609 -[553]: https://codeberg.org/dwl/dwl/issues/553 -[599]: https://codeberg.org/dwl/dwl/pulls/599 -[635]: https://codeberg.org/dwl/dwl/pulls/635 - - -### Removed - -* The SLOC limit is now removed ([#497][497]). - -[497]: https://codeberg.org/dwl/dwl/pulls/497 - - -### Fixed - -* Clients not having the correct border color when mapping. -* Compliance with the xdg-decoration-unstable-v1 ([#546][546]). -* dwl no longer sends negative values in xdg_toplevel.configure events. -* Crashes with disabled monitors ([#472][472]). - -[546]: https://codeberg.org/dwl/dwl/pulls/546 -[472]: https://codeberg.org/dwl/dwl/issues/472 - - -### Contributors - -Ben Jargowsky -Benjamin Chausse -David Donahue -Devin J. Pohly -Dima Krasner -Emil Miler -Forrest Bushstone -Guido Cella -Peter Hofmann -Rutherther -Squibid -choc -fictitiousexistence -korei999 -sewn -thanatos - - -## 0.5 - -### Added - -* Allow configure x and y position of outputs ([#301][301]) -* Implement repeatable keybindings ([#368][368]) -* Print app id in printstatus() output ([#381][381]) -* Display client count in monocle symbol ([#387][387]) -* Export XCURSOR_SIZE to fix apps using an older version of Qt ([#425][425]) -* Support for wp-fractional-scale-v1 (through wlr_scene: [wlroots!3511][wlroots!3511]) -* dwl now sends `wl_surface.preferred_buffer_scale` (through wlr_scene: [wlroots!4269][wlroots!4269]) -* Add support for xdg-shell v6 ([#465][465]) -* Add support for wp-cursor-shape-v1 ([#444][444]) -* Add desktop file ([#484][484]) -* Add macro to easily configure colors ([#466][466]) -* Color of urgent clients are now red ([#494][494]) -* New flag `-d` and option `log_level` to change the wlroots debug level -* Add CHANGELOG.md ([#501][501]) - -[301]: https://github.com/djpohly/dwl/pull/301 -[368]: https://github.com/djpohly/dwl/pull/368 -[381]: https://github.com/djpohly/dwl/pull/381 -[387]: https://github.com/djpohly/dwl/issues/387 -[425]: https://github.com/djpohly/dwl/pull/425 -[wlroots!4269]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4269 -[wlroots!3511]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3511 -[465]: https://github.com/djpohly/dwl/pull/465 -[444]: https://github.com/djpohly/dwl/pull/444 -[484]: https://github.com/djpohly/dwl/pull/484 -[466]: https://github.com/djpohly/dwl/issues/466 -[494]: https://github.com/djpohly/dwl/pull/494 -[501]: https://github.com/djpohly/dwl/pull/501 - - -### Changed - -* Replace `tags` with `TAGCOUNT` in config.def.h ([#403][403]) -* Pop ups are now destroyed when focusing another client ([#408][408]) -* dwl does not longer respect size hints, instead clip windows if they are - larger than they should be ([#455][455]) -* The version of wlr-layer-shell-unstable-v1 was lowered to 3 (from 4) -* Use the same border color as dwm ([#494][494]) - -[403]: https://github.com/djpohly/dwl/pull/403 -[408]: https://github.com/djpohly/dwl/pull/409 -[455]: https://github.com/djpohly/dwl/pull/455 -[494]: https://github.com/djpohly/dwl/pull/494 - - -### Removed - -* Remove unused `rootcolor` option ([#401][401]) -* Remove support for wlr-input-inhibitor-unstable-v1 ([#430][430]) -* Remove support for KDE idle protocol ([#431][431]) - -[401]: https://github.com/djpohly/dwl/pull/401 -[430]: https://github.com/djpohly/dwl/pull/430 -[431]: https://github.com/djpohly/dwl/pull/431 - - -### Fixed - -* Fix crash when creating a layer surface with all outputs disabled - ([#421][421]) -* Fix other clients being shown as focused if the focused client have pop ups - open ([#408][408]) -* Resize fullscreen clients when updating monitor mode -* dwl no longer crash at exit like sometimes did -* Fullscreen background appearing above clients ([#487][487]) -* Fix a segfault when user provides invalid xkb_rules ([#518][518]) - -[421]: https://github.com/djpohly/dwl/pull/421 -[408]: https://github.com/djpohly/dwl/issues/408 -[487]: https://github.com/djpohly/dwl/issues/487 -[518]: https://github.com/djpohly/dwl/pull/518 - - -### Contributors - -* A Frederick Christensen -* Angelo Antony -* Ben Collerson -* Devin J. Pohly -* Forrest Bushstone -* gan-of-culture -* godalming123 -* Job79 -* link2xt -* Micah Gorrell -* Nikita Ivanov -* Palanix -* pino-desktop -* Weiseguy -* Yves Zoundi diff --git a/dwl/dwl-v0.7/LICENSE b/dwl/dwl-v0.7/LICENSE deleted file mode 100644 index 658085a4..00000000 --- a/dwl/dwl-v0.7/LICENSE +++ /dev/null @@ -1,692 +0,0 @@ -dwl - dwm for Wayland - -Copyright © 2020 dwl team - -See also the files LICENSE.tinywl, LICENSE.dwm and LICENSE.sway. - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - ----- - - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/dwl/dwl-v0.7/LICENSE.dwm b/dwl/dwl-v0.7/LICENSE.dwm deleted file mode 100644 index 507e4dce..00000000 --- a/dwl/dwl-v0.7/LICENSE.dwm +++ /dev/null @@ -1,39 +0,0 @@ -Portions of dwl based on dwm code are used under the following license: - -MIT/X Consortium License - -© 2006-2019 Anselm R Garbe -© 2006-2009 Jukka Salmi -© 2006-2007 Sander van Dijk -© 2007-2011 Peter Hartlich -© 2007-2009 Szabolcs Nagy -© 2007-2009 Christof Musik -© 2007-2009 Premysl Hruby -© 2007-2008 Enno Gottox Boland -© 2008 Martin Hurton -© 2008 Neale Pickett -© 2009 Mate Nagy -© 2010-2016 Hiltjo Posthuma -© 2010-2012 Connor Lane Smith -© 2011 Christoph Lohmann <20h@r-36.net> -© 2015-2016 Quentin Rameau -© 2015-2016 Eric Pruitt -© 2016-2017 Markus Teich - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/dwl/dwl-v0.7/LICENSE.sway b/dwl/dwl-v0.7/LICENSE.sway deleted file mode 100644 index 3e0cacc2..00000000 --- a/dwl/dwl-v0.7/LICENSE.sway +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2016-2017 Drew DeVault - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/dwl/dwl-v0.7/LICENSE.tinywl b/dwl/dwl-v0.7/LICENSE.tinywl deleted file mode 100644 index 70236904..00000000 --- a/dwl/dwl-v0.7/LICENSE.tinywl +++ /dev/null @@ -1,127 +0,0 @@ -dwl is originally based on TinyWL, which is used under the following license: - -This work is licensed under CC0, which effectively puts it in the public domain. - ---- - -Creative Commons Legal Code - -CC0 1.0 Universal - - CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE - LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN - ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS - INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES - REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS - PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM - THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED - HEREUNDER. - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator -and subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for -the purpose of contributing to a commons of creative, cultural and -scientific works ("Commons") that the public can reliably and without fear -of later claims of infringement build upon, modify, incorporate in other -works, reuse and redistribute as freely as possible in any form whatsoever -and for any purposes, including without limitation commercial purposes. -These owners may contribute to the Commons to promote the ideal of a free -culture and the further production of creative, cultural and scientific -works, or to gain reputation or greater distribution for their Work in -part through the use and efforts of others. - -For these and/or other purposes and motivations, and without any -expectation of additional consideration or compensation, the person -associating CC0 with a Work (the "Affirmer"), to the extent that he or she -is an owner of Copyright and Related Rights in the Work, voluntarily -elects to apply CC0 to the Work and publicly distribute the Work under its -terms, with knowledge of his or her Copyright and Related Rights in the -Work and the meaning and intended legal effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not -limited to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, - communicate, and translate a Work; - ii. moral rights retained by the original author(s) and/or performer(s); -iii. publicity and privacy rights pertaining to a person's image or - likeness depicted in a Work; - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - v. rights protecting the extraction, dissemination, use and reuse of data - in a Work; - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation - thereof, including any amended or successor version of such - directive); and -vii. other similar, equivalent or corresponding rights throughout the - world based on applicable law or treaty, and any national - implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention -of, applicable law, Affirmer hereby overtly, fully, permanently, -irrevocably and unconditionally waives, abandons, and surrenders all of -Affirmer's Copyright and Related Rights and associated claims and causes -of action, whether now known or unknown (including existing as well as -future claims and causes of action), in the Work (i) in all territories -worldwide, (ii) for the maximum duration provided by applicable law or -treaty (including future time extensions), (iii) in any current or future -medium and for any number of copies, and (iv) for any purpose whatsoever, -including without limitation commercial, advertising or promotional -purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each -member of the public at large and to the detriment of Affirmer's heirs and -successors, fully intending that such Waiver shall not be subject to -revocation, rescission, cancellation, termination, or any other legal or -equitable action to disrupt the quiet enjoyment of the Work by the public -as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason -be judged legally invalid or ineffective under applicable law, then the -Waiver shall be preserved to the maximum extent permitted taking into -account Affirmer's express Statement of Purpose. In addition, to the -extent the Waiver is so judged Affirmer hereby grants to each affected -person a royalty-free, non transferable, non sublicensable, non exclusive, -irrevocable and unconditional license to exercise Affirmer's Copyright and -Related Rights in the Work (i) in all territories worldwide, (ii) for the -maximum duration provided by applicable law or treaty (including future -time extensions), (iii) in any current or future medium and for any number -of copies, and (iv) for any purpose whatsoever, including without -limitation commercial, advertising or promotional purposes (the -"License"). The License shall be deemed effective as of the date CC0 was -applied by Affirmer to the Work. Should any part of the License for any -reason be judged legally invalid or ineffective under applicable law, such -partial invalidity or ineffectiveness shall not invalidate the remainder -of the License, and in such case Affirmer hereby affirms that he or she -will not (i) exercise any of his or her remaining Copyright and Related -Rights in the Work or (ii) assert any associated claims and causes of -action with respect to the Work, in either case contrary to Affirmer's -express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - b. Affirmer offers the Work as-is and makes no representations or - warranties of any kind concerning the Work, express, implied, - statutory or otherwise, including without limitation warranties of - title, merchantability, fitness for a particular purpose, non - infringement, or the absence of latent or other defects, accuracy, or - the present or absence of errors, whether or not discoverable, all to - the greatest extent permissible under applicable law. - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without - limitation any person's Copyright and Related Rights in the Work. - Further, Affirmer disclaims responsibility for obtaining any necessary - consents, permissions or other rights required for any use of the - Work. - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to - this CC0 or use of the Work. diff --git a/dwl/dwl-v0.7/Makefile b/dwl/dwl-v0.7/Makefile deleted file mode 100644 index 3358bae9..00000000 --- a/dwl/dwl-v0.7/Makefile +++ /dev/null @@ -1,78 +0,0 @@ -.POSIX: -.SUFFIXES: - -include config.mk - -# flags for compiling -DWLCPPFLAGS = -I. -DWLR_USE_UNSTABLE -D_POSIX_C_SOURCE=200809L \ - -DVERSION=\"$(VERSION)\" $(XWAYLAND) -DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement \ - -Wno-unused-parameter -Wshadow -Wunused-macros -Werror=strict-prototypes \ - -Werror=implicit -Werror=return-type -Werror=incompatible-pointer-types \ - -Wfloat-conversion - -# CFLAGS / LDFLAGS -PKGS = wlroots-0.18 wayland-server xkbcommon libinput $(XLIBS) -DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) -LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` -lm $(LIBS) - -all: dwl -dwl: dwl.o util.o - $(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ -dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \ - pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \ - wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h -util.o: util.c util.h - -# wayland-scanner is a tool which generates C headers and rigging for Wayland -# protocols, which are specified in XML. wlroots requires you to rig these up -# to your build system yourself and provide them in the include path. -WAYLAND_SCANNER = `$(PKG_CONFIG) --variable=wayland_scanner wayland-scanner` -WAYLAND_PROTOCOLS = `$(PKG_CONFIG) --variable=pkgdatadir wayland-protocols` - -cursor-shape-v1-protocol.h: - $(WAYLAND_SCANNER) enum-header \ - $(WAYLAND_PROTOCOLS)/staging/cursor-shape/cursor-shape-v1.xml $@ -pointer-constraints-unstable-v1-protocol.h: - $(WAYLAND_SCANNER) enum-header \ - $(WAYLAND_PROTOCOLS)/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml $@ -wlr-layer-shell-unstable-v1-protocol.h: - $(WAYLAND_SCANNER) enum-header \ - protocols/wlr-layer-shell-unstable-v1.xml $@ -wlr-output-power-management-unstable-v1-protocol.h: - $(WAYLAND_SCANNER) server-header \ - protocols/wlr-output-power-management-unstable-v1.xml $@ -xdg-shell-protocol.h: - $(WAYLAND_SCANNER) server-header \ - $(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@ - -config.h: - cp config.def.h $@ -clean: - rm -f dwl *.o *-protocol.h - -dist: clean - mkdir -p dwl-$(VERSION) - cp -R LICENSE* Makefile CHANGELOG.md README.md client.h config.def.h \ - config.mk protocols dwl.1 dwl.c util.c util.h dwl.desktop \ - dwl-$(VERSION) - tar -caf dwl-$(VERSION).tar.gz dwl-$(VERSION) - rm -rf dwl-$(VERSION) - -install: dwl - mkdir -p $(DESTDIR)$(PREFIX)/bin - cp -f dwl $(DESTDIR)$(PREFIX)/bin - chmod 755 $(DESTDIR)$(PREFIX)/bin/dwl - mkdir -p $(DESTDIR)$(MANDIR)/man1 - cp -f dwl.1 $(DESTDIR)$(MANDIR)/man1 - chmod 644 $(DESTDIR)$(MANDIR)/man1/dwl.1 - mkdir -p $(DESTDIR)$(DATADIR)/wayland-sessions - cp -f dwl.desktop $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop - chmod 644 $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop -uninstall: - rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(MANDIR)/man1/dwl.1 \ - $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop - -.SUFFIXES: .c .o -.c.o: - $(CC) $(CPPFLAGS) $(DWLCFLAGS) -o $@ -c $< diff --git a/dwl/dwl-v0.7/README.md b/dwl/dwl-v0.7/README.md deleted file mode 100644 index aa95baba..00000000 --- a/dwl/dwl-v0.7/README.md +++ /dev/null @@ -1,201 +0,0 @@ -# dwl - dwm for Wayland - -Join us on our IRC channel: [#dwl on Libera Chat] -Or on our [Discord server]. - -dwl is a compact, hackable compositor for [Wayland] based on [wlroots]. It is -intended to fill the same space in the Wayland world that dwm does in X11, -primarily in terms of functionality, and secondarily in terms of -philosophy. Like dwm, dwl is: - -- Easy to understand, hack on, and extend with patches -- One C source file (or a very small number) configurable via `config.h` -- Tied to as few external dependencies as possible - -## Getting Started: - -### **dwl branch 0.7 and releases based upon 0.7 build against [wlroots] 0.18** - -### Latest semi-stable [release] -This is probably where you want to start. This builds against the dependent -packages' versions currently shipping in major distributions. If your -distribution's wlroots version is older, use an earlier dwl [release] or [0.x -branch]. - -### Development branch [main] -Active development progresses on the `main` branch. The `main` branch is built -against a late (and often changing) git commit of wlroots. While the adventurous -are welcome to use `main`, it is a rocky road. Using `main` requires that the -user be willing to chase git commits of wlroots. Testing development pull -requests may involve merging unmerged pull requests in [wlroots]' git repository -and/or git commits of wayland. - -### Building dwl -dwl has the following dependencies: -- libinput -- wayland -- wlroots (compiled with the libinput backend) -- xkbcommon -- wayland-protocols (compile-time only) -- pkg-config (compile-time only) - -dwl has the following additional dependencies if XWayland support is enabled: -- libxcb -- libxcb-wm -- wlroots (compiled with X11 support) -- Xwayland (runtime only) - -Install these (and their `-devel` versions if your distro has separate -development packages) and run `make`. If you wish to build against a released -version of wlroots (*you probably do*), use a [release] or a [0.x branch]. If -you want to use the unstable development `main` branch, you need to use the git -version of [wlroots]. - -To enable XWayland, you should uncomment its flags in `config.mk`. - -## Configuration - -All configuration is done by editing `config.h` and recompiling, in the same -manner as dwm. There is no way to separately restart the window manager in -Wayland without restarting the entire display server, so any changes will take -effect the next time dwl is executed. - -As in the dwm community, we encourage users to share patches they have -created. Check out the [dwl-patches] repository! - -## Running dwl - -dwl can be run on any of the backends supported by wlroots. This means you can -run it as a separate window inside either an X11 or Wayland session, as well as -directly from a VT console. Depending on your distro's setup, you may need to -add your user to the `video` and `input` groups before you can run dwl on a -VT. If you are using `elogind` or `systemd-logind` you need to install polkit; -otherwise you need to add yourself in the `seat` group and enable/start the -seatd daemon. - -When dwl is run with no arguments, it will launch the server and begin handling -any shortcuts configured in `config.h`. There is no status bar or other -decoration initially; these are instead clients that can be run within the -Wayland session. Do note that the default background color is black. This can be -modified in `config.h`. - -If you would like to run a script or command automatically at startup, you can -specify the command using the `-s` option. This command will be executed as a -shell command using `/bin/sh -c`. It serves a similar function to `.xinitrc`, -but differs in that the display server will not shut down when this process -terminates. Instead, dwl will send this process a SIGTERM at shutdown and wait -for it to terminate (if it hasn't already). This makes it ideal for execing into -a user service manager like [s6], [anopa], [runit], [dinit], or [`systemd ---user`]. - -Note: The `-s` command is run as a *child process* of dwl, which means that it -does not have the ability to affect the environment of dwl or of any processes -that it spawns. If you need to set environment variables that affect the entire -dwl session, these must be set prior to running dwl. For example, Wayland -requires a valid `XDG_RUNTIME_DIR`, which is usually set up by a session manager -such as `elogind` or `systemd-logind`. If your system doesn't do this -automatically, you will need to configure it prior to launching `dwl`, e.g.: - - export XDG_RUNTIME_DIR=/tmp/xdg-runtime-$(id -u) - mkdir -p $XDG_RUNTIME_DIR - dwl - -### Status information - -Information about selected layouts, current window title, app-id, and -selected/occupied/urgent tags is written to the stdin of the `-s` command (see -the `printstatus()` function for details). This information can be used to -populate an external status bar with a script that parses the -information. Failing to read this information will cause dwl to block, so if you -do want to run a startup command that does not consume the status information, -you can close standard input with the `<&-` shell redirection, for example: - - dwl -s 'foot --server <&-' - -If your startup command is a shell script, you can achieve the same inside the -script with the line - - exec <&- - -To get a list of status bars that work with dwl consult our [wiki]. - -## Replacements for X applications - -You can find a [list of useful resources on our wiki]. - -## Background - -dwl is not meant to provide every feature under the sun. Instead, like dwm, it -sticks to features which are necessary, simple, and straightforward to implement -given the base on which it is built. Implemented default features are: - -- Any features provided by dwm/Xlib: simple window borders, tags, keybindings, - client rules, mouse move/resize. Providing a built-in status bar is an - exception to this goal, to avoid dependencies on font rendering and/or drawing - libraries when an external bar could work well. -- Configurable multi-monitor layout support, including position and rotation -- Configurable HiDPI/multi-DPI support -- Idle-inhibit protocol which lets applications such as mpv disable idle - monitoring -- Provide information to external status bars via stdout/stdin -- Urgency hints via xdg-activate protocol -- Support screen lockers via ext-session-lock-v1 protocol -- Various Wayland protocols -- XWayland support as provided by wlroots (can be enabled in `config.mk`) -- Zero flickering - Wayland users naturally expect that "every frame is perfect" -- Layer shell popups (used by Waybar) -- Damage tracking provided by scenegraph API - -Given the Wayland architecture, dwl has to implement features from dwm **and** -the xorg-server. Because of this, it is impossible to maintain the original -project goal of 2000 SLOC and have a reasonably complete compositor with -features comparable to dwm. However, this does not mean that the code will grow -indiscriminately. We will try to keep the code as small as possible. - -Features under consideration (possibly as patches) are: - -- Protocols made trivial by wlroots -- Implement the text-input and input-method protocols to support IME once ibus - implements input-method v2 (see https://github.com/ibus/ibus/pull/2256 and - https://codeberg.org/dwl/dwl/pulls/235) - -Feature *non-goals* for the main codebase include: - -- Client-side decoration (any more than is necessary to tell the clients not to) -- Client-initiated window management, such as move, resize, and close, which can - be done through the compositor -- Animations and visual effects - -## Acknowledgements - -dwl began by extending the TinyWL example provided (CC0) by the sway/wlroots -developers. This was made possible in many cases by looking at how sway -accomplished something, then trying to do the same in as suckless a way as -possible. - -Many thanks to suckless.org and the dwm developers and community for the -inspiration, and to the various contributors to the project, including: - -- **Devin J. Pohly for creating and nurturing the fledgling project** -- Alexander Courtis for the XWayland implementation -- Guido Cella for the layer-shell protocol implementation, patch maintenance, - and for helping to keep the project running -- Stivvo for output management and fullscreen support, and patch maintenance - - -[`systemd --user`]: https://wiki.archlinux.org/title/Systemd/User -[#dwl on Libera Chat]: https://web.libera.chat/?channels=#dwl -[0.7-rc1]: https://codeberg.org/dwl/dwl/releases/tag/v0.7-rc1 -[0.x branch]: https://codeberg.org/dwl/dwl/branches -[anopa]: https://jjacky.com/anopa/ -[dinit]: https://davmac.org/projects/dinit/ -[dwl-patches]: https://codeberg.org/dwl/dwl-patches -[list of useful resources on our wiki]: https://codeberg.org/dwl/dwl/wiki/Home#migrating-from-x -[main]: https://codeberg.org/dwl/dwl/src/branch/main -[release]: https://codeberg.org/dwl/dwl/releases -[runit]: http://smarden.org/runit/faq.html#userservices -[s6]: https://skarnet.org/software/s6/ -[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots/ -[wiki]: https://codeberg.org/dwl/dwl/wiki/Home#compatible-status-bars -[Discord server]: https://discord.gg/jJxZnrGPWN -[Wayland]: https://wayland.freedesktop.org/ diff --git a/dwl/dwl-v0.7/client.h b/dwl/dwl-v0.7/client.h deleted file mode 100644 index 42f225f9..00000000 --- a/dwl/dwl-v0.7/client.h +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Attempt to consolidate unavoidable suck into one file, away from dwl.c. This - * file is not meant to be pretty. We use a .h file with static inline - * functions instead of a separate .c module, or function pointers like sway, so - * that they will simply compile out if the chosen #defines leave them unused. - */ - -/* Leave these functions first; they're used in the others */ -static inline int -client_is_x11(Client *c) -{ -#ifdef XWAYLAND - return c->type == X11; -#endif - return 0; -} - -static inline struct wlr_surface * -client_surface(Client *c) -{ -#ifdef XWAYLAND - if (client_is_x11(c)) - return c->surface.xwayland->surface; -#endif - return c->surface.xdg->surface; -} - -static inline int -toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc, LayerSurface **pl) -{ - struct wlr_xdg_surface *xdg_surface, *tmp_xdg_surface; - struct wlr_surface *root_surface; - struct wlr_layer_surface_v1 *layer_surface; - Client *c = NULL; - LayerSurface *l = NULL; - int type = -1; -#ifdef XWAYLAND - struct wlr_xwayland_surface *xsurface; -#endif - - if (!s) - return -1; - root_surface = wlr_surface_get_root_surface(s); - -#ifdef XWAYLAND - if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(root_surface))) { - c = xsurface->data; - type = c->type; - goto end; - } -#endif - - if ((layer_surface = wlr_layer_surface_v1_try_from_wlr_surface(root_surface))) { - l = layer_surface->data; - type = LayerShell; - goto end; - } - - 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; - } - } - -end: - if (pl) - *pl = l; - if (pc) - *pc = c; - return type; -} - -/* The others */ -static inline void -client_activate_surface(struct wlr_surface *s, int activated) -{ - struct wlr_xdg_toplevel *toplevel; -#ifdef XWAYLAND - struct wlr_xwayland_surface *xsurface; - if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(s))) { - wlr_xwayland_surface_activate(xsurface, activated); - return; - } -#endif - if ((toplevel = wlr_xdg_toplevel_try_from_wlr_surface(s))) - wlr_xdg_toplevel_set_activated(toplevel, activated); -} - -static inline uint32_t -client_set_bounds(Client *c, int32_t width, int32_t height) -{ -#ifdef XWAYLAND - if (client_is_x11(c)) - return 0; -#endif - 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 const char * -client_get_appid(Client *c) -{ -#ifdef XWAYLAND - if (client_is_x11(c)) - return c->surface.xwayland->class; -#endif - 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) -{ -#ifdef XWAYLAND - if (client_is_x11(c)) { - geom->x = c->surface.xwayland->x; - geom->y = c->surface.xwayland->y; - geom->width = c->surface.xwayland->width; - geom->height = c->surface.xwayland->height; - return; - } -#endif - wlr_xdg_surface_get_geometry(c->surface.xdg, geom); -} - -static inline Client * -client_get_parent(Client *c) -{ - Client *p = NULL; -#ifdef XWAYLAND - if (client_is_x11(c)) { - if (c->surface.xwayland->parent) - toplevel_from_wlr_surface(c->surface.xwayland->parent->surface, &p, NULL); - return p; - } -#endif - if (c->surface.xdg->toplevel->parent) - toplevel_from_wlr_surface(c->surface.xdg->toplevel->parent->base->surface, &p, NULL); - return p; -} - -static inline int -client_has_children(Client *c) -{ -#ifdef XWAYLAND - if (client_is_x11(c)) - return !wl_list_empty(&c->surface.xwayland->children); -#endif - /* surface.xdg->link is never empty because it always contains at least the - * surface itself. */ - return wl_list_length(&c->surface.xdg->link) > 1; -} - -static inline const char * -client_get_title(Client *c) -{ -#ifdef XWAYLAND - if (client_is_x11(c)) - return c->surface.xwayland->title; -#endif - return c->surface.xdg->toplevel->title; -} - -static inline int -client_is_float_type(Client *c) -{ - 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 (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 - - 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 -client_is_rendered_on_mon(Client *c, Monitor *m) -{ - /* This is needed for when you don't want to check formal assignment, - * but rather actual displaying of the pixels. - * Usually VISIBLEON suffices and is also faster. */ - struct wlr_surface_output *s; - 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) - return 1; - return 0; -} - -static inline int -client_is_stopped(Client *c) -{ - int pid; - siginfo_t in = {0}; -#ifdef XWAYLAND - if (client_is_x11(c)) - return 0; -#endif - - wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL); - if (waitid(P_PID, pid, &in, WNOHANG|WCONTINUED|WSTOPPED|WNOWAIT) < 0) { - /* This process is not our child process, while is very unluckely that - * it is stopped, in order to do not skip frames assume that it is. */ - if (errno == ECHILD) - return 1; - } else if (in.si_pid) { - if (in.si_code == CLD_STOPPED || in.si_code == CLD_TRAPPED) - return 1; - if (in.si_code == CLD_CONTINUED) - return 0; - } - - return 0; -} - -static inline int -client_is_unmanaged(Client *c) -{ -#ifdef XWAYLAND - if (client_is_x11(c)) - return c->surface.xwayland->override_redirect; -#endif - return 0; -} - -static inline void -client_notify_enter(struct wlr_surface *s, struct wlr_keyboard *kb) -{ - if (kb) - wlr_seat_keyboard_notify_enter(seat, s, kb->keycodes, - kb->num_keycodes, &kb->modifiers); - else - wlr_seat_keyboard_notify_enter(seat, s, NULL, 0, NULL); -} - -static inline void -client_restack_surface(Client *c) -{ -#ifdef XWAYLAND - if (client_is_x11(c)) - wlr_xwayland_surface_restack(c->surface.xwayland, NULL, - XCB_STACK_MODE_ABOVE); -#endif - return; -} - -static inline void -client_send_close(Client *c) -{ -#ifdef XWAYLAND - if (client_is_x11(c)) { - wlr_xwayland_surface_close(c->surface.xwayland); - return; - } -#endif - wlr_xdg_toplevel_send_close(c->surface.xdg->toplevel); -} - -static inline void -client_set_border_color(Client *c, const float color[static 4]) -{ - int i; - for (i = 0; i < 4; i++) - wlr_scene_rect_set_color(c->border[i], color); -} - -static inline void -client_set_fullscreen(Client *c, int fullscreen) -{ -#ifdef XWAYLAND - if (client_is_x11(c)) { - wlr_xwayland_surface_set_fullscreen(c->surface.xwayland, fullscreen); - return; - } -#endif - wlr_xdg_toplevel_set_fullscreen(c->surface.xdg->toplevel, fullscreen); -} - -static inline uint32_t -client_set_size(Client *c, uint32_t width, uint32_t height) -{ -#ifdef XWAYLAND - if (client_is_x11(c)) { - wlr_xwayland_surface_configure(c->surface.xwayland, - c->geom.x + c->bw, c->geom.y + c->bw, width, height); - return 0; - } -#endif - if ((int32_t)width == c->surface.xdg->toplevel->current.width - && (int32_t)height == c->surface.xdg->toplevel->current.height) - return 0; - return wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, (int32_t)width, (int32_t)height); -} - -static inline void -client_set_tiled(Client *c, uint32_t edges) -{ -#ifdef XWAYLAND - if (client_is_x11(c)) - return; -#endif - if (wl_resource_get_version(c->surface.xdg->toplevel->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 void -client_set_suspended(Client *c, int suspended) -{ -#ifdef XWAYLAND - if (client_is_x11(c)) - return; -#endif - - wlr_xdg_toplevel_set_suspended(c->surface.xdg->toplevel, suspended); -} - -static inline int -client_wants_focus(Client *c) -{ -#ifdef XWAYLAND - return client_is_unmanaged(c) - && wlr_xwayland_or_surface_wants_focus(c->surface.xwayland) - && wlr_xwayland_icccm_input_model(c->surface.xwayland) != WLR_ICCCM_INPUT_MODEL_NONE; -#endif - return 0; -} - -static inline int -client_wants_fullscreen(Client *c) -{ -#ifdef XWAYLAND - if (client_is_x11(c)) - return c->surface.xwayland->fullscreen; -#endif - return c->surface.xdg->toplevel->requested.fullscreen; -} diff --git a/dwl/dwl-v0.7/config.def.h b/dwl/dwl-v0.7/config.def.h deleted file mode 100644 index 22d2171d..00000000 --- a/dwl/dwl-v0.7/config.def.h +++ /dev/null @@ -1,176 +0,0 @@ -/* Taken from https://github.com/djpohly/dwl/issues/466 */ -#define COLOR(hex) { ((hex >> 24) & 0xFF) / 255.0f, \ - ((hex >> 16) & 0xFF) / 255.0f, \ - ((hex >> 8) & 0xFF) / 255.0f, \ - (hex & 0xFF) / 255.0f } -/* appearance */ -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 unsigned int borderpx = 1; /* border pixel of windows */ -static const float rootcolor[] = COLOR(0x222222ff); -static const float bordercolor[] = COLOR(0x444444ff); -static const float focuscolor[] = COLOR(0x005577ff); -static const float urgentcolor[] = COLOR(0xff0000ff); -/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ -static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ - -/* tagging - TAGCOUNT must be no greater than 31 */ -#define TAGCOUNT (9) - -/* logging */ -static int log_level = WLR_ERROR; - -/* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ -static const Rule rules[] = { - /* app_id title tags mask isfloating monitor */ - /* examples: */ - { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ - { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ -}; - -/* layout(s) */ -static const Layout layouts[] = { - /* symbol arrange function */ - { "[]=", tile }, - { "><>", NULL }, /* no layout function means floating behavior */ - { "[M]", monocle }, -}; - -/* monitors */ -/* (x=-1, y=-1) is reserved as an "autoconfigure" monitor position indicator - * WARNING: negative values other than (-1, -1) cause problems with Xwayland clients - * https://gitlab.freedesktop.org/xorg/xserver/-/issues/899 -*/ -/* NOTE: ALWAYS add a fallback rule, even if you are completely sure it won't be used */ -static const MonitorRule monrules[] = { - /* name mfact nmaster scale layout rotate/reflect x y */ - /* example of a HiDPI laptop monitor: - { "eDP-1", 0.5f, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, - */ - /* defaults */ - { NULL, 0.55f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, -}; - -/* keyboard */ -static const struct xkb_rule_names xkb_rules = { - /* can specify fields: rules, model, layout, variant, options */ - /* example: - .options = "ctrl:nocaps", - */ - .options = NULL, -}; - -static const int repeat_rate = 25; -static const int repeat_delay = 600; - -/* Trackpad */ -static const int tap_to_click = 1; -static const int tap_and_drag = 1; -static const int drag_lock = 1; -static const int natural_scrolling = 0; -static const int disable_while_typing = 1; -static const int left_handed = 0; -static const int middle_button_emulation = 0; -/* You can choose between: -LIBINPUT_CONFIG_SCROLL_NO_SCROLL -LIBINPUT_CONFIG_SCROLL_2FG -LIBINPUT_CONFIG_SCROLL_EDGE -LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN -*/ -static const enum libinput_config_scroll_method scroll_method = LIBINPUT_CONFIG_SCROLL_2FG; - -/* You can choose between: -LIBINPUT_CONFIG_CLICK_METHOD_NONE -LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS -LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER -*/ -static const enum libinput_config_click_method click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; - -/* You can choose between: -LIBINPUT_CONFIG_SEND_EVENTS_ENABLED -LIBINPUT_CONFIG_SEND_EVENTS_DISABLED -LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE -*/ -static const uint32_t send_events_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; - -/* You can choose between: -LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT -LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE -*/ -static const enum libinput_config_accel_profile accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; -static const double accel_speed = 0.0; - -/* You can choose between: -LIBINPUT_CONFIG_TAP_MAP_LRM -- 1/2/3 finger tap maps to left/right/middle -LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right -*/ -static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM; - -/* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */ -#define MODKEY WLR_MODIFIER_ALT - -#define TAGKEYS(KEY,SKEY,TAG) \ - { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ - { MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \ - { MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \ - { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} } - -/* helper for spawning shell commands in the pre dwm-5.0 fashion */ -#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } - -/* commands */ -static const char *termcmd[] = { "foot", NULL }; -static const char *menucmd[] = { "wmenu-run", NULL }; - -static const Key keys[] = { - /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ - /* modifier key function argument */ - { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, - { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, - { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, - { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, - { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, - { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, - { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, - { MODKEY, XKB_KEY_Return, zoom, {0} }, - { MODKEY, XKB_KEY_Tab, view, {0} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, - { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, - { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, - { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, - { MODKEY, XKB_KEY_space, setlayout, {0} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, - { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, - { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, - { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, - { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} }, - TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0), - TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1), - TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2), - TAGKEYS( XKB_KEY_4, XKB_KEY_dollar, 3), - TAGKEYS( XKB_KEY_5, XKB_KEY_percent, 4), - TAGKEYS( XKB_KEY_6, XKB_KEY_asciicircum, 5), - TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6), - TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7), - TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8), - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, quit, {0} }, - - /* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */ - { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} }, - /* Ctrl-Alt-Fx is used to switch to another VT, if you don't know what a VT is - * do not remove them. - */ -#define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_XF86Switch_VT_##n, chvt, {.ui = (n)} } - CHVT(1), CHVT(2), CHVT(3), CHVT(4), CHVT(5), CHVT(6), - CHVT(7), CHVT(8), CHVT(9), CHVT(10), CHVT(11), CHVT(12), -}; - -static const Button buttons[] = { - { MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, - { MODKEY, BTN_MIDDLE, togglefloating, {0} }, - { MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, -}; diff --git a/dwl/dwl-v0.7/config.h b/dwl/dwl-v0.7/config.h deleted file mode 100644 index 4cc09478..00000000 --- a/dwl/dwl-v0.7/config.h +++ /dev/null @@ -1,263 +0,0 @@ -/* Taken from https://github.com/djpohly/dwl/issues/466 */ -#define COLOR(hex) \ - {((hex >> 24) & 0xFF) / 255.0f, ((hex >> 16) & 0xFF) / 255.0f, \ - ((hex >> 8) & 0xFF) / 255.0f, (hex & 0xFF) / 255.0f} -/* appearance */ -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 unsigned int borderpx = 1; /* border pixel of windows */ -static const float rootcolor[] = COLOR(0x222222ff); -static const float bordercolor[] = COLOR(0x444444ff); -static const float focuscolor[] = COLOR(0x005577ff); -static const float urgentcolor[] = COLOR(0xff0000ff); -/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old - * behavior */ -static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, - 1.0f}; /* You can also use glsl colors */ -static int enableautoswallow = - 1; /* enables autoswallowing newly spawned clients */ - -/* tagging - TAGCOUNT must be no greater than 31 */ -#define TAGCOUNT (9) - -/* logging */ -static int log_level = WLR_ERROR; - -/* Autostart */ -static const char *const autostart[] = { - "swaybg", - "-i", - "/home/brian/Pictures/leaves.jpg", - "-m", - "fill", - NULL, - "gammastep", - "-b", - "0.95", - "-O", - "5500K", - NULL, - "foot", - "-c", - "/home/brian/.config/foot/bfoot.ini", - "/usr/bin/btop", - NULL, - - NULL /* terminate */ -}; - -/* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at - * least one example) */ -static const Rule rules[] = { - /* app_id title tags mask isfloating isterm - noswallow monitor */ - /* examples: */ - {"foot", NULL, 0, 0, 1, 1, -1}, - {"Gimp_EXAMPLE", NULL, 0, 1, 0, 0, - -1}, /* Start on currently visible tags floating, not tiled */ - {"firefox_EXAMPLE", NULL, 1 << 8, 0, 0, 0, -1}, /* Start on ONLY tag "9" */ -}; - -/* layout(s) */ -static const Layout layouts[] = { - /* symbol arrange function */ - {"[]=", tile}, - {"><>", NULL}, /* no layout function means floating behavior */ - {"[M]", monocle}, -}; - -/* monitors */ -/* (x=-1, y=-1) is reserved as an "autoconfigure" monitor position indicator - * WARNING: negative values other than (-1, -1) cause problems with Xwayland - * clients https://gitlab.freedesktop.org/xorg/xserver/-/issues/899 - */ -/* NOTE: ALWAYS add a fallback rule, even if you are completely sure it won't be - * used */ -static const MonitorRule monrules[] = { - /* name mfact nmaster scale layout rotate/reflect x y */ - /* example of a HiDPI laptop monitor: - { "eDP-1", 0.5f, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, - -1, -1 }, - */ - /* defaults */ - {NULL, 0.50f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1}, -}; - -/* keyboard */ -static const struct xkb_rule_names xkb_rules = { - /* can specify fields: rules, model, layout, variant, options */ - /* example: - .options = "ctrl:nocaps", - */ - .options = NULL, -}; - -static const int repeat_rate = 25; -static const int repeat_delay = 600; - -/* Trackpad */ -static const int tap_to_click = 1; -static const int tap_and_drag = 1; -static const int drag_lock = 1; -static const int natural_scrolling = 0; -static const int disable_while_typing = 1; -static const int left_handed = 0; -static const int middle_button_emulation = 0; -/* You can choose between: -LIBINPUT_CONFIG_SCROLL_NO_SCROLL -LIBINPUT_CONFIG_SCROLL_2FG -LIBINPUT_CONFIG_SCROLL_EDGE -LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN -*/ -static const enum libinput_config_scroll_method scroll_method = - LIBINPUT_CONFIG_SCROLL_2FG; - -/* You can choose between: -LIBINPUT_CONFIG_CLICK_METHOD_NONE -LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS -LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER -*/ -static const enum libinput_config_click_method click_method = - LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; - -/* You can choose between: -LIBINPUT_CONFIG_SEND_EVENTS_ENABLED -LIBINPUT_CONFIG_SEND_EVENTS_DISABLED -LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE -*/ -static const uint32_t send_events_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; - -/* You can choose between: -LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT -LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE -*/ -static const enum libinput_config_accel_profile accel_profile = - LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; -static const double accel_speed = 0.0; - -/* You can choose between: -LIBINPUT_CONFIG_TAP_MAP_LRM -- 1/2/3 finger tap maps to left/right/middle -LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right -*/ -static const enum libinput_config_tap_button_map button_map = - LIBINPUT_CONFIG_TAP_MAP_LRM; - -/* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */ -#define MODKEY WLR_MODIFIER_LOGO - -#define TAGKEYS(KEY, SKEY, TAG) \ - {MODKEY, KEY, view, {.ui = 1 << TAG}}, \ - {MODKEY | WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG}}, \ - {MODKEY | WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG}}, { \ - MODKEY | WLR_MODIFIER_CTRL | WLR_MODIFIER_SHIFT, SKEY, toggletag, { \ - .ui = 1 << TAG \ - } \ - } - -/* helper for spawning shell commands in the pre dwm-5.0 fashion */ -#define SHCMD(cmd) \ - { \ - .v = (const char *[]) { "/bin/sh", "-c", cmd, NULL } \ - } - -/* commands */ -static const char *termcmd[] = {"foot", NULL}; -static const char *menucmd[] = {"wmenu-run", NULL}; -static const char *librewolfcmd[] = {"librewolf-bin", NULL}; -static const char *chromiumcmd[] = {"chromium-bin", NULL}; -static const char *inkscapecmd[] = {"inkscape", NULL}; -static const char *gimpcmd[] = {"gimp", NULL}; -static const char *pcmanfmcmd[] = {"pcmanfm", NULL}; -static const char *keepassxccmd[] = {"keepassxc", NULL}; -static const char *libreofficecmd[] = {"libreoffice-bin", NULL}; -static const char *mousepadcmd[] = {"mousepad", NULL}; -static const char *virtmanagercmd[] = {"virt-manager", NULL}; -static const char *qalculatecmd[] = {"qalculate-qt", NULL}; - -static const Key keys[] = { - /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ - /* modifier key function argument */ - {MODKEY, XKB_KEY_Return, spawn, {.v = termcmd}}, - {MODKEY, XKB_KEY_d, spawn, {.v = menucmd}}, - {MODKEY, XKB_KEY_f, spawn, {.v = librewolfcmd}}, - {MODKEY, XKB_KEY_c, spawn, {.v = chromiumcmd}}, - {MODKEY, XKB_KEY_i, spawn, {.v = inkscapecmd}}, - {MODKEY, XKB_KEY_g, spawn, {.v = gimpcmd}}, - {MODKEY, XKB_KEY_p, spawn, {.v = pcmanfmcmd}}, - {MODKEY, XKB_KEY_k, spawn, {.v = keepassxccmd}}, - {MODKEY, XKB_KEY_n, spawn, {.v = libreofficecmd}}, - {MODKEY, XKB_KEY_m, spawn, {.v = mousepadcmd}}, - {MODKEY, XKB_KEY_v, spawn, {.v = virtmanagercmd}}, - {MODKEY, XKB_KEY_u, spawn, {.v = qalculatecmd}}, - {MODKEY, XKB_KEY_Left, setmfact, {.f = -0.025f}}, - {MODKEY, XKB_KEY_Right, setmfact, {.f = +0.025f}}, - {MODKEY | WLR_MODIFIER_SHIFT, XKB_KEY_Q, killclient, {0}}, - {MODKEY | WLR_MODIFIER_SHIFT, XKB_KEY_Escape, quit, {0}}, - {MODKEY, XKB_KEY_o, togglefloating, {0}}, - {MODKEY, XKB_KEY_j, focusstack, {.i = +1}}, - {MODKEY, XKB_KEY_k, focusstack, {.i = -1}}, - {MODKEY, XKB_KEY_i, incnmaster, {.i = +1}}, - {MODKEY, XKB_KEY_d, incnmaster, {.i = -1}}, - {MODKEY, XKB_KEY_Return, zoom, {0}}, - {MODKEY, XKB_KEY_Tab, view, {0}}, - // {MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]}}, - // {MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]}}, - // {MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]}}, - {MODKEY, XKB_KEY_space, setlayout, {0}}, - {MODKEY | WLR_MODIFIER_SHIFT, XKB_KEY_f, togglefullscreen, {0}}, - {MODKEY, XKB_KEY_a, toggleswallow, {0}}, - {MODKEY | WLR_MODIFIER_SHIFT, XKB_KEY_A, toggleautoswallow, {0}}, - {MODKEY, XKB_KEY_0, view, {.ui = ~0}}, - {MODKEY | WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0}}, - {MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT}}, - {MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT}}, - {MODKEY | WLR_MODIFIER_SHIFT, - XKB_KEY_less, - tagmon, - {.i = WLR_DIRECTION_LEFT}}, - {MODKEY | WLR_MODIFIER_SHIFT, - XKB_KEY_greater, - tagmon, - {.i = WLR_DIRECTION_RIGHT}}, - TAGKEYS(XKB_KEY_1, XKB_KEY_exclam, 0), - TAGKEYS(XKB_KEY_2, XKB_KEY_at, 1), - TAGKEYS(XKB_KEY_3, XKB_KEY_numbersign, 2), - TAGKEYS(XKB_KEY_4, XKB_KEY_dollar, 3), - TAGKEYS(XKB_KEY_5, XKB_KEY_percent, 4), - TAGKEYS(XKB_KEY_6, XKB_KEY_asciicircum, 5), - TAGKEYS(XKB_KEY_7, XKB_KEY_ampersand, 6), - TAGKEYS(XKB_KEY_8, XKB_KEY_asterisk, 7), - TAGKEYS(XKB_KEY_9, XKB_KEY_parenleft, 8), - - /* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */ - {WLR_MODIFIER_CTRL | WLR_MODIFIER_ALT, XKB_KEY_Terminate_Server, quit, {0}}, -/* Ctrl-Alt-Fx is used to switch to another VT, if you don't know what a VT is - * do not remove them. - */ -#define CHVT(n) \ - { \ - WLR_MODIFIER_CTRL | WLR_MODIFIER_ALT, XKB_KEY_XF86Switch_VT_##n, chvt, { \ - .ui = (n) \ - } \ - } - CHVT(1), - CHVT(2), - CHVT(3), - CHVT(4), - CHVT(5), - CHVT(6), - CHVT(7), - CHVT(8), - CHVT(9), - CHVT(10), - CHVT(11), - CHVT(12), -}; - -static const Button buttons[] = { - {MODKEY, BTN_LEFT, moveresize, {.ui = CurMove}}, - {MODKEY, BTN_MIDDLE, togglefloating, {0}}, - {MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize}}, -}; diff --git a/dwl/dwl-v0.7/config.mk b/dwl/dwl-v0.7/config.mk deleted file mode 100644 index 1e0b810f..00000000 --- a/dwl/dwl-v0.7/config.mk +++ /dev/null @@ -1,17 +0,0 @@ -_VERSION = 0.7 -VERSION = `git describe --tags --dirty 2>/dev/null || echo $(_VERSION)` - -PKG_CONFIG = pkg-config - -# paths -PREFIX = /usr/local -MANDIR = $(PREFIX)/share/man -DATADIR = $(PREFIX)/share - -XWAYLAND = -XLIBS = -# Uncomment to build XWayland support -#XWAYLAND = -DXWAYLAND -#XLIBS = xcb xcb-icccm - -CC = gcc diff --git a/dwl/dwl-v0.7/cursor-shape-v1-protocol.h b/dwl/dwl-v0.7/cursor-shape-v1-protocol.h deleted file mode 100644 index e49c7f52..00000000 --- a/dwl/dwl-v0.7/cursor-shape-v1-protocol.h +++ /dev/null @@ -1,201 +0,0 @@ -/* Generated by wayland-scanner 1.24.0 */ - -#ifndef CURSOR_SHAPE_V1_ENUM_PROTOCOL_H -#define CURSOR_SHAPE_V1_ENUM_PROTOCOL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ENUM -#define WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ENUM -/** - * @ingroup iface_wp_cursor_shape_device_v1 - * cursor shapes - * - * This enum describes cursor shapes. - * - * The names are taken from the CSS W3C specification: - * https://w3c.github.io/csswg-drafts/css-ui/#cursor - * with a few additions. - * - * Note that there are some groups of cursor shapes that are related: - * The first group is drag-and-drop cursors which are used to indicate - * the selected action during dnd operations. The second group is resize - * cursors which are used to indicate resizing and moving possibilities - * on window borders. It is recommended that the shapes in these groups - * should use visually compatible images and metaphors. - */ -enum wp_cursor_shape_device_v1_shape { - /** - * default cursor - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT = 1, - /** - * a context menu is available for the object under the cursor - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CONTEXT_MENU = 2, - /** - * help is available for the object under the cursor - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_HELP = 3, - /** - * pointer that indicates a link or another interactive element - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_POINTER = 4, - /** - * progress indicator - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_PROGRESS = 5, - /** - * program is busy, user should wait - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_WAIT = 6, - /** - * a cell or set of cells may be selected - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CELL = 7, - /** - * simple crosshair - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CROSSHAIR = 8, - /** - * text may be selected - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT = 9, - /** - * vertical text may be selected - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_VERTICAL_TEXT = 10, - /** - * drag-and-drop: alias of/shortcut to something is to be created - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALIAS = 11, - /** - * drag-and-drop: something is to be copied - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_COPY = 12, - /** - * drag-and-drop: something is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_MOVE = 13, - /** - * drag-and-drop: the dragged item cannot be dropped at the current cursor location - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NO_DROP = 14, - /** - * drag-and-drop: the requested action will not be carried out - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NOT_ALLOWED = 15, - /** - * drag-and-drop: something can be grabbed - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRAB = 16, - /** - * drag-and-drop: something is being grabbed - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRABBING = 17, - /** - * resizing: the east border is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_E_RESIZE = 18, - /** - * resizing: the north border is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_N_RESIZE = 19, - /** - * resizing: the north-east corner is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NE_RESIZE = 20, - /** - * resizing: the north-west corner is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NW_RESIZE = 21, - /** - * resizing: the south border is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_S_RESIZE = 22, - /** - * resizing: the south-east corner is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SE_RESIZE = 23, - /** - * resizing: the south-west corner is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SW_RESIZE = 24, - /** - * resizing: the west border is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_W_RESIZE = 25, - /** - * resizing: the east and west borders are to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_EW_RESIZE = 26, - /** - * resizing: the north and south borders are to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NS_RESIZE = 27, - /** - * resizing: the north-east and south-west corners are to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NESW_RESIZE = 28, - /** - * resizing: the north-west and south-east corners are to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NWSE_RESIZE = 29, - /** - * resizing: that the item/column can be resized horizontally - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_COL_RESIZE = 30, - /** - * resizing: that the item/row can be resized vertically - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ROW_RESIZE = 31, - /** - * something can be scrolled in any direction - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALL_SCROLL = 32, - /** - * something can be zoomed in - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ZOOM_IN = 33, - /** - * something can be zoomed out - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ZOOM_OUT = 34, - /** - * drag-and-drop: the user will select which action will be carried out (non-css value) - * @since 2 - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DND_ASK = 35, - /** - * resizing: something can be moved or resized in any direction (non-css value) - * @since 2 - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALL_RESIZE = 36, -}; -/** - * @ingroup iface_wp_cursor_shape_device_v1 - */ -#define WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DND_ASK_SINCE_VERSION 2 -/** - * @ingroup iface_wp_cursor_shape_device_v1 - */ -#define WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALL_RESIZE_SINCE_VERSION 2 -#endif /* WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ENUM */ - -#ifndef WP_CURSOR_SHAPE_DEVICE_V1_ERROR_ENUM -#define WP_CURSOR_SHAPE_DEVICE_V1_ERROR_ENUM -enum wp_cursor_shape_device_v1_error { - /** - * the specified shape value is invalid - */ - WP_CURSOR_SHAPE_DEVICE_V1_ERROR_INVALID_SHAPE = 1, -}; -#endif /* WP_CURSOR_SHAPE_DEVICE_V1_ERROR_ENUM */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/dwl/dwl-v0.7/dwl b/dwl/dwl-v0.7/dwl deleted file mode 100755 index 54583c55..00000000 Binary files a/dwl/dwl-v0.7/dwl and /dev/null differ diff --git a/dwl/dwl-v0.7/dwl.1 b/dwl/dwl-v0.7/dwl.1 deleted file mode 100644 index 780c78f4..00000000 --- a/dwl/dwl-v0.7/dwl.1 +++ /dev/null @@ -1,158 +0,0 @@ -.Dd January 8, 2021 -.Dt DWL 1 -.Os -.Sh NAME -.Nm dwl -.Nd dwm for Wayland -.Sh SYNOPSIS -.Nm -.Op Fl v -.Op Fl d -.Op Fl s Ar startup command -.Sh DESCRIPTION -.Nm -is a Wayland compositor based on wlroots. -It is intended to fill the same space in the Wayland world that -.Nm dwm -does for X11. -.Pp -When given the -.Fl v -option, -.Nm -writes its name and version to standard error and exits unsuccessfully. -.Pp -When given the -.Fl d -option, -.Nm -enables full wlroots logging, including debug information. -.Pp -When given the -.Fl s -option, -.Nm -starts a shell process running -.Ar command -when starting. -When stopping, it sends -.Dv SIGTERM -to the child process and waits for it to exit. -.Pp -Users are encouraged to customize -.Nm -by editing the sources, in particular -.Pa config.h . -The default key bindings are as follows: -.Bl -tag -width 20n -offset indent -compact -.It Mod-[1-9] -Show only all windows with a tag. -.It Mod-Ctrl-[1-9] -Show all windows with a tag. -.It Mod-Shift-[1-9] -Move window to a single tag. -.It Mod-Ctrl-Shift-[1-9] -Toggle tag for window. -.It Mod-p -Spawn -.Nm wmenu-run . -.It Mod-Shift-Return -Spawn -.Nm foot . -.It Mod-[jk] -Move focus down/up the stack. -.It Mod-[id] -Increase/decrease number of windows in master area. -.It Mod-[hl] -Decrease/increase master area. -.It Mod-Return -Move window on top of stack or switch top of stack with second window. -.It Mod-Tab -Show only all windows with previous tag. -.It Mod-Shift-c -Close window. -.It Mod-t -Switch to tabbed layout. -.It Mod-f -Switch to floating layout. -.It Mod-m -Switch to monocle layout. -.It Mod-Space -Switch to previous layout. -.It Mod-Shift-Space -Toggle floating state of window. -.It Mod-e -Toggle fullscreen state of window. -.It Mod-0 -Show all windows. -.It Mod-Shift-0 -Set all tags for window. -.It Mod-, -Move focus to previous monitor. -.It Mod-. -Move focus to next monitor. -.It Mod-Shift-, -Move window to previous monitor. -.It Mod-Shift-. -Move window to next monitor. -.It Mod-Shift-q -Quit -.Nm . -.El -These might differ depending on your keyboard layout. -.Sh ENVIRONMENT -These environment variables are used by -.Nm : -.Bl -tag -width XDG_RUNTIME_DIR -.It Ev XDG_RUNTIME_DIR -A directory where temporary user files, such as the Wayland socket, -are stored. -.It Ev XDG_CONFIG_DIR -A directory containing configuration of various programs and -libraries, including libxkbcommon. -.It Ev DISPLAY , WAYLAND_DISPLAY , WAYLAND_SOCKET -Tell how to connect to an underlying X11 or Wayland server. -.It Ev WLR_* -Various variables specific to wlroots. -.It Ev XKB_* , XLOCALEDIR , XCOMPOSEFILE -Various variables specific to libxkbcommon. -.It Ev XCURSOR_PATH -List of directories to search for XCursor themes in. -.It Ev HOME -A directory where there are always dear files there for you. -Waiting for you to clean them up. -.El -.Pp -These are set by -.Nm : -.Bl -tag -width WAYLAND_DISPLAY -.It Ev WAYLAND_DISPLAY -Tell how to connect to -.Nm . -.It Ev DISPLAY -If using -.Nm Xwayland , -tell how to connect to the -.Nm Xwayland -server. -.El -.Sh EXAMPLES -Start -.Nm -with s6 in the background: -.Dl dwl \-s \(aqs6\-svscan <&\-\(aq -.Sh SEE ALSO -.Xr foot 1 , -.Xr wmenu 1 , -.Xr dwm 1 , -.Xr xkeyboard-config 7 -.Sh CAVEATS -The child process's standard input is connected with a pipe to -.Nm . -If the child process neither reads from the pipe nor closes its -standard input, -.Nm -will freeze after a while due to it blocking when writing to the full -pipe buffer. -.Sh BUGS -All of them. diff --git a/dwl/dwl-v0.7/dwl.c b/dwl/dwl-v0.7/dwl.c deleted file mode 100644 index a2711f67..00000000 --- a/dwl/dwl-v0.7/dwl.c +++ /dev/null @@ -1,3215 +0,0 @@ -/* - * See LICENSE file for copyright and license details. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef XWAYLAND -#include -#include -#include -#endif - -#include "util.h" - -/* macros */ -#define MAX(A, B) ((A) > (B) ? (A) : (B)) -#define MIN(A, B) ((A) < (B) ? (A) : (B)) -#define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS) -#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags])) -#define LENGTH(X) (sizeof X / sizeof X[0]) -#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 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 */ -enum { XDGShell, LayerShell, X11 }; /* client types */ -enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ -#ifdef XWAYLAND -enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, - NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ -#endif - -typedef union { - int i; - uint32_t ui; - float f; - const void *v; -} Arg; - -typedef struct { - unsigned int mod; - unsigned int button; - void (*func)(const Arg *); - const Arg arg; -} Button; - -typedef struct Monitor Monitor; -typedef struct { - /* Must keep these three elements in this order */ - unsigned int type; /* XDGShell or X11* */ - struct wlr_box geom; /* layout-relative, includes border */ - Monitor *mon; - struct wlr_scene_tree *scene; - struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ - struct wlr_scene_tree *scene_surface; - struct wl_list link; - struct wl_list flink; - union { - struct wlr_xdg_surface *xdg; - struct wlr_xwayland_surface *xwayland; - } surface; - struct wlr_xdg_toplevel_decoration_v1 *decoration; - struct wl_listener commit; - struct wl_listener map; - struct wl_listener maximize; - struct wl_listener unmap; - struct wl_listener destroy; - struct wl_listener set_title; - struct wl_listener fullscreen; - struct wl_listener set_decoration_mode; - struct wl_listener destroy_decoration; - 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 - unsigned int bw; - uint32_t tags; - int isfloating, isurgent, isfullscreen; - uint32_t resize; /* configure serial of a pending resize */ -} Client; - -typedef struct { - uint32_t mod; - xkb_keysym_t keysym; - void (*func)(const Arg *); - const Arg arg; -} Key; - -typedef struct { - struct wl_list link; - struct wlr_keyboard_group *wlr_group; - - 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 key; - struct wl_listener destroy; -} KeyboardGroup; - -typedef struct { - /* Must keep these three elements in this order */ - unsigned int type; /* LayerShell */ - struct wlr_box geom; - Monitor *mon; - struct wlr_scene_tree *scene; - struct wlr_scene_tree *popups; - struct wlr_scene_layer_surface_v1 *scene_layer; - struct wl_list link; - int mapped; - struct wlr_layer_surface_v1 *layer_surface; - - struct wl_listener destroy; - struct wl_listener unmap; - struct wl_listener surface_commit; -} LayerSurface; - -typedef struct { - const char *symbol; - void (*arrange)(Monitor *); -} Layout; - -struct Monitor { - struct wl_list link; - struct wlr_output *wlr_output; - struct wlr_scene_output *scene_output; - 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 */ - struct wlr_box w; /* window area, layout-relative */ - struct wl_list layers[4]; /* LayerSurface.link */ - const Layout *lt[2]; - unsigned int seltags; - unsigned int sellt; - uint32_t tagset[2]; - float mfact; - int gamma_lut_changed; - int nmaster; - char ltsymbol[16]; - int asleep; -}; - -typedef struct { - const char *name; - float mfact; - int nmaster; - float scale; - const Layout *lt; - enum wl_output_transform rr; - int x, y; -} MonitorRule; - -typedef struct { - struct wlr_pointer_constraint_v1 *constraint; - struct wl_listener destroy; -} PointerConstraint; - -typedef struct { - const char *id; - const char *title; - uint32_t tags; - int isfloating; - int monitor; -} Rule; - -typedef struct { - struct wlr_scene_tree *scene; - - struct wlr_session_lock_v1 *lock; - struct wl_listener new_surface; - struct wl_listener unlock; - struct wl_listener destroy; -} SessionLock; - -/* function declarations */ -static void applybounds(Client *c, struct wlr_box *bbox); -static void applyrules(Client *c); -static void arrange(Monitor *m); -static void arrangelayer(Monitor *m, struct wl_list *list, - struct wlr_box *usable_area, int exclusive); -static void arrangelayers(Monitor *m); -static void axisnotify(struct wl_listener *listener, void *data); -static void buttonpress(struct wl_listener *listener, void *data); -static void chvt(const Arg *arg); -static void checkidleinhibitor(struct wlr_surface *exclude); -static void cleanup(void); -static void cleanupmon(struct wl_listener *listener, void *data); -static void closemon(Monitor *m); -static void commitlayersurfacenotify(struct wl_listener *listener, void *data); -static void commitnotify(struct wl_listener *listener, void *data); -static void commitpopup(struct wl_listener *listener, void *data); -static void createdecoration(struct wl_listener *listener, void *data); -static void createidleinhibitor(struct wl_listener *listener, void *data); -static void createkeyboard(struct wlr_keyboard *keyboard); -static KeyboardGroup *createkeyboardgroup(void); -static void createlayersurface(struct wl_listener *listener, void *data); -static void createlocksurface(struct wl_listener *listener, void *data); -static void createmon(struct wl_listener *listener, void *data); -static void createnotify(struct wl_listener *listener, void *data); -static void createpointer(struct wlr_pointer *pointer); -static void createpointerconstraint(struct wl_listener *listener, void *data); -static void createpopup(struct wl_listener *listener, void *data); -static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint); -static void cursorframe(struct wl_listener *listener, void *data); -static void cursorwarptohint(void); -static void destroydecoration(struct wl_listener *listener, void *data); -static void destroydragicon(struct wl_listener *listener, void *data); -static void destroyidleinhibitor(struct wl_listener *listener, void *data); -static void destroylayersurfacenotify(struct wl_listener *listener, void *data); -static void destroylock(SessionLock *lock, int unlocked); -static void destroylocksurface(struct wl_listener *listener, void *data); -static void destroynotify(struct wl_listener *listener, void *data); -static void destroypointerconstraint(struct wl_listener *listener, void *data); -static void destroysessionlock(struct wl_listener *listener, void *data); -static void destroysessionmgr(struct wl_listener *listener, void *data); -static void destroykeyboardgroup(struct wl_listener *listener, void *data); -static Monitor *dirtomon(enum wlr_direction dir); -static void focusclient(Client *c, int lift); -static void focusmon(const Arg *arg); -static void focusstack(const Arg *arg); -static Client *focustop(Monitor *m); -static void fullscreennotify(struct wl_listener *listener, void *data); -static void gpureset(struct wl_listener *listener, void *data); -static void handlesig(int signo); -static void incnmaster(const Arg *arg); -static void inputdevice(struct wl_listener *listener, void *data); -static int keybinding(uint32_t mods, xkb_keysym_t sym); -static void keypress(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 locksession(struct wl_listener *listener, void *data); -static void mapnotify(struct wl_listener *listener, void *data); -static void maximizenotify(struct wl_listener *listener, void *data); -static void monocle(Monitor *m); -static void motionabsolute(struct wl_listener *listener, void *data); -static void motionnotify(uint32_t time, struct wlr_input_device *device, double sx, - double sy, double sx_unaccel, double sy_unaccel); -static void motionrelative(struct wl_listener *listener, void *data); -static void moveresize(const Arg *arg); -static void outputmgrapply(struct wl_listener *listener, void *data); -static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test); -static void outputmgrtest(struct wl_listener *listener, void *data); -static void pointerfocus(Client *c, struct wlr_surface *surface, - double sx, double sy, uint32_t time); -static void printstatus(void); -static void powermgrsetmode(struct wl_listener *listener, void *data); -static void quit(const Arg *arg); -static void rendermon(struct wl_listener *listener, void *data); -static void requestdecorationmode(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); -static void setpsel(struct wl_listener *listener, void *data); -static void setsel(struct wl_listener *listener, void *data); -static void setup(void); -static void spawn(const Arg *arg); -static void startdrag(struct wl_listener *listener, void *data); -static void tag(const Arg *arg); -static void tagmon(const Arg *arg); -static void tile(Monitor *m); -static void togglefloating(const Arg *arg); -static void togglefullscreen(const Arg *arg); -static void toggletag(const Arg *arg); -static void toggleview(const Arg *arg); -static void unlocksession(struct wl_listener *listener, void *data); -static void unmaplayersurfacenotify(struct wl_listener *listener, void *data); -static void unmapnotify(struct wl_listener *listener, void *data); -static void updatemons(struct wl_listener *listener, void *data); -static void updatetitle(struct wl_listener *listener, void *data); -static void urgent(struct wl_listener *listener, void *data); -static void view(const Arg *arg); -static void virtualkeyboard(struct wl_listener *listener, void *data); -static void virtualpointer(struct wl_listener *listener, void *data); -static Monitor *xytomon(double x, double y); -static void xytonode(double x, double y, struct wlr_surface **psurface, - Client **pc, LayerSurface **pl, double *nx, double *ny); -static void zoom(const Arg *arg); - -/* variables */ -static const char broken[] = "broken"; -static pid_t child_pid = -1; -static int locked; -static void *exclusive_focus; -static struct wl_display *dpy; -static struct wl_event_loop *event_loop; -static struct wlr_backend *backend; -static struct wlr_scene *scene; -static struct wlr_scene_tree *layers[NUM_LAYERS]; -static struct wlr_scene_tree *drag_icon; -/* 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_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_notifier_v1 *idle_notifier; -static struct wlr_idle_inhibit_manager_v1 *idle_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_virtual_pointer_manager_v1 *virtual_pointer_mgr; -static struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr; -static struct wlr_output_power_manager_v1 *power_mgr; - -static struct wlr_pointer_constraints_v1 *pointer_constraints; -static struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr; -static struct wlr_pointer_constraint_v1 *active_constraint; - -static struct wlr_cursor *cursor; -static struct wlr_xcursor_manager *cursor_mgr; - -static struct wlr_scene_rect *root_bg; -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 KeyboardGroup *kb_group; -static unsigned int cursor_mode; -static Client *grabc; -static int grabcx, grabcy; /* client-relative */ - -static struct wlr_output_layout *output_layout; -static struct wlr_box sgeom; -static struct wl_list mons; -static Monitor *selmon; - -#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 wlr_xwayland *xwayland; -static xcb_atom_t netatom[NetLast]; -#endif - -/* configuration, allows nested code to access above variables */ -#include "config.h" - -/* attempt to encapsulate suck into one file */ -#include "client.h" - -/* function implementations */ -void -applybounds(Client *c, struct wlr_box *bbox) -{ - /* set minimum possible */ - c->geom.width = MAX(1 + 2 * (int)c->bw, c->geom.width); - c->geom.height = MAX(1 + 2 * (int)c->bw, c->geom.height); - - if (c->geom.x >= bbox->x + bbox->width) - c->geom.x = bbox->x + bbox->width - c->geom.width; - if (c->geom.y >= bbox->y + bbox->height) - c->geom.y = bbox->y + bbox->height - c->geom.height; - if (c->geom.x + c->geom.width <= bbox->x) - c->geom.x = bbox->x; - if (c->geom.y + c->geom.height <= bbox->y) - c->geom.y = bbox->y; -} - -void -applyrules(Client *c) -{ - /* rule matching */ - const char *appid, *title; - uint32_t newtags = 0; - int i; - const Rule *r; - Monitor *mon = selmon, *m; - - c->isfloating = client_is_float_type(c); - if (!(appid = client_get_appid(c))) - appid = broken; - if (!(title = client_get_title(c))) - title = broken; - - for (r = rules; r < END(rules); r++) { - if ((!r->title || strstr(title, r->title)) - && (!r->id || strstr(appid, r->id))) { - c->isfloating = r->isfloating; - newtags |= r->tags; - i = 0; - wl_list_for_each(m, &mons, link) { - if (r->monitor == i++) - mon = m; - } - } - } - setmon(c, mon, newtags); -} - -void -arrange(Monitor *m) -{ - Client *c; - - if (!m->wlr_output->enabled) - return; - - 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); - - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); - - /* We move all clients (except fullscreen and unmanaged) to LyrTile while - * in floating layout to avoid "real" floating clients be always on top */ - wl_list_for_each(c, &clients, link) { - if (c->mon != m || c->scene->node.parent == layers[LyrFS]) - continue; - - wlr_scene_node_reparent(&c->scene->node, - (!m->lt[m->sellt]->arrange && c->isfloating) - ? layers[LyrTile] - : (m->lt[m->sellt]->arrange && c->isfloating) - ? layers[LyrFloat] - : c->scene->node.parent); - } - - if (m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); - motionnotify(0, NULL, 0, 0, 0, 0); - checkidleinhibitor(NULL); -} - -void -arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, int exclusive) -{ - LayerSurface *l; - struct wlr_box full_area = m->m; - - wl_list_for_each(l, list, link) { - struct wlr_layer_surface_v1 *layer_surface = l->layer_surface; - - if (exclusive != (layer_surface->current.exclusive_zone > 0)) - continue; - - wlr_scene_layer_surface_v1_configure(l->scene_layer, &full_area, usable_area); - wlr_scene_node_set_position(&l->popups->node, l->scene->node.x, l->scene->node.y); - l->geom.x = l->scene->node.x; - l->geom.y = l->scene->node.y; - } -} - -void -arrangelayers(Monitor *m) -{ - int i; - struct wlr_box usable_area = m->m; - LayerSurface *l; - uint32_t layers_above_shell[] = { - ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, - ZWLR_LAYER_SHELL_V1_LAYER_TOP, - }; - if (!m->wlr_output->enabled) - return; - - /* Arrange exclusive surfaces from top->bottom */ - for (i = 3; i >= 0; i--) - arrangelayer(m, &m->layers[i], &usable_area, 1); - - if (!wlr_box_equal(&usable_area, &m->w)) { - m->w = usable_area; - arrange(m); - } - - /* Arrange non-exlusive surfaces from top->bottom */ - for (i = 3; i >= 0; i--) - arrangelayer(m, &m->layers[i], &usable_area, 0); - - /* Find topmost keyboard interactive layer, if such a layer exists */ - for (i = 0; i < (int)LENGTH(layers_above_shell); i++) { - wl_list_for_each_reverse(l, &m->layers[layers_above_shell[i]], link) { - if (locked || !l->layer_surface->current.keyboard_interactive || !l->mapped) - continue; - /* Deactivate the focused client. */ - focusclient(NULL, 0); - exclusive_focus = l; - client_notify_enter(l->layer_surface->surface, wlr_seat_get_keyboard(seat)); - return; - } - } -} - -void -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; - 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. */ - wlr_seat_pointer_notify_axis(seat, - event->time_msec, event->orientation, event->delta, - event->delta_discrete, event->source, event->relative_direction); -} - -void -buttonpress(struct wl_listener *listener, void *data) -{ - struct wlr_pointer_button_event *event = data; - struct wlr_keyboard *keyboard; - uint32_t mods; - Client *c; - const Button *b; - - wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); - - switch (event->state) { - case WL_POINTER_BUTTON_STATE_PRESSED: - cursor_mode = CurPressed; - selmon = xytomon(cursor->x, cursor->y); - if (locked) - break; - - /* Change focus if the button was _pressed_ over a client */ - xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); - if (c && (!client_is_unmanaged(c) || client_wants_focus(c))) - focusclient(c, 1); - - keyboard = wlr_seat_get_keyboard(seat); - mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; - for (b = buttons; b < END(buttons); b++) { - if (CLEANMASK(mods) == CLEANMASK(b->mod) && - event->button == b->button && b->func) { - b->func(&b->arg); - return; - } - } - break; - case WL_POINTER_BUTTON_STATE_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; - /* Drop the window off on its new monitor */ - selmon = xytomon(cursor->x, cursor->y); - setmon(grabc, selmon, 0); - return; - } else { - cursor_mode = CurNormal; - } - break; - } - /* If the event wasn't handled by the compositor, notify the client with - * pointer focus that a button press has occurred */ - wlr_seat_pointer_notify_button(seat, - event->time_msec, event->button, event->state); -} - -void -chvt(const Arg *arg) -{ - wlr_session_change_vt(session, arg->ui); -} - -void -checkidleinhibitor(struct wlr_surface *exclude) -{ - int inhibited = 0, unused_lx, unused_ly; - struct wlr_idle_inhibitor_v1 *inhibitor; - wl_list_for_each(inhibitor, &idle_inhibit_mgr->inhibitors, link) { - struct wlr_surface *surface = wlr_surface_get_root_surface(inhibitor->surface); - struct wlr_scene_tree *tree = surface->data; - if (exclude != surface && (bypass_surface_visibility || (!tree - || wlr_scene_node_coords(&tree->node, &unused_lx, &unused_ly)))) { - inhibited = 1; - break; - } - } - - wlr_idle_notifier_v1_set_inhibited(idle_notifier, inhibited); -} - -void -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_xcursor_manager_destroy(cursor_mgr); - - destroykeyboardgroup(&kb_group->destroy, NULL); - - /* If it's not destroyed manually it will cause a use-after-free of wlr_seat. - * Destroy it until it's fixed in the wlroots side */ - wlr_backend_destroy(backend); - - 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 -cleanupmon(struct wl_listener *listener, void *data) -{ - Monitor *m = wl_container_of(listener, m, destroy); - LayerSurface *l, *tmp; - size_t i; - - /* m->layers[i] are intentionally not unlinked */ - for (i = 0; i < LENGTH(m->layers); i++) { - wl_list_for_each_safe(l, tmp, &m->layers[i], link) - wlr_layer_surface_v1_destroy(l->layer_surface); - } - - wl_list_remove(&m->destroy.link); - wl_list_remove(&m->frame.link); - wl_list_remove(&m->link); - wl_list_remove(&m->request_state.link); - m->wlr_output->data = NULL; - wlr_output_layout_remove(output_layout, m->wlr_output); - wlr_scene_output_destroy(m->scene_output); - - closemon(m); - wlr_scene_node_destroy(&m->fullscreen_bg->node); - free(m); -} - -void -closemon(Monitor *m) -{ - /* update selmon if needed and - * move closed monitor's clients to the focused one */ - Client *c; - int i = 0, nmons = wl_list_length(&mons); - if (!nmons) { - selmon = NULL; - } else if (m == selmon) { - do /* don't switch to disabled mons */ - selmon = wl_container_of(mons.next, selmon, link); - while (!selmon->wlr_output->enabled && i++ < nmons); - - if (!selmon->wlr_output->enabled) - selmon = NULL; - } - - wl_list_for_each(c, &clients, link) { - if (c->isfloating && c->geom.x > m->m.width) - resize(c, (struct wlr_box){.x = c->geom.x - m->w.width, .y = c->geom.y, - .width = c->geom.width, .height = c->geom.height}, 0); - if (c->mon == m) - setmon(c, selmon, c->tags); - } - focusclient(focustop(selmon), 1); - printstatus(); -} - -void -commitlayersurfacenotify(struct wl_listener *listener, void *data) -{ - LayerSurface *l = wl_container_of(listener, l, surface_commit); - struct wlr_layer_surface_v1 *layer_surface = l->layer_surface; - struct wlr_scene_tree *scene_layer = layers[layermap[layer_surface->current.layer]]; - struct wlr_layer_surface_v1_state old_state; - - if (l->layer_surface->initial_commit) { - wlr_fractional_scale_v1_notify_scale(layer_surface->surface, l->mon->wlr_output->scale); - wlr_surface_set_preferred_buffer_scale(layer_surface->surface, (int32_t)ceilf(l->mon->wlr_output->scale)); - - /* Temporarily set the layer's current state to pending - * so that we can easily arrange it */ - old_state = l->layer_surface->current; - l->layer_surface->current = l->layer_surface->pending; - arrangelayers(l->mon); - l->layer_surface->current = old_state; - return; - } - - if (layer_surface->current.committed == 0 && l->mapped == layer_surface->surface->mapped) - return; - l->mapped = layer_surface->surface->mapped; - - if (scene_layer != l->scene->node.parent) { - wlr_scene_node_reparent(&l->scene->node, scene_layer); - wl_list_remove(&l->link); - wl_list_insert(&l->mon->layers[layer_surface->current.layer], &l->link); - wlr_scene_node_reparent(&l->popups->node, (layer_surface->current.layer - < ZWLR_LAYER_SHELL_V1_LAYER_TOP ? layers[LyrTop] : scene_layer)); - } - - arrangelayers(l->mon); -} - -void -commitnotify(struct wl_listener *listener, void *data) -{ - Client *c = wl_container_of(listener, c, commit); - - if (c->surface.xdg->initial_commit) { - /* - * Get the monitor this client will be rendered on - * Note that if the user set a rule in which the client is placed on - * a different monitor based on its title this will likely select - * a wrong monitor. - */ - applyrules(c); - wlr_surface_set_preferred_buffer_scale(client_surface(c), (int)ceilf(c->mon->wlr_output->scale)); - wlr_fractional_scale_v1_notify_scale(client_surface(c), c->mon->wlr_output->scale); - setmon(c, NULL, 0); /* Make sure to reapply rules in mapnotify() */ - - wlr_xdg_toplevel_set_wm_capabilities(c->surface.xdg->toplevel, WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN); - wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, 0, 0); - if (c->decoration) - requestdecorationmode(&c->set_decoration_mode, c->decoration); - return; - } - - if (client_surface(c)->mapped && c->mon) - 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; -} - -void -commitpopup(struct wl_listener *listener, void *data) -{ - struct wlr_surface *surface = data; - struct wlr_xdg_popup *popup = wlr_xdg_popup_try_from_wlr_surface(surface); - LayerSurface *l = NULL; - Client *c = NULL; - struct wlr_box box; - int type = -1; - - if (!popup->base->initial_commit) - return; - - type = toplevel_from_wlr_surface(popup->base->surface, &c, &l); - if (!popup->parent || type < 0) - return; - popup->base->surface->data = wlr_scene_xdg_surface_create( - popup->parent->data, popup->base); - if ((l && !l->mon) || (c && !c->mon)) - return; - box = type == LayerShell ? l->mon->m : c->mon->w; - box.x -= (type == LayerShell ? l->geom.x : c->geom.x); - box.y -= (type == LayerShell ? l->geom.y : c->geom.y); - wlr_xdg_popup_unconstrain_from_box(popup, &box); - wl_list_remove(&listener->link); -} - -void -createdecoration(struct wl_listener *listener, void *data) -{ - struct wlr_xdg_toplevel_decoration_v1 *deco = data; - Client *c = deco->toplevel->base->data; - c->decoration = deco; - - LISTEN(&deco->events.request_mode, &c->set_decoration_mode, requestdecorationmode); - LISTEN(&deco->events.destroy, &c->destroy_decoration, destroydecoration); - - requestdecorationmode(&c->set_decoration_mode, deco); -} - -void -createidleinhibitor(struct wl_listener *listener, void *data) -{ - struct wlr_idle_inhibitor_v1 *idle_inhibitor = data; - LISTEN_STATIC(&idle_inhibitor->events.destroy, destroyidleinhibitor); - - checkidleinhibitor(NULL); -} - -void -createkeyboard(struct wlr_keyboard *keyboard) -{ - /* Set the keymap to match the group keymap */ - wlr_keyboard_set_keymap(keyboard, kb_group->wlr_group->keyboard.keymap); - - /* Add the new keyboard to the group */ - wlr_keyboard_group_add_keyboard(kb_group->wlr_group, keyboard); -} - -KeyboardGroup * -createkeyboardgroup(void) -{ - KeyboardGroup *group = ecalloc(1, sizeof(*group)); - struct xkb_context *context; - struct xkb_keymap *keymap; - - group->wlr_group = wlr_keyboard_group_create(); - group->wlr_group->data = group; - - /* Prepare an XKB keymap and assign it to the keyboard group. */ - context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - if (!(keymap = xkb_keymap_new_from_names(context, &xkb_rules, - XKB_KEYMAP_COMPILE_NO_FLAGS))) - die("failed to compile keymap"); - - wlr_keyboard_set_keymap(&group->wlr_group->keyboard, keymap); - xkb_keymap_unref(keymap); - xkb_context_unref(context); - - wlr_keyboard_set_repeat_info(&group->wlr_group->keyboard, repeat_rate, repeat_delay); - - /* Set up listeners for keyboard events */ - LISTEN(&group->wlr_group->keyboard.events.key, &group->key, keypress); - LISTEN(&group->wlr_group->keyboard.events.modifiers, &group->modifiers, keypressmod); - - group->key_repeat_source = wl_event_loop_add_timer(event_loop, keyrepeat, group); - - /* A seat can only have one keyboard, but this is a limitation of the - * Wayland protocol - not wlroots. We assign all connected keyboards to the - * same wlr_keyboard_group, which provides a single wlr_keyboard interface for - * all of them. Set this combined wlr_keyboard as the seat keyboard. - */ - wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard); - return group; -} - -void -createlayersurface(struct wl_listener *listener, void *data) -{ - struct wlr_layer_surface_v1 *layer_surface = data; - LayerSurface *l; - struct wlr_surface *surface = layer_surface->surface; - struct wlr_scene_tree *scene_layer = layers[layermap[layer_surface->pending.layer]]; - - if (!layer_surface->output - && !(layer_surface->output = selmon ? selmon->wlr_output : NULL)) { - wlr_layer_surface_v1_destroy(layer_surface); - return; - } - - l = layer_surface->data = ecalloc(1, sizeof(*l)); - l->type = LayerShell; - LISTEN(&surface->events.commit, &l->surface_commit, commitlayersurfacenotify); - LISTEN(&surface->events.unmap, &l->unmap, unmaplayersurfacenotify); - LISTEN(&layer_surface->events.destroy, &l->destroy, destroylayersurfacenotify); - - l->layer_surface = layer_surface; - l->mon = layer_surface->output->data; - l->scene_layer = wlr_scene_layer_surface_v1_create(scene_layer, layer_surface); - l->scene = l->scene_layer->tree; - l->popups = surface->data = wlr_scene_tree_create(layer_surface->current.layer - < ZWLR_LAYER_SHELL_V1_LAYER_TOP ? layers[LyrTop] : scene_layer); - l->scene->node.data = l->popups->node.data = l; - - wl_list_insert(&l->mon->layers[layer_surface->pending.layer],&l->link); - wlr_surface_send_enter(surface, layer_surface->output); -} - -void -createlocksurface(struct wl_listener *listener, void *data) -{ - SessionLock *lock = wl_container_of(listener, lock, new_surface); - struct wlr_session_lock_surface_v1 *lock_surface = data; - Monitor *m = lock_surface->output->data; - struct wlr_scene_tree *scene_tree = lock_surface->surface->data - = wlr_scene_subsurface_tree_create(lock->scene, lock_surface->surface); - m->lock_surface = lock_surface; - - wlr_scene_node_set_position(&scene_tree->node, m->m.x, m->m.y); - wlr_session_lock_surface_v1_configure(lock_surface, m->m.width, m->m.height); - - LISTEN(&lock_surface->events.destroy, &m->destroy_lock_surface, destroylocksurface); - - if (m == selmon) - client_notify_enter(lock_surface->surface, wlr_seat_get_keyboard(seat)); -} - -void -createmon(struct wl_listener *listener, void *data) -{ - /* This event is raised by the backend when a new output (aka a display or - * monitor) becomes available. */ - struct wlr_output *wlr_output = data; - const MonitorRule *r; - size_t i; - struct wlr_output_state state; - Monitor *m; - - if (!wlr_output_init_render(wlr_output, alloc, drw)) - return; - - m = wlr_output->data = ecalloc(1, sizeof(*m)); - m->wlr_output = wlr_output; - - for (i = 0; i < LENGTH(m->layers); i++) - wl_list_init(&m->layers[i]); - - wlr_output_state_init(&state); - /* Initialize monitor state using configured rules */ - m->tagset[0] = m->tagset[1] = 1; - for (r = monrules; r < END(monrules); r++) { - if (!r->name || strstr(wlr_output->name, r->name)) { - m->m.x = r->x; - m->m.y = r->y; - m->mfact = r->mfact; - m->nmaster = r->nmaster; - m->lt[0] = r->lt; - m->lt[1] = &layouts[LENGTH(layouts) > 1 && r->lt != &layouts[1]]; - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); - wlr_output_state_set_scale(&state, r->scale); - wlr_output_state_set_transform(&state, r->rr); - break; - } - } - - /* The mode is a tuple of (width, height, refresh rate), and each - * monitor supports only a specific set of modes. We just pick the - * monitor's preferred mode; a more sophisticated compositor would let - * the user configure it. */ - wlr_output_state_set_mode(&state, wlr_output_preferred_mode(wlr_output)); - - /* 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_state_set_enabled(&state, 1); - wlr_output_commit_state(wlr_output, &state); - wlr_output_state_finish(&state); - - wl_list_insert(&mons, &m->link); - printstatus(); - - /* The xdg-protocol specifies: - * - * If the fullscreened surface is not opaque, the compositor must make - * sure that other screen content not part of the same surface tree (made - * up of subsurfaces, popups or similarly coupled surfaces) are not - * visible below the fullscreened surface. - * - */ - /* updatemons() will resize and set correct position */ - m->fullscreen_bg = wlr_scene_rect_create(layers[LyrFS], 0, 0, fullscreen_bg); - wlr_scene_node_set_enabled(&m->fullscreen_bg->node, 0); - - /* Adds this to the output layout in the order it was configured. - * - * The output layout utility automatically adds a wl_output global to the - * display, which Wayland clients can see to find out information about the - * output (such as DPI, scale factor, manufacturer, etc). - */ - m->scene_output = wlr_scene_output_create(scene, wlr_output); - if (m->m.x == -1 && m->m.y == -1) - wlr_output_layout_add_auto(output_layout, wlr_output); - else - wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y); -} - -void -createnotify(struct wl_listener *listener, void *data) -{ - /* This event is raised when a client creates a new toplevel (application window). */ - struct wlr_xdg_toplevel *toplevel = data; - Client *c = NULL; - - /* Allocate a Client for this surface */ - c = toplevel->base->data = ecalloc(1, sizeof(*c)); - c->surface.xdg = toplevel->base; - c->bw = borderpx; - - LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify); - LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify); - LISTEN(&toplevel->base->surface->events.unmap, &c->unmap, unmapnotify); - LISTEN(&toplevel->events.destroy, &c->destroy, destroynotify); - LISTEN(&toplevel->events.request_fullscreen, &c->fullscreen, fullscreennotify); - LISTEN(&toplevel->events.request_maximize, &c->maximize, maximizenotify); - LISTEN(&toplevel->events.set_title, &c->set_title, updatetitle); -} - -void -createpointer(struct wlr_pointer *pointer) -{ - struct libinput_device *device; - if (wlr_input_device_is_libinput(&pointer->base) - && (device = wlr_libinput_get_device_handle(&pointer->base))) { - - if (libinput_device_config_tap_get_finger_count(device)) { - libinput_device_config_tap_set_enabled(device, tap_to_click); - libinput_device_config_tap_set_drag_enabled(device, tap_and_drag); - libinput_device_config_tap_set_drag_lock_enabled(device, drag_lock); - libinput_device_config_tap_set_button_map(device, button_map); - } - - if (libinput_device_config_scroll_has_natural_scroll(device)) - libinput_device_config_scroll_set_natural_scroll_enabled(device, natural_scrolling); - - if (libinput_device_config_dwt_is_available(device)) - libinput_device_config_dwt_set_enabled(device, disable_while_typing); - - if (libinput_device_config_left_handed_is_available(device)) - libinput_device_config_left_handed_set(device, left_handed); - - if (libinput_device_config_middle_emulation_is_available(device)) - libinput_device_config_middle_emulation_set_enabled(device, middle_button_emulation); - - if (libinput_device_config_scroll_get_methods(device) != LIBINPUT_CONFIG_SCROLL_NO_SCROLL) - libinput_device_config_scroll_set_method (device, scroll_method); - - if (libinput_device_config_click_get_methods(device) != LIBINPUT_CONFIG_CLICK_METHOD_NONE) - libinput_device_config_click_set_method (device, click_method); - - if (libinput_device_config_send_events_get_modes(device)) - libinput_device_config_send_events_set_mode(device, send_events_mode); - - if (libinput_device_config_accel_is_available(device)) { - libinput_device_config_accel_set_profile(device, accel_profile); - libinput_device_config_accel_set_speed(device, accel_speed); - } - } - - wlr_cursor_attach_input_device(cursor, &pointer->base); -} - -void -createpointerconstraint(struct wl_listener *listener, void *data) -{ - PointerConstraint *pointer_constraint = ecalloc(1, sizeof(*pointer_constraint)); - pointer_constraint->constraint = data; - LISTEN(&pointer_constraint->constraint->events.destroy, - &pointer_constraint->destroy, destroypointerconstraint); -} - -void -createpopup(struct wl_listener *listener, void *data) -{ - /* This event is raised when a client (either xdg-shell or layer-shell) - * creates a new popup. */ - struct wlr_xdg_popup *popup = data; - LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup); -} - -void -cursorconstrain(struct wlr_pointer_constraint_v1 *constraint) -{ - if (active_constraint == constraint) - return; - - if (active_constraint) - wlr_pointer_constraint_v1_send_deactivated(active_constraint); - - active_constraint = constraint; - wlr_pointer_constraint_v1_send_activated(constraint); -} - -void -cursorframe(struct wl_listener *listener, void *data) -{ - /* This event is forwarded by the cursor when a pointer emits an frame - * event. Frame events are sent after regular pointer events to group - * multiple events together. For instance, two axis events may happen at the - * same time, in which case a frame event won't be sent in between. */ - /* Notify the client with pointer focus of the frame event. */ - wlr_seat_pointer_notify_frame(seat); -} - -void -cursorwarptohint(void) -{ - Client *c = NULL; - double sx = active_constraint->current.cursor_hint.x; - double sy = active_constraint->current.cursor_hint.y; - - toplevel_from_wlr_surface(active_constraint->surface, &c, NULL); - if (c && active_constraint->current.cursor_hint.enabled) { - wlr_cursor_warp(cursor, NULL, sx + c->geom.x + c->bw, sy + c->geom.y + c->bw); - wlr_seat_pointer_warp(active_constraint->seat, sx, sy); - } -} - -void -destroydecoration(struct wl_listener *listener, void *data) -{ - Client *c = wl_container_of(listener, c, destroy_decoration); - c->decoration = NULL; - - wl_list_remove(&c->destroy_decoration.link); - wl_list_remove(&c->set_decoration_mode.link); -} - -void -destroydragicon(struct wl_listener *listener, void *data) -{ - /* Focus enter isn't sent during drag, so refocus the focused node. */ - focusclient(focustop(selmon), 1); - motionnotify(0, NULL, 0, 0, 0, 0); -} - -void -destroyidleinhibitor(struct wl_listener *listener, void *data) -{ - /* `data` is the wlr_surface of the idle inhibitor being destroyed, - * at this point the idle inhibitor is still in the list of the manager */ - checkidleinhibitor(wlr_surface_get_root_surface(data)); -} - -void -destroylayersurfacenotify(struct wl_listener *listener, void *data) -{ - LayerSurface *l = wl_container_of(listener, l, destroy); - - wl_list_remove(&l->link); - wl_list_remove(&l->destroy.link); - wl_list_remove(&l->unmap.link); - wl_list_remove(&l->surface_commit.link); - wlr_scene_node_destroy(&l->scene->node); - wlr_scene_node_destroy(&l->popups->node); - free(l); -} - -void -destroylock(SessionLock *lock, int unlock) -{ - wlr_seat_keyboard_notify_clear_focus(seat); - if ((locked = !unlock)) - goto destroy; - - wlr_scene_node_set_enabled(&locked_bg->node, 0); - - focusclient(focustop(selmon), 0); - motionnotify(0, NULL, 0, 0, 0, 0); - -destroy: - wl_list_remove(&lock->new_surface.link); - wl_list_remove(&lock->unlock.link); - wl_list_remove(&lock->destroy.link); - - wlr_scene_node_destroy(&lock->scene->node); - cur_lock = NULL; - free(lock); -} - -void -destroylocksurface(struct wl_listener *listener, void *data) -{ - Monitor *m = wl_container_of(listener, m, destroy_lock_surface); - struct wlr_session_lock_surface_v1 *surface, *lock_surface = m->lock_surface; - - m->lock_surface = NULL; - wl_list_remove(&m->destroy_lock_surface.link); - - if (lock_surface->surface != seat->keyboard_state.focused_surface) - return; - - if (locked && cur_lock && !wl_list_empty(&cur_lock->surfaces)) { - surface = wl_container_of(cur_lock->surfaces.next, surface, link); - client_notify_enter(surface->surface, wlr_seat_get_keyboard(seat)); - } else if (!locked) { - focusclient(focustop(selmon), 1); - } else { - wlr_seat_keyboard_clear_focus(seat); - } -} - -void -destroynotify(struct wl_listener *listener, void *data) -{ - /* Called when the xdg_toplevel is destroyed. */ - Client *c = wl_container_of(listener, c, destroy); - 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->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); -} - -void -destroypointerconstraint(struct wl_listener *listener, void *data) -{ - PointerConstraint *pointer_constraint = wl_container_of(listener, pointer_constraint, destroy); - - if (active_constraint == pointer_constraint->constraint) { - cursorwarptohint(); - active_constraint = NULL; - } - - wl_list_remove(&pointer_constraint->destroy.link); - free(pointer_constraint); -} - -void -destroysessionlock(struct wl_listener *listener, void *data) -{ - SessionLock *lock = wl_container_of(listener, lock, destroy); - destroylock(lock, 0); -} - -void -destroysessionmgr(struct wl_listener *listener, void *data) -{ - wl_list_remove(&lock_listener.link); - wl_list_remove(&listener->link); -} - -void -destroykeyboardgroup(struct wl_listener *listener, void *data) -{ - KeyboardGroup *group = wl_container_of(listener, group, destroy); - wl_event_source_remove(group->key_repeat_source); - wlr_keyboard_group_destroy(group->wlr_group); - wl_list_remove(&group->key.link); - wl_list_remove(&group->modifiers.link); - wl_list_remove(&group->destroy.link); - free(group); -} - -Monitor * -dirtomon(enum wlr_direction dir) -{ - struct wlr_output *next; - if (!wlr_output_layout_get(output_layout, selmon->wlr_output)) - return selmon; - if ((next = wlr_output_layout_adjacent_output(output_layout, - dir, selmon->wlr_output, selmon->m.x, selmon->m.y))) - return next->data; - if ((next = wlr_output_layout_farthest_output(output_layout, - dir ^ (WLR_DIRECTION_LEFT|WLR_DIRECTION_RIGHT), - selmon->wlr_output, selmon->m.x, selmon->m.y))) - return next->data; - return selmon; -} - -void -focusclient(Client *c, int lift) -{ - struct wlr_surface *old = seat->keyboard_state.focused_surface; - int unused_lx, unused_ly, old_client_type; - Client *old_c = NULL; - LayerSurface *old_l = NULL; - - if (locked) - return; - - /* Raise client in stacking order if requested */ - if (c && lift) - wlr_scene_node_raise_to_top(&c->scene->node); - - if (c && client_surface(c) == old) - 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 */ - if (c && !client_is_unmanaged(c)) { - wl_list_remove(&c->flink); - wl_list_insert(&fstack, &c->flink); - selmon = c->mon; - c->isurgent = 0; - client_restack_surface(c); - - /* Don't change border color if there is an exclusive focus or we are - * handling a drag operation */ - if (!exclusive_focus && !seat->drag) - client_set_border_color(c, focuscolor); - } - - /* Deactivate old client if focus is changing */ - if (old && (!c || client_surface(c) != old)) { - /* 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 - * and focus it after the overlay is closed. */ - if (old_client_type == LayerShell && wlr_scene_node_coords( - &old_l->scene->node, &unused_lx, &unused_ly) - && old_l->layer_surface->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { - return; - } else if (old_c && old_c == exclusive_focus && client_wants_focus(old_c)) { - return; - /* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg - * and probably other clients */ - } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { - client_set_border_color(old_c, bordercolor); - - client_activate_surface(old, 0); - } - } - printstatus(); - - if (!c) { - /* With no client, all we have left is to clear focus */ - wlr_seat_keyboard_notify_clear_focus(seat); - return; - } - - /* Change cursor surface */ - motionnotify(0, NULL, 0, 0, 0, 0); - - /* Have a client, so focus its top-level wlr_surface */ - client_notify_enter(client_surface(c), wlr_seat_get_keyboard(seat)); - - /* Activate the new client */ - client_activate_surface(client_surface(c), 1); -} - -void -focusmon(const Arg *arg) -{ - int i = 0, nmons = wl_list_length(&mons); - if (nmons) { - do /* don't switch to disabled mons */ - selmon = dirtomon(arg->i); - while (!selmon->wlr_output->enabled && i++ < nmons); - } - focusclient(focustop(selmon), 1); -} - -void -focusstack(const Arg *arg) -{ - /* Focus the next or previous client (in tiling order) on selmon */ - Client *c, *sel = focustop(selmon); - if (!sel || (sel->isfullscreen && !client_has_children(sel))) - return; - if (arg->i > 0) { - wl_list_for_each(c, &sel->link, link) { - if (&c->link == &clients) - continue; /* wrap past the sentinel node */ - if (VISIBLEON(c, selmon)) - break; /* found it */ - } - } else { - wl_list_for_each_reverse(c, &sel->link, link) { - if (&c->link == &clients) - continue; /* wrap past the sentinel node */ - if (VISIBLEON(c, selmon)) - break; /* found it */ - } - } - /* If only one client is visible on selmon, then c == sel */ - focusclient(c, 1); -} - -/* We probably should change the name of this, it sounds like - * will focus the topmost client of this mon, when actually will - * only return that client */ -Client * -focustop(Monitor *m) -{ - Client *c; - wl_list_for_each(c, &fstack, flink) { - if (VISIBLEON(c, m)) - return c; - } - return NULL; -} - -void -fullscreennotify(struct wl_listener *listener, void *data) -{ - Client *c = wl_container_of(listener, c, fullscreen); - setfullscreen(c, client_wants_fullscreen(c)); -} - -void -gpureset(struct wl_listener *listener, void *data) -{ - struct wlr_renderer *old_drw = drw; - struct wlr_allocator *old_alloc = alloc; - struct Monitor *m; - if (!(drw = wlr_renderer_autocreate(backend))) - die("couldn't recreate renderer"); - - if (!(alloc = wlr_allocator_autocreate(backend, drw))) - die("couldn't recreate allocator"); - - LISTEN_STATIC(&drw->events.lost, gpureset); - - wlr_compositor_set_renderer(compositor, drw); - - wl_list_for_each(m, &mons, link) { - wlr_output_init_render(m->wlr_output, alloc, drw); - } - - wlr_allocator_destroy(old_alloc); - wlr_renderer_destroy(old_drw); -} - -void -handlesig(int signo) -{ - if (signo == SIGCHLD) { -#ifdef XWAYLAND - siginfo_t in; - /* wlroots expects to reap the XWayland process itself, so we - * use WNOWAIT to keep the child waitable until we know it's not - * XWayland. - */ - 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 - } else if (signo == SIGINT || signo == SIGTERM) { - quit(NULL); - } -} - -void -incnmaster(const Arg *arg) -{ - if (!arg || !selmon) - return; - selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); - arrange(selmon); -} - -void -inputdevice(struct wl_listener *listener, void *data) -{ - /* This event is raised by the backend when a new input device becomes - * available. */ - struct wlr_input_device *device = data; - uint32_t caps; - - switch (device->type) { - case WLR_INPUT_DEVICE_KEYBOARD: - createkeyboard(wlr_keyboard_from_input_device(device)); - break; - case WLR_INPUT_DEVICE_POINTER: - createpointer(wlr_pointer_from_input_device(device)); - break; - default: - /* TODO handle other input device types */ - break; - } - - /* We need to let the wlr_seat know what our capabilities are, which is - * communiciated to the client. In dwl we always have a cursor, even if - * there are no pointer devices, so we always include that capability. */ - /* TODO do we actually require a cursor? */ - caps = WL_SEAT_CAPABILITY_POINTER; - if (!wl_list_empty(&kb_group->wlr_group->devices)) - caps |= WL_SEAT_CAPABILITY_KEYBOARD; - wlr_seat_set_capabilities(seat, caps); -} - -int -keybinding(uint32_t mods, xkb_keysym_t sym) -{ - /* - * Here we handle compositor keybindings. This is when the compositor is - * processing keys, rather than passing them on to the client for its own - * processing. - */ - const Key *k; - for (k = keys; k < END(keys); k++) { - if (CLEANMASK(mods) == CLEANMASK(k->mod) - && sym == k->keysym && k->func) { - k->func(&k->arg); - return 1; - } - } - return 0; -} - -void -keypress(struct wl_listener *listener, void *data) -{ - int i; - /* This event is raised when a key is pressed or released. */ - KeyboardGroup *group = wl_container_of(listener, group, key); - struct wlr_keyboard_key_event *event = data; - - /* Translate libinput keycode -> xkbcommon */ - uint32_t keycode = event->keycode + 8; - /* Get a list of keysyms based on the keymap for this keyboard */ - const xkb_keysym_t *syms; - int nsyms = xkb_state_key_get_syms( - group->wlr_group->keyboard.xkb_state, keycode, &syms); - - int handled = 0; - uint32_t mods = wlr_keyboard_get_modifiers(&group->wlr_group->keyboard); - - 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 && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { - for (i = 0; i < nsyms; i++) - handled = keybinding(mods, syms[i]) || handled; - } - - if (handled && group->wlr_group->keyboard.repeat_info.delay > 0) { - group->mods = mods; - group->keysyms = syms; - group->nsyms = nsyms; - wl_event_source_timer_update(group->key_repeat_source, - group->wlr_group->keyboard.repeat_info.delay); - } else { - group->nsyms = 0; - wl_event_source_timer_update(group->key_repeat_source, 0); - } - - if (handled) - return; - - wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard); - /* Pass unhandled keycodes along to the client. */ - wlr_seat_keyboard_notify_key(seat, event->time_msec, - event->keycode, event->state); -} - -void -keypressmod(struct wl_listener *listener, void *data) -{ - /* This event is raised when a modifier key, such as shift or alt, is - * pressed. We simply communicate this to the client. */ - KeyboardGroup *group = wl_container_of(listener, group, modifiers); - - wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard); - /* Send modifiers to the client. */ - wlr_seat_keyboard_notify_modifiers(seat, - &group->wlr_group->keyboard.modifiers); -} - -int -keyrepeat(void *data) -{ - KeyboardGroup *group = data; - int i; - if (!group->nsyms || group->wlr_group->keyboard.repeat_info.rate <= 0) - return 0; - - wl_event_source_timer_update(group->key_repeat_source, - 1000 / group->wlr_group->keyboard.repeat_info.rate); - - for (i = 0; i < group->nsyms; i++) - keybinding(group->mods, group->keysyms[i]); - - return 0; -} - -void -killclient(const Arg *arg) -{ - Client *sel = focustop(selmon); - if (sel) - client_send_close(sel); -} - -void -locksession(struct wl_listener *listener, void *data) -{ - struct wlr_session_lock_v1 *session_lock = data; - SessionLock *lock; - wlr_scene_node_set_enabled(&locked_bg->node, 1); - if (cur_lock) { - wlr_session_lock_v1_destroy(session_lock); - return; - } - 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; - - LISTEN(&session_lock->events.new_surface, &lock->new_surface, createlocksurface); - LISTEN(&session_lock->events.destroy, &lock->destroy, destroysessionlock); - LISTEN(&session_lock->events.unlock, &lock->unlock, unlocksession); - - wlr_session_lock_v1_send_locked(session_lock); -} - -void -mapnotify(struct wl_listener *listener, void *data) -{ - /* Called when the surface is mapped, or ready to display on-screen. */ - Client *p = NULL; - Client *w, *c = wl_container_of(listener, c, map); - Monitor *m; - int i; - - /* Create scene tree for this client and its border */ - 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)); - c->scene->node.data = c->scene_surface->node.data = c; - - client_get_geometry(c, &c->geom); - - /* Handle unmanaged clients first so we can return prior create borders */ - if (client_is_unmanaged(c)) { - /* Unmanaged clients always are floating */ - wlr_scene_node_reparent(&c->scene->node, layers[LyrFloat]); - wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); - if (client_wants_focus(c)) { - focusclient(c, 1); - exclusive_focus = c; - } - goto unset_fullscreen; - } - - for (i = 0; i < 4; i++) { - c->border[i] = wlr_scene_rect_create(c->scene, 0, 0, - c->isurgent ? urgentcolor : bordercolor); - c->border[i]->node.data = c; - } - - /* Initialize client geometry with room for border */ - client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); - c->geom.width += 2 * c->bw; - c->geom.height += 2 * c->bw; - - /* Insert this client into client lists. */ - wl_list_insert(&clients, &c->link); - wl_list_insert(&fstack, &c->flink); - - /* Set initial monitor, tags, floating status, and focus: - * we always consider floating, clients that have parent and thus - * we set the same tags and monitor than its parent, if not - * try to apply rules for them */ - if ((p = client_get_parent(c))) { - c->isfloating = 1; - setmon(c, p->mon, p->tags); - } else { - applyrules(c); - } - printstatus(); - -unset_fullscreen: - m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y); - wl_list_for_each(w, &clients, link) { - if (w != c && w != p && w->isfullscreen && m == w->mon && (w->tags & c->tags)) - setfullscreen(w, 0); - } -} - -void -maximizenotify(struct wl_listener *listener, void *data) -{ - /* This event is raised when a client would like to maximize itself, - * 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); - if (c->surface.xdg->initialized - && wl_resource_get_version(c->surface.xdg->toplevel->resource) - < XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION) - wlr_xdg_surface_schedule_configure(c->surface.xdg); -} - -void -monocle(Monitor *m) -{ - Client *c; - int n = 0; - - wl_list_for_each(c, &clients, link) { - if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) - continue; - resize(c, m->w, 0); - n++; - } - if (n) - snprintf(m->ltsymbol, LENGTH(m->ltsymbol), "[%d]", n); - if ((c = focustop(m))) - wlr_scene_node_raise_to_top(&c->scene->node); -} - -void -motionabsolute(struct wl_listener *listener, void *data) -{ - /* This event is forwarded by the cursor when a pointer emits an _absolute_ - * motion event, from 0..1 on each axis. This happens, for example, when - * wlroots is running under a Wayland window rather than KMS+DRM, and you - * move the mouse over the window. You could enter the window from any edge, - * so we have to warp the mouse there. There is also some hardware which - * emits these events. */ - struct wlr_pointer_motion_absolute_event *event = data; - double lx, ly, dx, dy; - - if (!event->time_msec) /* this is 0 with virtual pointers */ - wlr_cursor_warp_absolute(cursor, &event->pointer->base, event->x, event->y); - - wlr_cursor_absolute_to_layout_coords(cursor, &event->pointer->base, event->x, event->y, &lx, &ly); - dx = lx - cursor->x; - dy = ly - cursor->y; - motionnotify(event->time_msec, &event->pointer->base, dx, dy, dx, dy); -} - -void -motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy, - double dx_unaccel, double dy_unaccel) -{ - double sx = 0, sy = 0, sx_confined, sy_confined; - Client *c = NULL, *w = NULL; - LayerSurface *l = NULL; - struct wlr_surface *surface = NULL; - struct wlr_pointer_constraint_v1 *constraint; - - /* Find the client under the pointer and send the event along. */ - xytonode(cursor->x, cursor->y, &surface, &c, NULL, &sx, &sy); - - if (cursor_mode == CurPressed && !seat->drag - && surface != seat->pointer_state.focused_surface - && toplevel_from_wlr_surface(seat->pointer_state.focused_surface, &w, &l) >= 0) { - c = w; - surface = seat->pointer_state.focused_surface; - sx = cursor->x - (l ? l->geom.x : w->geom.x); - sy = cursor->y - (l ? l->geom.y : w->geom.y); - } - - /* time is 0 in internal calls meant to restore pointer focus. */ - if (time) { - wlr_relative_pointer_manager_v1_send_relative_motion( - relative_pointer_mgr, seat, (uint64_t)time * 1000, - dx, dy, dx_unaccel, dy_unaccel); - - wl_list_for_each(constraint, &pointer_constraints->constraints, link) - cursorconstrain(constraint); - - if (active_constraint && cursor_mode != CurResize && cursor_mode != CurMove) { - toplevel_from_wlr_surface(active_constraint->surface, &c, NULL); - if (c && active_constraint->surface == seat->pointer_state.focused_surface) { - sx = cursor->x - c->geom.x - c->bw; - sy = cursor->y - c->geom.y - c->bw; - if (wlr_region_confine(&active_constraint->region, sx, sy, - sx + dx, sy + dy, &sx_confined, &sy_confined)) { - dx = sx_confined - sx; - dy = sy_confined - sy; - } - - if (active_constraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED) - return; - } - } - - wlr_cursor_move(cursor, device, dx, dy); - wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); - - /* Update selmon (even while dragging a window) */ - if (sloppyfocus) - selmon = xytomon(cursor->x, cursor->y); - } - - /* Update drag icon's position */ - wlr_scene_node_set_position(&drag_icon->node, (int)round(cursor->x), (int)round(cursor->y)); - - /* If we are currently grabbing the mouse, handle and return */ - if (cursor_mode == CurMove) { - /* Move the grabbed client to the new position. */ - resize(grabc, (struct wlr_box){.x = (int)round(cursor->x) - grabcx, .y = (int)round(cursor->y) - grabcy, - .width = grabc->geom.width, .height = grabc->geom.height}, 1); - return; - } else if (cursor_mode == CurResize) { - resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y, - .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1); - return; - } - - /* 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) - wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); - - pointerfocus(c, surface, sx, sy, time); -} - -void -motionrelative(struct wl_listener *listener, void *data) -{ - /* This event is forwarded by the cursor when a pointer emits a _relative_ - * pointer motion event (i.e. a delta) */ - struct wlr_pointer_motion_event *event = data; - /* The cursor doesn't move unless we tell it to. The cursor automatically - * handles constraining the motion to the output layout, as well as any - * special configuration applied for the specific input device which - * generated the event. You can pass NULL for the device if you want to move - * the cursor around without any input. */ - motionnotify(event->time_msec, &event->pointer->base, event->delta_x, event->delta_y, - event->unaccel_dx, event->unaccel_dy); -} - -void -moveresize(const Arg *arg) -{ - if (cursor_mode != CurNormal && cursor_mode != CurPressed) - return; - xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL); - if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen) - return; - - /* Float the window and tell motionnotify to grab it */ - setfloating(grabc, 1); - switch (cursor_mode = arg->ui) { - case CurMove: - grabcx = (int)round(cursor->x) - grabc->geom.x; - grabcy = (int)round(cursor->y) - grabc->geom.y; - wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur"); - break; - case CurResize: - /* Doesn't work for X11 output - the next absolute motion event - * returns the cursor to where it started */ - wlr_cursor_warp_closest(cursor, NULL, - grabc->geom.x + grabc->geom.width, - grabc->geom.y + grabc->geom.height); - wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); - break; - } -} - -void -outputmgrapply(struct wl_listener *listener, void *data) -{ - struct wlr_output_configuration_v1 *config = data; - outputmgrapplyortest(config, 0); -} - -void -outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test) -{ - /* - * 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, - * so any Monitor information should be updated by updatemons() after an - * output_layout.change event, not here. - */ - struct wlr_output_configuration_head_v1 *config_head; - int ok = 1; - - wl_list_for_each(config_head, &config->heads, link) { - struct wlr_output *wlr_output = config_head->state.output; - Monitor *m = wlr_output->data; - struct wlr_output_state state; - - /* Ensure displays previously disabled by wlr-output-power-management-v1 - * are properly handled*/ - m->asleep = 0; - - wlr_output_state_init(&state); - wlr_output_state_set_enabled(&state, config_head->state.enabled); - if (!config_head->state.enabled) - goto apply_or_test; - - if (config_head->state.mode) - wlr_output_state_set_mode(&state, config_head->state.mode); - else - wlr_output_state_set_custom_mode(&state, - config_head->state.custom_mode.width, - config_head->state.custom_mode.height, - config_head->state.custom_mode.refresh); - - wlr_output_state_set_transform(&state, config_head->state.transform); - wlr_output_state_set_scale(&state, config_head->state.scale); - wlr_output_state_set_adaptive_sync_enabled(&state, - config_head->state.adaptive_sync_enabled); - -apply_or_test: - ok &= test ? wlr_output_test_state(wlr_output, &state) - : wlr_output_commit_state(wlr_output, &state); - - /* Don't move monitors if position wouldn't change, this to avoid - * wlroots marking the output as manually configured. - * wlr_output_layout_add does not like disabled outputs */ - if (!test && wlr_output->enabled && (m->m.x != config_head->state.x || m->m.y != config_head->state.y)) - wlr_output_layout_add(output_layout, wlr_output, - config_head->state.x, config_head->state.y); - - wlr_output_state_finish(&state); - } - - if (ok) - wlr_output_configuration_v1_send_succeeded(config); - else - wlr_output_configuration_v1_send_failed(config); - wlr_output_configuration_v1_destroy(config); - - /* https://codeberg.org/dwl/dwl/issues/577 */ - updatemons(NULL, NULL); -} - -void -outputmgrtest(struct wl_listener *listener, void *data) -{ - struct wlr_output_configuration_v1 *config = data; - outputmgrapplyortest(config, 1); -} - -void -pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, - uint32_t time) -{ - struct timespec now; - - if (surface != seat->pointer_state.focused_surface && - sloppyfocus && time && c && !client_is_unmanaged(c)) - focusclient(c, 0); - - /* If surface is NULL, clear pointer focus */ - if (!surface) { - wlr_seat_pointer_notify_clear_focus(seat); - return; - } - - if (!time) { - clock_gettime(CLOCK_MONOTONIC, &now); - time = now.tv_sec * 1000 + now.tv_nsec / 1000000; - } - - /* Let the client know that the mouse cursor has entered one - * of its surfaces, and make keyboard focus follow if desired. - * 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 -printstatus(void) -{ - Monitor *m = NULL; - Client *c; - uint32_t occ, urg, sel; - const char *appid, *title; - - wl_list_for_each(m, &mons, link) { - occ = urg = 0; - wl_list_for_each(c, &clients, link) { - if (c->mon != m) - continue; - occ |= c->tags; - if (c->isurgent) - urg |= c->tags; - } - if ((c = focustop(m))) { - 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 %d\n", m->wlr_output->name, c->isfullscreen); - printf("%s floating %d\n", m->wlr_output->name, c->isfloating); - sel = c->tags; - } else { - 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 floating \n", m->wlr_output->name); - sel = 0; - } - - printf("%s selmon %u\n", m->wlr_output->name, m == selmon); - printf("%s tags %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32"\n", - m->wlr_output->name, occ, m->tagset[m->seltags], sel, urg); - printf("%s layout %s\n", m->wlr_output->name, m->ltsymbol); - } - fflush(stdout); -} - -void -powermgrsetmode(struct wl_listener *listener, void *data) -{ - struct wlr_output_power_v1_set_mode_event *event = data; - struct wlr_output_state state = {0}; - Monitor *m = event->output->data; - - if (!m) - return; - - m->gamma_lut_changed = 1; /* Reapply gamma LUT when re-enabling the ouput */ - wlr_output_state_set_enabled(&state, event->mode); - wlr_output_commit_state(m->wlr_output, &state); - - m->asleep = !event->mode; -} - -void -quit(const Arg *arg) -{ - wl_display_terminate(dpy); -} - -void -rendermon(struct wl_listener *listener, void *data) -{ - /* This function is called every time an output is ready to display a frame, - * 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 - * this monitor. */ - 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; - } - - /* - * 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 -requestdecorationmode(struct wl_listener *listener, void *data) -{ - Client *c = wl_container_of(listener, c, set_decoration_mode); - if (c->surface.xdg->initialized) - wlr_xdg_toplevel_decoration_v1_set_mode(c->decoration, - WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); -} - -void -requeststartdrag(struct wl_listener *listener, void *data) -{ - struct wlr_seat_request_start_drag_event *event = data; - - if (wlr_seat_validate_pointer_grab_serial(seat, event->origin, - event->serial)) - wlr_seat_start_pointer_drag(seat, event->drag, event->serial); - else - 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; - struct wlr_box clip; - - if (!c->mon || !client_surface(c)->mapped) - return; - - bbox = interact ? &sgeom : &c->mon->w; - - client_set_bounds(c, geo.width, geo.height); - c->geom = geo; - applybounds(c, bbox); - - /* Update scene-graph, including borders */ - wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); - wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); - wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw); - wlr_scene_rect_set_size(c->border[1], c->geom.width, c->bw); - wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - 2 * c->bw); - wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - 2 * c->bw); - wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - 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); - - /* 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 -run(char *startup_cmd) -{ - /* Add a Unix socket to the Wayland display. */ - const char *socket = wl_display_add_socket_auto(dpy); - if (!socket) - die("startup: display_add_socket_auto"); - setenv("WAYLAND_DISPLAY", socket, 1); - - /* Start the backend. This will enumerate outputs and inputs, become the DRM - * master, etc */ - if (!wlr_backend_start(backend)) - die("startup: backend_start"); - - /* Now that the socket exists and the backend is started, run the startup command */ - if (startup_cmd) { - int piperw[2]; - if (pipe(piperw) < 0) - die("startup: pipe:"); - if ((child_pid = fork()) < 0) - die("startup: fork:"); - if (child_pid == 0) { - setsid(); - dup2(piperw[0], STDIN_FILENO); - close(piperw[0]); - close(piperw[1]); - execl("/bin/sh", "/bin/sh", "-c", startup_cmd, NULL); - die("startup: execl:"); - } - dup2(piperw[1], STDOUT_FILENO); - close(piperw[1]); - close(piperw[0]); - } - - /* Mark stdout as non-blocking to avoid people who does not close stdin - * nor consumes it in their startup script getting dwl frozen */ - if (fd_set_nonblock(STDOUT_FILENO) < 0) - close(STDOUT_FILENO); - - printstatus(); - - /* At this point the outputs are initialized, choose initial selmon based on - * cursor position, and set default cursor image */ - selmon = xytomon(cursor->x, cursor->y); - - /* 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 - * 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_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 - * loop configuration to listen to libinput events, DRM events, generate - * frame events at the refresh rate, and so on. */ - wl_display_run(dpy); -} - -void -setcursor(struct wl_listener *listener, void *data) -{ - /* This event is raised by the seat when a client provides a cursor image */ - struct wlr_seat_pointer_request_set_cursor_event *event = data; - /* If we're "grabbing" the cursor, don't use the client's image, we will - * restore it after "grabbing" sending a leave event, followed by a enter - * event, which will result in the client requesting set the cursor surface */ - 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 surface as the cursor image. It will set the - * hardware cursor on the output that it's currently on and continue to - * do so as the cursor moves between outputs. */ - if (event->seat_client == seat->pointer_state.focused_client) - wlr_cursor_set_surface(cursor, event->surface, - 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) -{ - Client *p = client_get_parent(c); - c->isfloating = floating; - /* If in floating layout do not change the client's layer */ - if (!c->mon || !client_surface(c)->mapped || !c->mon->lt[c->mon->sellt]->arrange) - return; - wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen || - (p && p->isfullscreen) ? LyrFS - : c->isfloating ? LyrFloat : LyrTile]); - arrange(c->mon); - printstatus(); -} - -void -setfullscreen(Client *c, int fullscreen) -{ - c->isfullscreen = fullscreen; - if (!c->mon || !client_surface(c)->mapped) - return; - c->bw = fullscreen ? 0 : borderpx; - client_set_fullscreen(c, fullscreen); - wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen - ? LyrFS : c->isfloating ? LyrFloat : LyrTile]); - - if (fullscreen) { - c->prev = c->geom; - resize(c, c->mon->m, 0); - } else { - /* restore previous size instead of arrange for floating windows since - * client positions are set by the user and cannot be recalculated */ - resize(c, c->prev, 0); - } - arrange(c->mon); - 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; - if (!m) - return; - m->gamma_lut_changed = 1; - wlr_output_schedule_frame(m->wlr_output); -} - -void -setlayout(const Arg *arg) -{ - if (!selmon) - return; - if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) - selmon->sellt ^= 1; - if (arg && arg->v) - selmon->lt[selmon->sellt] = (Layout *)arg->v; - strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol)); - arrange(selmon); - printstatus(); -} - -/* arg > 1.0 will set mfact absolutely */ -void -setmfact(const Arg *arg) -{ - float f; - - if (!arg || !selmon || !selmon->lt[selmon->sellt]->arrange) - return; - f = arg->f < 1.0f ? arg->f + selmon->mfact : arg->f - 1.0f; - if (f < 0.1 || f > 0.9) - return; - selmon->mfact = f; - arrange(selmon); -} - -void -setmon(Client *c, Monitor *m, uint32_t newtags) -{ - Monitor *oldmon = c->mon; - - if (oldmon == m) - return; - c->mon = m; - c->prev = c->geom; - - /* Scene graph sends surface leave/enter events on move and resize */ - if (oldmon) - arrange(oldmon); - if (m) { - /* Make sure window actually overlaps with the monitor */ - resize(c, c->geom, 0); - c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */ - setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */ - setfloating(c, c->isfloating); - } - focusclient(focustop(selmon), 1); -} - -void -setpsel(struct wl_listener *listener, void *data) -{ - /* This event is raised by the seat when a client wants to set the selection, - * usually when the user copies something. wlroots allows compositors to - * ignore such requests if they so choose, but in dwl we always honor - */ - struct wlr_seat_request_set_primary_selection_event *event = data; - wlr_seat_set_primary_selection(seat, event->source, event->serial); -} - -void -setsel(struct wl_listener *listener, void *data) -{ - /* This event is raised by the seat when a client wants to set the selection, - * usually when the user copies something. wlroots allows compositors to - * ignore such requests if they so choose, but in dwl we always honor - */ - struct wlr_seat_request_set_selection_event *event = data; - wlr_seat_set_selection(seat, event->source, event->serial); -} - -void -setup(void) -{ - int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE}; - struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = handlesig}; - sigemptyset(&sa.sa_mask); - - for (i = 0; i < (int)LENGTH(sig); i++) - sigaction(sig[i], &sa, NULL); - - wlr_log_init(log_level, NULL); - - /* The Wayland display is managed by libwayland. It handles accepting - * clients from the Unix socket, manging Wayland globals, and so on. */ - dpy = wl_display_create(); - event_loop = wl_display_get_event_loop(dpy); - - /* 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. */ - if (!(backend = wlr_backend_autocreate(event_loop, &session))) - die("couldn't create backend"); - - /* Initialize the scene graph used to lay out windows */ - scene = wlr_scene_create(); - root_bg = wlr_scene_rect_create(&scene->tree, 0, 0, rootcolor); - for (i = 0; i < NUM_LAYERS; i++) - layers[i] = wlr_scene_tree_create(&scene->tree); - drag_icon = wlr_scene_tree_create(&scene->tree); - wlr_scene_node_place_below(&drag_icon->node, &layers[LyrBlock]->node); - - /* 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"); - LISTEN_STATIC(&drw->events.lost, gpureset); - - /* 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_texture_formats(drw, WLR_BUFFER_CAP_DMABUF)) { - wlr_drm_create(dpy, drw); - wlr_scene_set_linux_dmabuf_v1(scene, - wlr_linux_dmabuf_v1_create_with_renderer(dpy, 5, 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"); - - /* This creates some hands-off wlroots interfaces. The compositor is - * necessary for clients to allocate surfaces and the data device manager - * handles the clipboard. Each of these wlroots interfaces has room for you - * 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, 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_primary_selection_v1_device_manager_create(dpy); - wlr_viewporter_create(dpy); - wlr_single_pixel_buffer_manager_v1_create(dpy); - wlr_fractional_scale_manager_v1_create(dpy, 1); - wlr_presentation_create(dpy, backend); - wlr_alpha_modifier_v1_create(dpy); - - /* Initializes the interface used to implement urgency hints */ - activation = wlr_xdg_activation_v1_create(dpy); - 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); - - power_mgr = wlr_output_power_manager_v1_create(dpy); - LISTEN_STATIC(&power_mgr->events.set_mode, powermgrsetmode); - - /* 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(dpy); - 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); - LISTEN_STATIC(&backend->events.new_output, createmon); - - /* 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: - * - * https://drewdevault.com/2018/07/29/Wayland-shells.html - */ - wl_list_init(&clients); - wl_list_init(&fstack); - - xdg_shell = wlr_xdg_shell_create(dpy, 6); - LISTEN_STATIC(&xdg_shell->events.new_toplevel, createnotify); - LISTEN_STATIC(&xdg_shell->events.new_popup, createpopup); - - 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); - LISTEN_STATIC(&idle_inhibit_mgr->events.new_inhibitor, createidleinhibitor); - - session_lock_mgr = wlr_session_lock_manager_v1_create(dpy); - 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.1f, 0.1f, 0.1f, 1.0f}); - wlr_scene_node_set_enabled(&locked_bg->node, 0); - - /* Use decoration protocols to negotiate server-side decorations */ - wlr_server_decoration_manager_set_default_mode( - wlr_server_decoration_manager_create(dpy), - WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); - xdg_decoration_mgr = wlr_xdg_decoration_manager_v1_create(dpy); - LISTEN_STATIC(&xdg_decoration_mgr->events.new_toplevel_decoration, createdecoration); - - pointer_constraints = wlr_pointer_constraints_v1_create(dpy); - LISTEN_STATIC(&pointer_constraints->events.new_constraint, createpointerconstraint); - - relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(dpy); - - /* - * Creates a cursor, which is a wlroots utility for tracking the cursor - * image shown on screen. - */ - cursor = wlr_cursor_create(); - wlr_cursor_attach_output_layout(cursor, output_layout); - - /* Creates an xcursor manager, another wlroots utility which loads up - * Xcursor themes to source cursor images from and makes sure that cursor - * images are available at all scale factors on the screen (necessary for - * HiDPI support). Scaled cursors will be loaded with each output. */ - 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 - * 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 - * https://drewdevault.com/2018/07/17/Input-handling-in-wlroots.html - * - * And more comments are sprinkled throughout the notify functions above. - */ - 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 - * operates the computer. This conceptually includes up to one keyboard, - * pointer, touch, and drawing tablet device. We also rig up a listener to - * let us know when new input devices are available on the backend. - */ - LISTEN_STATIC(&backend->events.new_input, inputdevice); - virtual_keyboard_mgr = wlr_virtual_keyboard_manager_v1_create(dpy); - LISTEN_STATIC(&virtual_keyboard_mgr->events.new_virtual_keyboard, virtualkeyboard); - virtual_pointer_mgr = wlr_virtual_pointer_manager_v1_create(dpy); - LISTEN_STATIC(&virtual_pointer_mgr->events.new_virtual_pointer, virtualpointer); - - seat = wlr_seat_create(dpy, "seat0"); - 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); - - kb_group = createkeyboardgroup(); - wl_list_init(&kb_group->destroy.link); - - output_mgr = wlr_output_manager_v1_create(dpy); - LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply); - LISTEN_STATIC(&output_mgr->events.test, outputmgrtest); - - /* Make sure XWayland clients don't connect to the parent X server, - * e.g when running in the x11 backend or the wayland backend and the - * compositor has Xwayland support */ - unsetenv("DISPLAY"); -#ifdef XWAYLAND - /* - * Initialise the XWayland X server. - * It will be started when the first X client is started. - */ - if ((xwayland = wlr_xwayland_create(dpy, compositor, 1))) { - LISTEN_STATIC(&xwayland->events.ready, xwaylandready); - LISTEN_STATIC(&xwayland->events.new_surface, createnotifyx11); - - setenv("DISPLAY", xwayland->display_name, 1); - } else { - fprintf(stderr, "failed to setup XWayland X server, continuing without it\n"); - } -#endif -} - -void -spawn(const Arg *arg) -{ - if (fork() == 0) { - dup2(STDERR_FILENO, STDOUT_FILENO); - setsid(); - execvp(((char **)arg->v)[0], (char **)arg->v); - die("dwl: execvp %s failed:", ((char **)arg->v)[0]); - } -} - -void -startdrag(struct wl_listener *listener, void *data) -{ - struct wlr_drag *drag = data; - if (!drag->icon) - return; - - drag->icon->data = &wlr_scene_drag_icon_create(drag_icon, drag->icon)->node; - LISTEN_STATIC(&drag->icon->events.destroy, destroydragicon); -} - -void -tag(const Arg *arg) -{ - Client *sel = focustop(selmon); - if (!sel || (arg->ui & TAGMASK) == 0) - return; - - sel->tags = arg->ui & TAGMASK; - focusclient(focustop(selmon), 1); - arrange(selmon); - printstatus(); -} - -void -tagmon(const Arg *arg) -{ - Client *sel = focustop(selmon); - if (sel) - setmon(sel, dirtomon(arg->i), 0); -} - -void -tile(Monitor *m) -{ - unsigned int mw, my, ty; - int i, n = 0; - Client *c; - - wl_list_for_each(c, &clients, link) - if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) - n++; - if (n == 0) - return; - - if (n > m->nmaster) - mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0; - else - mw = m->w.width; - i = my = ty = 0; - wl_list_for_each(c, &clients, link) { - if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) - continue; - if (i < m->nmaster) { - resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw, - .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0); - my += c->geom.height; - } else { - resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty, - .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0); - ty += c->geom.height; - } - i++; - } -} - -void -togglefloating(const Arg *arg) -{ - Client *sel = focustop(selmon); - /* return if fullscreen */ - if (sel && !sel->isfullscreen) - setfloating(sel, !sel->isfloating); -} - -void -togglefullscreen(const Arg *arg) -{ - Client *sel = focustop(selmon); - if (sel) - setfullscreen(sel, !sel->isfullscreen); -} - -void -toggletag(const Arg *arg) -{ - uint32_t newtags; - Client *sel = focustop(selmon); - if (!sel || !(newtags = sel->tags ^ (arg->ui & TAGMASK))) - return; - - sel->tags = newtags; - focusclient(focustop(selmon), 1); - arrange(selmon); - printstatus(); -} - -void -toggleview(const Arg *arg) -{ - uint32_t newtagset; - if (!(newtagset = selmon ? selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK) : 0)) - return; - - selmon->tagset[selmon->seltags] = newtagset; - focusclient(focustop(selmon), 1); - arrange(selmon); - printstatus(); -} - -void -unlocksession(struct wl_listener *listener, void *data) -{ - SessionLock *lock = wl_container_of(listener, lock, unlock); - destroylock(lock, 1); -} - -void -unmaplayersurfacenotify(struct wl_listener *listener, void *data) -{ - LayerSurface *l = wl_container_of(listener, l, unmap); - - l->mapped = 0; - wlr_scene_node_set_enabled(&l->scene->node, 0); - if (l == exclusive_focus) - exclusive_focus = NULL; - if (l->layer_surface->output && (l->mon = l->layer_surface->output->data)) - arrangelayers(l->mon); - if (l->layer_surface->surface == seat->keyboard_state.focused_surface) - focusclient(focustop(selmon), 1); - motionnotify(0, NULL, 0, 0, 0, 0); -} - -void -unmapnotify(struct wl_listener *listener, void *data) -{ - /* Called when the surface is unmapped, and should no longer be shown. */ - Client *c = wl_container_of(listener, c, unmap); - if (c == grabc) { - cursor_mode = CurNormal; - grabc = NULL; - } - - if (client_is_unmanaged(c)) { - if (c == exclusive_focus) { - exclusive_focus = NULL; - focusclient(focustop(selmon), 1); - } - } else { - wl_list_remove(&c->link); - setmon(c, NULL, 0); - wl_list_remove(&c->flink); - } - - wlr_scene_node_destroy(&c->scene->node); - printstatus(); - motionnotify(0, NULL, 0, 0, 0, 0); -} - -void -updatemons(struct wl_listener *listener, void *data) -{ - /* - * Called whenever the output layout changes: adding or removing a - * monitor, changing an output's mode or position, etc. This is where - * the change officially happens and we update geometry, window - * positions, focus, and the stored configuration in wlroots' - * output-manager implementation. - */ - struct wlr_output_configuration_v1 *config - = wlr_output_configuration_v1_create(); - Client *c; - struct wlr_output_configuration_head_v1 *config_head; - Monitor *m; - - /* First remove from the layout the disabled monitors */ - wl_list_for_each(m, &mons, link) { - if (m->wlr_output->enabled || m->asleep) - continue; - config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output); - config_head->state.enabled = 0; - /* Remove this output from the layout to avoid cursor enter inside it */ - wlr_output_layout_remove(output_layout, m->wlr_output); - closemon(m); - m->m = m->w = (struct wlr_box){0}; - } - /* Insert outputs that need to */ - wl_list_for_each(m, &mons, link) { - 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); - - wlr_scene_node_set_position(&root_bg->node, sgeom.x, sgeom.y); - wlr_scene_rect_set_size(root_bg, sgeom.width, sgeom.height); - - /* 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); - - wl_list_for_each(m, &mons, link) { - if (!m->wlr_output->enabled) - continue; - 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); - 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); - wlr_scene_rect_set_size(m->fullscreen_bg, m->m.width, m->m.height); - - if (m->lock_surface) { - struct wlr_scene_tree *scene_tree = m->lock_surface->surface->data; - wlr_scene_node_set_position(&scene_tree->node, m->m.x, m->m.y); - wlr_session_lock_surface_v1_configure(m->lock_surface, m->m.width, 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); - /* make sure fullscreen clients have the right size */ - if ((c = focustop(m)) && c->isfullscreen) - resize(c, m->m, 0); - - /* Try to re-set the gamma LUT when updating monitors, - * it's only really needed when enabling a disabled output, but meh. */ - m->gamma_lut_changed = 1; - - config_head->state.x = m->m.x; - config_head->state.y = m->m.y; - - if (!selmon) { - selmon = m; - } - } - - if (selmon && selmon->wlr_output->enabled) { - wl_list_for_each(c, &clients, link) { - if (!c->mon && client_surface(c)->mapped) - setmon(c, selmon, c->tags); - } - focusclient(focustop(selmon), 1); - if (selmon->lock_surface) { - client_notify_enter(selmon->lock_surface->surface, - wlr_seat_get_keyboard(seat)); - client_activate_surface(selmon->lock_surface->surface, 1); - } - } - - /* 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); -} - -void -updatetitle(struct wl_listener *listener, void *data) -{ - Client *c = wl_container_of(listener, c, set_title); - if (c == focustop(c->mon)) - printstatus(); -} - -void -urgent(struct wl_listener *listener, void *data) -{ - struct wlr_xdg_activation_v1_request_activate_event *event = data; - Client *c = NULL; - toplevel_from_wlr_surface(event->surface, &c, NULL); - if (!c || c == focustop(selmon)) - return; - - c->isurgent = 1; - printstatus(); - - if (client_surface(c)->mapped) - client_set_border_color(c, urgentcolor); -} - -void -view(const Arg *arg) -{ - if (!selmon || (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) - return; - selmon->seltags ^= 1; /* toggle sel tagset */ - if (arg->ui & TAGMASK) - selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; - focusclient(focustop(selmon), 1); - arrange(selmon); - printstatus(); -} - -void -virtualkeyboard(struct wl_listener *listener, void *data) -{ - struct wlr_virtual_keyboard_v1 *kb = data; - /* virtual keyboards shouldn't share keyboard group */ - KeyboardGroup *group = createkeyboardgroup(); - /* Set the keymap to match the group keymap */ - wlr_keyboard_set_keymap(&kb->keyboard, group->wlr_group->keyboard.keymap); - LISTEN(&kb->keyboard.base.events.destroy, &group->destroy, destroykeyboardgroup); - - /* Add the new keyboard to the group */ - wlr_keyboard_group_add_keyboard(group->wlr_group, &kb->keyboard); -} - -void -virtualpointer(struct wl_listener *listener, void *data) -{ - struct wlr_virtual_pointer_v1_new_pointer_event *event = data; - struct wlr_input_device *device = &event->new_pointer->pointer.base; - - wlr_cursor_attach_input_device(cursor, device); - if (event->suggested_output) - wlr_cursor_map_input_to_output(cursor, device, event->suggested_output); -} - -Monitor * -xytomon(double x, double y) -{ - struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y); - return o ? o->data : NULL; -} - -void -xytonode(double x, double y, struct wlr_surface **psurface, - Client **pc, LayerSurface **pl, double *nx, double *ny) -{ - struct wlr_scene_node *node, *pnode; - struct wlr_surface *surface = NULL; - Client *c = NULL; - LayerSurface *l = NULL; - int layer; - - for (layer = NUM_LAYERS - 1; !surface && layer >= 0; layer--) { - if (!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny))) - continue; - - if (node->type == WLR_SCENE_NODE_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) - c = pnode->data; - if (c && c->type == LayerShell) { - c = NULL; - l = pnode->data; - } - } - - if (psurface) *psurface = surface; - if (pc) *pc = c; - if (pl) *pl = l; -} - -void -zoom(const Arg *arg) -{ - Client *c, *sel = focustop(selmon); - - if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange || sel->isfloating) - return; - - /* Search for the first tiled window that is not sel, marking sel as - * NULL if we pass it along the way */ - wl_list_for_each(c, &clients, link) { - if (VISIBLEON(c, selmon) && !c->isfloating) { - if (c != sel) - break; - sel = NULL; - } - } - - /* Return if no other tiled window was found */ - if (&c->link == &clients) - return; - - /* If we passed sel, move c to the front; otherwise, move sel to the - * front */ - if (!sel) - sel = c; - wl_list_remove(&sel->link); - wl_list_insert(&clients, &sel->link); - - focusclient(sel, 1); - arrange(selmon); -} - -#ifdef XWAYLAND -void -activatex11(struct wl_listener *listener, void *data) -{ - Client *c = wl_container_of(listener, c, activate); - - /* Only "managed" windows can be activated */ - if (!client_is_unmanaged(c)) - 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) -{ - Client *c = wl_container_of(listener, c, configure); - struct wlr_xwayland_surface_configure_event *event = data; - /* TODO: figure out if there is another way to do this */ - if (!c->mon) { - wlr_xwayland_surface_configure(c->surface.xwayland, - event->x, event->y, event->width, event->height); - return; - } - if (c->isfloating || client_is_unmanaged(c)) - resize(c, (struct wlr_box){.x = event->x, .y = event->y, - .width = event->width + c->bw * 2, .height = event->height + c->bw * 2}, 0); - else - arrange(c->mon); -} - -void -createnotifyx11(struct wl_listener *listener, void *data) -{ - struct wlr_xwayland_surface *xsurface = data; - Client *c; - - /* Allocate a Client for this surface */ - c = xsurface->data = ecalloc(1, sizeof(*c)); - c->surface.xwayland = xsurface; - c->type = X11; - c->bw = client_is_unmanaged(c) ? 0 : borderpx; - - /* Listen to the various events it can emit */ - LISTEN(&xsurface->events.associate, &c->associate, associatex11); - LISTEN(&xsurface->events.destroy, &c->destroy, destroynotify); - 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.request_fullscreen, &c->fullscreen, fullscreennotify); - LISTEN(&xsurface->events.set_hints, &c->set_hints, sethints); - LISTEN(&xsurface->events.set_title, &c->set_title, updatetitle); -} - -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) -{ - xcb_atom_t atom = 0; - xcb_intern_atom_reply_t *reply; - xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xc, 0, strlen(name), name); - if ((reply = xcb_intern_atom_reply(xc, cookie, NULL))) - atom = reply->atom; - free(reply); - - return atom; -} - -void -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); - printstatus(); - - if (c->isurgent && surface && surface->mapped) - client_set_border_color(c, urgentcolor); -} - -void -xwaylandready(struct wl_listener *listener, void *data) -{ - struct wlr_xcursor *xcursor; - xcb_connection_t *xc = xcb_connect(xwayland->display_name, NULL); - int err = xcb_connection_has_error(xc); - if (err) { - fprintf(stderr, "xcb_connect to X server failed with code %d\n. Continuing with degraded functionality.\n", err); - return; - } - - /* Collect atoms we are interested in. If getatom returns 0, we will - * not detect that window type. */ - netatom[NetWMWindowTypeDialog] = getatom(xc, "_NET_WM_WINDOW_TYPE_DIALOG"); - netatom[NetWMWindowTypeSplash] = getatom(xc, "_NET_WM_WINDOW_TYPE_SPLASH"); - netatom[NetWMWindowTypeToolbar] = getatom(xc, "_NET_WM_WINDOW_TYPE_TOOLBAR"); - netatom[NetWMWindowTypeUtility] = getatom(xc, "_NET_WM_WINDOW_TYPE_UTILITY"); - - /* assign the one and only seat */ - 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, "default", 1))) - wlr_xwayland_set_cursor(xwayland, - xcursor->images[0]->buffer, xcursor->images[0]->width * 4, - xcursor->images[0]->width, xcursor->images[0]->height, - xcursor->images[0]->hotspot_x, xcursor->images[0]->hotspot_y); - - xcb_disconnect(xc); -} -#endif - -int -main(int argc, char *argv[]) -{ - char *startup_cmd = NULL; - int c; - - while ((c = getopt(argc, argv, "s:hdv")) != -1) { - if (c == 's') - startup_cmd = optarg; - else if (c == 'd') - log_level = WLR_DEBUG; - else if (c == 'v') - die("dwl " VERSION); - else - goto usage; - } - if (optind < argc) - goto usage; - - /* Wayland requires XDG_RUNTIME_DIR for creating its communications socket */ - if (!getenv("XDG_RUNTIME_DIR")) - die("XDG_RUNTIME_DIR must be set"); - setup(); - run(startup_cmd); - cleanup(); - return EXIT_SUCCESS; - -usage: - die("Usage: %s [-v] [-d] [-s startup command]", argv[0]); -} diff --git a/dwl/dwl-v0.7/dwl.c.orig b/dwl/dwl-v0.7/dwl.c.orig deleted file mode 100644 index a2711f67..00000000 --- a/dwl/dwl-v0.7/dwl.c.orig +++ /dev/null @@ -1,3215 +0,0 @@ -/* - * See LICENSE file for copyright and license details. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef XWAYLAND -#include -#include -#include -#endif - -#include "util.h" - -/* macros */ -#define MAX(A, B) ((A) > (B) ? (A) : (B)) -#define MIN(A, B) ((A) < (B) ? (A) : (B)) -#define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS) -#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags])) -#define LENGTH(X) (sizeof X / sizeof X[0]) -#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 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 */ -enum { XDGShell, LayerShell, X11 }; /* client types */ -enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ -#ifdef XWAYLAND -enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, - NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ -#endif - -typedef union { - int i; - uint32_t ui; - float f; - const void *v; -} Arg; - -typedef struct { - unsigned int mod; - unsigned int button; - void (*func)(const Arg *); - const Arg arg; -} Button; - -typedef struct Monitor Monitor; -typedef struct { - /* Must keep these three elements in this order */ - unsigned int type; /* XDGShell or X11* */ - struct wlr_box geom; /* layout-relative, includes border */ - Monitor *mon; - struct wlr_scene_tree *scene; - struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ - struct wlr_scene_tree *scene_surface; - struct wl_list link; - struct wl_list flink; - union { - struct wlr_xdg_surface *xdg; - struct wlr_xwayland_surface *xwayland; - } surface; - struct wlr_xdg_toplevel_decoration_v1 *decoration; - struct wl_listener commit; - struct wl_listener map; - struct wl_listener maximize; - struct wl_listener unmap; - struct wl_listener destroy; - struct wl_listener set_title; - struct wl_listener fullscreen; - struct wl_listener set_decoration_mode; - struct wl_listener destroy_decoration; - 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 - unsigned int bw; - uint32_t tags; - int isfloating, isurgent, isfullscreen; - uint32_t resize; /* configure serial of a pending resize */ -} Client; - -typedef struct { - uint32_t mod; - xkb_keysym_t keysym; - void (*func)(const Arg *); - const Arg arg; -} Key; - -typedef struct { - struct wl_list link; - struct wlr_keyboard_group *wlr_group; - - 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 key; - struct wl_listener destroy; -} KeyboardGroup; - -typedef struct { - /* Must keep these three elements in this order */ - unsigned int type; /* LayerShell */ - struct wlr_box geom; - Monitor *mon; - struct wlr_scene_tree *scene; - struct wlr_scene_tree *popups; - struct wlr_scene_layer_surface_v1 *scene_layer; - struct wl_list link; - int mapped; - struct wlr_layer_surface_v1 *layer_surface; - - struct wl_listener destroy; - struct wl_listener unmap; - struct wl_listener surface_commit; -} LayerSurface; - -typedef struct { - const char *symbol; - void (*arrange)(Monitor *); -} Layout; - -struct Monitor { - struct wl_list link; - struct wlr_output *wlr_output; - struct wlr_scene_output *scene_output; - 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 */ - struct wlr_box w; /* window area, layout-relative */ - struct wl_list layers[4]; /* LayerSurface.link */ - const Layout *lt[2]; - unsigned int seltags; - unsigned int sellt; - uint32_t tagset[2]; - float mfact; - int gamma_lut_changed; - int nmaster; - char ltsymbol[16]; - int asleep; -}; - -typedef struct { - const char *name; - float mfact; - int nmaster; - float scale; - const Layout *lt; - enum wl_output_transform rr; - int x, y; -} MonitorRule; - -typedef struct { - struct wlr_pointer_constraint_v1 *constraint; - struct wl_listener destroy; -} PointerConstraint; - -typedef struct { - const char *id; - const char *title; - uint32_t tags; - int isfloating; - int monitor; -} Rule; - -typedef struct { - struct wlr_scene_tree *scene; - - struct wlr_session_lock_v1 *lock; - struct wl_listener new_surface; - struct wl_listener unlock; - struct wl_listener destroy; -} SessionLock; - -/* function declarations */ -static void applybounds(Client *c, struct wlr_box *bbox); -static void applyrules(Client *c); -static void arrange(Monitor *m); -static void arrangelayer(Monitor *m, struct wl_list *list, - struct wlr_box *usable_area, int exclusive); -static void arrangelayers(Monitor *m); -static void axisnotify(struct wl_listener *listener, void *data); -static void buttonpress(struct wl_listener *listener, void *data); -static void chvt(const Arg *arg); -static void checkidleinhibitor(struct wlr_surface *exclude); -static void cleanup(void); -static void cleanupmon(struct wl_listener *listener, void *data); -static void closemon(Monitor *m); -static void commitlayersurfacenotify(struct wl_listener *listener, void *data); -static void commitnotify(struct wl_listener *listener, void *data); -static void commitpopup(struct wl_listener *listener, void *data); -static void createdecoration(struct wl_listener *listener, void *data); -static void createidleinhibitor(struct wl_listener *listener, void *data); -static void createkeyboard(struct wlr_keyboard *keyboard); -static KeyboardGroup *createkeyboardgroup(void); -static void createlayersurface(struct wl_listener *listener, void *data); -static void createlocksurface(struct wl_listener *listener, void *data); -static void createmon(struct wl_listener *listener, void *data); -static void createnotify(struct wl_listener *listener, void *data); -static void createpointer(struct wlr_pointer *pointer); -static void createpointerconstraint(struct wl_listener *listener, void *data); -static void createpopup(struct wl_listener *listener, void *data); -static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint); -static void cursorframe(struct wl_listener *listener, void *data); -static void cursorwarptohint(void); -static void destroydecoration(struct wl_listener *listener, void *data); -static void destroydragicon(struct wl_listener *listener, void *data); -static void destroyidleinhibitor(struct wl_listener *listener, void *data); -static void destroylayersurfacenotify(struct wl_listener *listener, void *data); -static void destroylock(SessionLock *lock, int unlocked); -static void destroylocksurface(struct wl_listener *listener, void *data); -static void destroynotify(struct wl_listener *listener, void *data); -static void destroypointerconstraint(struct wl_listener *listener, void *data); -static void destroysessionlock(struct wl_listener *listener, void *data); -static void destroysessionmgr(struct wl_listener *listener, void *data); -static void destroykeyboardgroup(struct wl_listener *listener, void *data); -static Monitor *dirtomon(enum wlr_direction dir); -static void focusclient(Client *c, int lift); -static void focusmon(const Arg *arg); -static void focusstack(const Arg *arg); -static Client *focustop(Monitor *m); -static void fullscreennotify(struct wl_listener *listener, void *data); -static void gpureset(struct wl_listener *listener, void *data); -static void handlesig(int signo); -static void incnmaster(const Arg *arg); -static void inputdevice(struct wl_listener *listener, void *data); -static int keybinding(uint32_t mods, xkb_keysym_t sym); -static void keypress(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 locksession(struct wl_listener *listener, void *data); -static void mapnotify(struct wl_listener *listener, void *data); -static void maximizenotify(struct wl_listener *listener, void *data); -static void monocle(Monitor *m); -static void motionabsolute(struct wl_listener *listener, void *data); -static void motionnotify(uint32_t time, struct wlr_input_device *device, double sx, - double sy, double sx_unaccel, double sy_unaccel); -static void motionrelative(struct wl_listener *listener, void *data); -static void moveresize(const Arg *arg); -static void outputmgrapply(struct wl_listener *listener, void *data); -static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test); -static void outputmgrtest(struct wl_listener *listener, void *data); -static void pointerfocus(Client *c, struct wlr_surface *surface, - double sx, double sy, uint32_t time); -static void printstatus(void); -static void powermgrsetmode(struct wl_listener *listener, void *data); -static void quit(const Arg *arg); -static void rendermon(struct wl_listener *listener, void *data); -static void requestdecorationmode(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); -static void setpsel(struct wl_listener *listener, void *data); -static void setsel(struct wl_listener *listener, void *data); -static void setup(void); -static void spawn(const Arg *arg); -static void startdrag(struct wl_listener *listener, void *data); -static void tag(const Arg *arg); -static void tagmon(const Arg *arg); -static void tile(Monitor *m); -static void togglefloating(const Arg *arg); -static void togglefullscreen(const Arg *arg); -static void toggletag(const Arg *arg); -static void toggleview(const Arg *arg); -static void unlocksession(struct wl_listener *listener, void *data); -static void unmaplayersurfacenotify(struct wl_listener *listener, void *data); -static void unmapnotify(struct wl_listener *listener, void *data); -static void updatemons(struct wl_listener *listener, void *data); -static void updatetitle(struct wl_listener *listener, void *data); -static void urgent(struct wl_listener *listener, void *data); -static void view(const Arg *arg); -static void virtualkeyboard(struct wl_listener *listener, void *data); -static void virtualpointer(struct wl_listener *listener, void *data); -static Monitor *xytomon(double x, double y); -static void xytonode(double x, double y, struct wlr_surface **psurface, - Client **pc, LayerSurface **pl, double *nx, double *ny); -static void zoom(const Arg *arg); - -/* variables */ -static const char broken[] = "broken"; -static pid_t child_pid = -1; -static int locked; -static void *exclusive_focus; -static struct wl_display *dpy; -static struct wl_event_loop *event_loop; -static struct wlr_backend *backend; -static struct wlr_scene *scene; -static struct wlr_scene_tree *layers[NUM_LAYERS]; -static struct wlr_scene_tree *drag_icon; -/* 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_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_notifier_v1 *idle_notifier; -static struct wlr_idle_inhibit_manager_v1 *idle_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_virtual_pointer_manager_v1 *virtual_pointer_mgr; -static struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr; -static struct wlr_output_power_manager_v1 *power_mgr; - -static struct wlr_pointer_constraints_v1 *pointer_constraints; -static struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr; -static struct wlr_pointer_constraint_v1 *active_constraint; - -static struct wlr_cursor *cursor; -static struct wlr_xcursor_manager *cursor_mgr; - -static struct wlr_scene_rect *root_bg; -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 KeyboardGroup *kb_group; -static unsigned int cursor_mode; -static Client *grabc; -static int grabcx, grabcy; /* client-relative */ - -static struct wlr_output_layout *output_layout; -static struct wlr_box sgeom; -static struct wl_list mons; -static Monitor *selmon; - -#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 wlr_xwayland *xwayland; -static xcb_atom_t netatom[NetLast]; -#endif - -/* configuration, allows nested code to access above variables */ -#include "config.h" - -/* attempt to encapsulate suck into one file */ -#include "client.h" - -/* function implementations */ -void -applybounds(Client *c, struct wlr_box *bbox) -{ - /* set minimum possible */ - c->geom.width = MAX(1 + 2 * (int)c->bw, c->geom.width); - c->geom.height = MAX(1 + 2 * (int)c->bw, c->geom.height); - - if (c->geom.x >= bbox->x + bbox->width) - c->geom.x = bbox->x + bbox->width - c->geom.width; - if (c->geom.y >= bbox->y + bbox->height) - c->geom.y = bbox->y + bbox->height - c->geom.height; - if (c->geom.x + c->geom.width <= bbox->x) - c->geom.x = bbox->x; - if (c->geom.y + c->geom.height <= bbox->y) - c->geom.y = bbox->y; -} - -void -applyrules(Client *c) -{ - /* rule matching */ - const char *appid, *title; - uint32_t newtags = 0; - int i; - const Rule *r; - Monitor *mon = selmon, *m; - - c->isfloating = client_is_float_type(c); - if (!(appid = client_get_appid(c))) - appid = broken; - if (!(title = client_get_title(c))) - title = broken; - - for (r = rules; r < END(rules); r++) { - if ((!r->title || strstr(title, r->title)) - && (!r->id || strstr(appid, r->id))) { - c->isfloating = r->isfloating; - newtags |= r->tags; - i = 0; - wl_list_for_each(m, &mons, link) { - if (r->monitor == i++) - mon = m; - } - } - } - setmon(c, mon, newtags); -} - -void -arrange(Monitor *m) -{ - Client *c; - - if (!m->wlr_output->enabled) - return; - - 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); - - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); - - /* We move all clients (except fullscreen and unmanaged) to LyrTile while - * in floating layout to avoid "real" floating clients be always on top */ - wl_list_for_each(c, &clients, link) { - if (c->mon != m || c->scene->node.parent == layers[LyrFS]) - continue; - - wlr_scene_node_reparent(&c->scene->node, - (!m->lt[m->sellt]->arrange && c->isfloating) - ? layers[LyrTile] - : (m->lt[m->sellt]->arrange && c->isfloating) - ? layers[LyrFloat] - : c->scene->node.parent); - } - - if (m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); - motionnotify(0, NULL, 0, 0, 0, 0); - checkidleinhibitor(NULL); -} - -void -arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, int exclusive) -{ - LayerSurface *l; - struct wlr_box full_area = m->m; - - wl_list_for_each(l, list, link) { - struct wlr_layer_surface_v1 *layer_surface = l->layer_surface; - - if (exclusive != (layer_surface->current.exclusive_zone > 0)) - continue; - - wlr_scene_layer_surface_v1_configure(l->scene_layer, &full_area, usable_area); - wlr_scene_node_set_position(&l->popups->node, l->scene->node.x, l->scene->node.y); - l->geom.x = l->scene->node.x; - l->geom.y = l->scene->node.y; - } -} - -void -arrangelayers(Monitor *m) -{ - int i; - struct wlr_box usable_area = m->m; - LayerSurface *l; - uint32_t layers_above_shell[] = { - ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, - ZWLR_LAYER_SHELL_V1_LAYER_TOP, - }; - if (!m->wlr_output->enabled) - return; - - /* Arrange exclusive surfaces from top->bottom */ - for (i = 3; i >= 0; i--) - arrangelayer(m, &m->layers[i], &usable_area, 1); - - if (!wlr_box_equal(&usable_area, &m->w)) { - m->w = usable_area; - arrange(m); - } - - /* Arrange non-exlusive surfaces from top->bottom */ - for (i = 3; i >= 0; i--) - arrangelayer(m, &m->layers[i], &usable_area, 0); - - /* Find topmost keyboard interactive layer, if such a layer exists */ - for (i = 0; i < (int)LENGTH(layers_above_shell); i++) { - wl_list_for_each_reverse(l, &m->layers[layers_above_shell[i]], link) { - if (locked || !l->layer_surface->current.keyboard_interactive || !l->mapped) - continue; - /* Deactivate the focused client. */ - focusclient(NULL, 0); - exclusive_focus = l; - client_notify_enter(l->layer_surface->surface, wlr_seat_get_keyboard(seat)); - return; - } - } -} - -void -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; - 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. */ - wlr_seat_pointer_notify_axis(seat, - event->time_msec, event->orientation, event->delta, - event->delta_discrete, event->source, event->relative_direction); -} - -void -buttonpress(struct wl_listener *listener, void *data) -{ - struct wlr_pointer_button_event *event = data; - struct wlr_keyboard *keyboard; - uint32_t mods; - Client *c; - const Button *b; - - wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); - - switch (event->state) { - case WL_POINTER_BUTTON_STATE_PRESSED: - cursor_mode = CurPressed; - selmon = xytomon(cursor->x, cursor->y); - if (locked) - break; - - /* Change focus if the button was _pressed_ over a client */ - xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); - if (c && (!client_is_unmanaged(c) || client_wants_focus(c))) - focusclient(c, 1); - - keyboard = wlr_seat_get_keyboard(seat); - mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; - for (b = buttons; b < END(buttons); b++) { - if (CLEANMASK(mods) == CLEANMASK(b->mod) && - event->button == b->button && b->func) { - b->func(&b->arg); - return; - } - } - break; - case WL_POINTER_BUTTON_STATE_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; - /* Drop the window off on its new monitor */ - selmon = xytomon(cursor->x, cursor->y); - setmon(grabc, selmon, 0); - return; - } else { - cursor_mode = CurNormal; - } - break; - } - /* If the event wasn't handled by the compositor, notify the client with - * pointer focus that a button press has occurred */ - wlr_seat_pointer_notify_button(seat, - event->time_msec, event->button, event->state); -} - -void -chvt(const Arg *arg) -{ - wlr_session_change_vt(session, arg->ui); -} - -void -checkidleinhibitor(struct wlr_surface *exclude) -{ - int inhibited = 0, unused_lx, unused_ly; - struct wlr_idle_inhibitor_v1 *inhibitor; - wl_list_for_each(inhibitor, &idle_inhibit_mgr->inhibitors, link) { - struct wlr_surface *surface = wlr_surface_get_root_surface(inhibitor->surface); - struct wlr_scene_tree *tree = surface->data; - if (exclude != surface && (bypass_surface_visibility || (!tree - || wlr_scene_node_coords(&tree->node, &unused_lx, &unused_ly)))) { - inhibited = 1; - break; - } - } - - wlr_idle_notifier_v1_set_inhibited(idle_notifier, inhibited); -} - -void -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_xcursor_manager_destroy(cursor_mgr); - - destroykeyboardgroup(&kb_group->destroy, NULL); - - /* If it's not destroyed manually it will cause a use-after-free of wlr_seat. - * Destroy it until it's fixed in the wlroots side */ - wlr_backend_destroy(backend); - - 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 -cleanupmon(struct wl_listener *listener, void *data) -{ - Monitor *m = wl_container_of(listener, m, destroy); - LayerSurface *l, *tmp; - size_t i; - - /* m->layers[i] are intentionally not unlinked */ - for (i = 0; i < LENGTH(m->layers); i++) { - wl_list_for_each_safe(l, tmp, &m->layers[i], link) - wlr_layer_surface_v1_destroy(l->layer_surface); - } - - wl_list_remove(&m->destroy.link); - wl_list_remove(&m->frame.link); - wl_list_remove(&m->link); - wl_list_remove(&m->request_state.link); - m->wlr_output->data = NULL; - wlr_output_layout_remove(output_layout, m->wlr_output); - wlr_scene_output_destroy(m->scene_output); - - closemon(m); - wlr_scene_node_destroy(&m->fullscreen_bg->node); - free(m); -} - -void -closemon(Monitor *m) -{ - /* update selmon if needed and - * move closed monitor's clients to the focused one */ - Client *c; - int i = 0, nmons = wl_list_length(&mons); - if (!nmons) { - selmon = NULL; - } else if (m == selmon) { - do /* don't switch to disabled mons */ - selmon = wl_container_of(mons.next, selmon, link); - while (!selmon->wlr_output->enabled && i++ < nmons); - - if (!selmon->wlr_output->enabled) - selmon = NULL; - } - - wl_list_for_each(c, &clients, link) { - if (c->isfloating && c->geom.x > m->m.width) - resize(c, (struct wlr_box){.x = c->geom.x - m->w.width, .y = c->geom.y, - .width = c->geom.width, .height = c->geom.height}, 0); - if (c->mon == m) - setmon(c, selmon, c->tags); - } - focusclient(focustop(selmon), 1); - printstatus(); -} - -void -commitlayersurfacenotify(struct wl_listener *listener, void *data) -{ - LayerSurface *l = wl_container_of(listener, l, surface_commit); - struct wlr_layer_surface_v1 *layer_surface = l->layer_surface; - struct wlr_scene_tree *scene_layer = layers[layermap[layer_surface->current.layer]]; - struct wlr_layer_surface_v1_state old_state; - - if (l->layer_surface->initial_commit) { - wlr_fractional_scale_v1_notify_scale(layer_surface->surface, l->mon->wlr_output->scale); - wlr_surface_set_preferred_buffer_scale(layer_surface->surface, (int32_t)ceilf(l->mon->wlr_output->scale)); - - /* Temporarily set the layer's current state to pending - * so that we can easily arrange it */ - old_state = l->layer_surface->current; - l->layer_surface->current = l->layer_surface->pending; - arrangelayers(l->mon); - l->layer_surface->current = old_state; - return; - } - - if (layer_surface->current.committed == 0 && l->mapped == layer_surface->surface->mapped) - return; - l->mapped = layer_surface->surface->mapped; - - if (scene_layer != l->scene->node.parent) { - wlr_scene_node_reparent(&l->scene->node, scene_layer); - wl_list_remove(&l->link); - wl_list_insert(&l->mon->layers[layer_surface->current.layer], &l->link); - wlr_scene_node_reparent(&l->popups->node, (layer_surface->current.layer - < ZWLR_LAYER_SHELL_V1_LAYER_TOP ? layers[LyrTop] : scene_layer)); - } - - arrangelayers(l->mon); -} - -void -commitnotify(struct wl_listener *listener, void *data) -{ - Client *c = wl_container_of(listener, c, commit); - - if (c->surface.xdg->initial_commit) { - /* - * Get the monitor this client will be rendered on - * Note that if the user set a rule in which the client is placed on - * a different monitor based on its title this will likely select - * a wrong monitor. - */ - applyrules(c); - wlr_surface_set_preferred_buffer_scale(client_surface(c), (int)ceilf(c->mon->wlr_output->scale)); - wlr_fractional_scale_v1_notify_scale(client_surface(c), c->mon->wlr_output->scale); - setmon(c, NULL, 0); /* Make sure to reapply rules in mapnotify() */ - - wlr_xdg_toplevel_set_wm_capabilities(c->surface.xdg->toplevel, WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN); - wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, 0, 0); - if (c->decoration) - requestdecorationmode(&c->set_decoration_mode, c->decoration); - return; - } - - if (client_surface(c)->mapped && c->mon) - 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; -} - -void -commitpopup(struct wl_listener *listener, void *data) -{ - struct wlr_surface *surface = data; - struct wlr_xdg_popup *popup = wlr_xdg_popup_try_from_wlr_surface(surface); - LayerSurface *l = NULL; - Client *c = NULL; - struct wlr_box box; - int type = -1; - - if (!popup->base->initial_commit) - return; - - type = toplevel_from_wlr_surface(popup->base->surface, &c, &l); - if (!popup->parent || type < 0) - return; - popup->base->surface->data = wlr_scene_xdg_surface_create( - popup->parent->data, popup->base); - if ((l && !l->mon) || (c && !c->mon)) - return; - box = type == LayerShell ? l->mon->m : c->mon->w; - box.x -= (type == LayerShell ? l->geom.x : c->geom.x); - box.y -= (type == LayerShell ? l->geom.y : c->geom.y); - wlr_xdg_popup_unconstrain_from_box(popup, &box); - wl_list_remove(&listener->link); -} - -void -createdecoration(struct wl_listener *listener, void *data) -{ - struct wlr_xdg_toplevel_decoration_v1 *deco = data; - Client *c = deco->toplevel->base->data; - c->decoration = deco; - - LISTEN(&deco->events.request_mode, &c->set_decoration_mode, requestdecorationmode); - LISTEN(&deco->events.destroy, &c->destroy_decoration, destroydecoration); - - requestdecorationmode(&c->set_decoration_mode, deco); -} - -void -createidleinhibitor(struct wl_listener *listener, void *data) -{ - struct wlr_idle_inhibitor_v1 *idle_inhibitor = data; - LISTEN_STATIC(&idle_inhibitor->events.destroy, destroyidleinhibitor); - - checkidleinhibitor(NULL); -} - -void -createkeyboard(struct wlr_keyboard *keyboard) -{ - /* Set the keymap to match the group keymap */ - wlr_keyboard_set_keymap(keyboard, kb_group->wlr_group->keyboard.keymap); - - /* Add the new keyboard to the group */ - wlr_keyboard_group_add_keyboard(kb_group->wlr_group, keyboard); -} - -KeyboardGroup * -createkeyboardgroup(void) -{ - KeyboardGroup *group = ecalloc(1, sizeof(*group)); - struct xkb_context *context; - struct xkb_keymap *keymap; - - group->wlr_group = wlr_keyboard_group_create(); - group->wlr_group->data = group; - - /* Prepare an XKB keymap and assign it to the keyboard group. */ - context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - if (!(keymap = xkb_keymap_new_from_names(context, &xkb_rules, - XKB_KEYMAP_COMPILE_NO_FLAGS))) - die("failed to compile keymap"); - - wlr_keyboard_set_keymap(&group->wlr_group->keyboard, keymap); - xkb_keymap_unref(keymap); - xkb_context_unref(context); - - wlr_keyboard_set_repeat_info(&group->wlr_group->keyboard, repeat_rate, repeat_delay); - - /* Set up listeners for keyboard events */ - LISTEN(&group->wlr_group->keyboard.events.key, &group->key, keypress); - LISTEN(&group->wlr_group->keyboard.events.modifiers, &group->modifiers, keypressmod); - - group->key_repeat_source = wl_event_loop_add_timer(event_loop, keyrepeat, group); - - /* A seat can only have one keyboard, but this is a limitation of the - * Wayland protocol - not wlroots. We assign all connected keyboards to the - * same wlr_keyboard_group, which provides a single wlr_keyboard interface for - * all of them. Set this combined wlr_keyboard as the seat keyboard. - */ - wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard); - return group; -} - -void -createlayersurface(struct wl_listener *listener, void *data) -{ - struct wlr_layer_surface_v1 *layer_surface = data; - LayerSurface *l; - struct wlr_surface *surface = layer_surface->surface; - struct wlr_scene_tree *scene_layer = layers[layermap[layer_surface->pending.layer]]; - - if (!layer_surface->output - && !(layer_surface->output = selmon ? selmon->wlr_output : NULL)) { - wlr_layer_surface_v1_destroy(layer_surface); - return; - } - - l = layer_surface->data = ecalloc(1, sizeof(*l)); - l->type = LayerShell; - LISTEN(&surface->events.commit, &l->surface_commit, commitlayersurfacenotify); - LISTEN(&surface->events.unmap, &l->unmap, unmaplayersurfacenotify); - LISTEN(&layer_surface->events.destroy, &l->destroy, destroylayersurfacenotify); - - l->layer_surface = layer_surface; - l->mon = layer_surface->output->data; - l->scene_layer = wlr_scene_layer_surface_v1_create(scene_layer, layer_surface); - l->scene = l->scene_layer->tree; - l->popups = surface->data = wlr_scene_tree_create(layer_surface->current.layer - < ZWLR_LAYER_SHELL_V1_LAYER_TOP ? layers[LyrTop] : scene_layer); - l->scene->node.data = l->popups->node.data = l; - - wl_list_insert(&l->mon->layers[layer_surface->pending.layer],&l->link); - wlr_surface_send_enter(surface, layer_surface->output); -} - -void -createlocksurface(struct wl_listener *listener, void *data) -{ - SessionLock *lock = wl_container_of(listener, lock, new_surface); - struct wlr_session_lock_surface_v1 *lock_surface = data; - Monitor *m = lock_surface->output->data; - struct wlr_scene_tree *scene_tree = lock_surface->surface->data - = wlr_scene_subsurface_tree_create(lock->scene, lock_surface->surface); - m->lock_surface = lock_surface; - - wlr_scene_node_set_position(&scene_tree->node, m->m.x, m->m.y); - wlr_session_lock_surface_v1_configure(lock_surface, m->m.width, m->m.height); - - LISTEN(&lock_surface->events.destroy, &m->destroy_lock_surface, destroylocksurface); - - if (m == selmon) - client_notify_enter(lock_surface->surface, wlr_seat_get_keyboard(seat)); -} - -void -createmon(struct wl_listener *listener, void *data) -{ - /* This event is raised by the backend when a new output (aka a display or - * monitor) becomes available. */ - struct wlr_output *wlr_output = data; - const MonitorRule *r; - size_t i; - struct wlr_output_state state; - Monitor *m; - - if (!wlr_output_init_render(wlr_output, alloc, drw)) - return; - - m = wlr_output->data = ecalloc(1, sizeof(*m)); - m->wlr_output = wlr_output; - - for (i = 0; i < LENGTH(m->layers); i++) - wl_list_init(&m->layers[i]); - - wlr_output_state_init(&state); - /* Initialize monitor state using configured rules */ - m->tagset[0] = m->tagset[1] = 1; - for (r = monrules; r < END(monrules); r++) { - if (!r->name || strstr(wlr_output->name, r->name)) { - m->m.x = r->x; - m->m.y = r->y; - m->mfact = r->mfact; - m->nmaster = r->nmaster; - m->lt[0] = r->lt; - m->lt[1] = &layouts[LENGTH(layouts) > 1 && r->lt != &layouts[1]]; - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); - wlr_output_state_set_scale(&state, r->scale); - wlr_output_state_set_transform(&state, r->rr); - break; - } - } - - /* The mode is a tuple of (width, height, refresh rate), and each - * monitor supports only a specific set of modes. We just pick the - * monitor's preferred mode; a more sophisticated compositor would let - * the user configure it. */ - wlr_output_state_set_mode(&state, wlr_output_preferred_mode(wlr_output)); - - /* 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_state_set_enabled(&state, 1); - wlr_output_commit_state(wlr_output, &state); - wlr_output_state_finish(&state); - - wl_list_insert(&mons, &m->link); - printstatus(); - - /* The xdg-protocol specifies: - * - * If the fullscreened surface is not opaque, the compositor must make - * sure that other screen content not part of the same surface tree (made - * up of subsurfaces, popups or similarly coupled surfaces) are not - * visible below the fullscreened surface. - * - */ - /* updatemons() will resize and set correct position */ - m->fullscreen_bg = wlr_scene_rect_create(layers[LyrFS], 0, 0, fullscreen_bg); - wlr_scene_node_set_enabled(&m->fullscreen_bg->node, 0); - - /* Adds this to the output layout in the order it was configured. - * - * The output layout utility automatically adds a wl_output global to the - * display, which Wayland clients can see to find out information about the - * output (such as DPI, scale factor, manufacturer, etc). - */ - m->scene_output = wlr_scene_output_create(scene, wlr_output); - if (m->m.x == -1 && m->m.y == -1) - wlr_output_layout_add_auto(output_layout, wlr_output); - else - wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y); -} - -void -createnotify(struct wl_listener *listener, void *data) -{ - /* This event is raised when a client creates a new toplevel (application window). */ - struct wlr_xdg_toplevel *toplevel = data; - Client *c = NULL; - - /* Allocate a Client for this surface */ - c = toplevel->base->data = ecalloc(1, sizeof(*c)); - c->surface.xdg = toplevel->base; - c->bw = borderpx; - - LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify); - LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify); - LISTEN(&toplevel->base->surface->events.unmap, &c->unmap, unmapnotify); - LISTEN(&toplevel->events.destroy, &c->destroy, destroynotify); - LISTEN(&toplevel->events.request_fullscreen, &c->fullscreen, fullscreennotify); - LISTEN(&toplevel->events.request_maximize, &c->maximize, maximizenotify); - LISTEN(&toplevel->events.set_title, &c->set_title, updatetitle); -} - -void -createpointer(struct wlr_pointer *pointer) -{ - struct libinput_device *device; - if (wlr_input_device_is_libinput(&pointer->base) - && (device = wlr_libinput_get_device_handle(&pointer->base))) { - - if (libinput_device_config_tap_get_finger_count(device)) { - libinput_device_config_tap_set_enabled(device, tap_to_click); - libinput_device_config_tap_set_drag_enabled(device, tap_and_drag); - libinput_device_config_tap_set_drag_lock_enabled(device, drag_lock); - libinput_device_config_tap_set_button_map(device, button_map); - } - - if (libinput_device_config_scroll_has_natural_scroll(device)) - libinput_device_config_scroll_set_natural_scroll_enabled(device, natural_scrolling); - - if (libinput_device_config_dwt_is_available(device)) - libinput_device_config_dwt_set_enabled(device, disable_while_typing); - - if (libinput_device_config_left_handed_is_available(device)) - libinput_device_config_left_handed_set(device, left_handed); - - if (libinput_device_config_middle_emulation_is_available(device)) - libinput_device_config_middle_emulation_set_enabled(device, middle_button_emulation); - - if (libinput_device_config_scroll_get_methods(device) != LIBINPUT_CONFIG_SCROLL_NO_SCROLL) - libinput_device_config_scroll_set_method (device, scroll_method); - - if (libinput_device_config_click_get_methods(device) != LIBINPUT_CONFIG_CLICK_METHOD_NONE) - libinput_device_config_click_set_method (device, click_method); - - if (libinput_device_config_send_events_get_modes(device)) - libinput_device_config_send_events_set_mode(device, send_events_mode); - - if (libinput_device_config_accel_is_available(device)) { - libinput_device_config_accel_set_profile(device, accel_profile); - libinput_device_config_accel_set_speed(device, accel_speed); - } - } - - wlr_cursor_attach_input_device(cursor, &pointer->base); -} - -void -createpointerconstraint(struct wl_listener *listener, void *data) -{ - PointerConstraint *pointer_constraint = ecalloc(1, sizeof(*pointer_constraint)); - pointer_constraint->constraint = data; - LISTEN(&pointer_constraint->constraint->events.destroy, - &pointer_constraint->destroy, destroypointerconstraint); -} - -void -createpopup(struct wl_listener *listener, void *data) -{ - /* This event is raised when a client (either xdg-shell or layer-shell) - * creates a new popup. */ - struct wlr_xdg_popup *popup = data; - LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup); -} - -void -cursorconstrain(struct wlr_pointer_constraint_v1 *constraint) -{ - if (active_constraint == constraint) - return; - - if (active_constraint) - wlr_pointer_constraint_v1_send_deactivated(active_constraint); - - active_constraint = constraint; - wlr_pointer_constraint_v1_send_activated(constraint); -} - -void -cursorframe(struct wl_listener *listener, void *data) -{ - /* This event is forwarded by the cursor when a pointer emits an frame - * event. Frame events are sent after regular pointer events to group - * multiple events together. For instance, two axis events may happen at the - * same time, in which case a frame event won't be sent in between. */ - /* Notify the client with pointer focus of the frame event. */ - wlr_seat_pointer_notify_frame(seat); -} - -void -cursorwarptohint(void) -{ - Client *c = NULL; - double sx = active_constraint->current.cursor_hint.x; - double sy = active_constraint->current.cursor_hint.y; - - toplevel_from_wlr_surface(active_constraint->surface, &c, NULL); - if (c && active_constraint->current.cursor_hint.enabled) { - wlr_cursor_warp(cursor, NULL, sx + c->geom.x + c->bw, sy + c->geom.y + c->bw); - wlr_seat_pointer_warp(active_constraint->seat, sx, sy); - } -} - -void -destroydecoration(struct wl_listener *listener, void *data) -{ - Client *c = wl_container_of(listener, c, destroy_decoration); - c->decoration = NULL; - - wl_list_remove(&c->destroy_decoration.link); - wl_list_remove(&c->set_decoration_mode.link); -} - -void -destroydragicon(struct wl_listener *listener, void *data) -{ - /* Focus enter isn't sent during drag, so refocus the focused node. */ - focusclient(focustop(selmon), 1); - motionnotify(0, NULL, 0, 0, 0, 0); -} - -void -destroyidleinhibitor(struct wl_listener *listener, void *data) -{ - /* `data` is the wlr_surface of the idle inhibitor being destroyed, - * at this point the idle inhibitor is still in the list of the manager */ - checkidleinhibitor(wlr_surface_get_root_surface(data)); -} - -void -destroylayersurfacenotify(struct wl_listener *listener, void *data) -{ - LayerSurface *l = wl_container_of(listener, l, destroy); - - wl_list_remove(&l->link); - wl_list_remove(&l->destroy.link); - wl_list_remove(&l->unmap.link); - wl_list_remove(&l->surface_commit.link); - wlr_scene_node_destroy(&l->scene->node); - wlr_scene_node_destroy(&l->popups->node); - free(l); -} - -void -destroylock(SessionLock *lock, int unlock) -{ - wlr_seat_keyboard_notify_clear_focus(seat); - if ((locked = !unlock)) - goto destroy; - - wlr_scene_node_set_enabled(&locked_bg->node, 0); - - focusclient(focustop(selmon), 0); - motionnotify(0, NULL, 0, 0, 0, 0); - -destroy: - wl_list_remove(&lock->new_surface.link); - wl_list_remove(&lock->unlock.link); - wl_list_remove(&lock->destroy.link); - - wlr_scene_node_destroy(&lock->scene->node); - cur_lock = NULL; - free(lock); -} - -void -destroylocksurface(struct wl_listener *listener, void *data) -{ - Monitor *m = wl_container_of(listener, m, destroy_lock_surface); - struct wlr_session_lock_surface_v1 *surface, *lock_surface = m->lock_surface; - - m->lock_surface = NULL; - wl_list_remove(&m->destroy_lock_surface.link); - - if (lock_surface->surface != seat->keyboard_state.focused_surface) - return; - - if (locked && cur_lock && !wl_list_empty(&cur_lock->surfaces)) { - surface = wl_container_of(cur_lock->surfaces.next, surface, link); - client_notify_enter(surface->surface, wlr_seat_get_keyboard(seat)); - } else if (!locked) { - focusclient(focustop(selmon), 1); - } else { - wlr_seat_keyboard_clear_focus(seat); - } -} - -void -destroynotify(struct wl_listener *listener, void *data) -{ - /* Called when the xdg_toplevel is destroyed. */ - Client *c = wl_container_of(listener, c, destroy); - 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->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); -} - -void -destroypointerconstraint(struct wl_listener *listener, void *data) -{ - PointerConstraint *pointer_constraint = wl_container_of(listener, pointer_constraint, destroy); - - if (active_constraint == pointer_constraint->constraint) { - cursorwarptohint(); - active_constraint = NULL; - } - - wl_list_remove(&pointer_constraint->destroy.link); - free(pointer_constraint); -} - -void -destroysessionlock(struct wl_listener *listener, void *data) -{ - SessionLock *lock = wl_container_of(listener, lock, destroy); - destroylock(lock, 0); -} - -void -destroysessionmgr(struct wl_listener *listener, void *data) -{ - wl_list_remove(&lock_listener.link); - wl_list_remove(&listener->link); -} - -void -destroykeyboardgroup(struct wl_listener *listener, void *data) -{ - KeyboardGroup *group = wl_container_of(listener, group, destroy); - wl_event_source_remove(group->key_repeat_source); - wlr_keyboard_group_destroy(group->wlr_group); - wl_list_remove(&group->key.link); - wl_list_remove(&group->modifiers.link); - wl_list_remove(&group->destroy.link); - free(group); -} - -Monitor * -dirtomon(enum wlr_direction dir) -{ - struct wlr_output *next; - if (!wlr_output_layout_get(output_layout, selmon->wlr_output)) - return selmon; - if ((next = wlr_output_layout_adjacent_output(output_layout, - dir, selmon->wlr_output, selmon->m.x, selmon->m.y))) - return next->data; - if ((next = wlr_output_layout_farthest_output(output_layout, - dir ^ (WLR_DIRECTION_LEFT|WLR_DIRECTION_RIGHT), - selmon->wlr_output, selmon->m.x, selmon->m.y))) - return next->data; - return selmon; -} - -void -focusclient(Client *c, int lift) -{ - struct wlr_surface *old = seat->keyboard_state.focused_surface; - int unused_lx, unused_ly, old_client_type; - Client *old_c = NULL; - LayerSurface *old_l = NULL; - - if (locked) - return; - - /* Raise client in stacking order if requested */ - if (c && lift) - wlr_scene_node_raise_to_top(&c->scene->node); - - if (c && client_surface(c) == old) - 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 */ - if (c && !client_is_unmanaged(c)) { - wl_list_remove(&c->flink); - wl_list_insert(&fstack, &c->flink); - selmon = c->mon; - c->isurgent = 0; - client_restack_surface(c); - - /* Don't change border color if there is an exclusive focus or we are - * handling a drag operation */ - if (!exclusive_focus && !seat->drag) - client_set_border_color(c, focuscolor); - } - - /* Deactivate old client if focus is changing */ - if (old && (!c || client_surface(c) != old)) { - /* 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 - * and focus it after the overlay is closed. */ - if (old_client_type == LayerShell && wlr_scene_node_coords( - &old_l->scene->node, &unused_lx, &unused_ly) - && old_l->layer_surface->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { - return; - } else if (old_c && old_c == exclusive_focus && client_wants_focus(old_c)) { - return; - /* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg - * and probably other clients */ - } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { - client_set_border_color(old_c, bordercolor); - - client_activate_surface(old, 0); - } - } - printstatus(); - - if (!c) { - /* With no client, all we have left is to clear focus */ - wlr_seat_keyboard_notify_clear_focus(seat); - return; - } - - /* Change cursor surface */ - motionnotify(0, NULL, 0, 0, 0, 0); - - /* Have a client, so focus its top-level wlr_surface */ - client_notify_enter(client_surface(c), wlr_seat_get_keyboard(seat)); - - /* Activate the new client */ - client_activate_surface(client_surface(c), 1); -} - -void -focusmon(const Arg *arg) -{ - int i = 0, nmons = wl_list_length(&mons); - if (nmons) { - do /* don't switch to disabled mons */ - selmon = dirtomon(arg->i); - while (!selmon->wlr_output->enabled && i++ < nmons); - } - focusclient(focustop(selmon), 1); -} - -void -focusstack(const Arg *arg) -{ - /* Focus the next or previous client (in tiling order) on selmon */ - Client *c, *sel = focustop(selmon); - if (!sel || (sel->isfullscreen && !client_has_children(sel))) - return; - if (arg->i > 0) { - wl_list_for_each(c, &sel->link, link) { - if (&c->link == &clients) - continue; /* wrap past the sentinel node */ - if (VISIBLEON(c, selmon)) - break; /* found it */ - } - } else { - wl_list_for_each_reverse(c, &sel->link, link) { - if (&c->link == &clients) - continue; /* wrap past the sentinel node */ - if (VISIBLEON(c, selmon)) - break; /* found it */ - } - } - /* If only one client is visible on selmon, then c == sel */ - focusclient(c, 1); -} - -/* We probably should change the name of this, it sounds like - * will focus the topmost client of this mon, when actually will - * only return that client */ -Client * -focustop(Monitor *m) -{ - Client *c; - wl_list_for_each(c, &fstack, flink) { - if (VISIBLEON(c, m)) - return c; - } - return NULL; -} - -void -fullscreennotify(struct wl_listener *listener, void *data) -{ - Client *c = wl_container_of(listener, c, fullscreen); - setfullscreen(c, client_wants_fullscreen(c)); -} - -void -gpureset(struct wl_listener *listener, void *data) -{ - struct wlr_renderer *old_drw = drw; - struct wlr_allocator *old_alloc = alloc; - struct Monitor *m; - if (!(drw = wlr_renderer_autocreate(backend))) - die("couldn't recreate renderer"); - - if (!(alloc = wlr_allocator_autocreate(backend, drw))) - die("couldn't recreate allocator"); - - LISTEN_STATIC(&drw->events.lost, gpureset); - - wlr_compositor_set_renderer(compositor, drw); - - wl_list_for_each(m, &mons, link) { - wlr_output_init_render(m->wlr_output, alloc, drw); - } - - wlr_allocator_destroy(old_alloc); - wlr_renderer_destroy(old_drw); -} - -void -handlesig(int signo) -{ - if (signo == SIGCHLD) { -#ifdef XWAYLAND - siginfo_t in; - /* wlroots expects to reap the XWayland process itself, so we - * use WNOWAIT to keep the child waitable until we know it's not - * XWayland. - */ - 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 - } else if (signo == SIGINT || signo == SIGTERM) { - quit(NULL); - } -} - -void -incnmaster(const Arg *arg) -{ - if (!arg || !selmon) - return; - selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); - arrange(selmon); -} - -void -inputdevice(struct wl_listener *listener, void *data) -{ - /* This event is raised by the backend when a new input device becomes - * available. */ - struct wlr_input_device *device = data; - uint32_t caps; - - switch (device->type) { - case WLR_INPUT_DEVICE_KEYBOARD: - createkeyboard(wlr_keyboard_from_input_device(device)); - break; - case WLR_INPUT_DEVICE_POINTER: - createpointer(wlr_pointer_from_input_device(device)); - break; - default: - /* TODO handle other input device types */ - break; - } - - /* We need to let the wlr_seat know what our capabilities are, which is - * communiciated to the client. In dwl we always have a cursor, even if - * there are no pointer devices, so we always include that capability. */ - /* TODO do we actually require a cursor? */ - caps = WL_SEAT_CAPABILITY_POINTER; - if (!wl_list_empty(&kb_group->wlr_group->devices)) - caps |= WL_SEAT_CAPABILITY_KEYBOARD; - wlr_seat_set_capabilities(seat, caps); -} - -int -keybinding(uint32_t mods, xkb_keysym_t sym) -{ - /* - * Here we handle compositor keybindings. This is when the compositor is - * processing keys, rather than passing them on to the client for its own - * processing. - */ - const Key *k; - for (k = keys; k < END(keys); k++) { - if (CLEANMASK(mods) == CLEANMASK(k->mod) - && sym == k->keysym && k->func) { - k->func(&k->arg); - return 1; - } - } - return 0; -} - -void -keypress(struct wl_listener *listener, void *data) -{ - int i; - /* This event is raised when a key is pressed or released. */ - KeyboardGroup *group = wl_container_of(listener, group, key); - struct wlr_keyboard_key_event *event = data; - - /* Translate libinput keycode -> xkbcommon */ - uint32_t keycode = event->keycode + 8; - /* Get a list of keysyms based on the keymap for this keyboard */ - const xkb_keysym_t *syms; - int nsyms = xkb_state_key_get_syms( - group->wlr_group->keyboard.xkb_state, keycode, &syms); - - int handled = 0; - uint32_t mods = wlr_keyboard_get_modifiers(&group->wlr_group->keyboard); - - 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 && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { - for (i = 0; i < nsyms; i++) - handled = keybinding(mods, syms[i]) || handled; - } - - if (handled && group->wlr_group->keyboard.repeat_info.delay > 0) { - group->mods = mods; - group->keysyms = syms; - group->nsyms = nsyms; - wl_event_source_timer_update(group->key_repeat_source, - group->wlr_group->keyboard.repeat_info.delay); - } else { - group->nsyms = 0; - wl_event_source_timer_update(group->key_repeat_source, 0); - } - - if (handled) - return; - - wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard); - /* Pass unhandled keycodes along to the client. */ - wlr_seat_keyboard_notify_key(seat, event->time_msec, - event->keycode, event->state); -} - -void -keypressmod(struct wl_listener *listener, void *data) -{ - /* This event is raised when a modifier key, such as shift or alt, is - * pressed. We simply communicate this to the client. */ - KeyboardGroup *group = wl_container_of(listener, group, modifiers); - - wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard); - /* Send modifiers to the client. */ - wlr_seat_keyboard_notify_modifiers(seat, - &group->wlr_group->keyboard.modifiers); -} - -int -keyrepeat(void *data) -{ - KeyboardGroup *group = data; - int i; - if (!group->nsyms || group->wlr_group->keyboard.repeat_info.rate <= 0) - return 0; - - wl_event_source_timer_update(group->key_repeat_source, - 1000 / group->wlr_group->keyboard.repeat_info.rate); - - for (i = 0; i < group->nsyms; i++) - keybinding(group->mods, group->keysyms[i]); - - return 0; -} - -void -killclient(const Arg *arg) -{ - Client *sel = focustop(selmon); - if (sel) - client_send_close(sel); -} - -void -locksession(struct wl_listener *listener, void *data) -{ - struct wlr_session_lock_v1 *session_lock = data; - SessionLock *lock; - wlr_scene_node_set_enabled(&locked_bg->node, 1); - if (cur_lock) { - wlr_session_lock_v1_destroy(session_lock); - return; - } - 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; - - LISTEN(&session_lock->events.new_surface, &lock->new_surface, createlocksurface); - LISTEN(&session_lock->events.destroy, &lock->destroy, destroysessionlock); - LISTEN(&session_lock->events.unlock, &lock->unlock, unlocksession); - - wlr_session_lock_v1_send_locked(session_lock); -} - -void -mapnotify(struct wl_listener *listener, void *data) -{ - /* Called when the surface is mapped, or ready to display on-screen. */ - Client *p = NULL; - Client *w, *c = wl_container_of(listener, c, map); - Monitor *m; - int i; - - /* Create scene tree for this client and its border */ - 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)); - c->scene->node.data = c->scene_surface->node.data = c; - - client_get_geometry(c, &c->geom); - - /* Handle unmanaged clients first so we can return prior create borders */ - if (client_is_unmanaged(c)) { - /* Unmanaged clients always are floating */ - wlr_scene_node_reparent(&c->scene->node, layers[LyrFloat]); - wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); - if (client_wants_focus(c)) { - focusclient(c, 1); - exclusive_focus = c; - } - goto unset_fullscreen; - } - - for (i = 0; i < 4; i++) { - c->border[i] = wlr_scene_rect_create(c->scene, 0, 0, - c->isurgent ? urgentcolor : bordercolor); - c->border[i]->node.data = c; - } - - /* Initialize client geometry with room for border */ - client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); - c->geom.width += 2 * c->bw; - c->geom.height += 2 * c->bw; - - /* Insert this client into client lists. */ - wl_list_insert(&clients, &c->link); - wl_list_insert(&fstack, &c->flink); - - /* Set initial monitor, tags, floating status, and focus: - * we always consider floating, clients that have parent and thus - * we set the same tags and monitor than its parent, if not - * try to apply rules for them */ - if ((p = client_get_parent(c))) { - c->isfloating = 1; - setmon(c, p->mon, p->tags); - } else { - applyrules(c); - } - printstatus(); - -unset_fullscreen: - m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y); - wl_list_for_each(w, &clients, link) { - if (w != c && w != p && w->isfullscreen && m == w->mon && (w->tags & c->tags)) - setfullscreen(w, 0); - } -} - -void -maximizenotify(struct wl_listener *listener, void *data) -{ - /* This event is raised when a client would like to maximize itself, - * 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); - if (c->surface.xdg->initialized - && wl_resource_get_version(c->surface.xdg->toplevel->resource) - < XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION) - wlr_xdg_surface_schedule_configure(c->surface.xdg); -} - -void -monocle(Monitor *m) -{ - Client *c; - int n = 0; - - wl_list_for_each(c, &clients, link) { - if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) - continue; - resize(c, m->w, 0); - n++; - } - if (n) - snprintf(m->ltsymbol, LENGTH(m->ltsymbol), "[%d]", n); - if ((c = focustop(m))) - wlr_scene_node_raise_to_top(&c->scene->node); -} - -void -motionabsolute(struct wl_listener *listener, void *data) -{ - /* This event is forwarded by the cursor when a pointer emits an _absolute_ - * motion event, from 0..1 on each axis. This happens, for example, when - * wlroots is running under a Wayland window rather than KMS+DRM, and you - * move the mouse over the window. You could enter the window from any edge, - * so we have to warp the mouse there. There is also some hardware which - * emits these events. */ - struct wlr_pointer_motion_absolute_event *event = data; - double lx, ly, dx, dy; - - if (!event->time_msec) /* this is 0 with virtual pointers */ - wlr_cursor_warp_absolute(cursor, &event->pointer->base, event->x, event->y); - - wlr_cursor_absolute_to_layout_coords(cursor, &event->pointer->base, event->x, event->y, &lx, &ly); - dx = lx - cursor->x; - dy = ly - cursor->y; - motionnotify(event->time_msec, &event->pointer->base, dx, dy, dx, dy); -} - -void -motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy, - double dx_unaccel, double dy_unaccel) -{ - double sx = 0, sy = 0, sx_confined, sy_confined; - Client *c = NULL, *w = NULL; - LayerSurface *l = NULL; - struct wlr_surface *surface = NULL; - struct wlr_pointer_constraint_v1 *constraint; - - /* Find the client under the pointer and send the event along. */ - xytonode(cursor->x, cursor->y, &surface, &c, NULL, &sx, &sy); - - if (cursor_mode == CurPressed && !seat->drag - && surface != seat->pointer_state.focused_surface - && toplevel_from_wlr_surface(seat->pointer_state.focused_surface, &w, &l) >= 0) { - c = w; - surface = seat->pointer_state.focused_surface; - sx = cursor->x - (l ? l->geom.x : w->geom.x); - sy = cursor->y - (l ? l->geom.y : w->geom.y); - } - - /* time is 0 in internal calls meant to restore pointer focus. */ - if (time) { - wlr_relative_pointer_manager_v1_send_relative_motion( - relative_pointer_mgr, seat, (uint64_t)time * 1000, - dx, dy, dx_unaccel, dy_unaccel); - - wl_list_for_each(constraint, &pointer_constraints->constraints, link) - cursorconstrain(constraint); - - if (active_constraint && cursor_mode != CurResize && cursor_mode != CurMove) { - toplevel_from_wlr_surface(active_constraint->surface, &c, NULL); - if (c && active_constraint->surface == seat->pointer_state.focused_surface) { - sx = cursor->x - c->geom.x - c->bw; - sy = cursor->y - c->geom.y - c->bw; - if (wlr_region_confine(&active_constraint->region, sx, sy, - sx + dx, sy + dy, &sx_confined, &sy_confined)) { - dx = sx_confined - sx; - dy = sy_confined - sy; - } - - if (active_constraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED) - return; - } - } - - wlr_cursor_move(cursor, device, dx, dy); - wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); - - /* Update selmon (even while dragging a window) */ - if (sloppyfocus) - selmon = xytomon(cursor->x, cursor->y); - } - - /* Update drag icon's position */ - wlr_scene_node_set_position(&drag_icon->node, (int)round(cursor->x), (int)round(cursor->y)); - - /* If we are currently grabbing the mouse, handle and return */ - if (cursor_mode == CurMove) { - /* Move the grabbed client to the new position. */ - resize(grabc, (struct wlr_box){.x = (int)round(cursor->x) - grabcx, .y = (int)round(cursor->y) - grabcy, - .width = grabc->geom.width, .height = grabc->geom.height}, 1); - return; - } else if (cursor_mode == CurResize) { - resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y, - .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1); - return; - } - - /* 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) - wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); - - pointerfocus(c, surface, sx, sy, time); -} - -void -motionrelative(struct wl_listener *listener, void *data) -{ - /* This event is forwarded by the cursor when a pointer emits a _relative_ - * pointer motion event (i.e. a delta) */ - struct wlr_pointer_motion_event *event = data; - /* The cursor doesn't move unless we tell it to. The cursor automatically - * handles constraining the motion to the output layout, as well as any - * special configuration applied for the specific input device which - * generated the event. You can pass NULL for the device if you want to move - * the cursor around without any input. */ - motionnotify(event->time_msec, &event->pointer->base, event->delta_x, event->delta_y, - event->unaccel_dx, event->unaccel_dy); -} - -void -moveresize(const Arg *arg) -{ - if (cursor_mode != CurNormal && cursor_mode != CurPressed) - return; - xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL); - if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen) - return; - - /* Float the window and tell motionnotify to grab it */ - setfloating(grabc, 1); - switch (cursor_mode = arg->ui) { - case CurMove: - grabcx = (int)round(cursor->x) - grabc->geom.x; - grabcy = (int)round(cursor->y) - grabc->geom.y; - wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur"); - break; - case CurResize: - /* Doesn't work for X11 output - the next absolute motion event - * returns the cursor to where it started */ - wlr_cursor_warp_closest(cursor, NULL, - grabc->geom.x + grabc->geom.width, - grabc->geom.y + grabc->geom.height); - wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); - break; - } -} - -void -outputmgrapply(struct wl_listener *listener, void *data) -{ - struct wlr_output_configuration_v1 *config = data; - outputmgrapplyortest(config, 0); -} - -void -outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test) -{ - /* - * 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, - * so any Monitor information should be updated by updatemons() after an - * output_layout.change event, not here. - */ - struct wlr_output_configuration_head_v1 *config_head; - int ok = 1; - - wl_list_for_each(config_head, &config->heads, link) { - struct wlr_output *wlr_output = config_head->state.output; - Monitor *m = wlr_output->data; - struct wlr_output_state state; - - /* Ensure displays previously disabled by wlr-output-power-management-v1 - * are properly handled*/ - m->asleep = 0; - - wlr_output_state_init(&state); - wlr_output_state_set_enabled(&state, config_head->state.enabled); - if (!config_head->state.enabled) - goto apply_or_test; - - if (config_head->state.mode) - wlr_output_state_set_mode(&state, config_head->state.mode); - else - wlr_output_state_set_custom_mode(&state, - config_head->state.custom_mode.width, - config_head->state.custom_mode.height, - config_head->state.custom_mode.refresh); - - wlr_output_state_set_transform(&state, config_head->state.transform); - wlr_output_state_set_scale(&state, config_head->state.scale); - wlr_output_state_set_adaptive_sync_enabled(&state, - config_head->state.adaptive_sync_enabled); - -apply_or_test: - ok &= test ? wlr_output_test_state(wlr_output, &state) - : wlr_output_commit_state(wlr_output, &state); - - /* Don't move monitors if position wouldn't change, this to avoid - * wlroots marking the output as manually configured. - * wlr_output_layout_add does not like disabled outputs */ - if (!test && wlr_output->enabled && (m->m.x != config_head->state.x || m->m.y != config_head->state.y)) - wlr_output_layout_add(output_layout, wlr_output, - config_head->state.x, config_head->state.y); - - wlr_output_state_finish(&state); - } - - if (ok) - wlr_output_configuration_v1_send_succeeded(config); - else - wlr_output_configuration_v1_send_failed(config); - wlr_output_configuration_v1_destroy(config); - - /* https://codeberg.org/dwl/dwl/issues/577 */ - updatemons(NULL, NULL); -} - -void -outputmgrtest(struct wl_listener *listener, void *data) -{ - struct wlr_output_configuration_v1 *config = data; - outputmgrapplyortest(config, 1); -} - -void -pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, - uint32_t time) -{ - struct timespec now; - - if (surface != seat->pointer_state.focused_surface && - sloppyfocus && time && c && !client_is_unmanaged(c)) - focusclient(c, 0); - - /* If surface is NULL, clear pointer focus */ - if (!surface) { - wlr_seat_pointer_notify_clear_focus(seat); - return; - } - - if (!time) { - clock_gettime(CLOCK_MONOTONIC, &now); - time = now.tv_sec * 1000 + now.tv_nsec / 1000000; - } - - /* Let the client know that the mouse cursor has entered one - * of its surfaces, and make keyboard focus follow if desired. - * 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 -printstatus(void) -{ - Monitor *m = NULL; - Client *c; - uint32_t occ, urg, sel; - const char *appid, *title; - - wl_list_for_each(m, &mons, link) { - occ = urg = 0; - wl_list_for_each(c, &clients, link) { - if (c->mon != m) - continue; - occ |= c->tags; - if (c->isurgent) - urg |= c->tags; - } - if ((c = focustop(m))) { - 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 %d\n", m->wlr_output->name, c->isfullscreen); - printf("%s floating %d\n", m->wlr_output->name, c->isfloating); - sel = c->tags; - } else { - 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 floating \n", m->wlr_output->name); - sel = 0; - } - - printf("%s selmon %u\n", m->wlr_output->name, m == selmon); - printf("%s tags %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32"\n", - m->wlr_output->name, occ, m->tagset[m->seltags], sel, urg); - printf("%s layout %s\n", m->wlr_output->name, m->ltsymbol); - } - fflush(stdout); -} - -void -powermgrsetmode(struct wl_listener *listener, void *data) -{ - struct wlr_output_power_v1_set_mode_event *event = data; - struct wlr_output_state state = {0}; - Monitor *m = event->output->data; - - if (!m) - return; - - m->gamma_lut_changed = 1; /* Reapply gamma LUT when re-enabling the ouput */ - wlr_output_state_set_enabled(&state, event->mode); - wlr_output_commit_state(m->wlr_output, &state); - - m->asleep = !event->mode; -} - -void -quit(const Arg *arg) -{ - wl_display_terminate(dpy); -} - -void -rendermon(struct wl_listener *listener, void *data) -{ - /* This function is called every time an output is ready to display a frame, - * 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 - * this monitor. */ - 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; - } - - /* - * 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 -requestdecorationmode(struct wl_listener *listener, void *data) -{ - Client *c = wl_container_of(listener, c, set_decoration_mode); - if (c->surface.xdg->initialized) - wlr_xdg_toplevel_decoration_v1_set_mode(c->decoration, - WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); -} - -void -requeststartdrag(struct wl_listener *listener, void *data) -{ - struct wlr_seat_request_start_drag_event *event = data; - - if (wlr_seat_validate_pointer_grab_serial(seat, event->origin, - event->serial)) - wlr_seat_start_pointer_drag(seat, event->drag, event->serial); - else - 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; - struct wlr_box clip; - - if (!c->mon || !client_surface(c)->mapped) - return; - - bbox = interact ? &sgeom : &c->mon->w; - - client_set_bounds(c, geo.width, geo.height); - c->geom = geo; - applybounds(c, bbox); - - /* Update scene-graph, including borders */ - wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); - wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); - wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw); - wlr_scene_rect_set_size(c->border[1], c->geom.width, c->bw); - wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - 2 * c->bw); - wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - 2 * c->bw); - wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - 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); - - /* 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 -run(char *startup_cmd) -{ - /* Add a Unix socket to the Wayland display. */ - const char *socket = wl_display_add_socket_auto(dpy); - if (!socket) - die("startup: display_add_socket_auto"); - setenv("WAYLAND_DISPLAY", socket, 1); - - /* Start the backend. This will enumerate outputs and inputs, become the DRM - * master, etc */ - if (!wlr_backend_start(backend)) - die("startup: backend_start"); - - /* Now that the socket exists and the backend is started, run the startup command */ - if (startup_cmd) { - int piperw[2]; - if (pipe(piperw) < 0) - die("startup: pipe:"); - if ((child_pid = fork()) < 0) - die("startup: fork:"); - if (child_pid == 0) { - setsid(); - dup2(piperw[0], STDIN_FILENO); - close(piperw[0]); - close(piperw[1]); - execl("/bin/sh", "/bin/sh", "-c", startup_cmd, NULL); - die("startup: execl:"); - } - dup2(piperw[1], STDOUT_FILENO); - close(piperw[1]); - close(piperw[0]); - } - - /* Mark stdout as non-blocking to avoid people who does not close stdin - * nor consumes it in their startup script getting dwl frozen */ - if (fd_set_nonblock(STDOUT_FILENO) < 0) - close(STDOUT_FILENO); - - printstatus(); - - /* At this point the outputs are initialized, choose initial selmon based on - * cursor position, and set default cursor image */ - selmon = xytomon(cursor->x, cursor->y); - - /* 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 - * 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_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 - * loop configuration to listen to libinput events, DRM events, generate - * frame events at the refresh rate, and so on. */ - wl_display_run(dpy); -} - -void -setcursor(struct wl_listener *listener, void *data) -{ - /* This event is raised by the seat when a client provides a cursor image */ - struct wlr_seat_pointer_request_set_cursor_event *event = data; - /* If we're "grabbing" the cursor, don't use the client's image, we will - * restore it after "grabbing" sending a leave event, followed by a enter - * event, which will result in the client requesting set the cursor surface */ - 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 surface as the cursor image. It will set the - * hardware cursor on the output that it's currently on and continue to - * do so as the cursor moves between outputs. */ - if (event->seat_client == seat->pointer_state.focused_client) - wlr_cursor_set_surface(cursor, event->surface, - 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) -{ - Client *p = client_get_parent(c); - c->isfloating = floating; - /* If in floating layout do not change the client's layer */ - if (!c->mon || !client_surface(c)->mapped || !c->mon->lt[c->mon->sellt]->arrange) - return; - wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen || - (p && p->isfullscreen) ? LyrFS - : c->isfloating ? LyrFloat : LyrTile]); - arrange(c->mon); - printstatus(); -} - -void -setfullscreen(Client *c, int fullscreen) -{ - c->isfullscreen = fullscreen; - if (!c->mon || !client_surface(c)->mapped) - return; - c->bw = fullscreen ? 0 : borderpx; - client_set_fullscreen(c, fullscreen); - wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen - ? LyrFS : c->isfloating ? LyrFloat : LyrTile]); - - if (fullscreen) { - c->prev = c->geom; - resize(c, c->mon->m, 0); - } else { - /* restore previous size instead of arrange for floating windows since - * client positions are set by the user and cannot be recalculated */ - resize(c, c->prev, 0); - } - arrange(c->mon); - 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; - if (!m) - return; - m->gamma_lut_changed = 1; - wlr_output_schedule_frame(m->wlr_output); -} - -void -setlayout(const Arg *arg) -{ - if (!selmon) - return; - if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) - selmon->sellt ^= 1; - if (arg && arg->v) - selmon->lt[selmon->sellt] = (Layout *)arg->v; - strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol)); - arrange(selmon); - printstatus(); -} - -/* arg > 1.0 will set mfact absolutely */ -void -setmfact(const Arg *arg) -{ - float f; - - if (!arg || !selmon || !selmon->lt[selmon->sellt]->arrange) - return; - f = arg->f < 1.0f ? arg->f + selmon->mfact : arg->f - 1.0f; - if (f < 0.1 || f > 0.9) - return; - selmon->mfact = f; - arrange(selmon); -} - -void -setmon(Client *c, Monitor *m, uint32_t newtags) -{ - Monitor *oldmon = c->mon; - - if (oldmon == m) - return; - c->mon = m; - c->prev = c->geom; - - /* Scene graph sends surface leave/enter events on move and resize */ - if (oldmon) - arrange(oldmon); - if (m) { - /* Make sure window actually overlaps with the monitor */ - resize(c, c->geom, 0); - c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */ - setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */ - setfloating(c, c->isfloating); - } - focusclient(focustop(selmon), 1); -} - -void -setpsel(struct wl_listener *listener, void *data) -{ - /* This event is raised by the seat when a client wants to set the selection, - * usually when the user copies something. wlroots allows compositors to - * ignore such requests if they so choose, but in dwl we always honor - */ - struct wlr_seat_request_set_primary_selection_event *event = data; - wlr_seat_set_primary_selection(seat, event->source, event->serial); -} - -void -setsel(struct wl_listener *listener, void *data) -{ - /* This event is raised by the seat when a client wants to set the selection, - * usually when the user copies something. wlroots allows compositors to - * ignore such requests if they so choose, but in dwl we always honor - */ - struct wlr_seat_request_set_selection_event *event = data; - wlr_seat_set_selection(seat, event->source, event->serial); -} - -void -setup(void) -{ - int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE}; - struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = handlesig}; - sigemptyset(&sa.sa_mask); - - for (i = 0; i < (int)LENGTH(sig); i++) - sigaction(sig[i], &sa, NULL); - - wlr_log_init(log_level, NULL); - - /* The Wayland display is managed by libwayland. It handles accepting - * clients from the Unix socket, manging Wayland globals, and so on. */ - dpy = wl_display_create(); - event_loop = wl_display_get_event_loop(dpy); - - /* 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. */ - if (!(backend = wlr_backend_autocreate(event_loop, &session))) - die("couldn't create backend"); - - /* Initialize the scene graph used to lay out windows */ - scene = wlr_scene_create(); - root_bg = wlr_scene_rect_create(&scene->tree, 0, 0, rootcolor); - for (i = 0; i < NUM_LAYERS; i++) - layers[i] = wlr_scene_tree_create(&scene->tree); - drag_icon = wlr_scene_tree_create(&scene->tree); - wlr_scene_node_place_below(&drag_icon->node, &layers[LyrBlock]->node); - - /* 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"); - LISTEN_STATIC(&drw->events.lost, gpureset); - - /* 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_texture_formats(drw, WLR_BUFFER_CAP_DMABUF)) { - wlr_drm_create(dpy, drw); - wlr_scene_set_linux_dmabuf_v1(scene, - wlr_linux_dmabuf_v1_create_with_renderer(dpy, 5, 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"); - - /* This creates some hands-off wlroots interfaces. The compositor is - * necessary for clients to allocate surfaces and the data device manager - * handles the clipboard. Each of these wlroots interfaces has room for you - * 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, 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_primary_selection_v1_device_manager_create(dpy); - wlr_viewporter_create(dpy); - wlr_single_pixel_buffer_manager_v1_create(dpy); - wlr_fractional_scale_manager_v1_create(dpy, 1); - wlr_presentation_create(dpy, backend); - wlr_alpha_modifier_v1_create(dpy); - - /* Initializes the interface used to implement urgency hints */ - activation = wlr_xdg_activation_v1_create(dpy); - 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); - - power_mgr = wlr_output_power_manager_v1_create(dpy); - LISTEN_STATIC(&power_mgr->events.set_mode, powermgrsetmode); - - /* 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(dpy); - 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); - LISTEN_STATIC(&backend->events.new_output, createmon); - - /* 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: - * - * https://drewdevault.com/2018/07/29/Wayland-shells.html - */ - wl_list_init(&clients); - wl_list_init(&fstack); - - xdg_shell = wlr_xdg_shell_create(dpy, 6); - LISTEN_STATIC(&xdg_shell->events.new_toplevel, createnotify); - LISTEN_STATIC(&xdg_shell->events.new_popup, createpopup); - - 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); - LISTEN_STATIC(&idle_inhibit_mgr->events.new_inhibitor, createidleinhibitor); - - session_lock_mgr = wlr_session_lock_manager_v1_create(dpy); - 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.1f, 0.1f, 0.1f, 1.0f}); - wlr_scene_node_set_enabled(&locked_bg->node, 0); - - /* Use decoration protocols to negotiate server-side decorations */ - wlr_server_decoration_manager_set_default_mode( - wlr_server_decoration_manager_create(dpy), - WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); - xdg_decoration_mgr = wlr_xdg_decoration_manager_v1_create(dpy); - LISTEN_STATIC(&xdg_decoration_mgr->events.new_toplevel_decoration, createdecoration); - - pointer_constraints = wlr_pointer_constraints_v1_create(dpy); - LISTEN_STATIC(&pointer_constraints->events.new_constraint, createpointerconstraint); - - relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(dpy); - - /* - * Creates a cursor, which is a wlroots utility for tracking the cursor - * image shown on screen. - */ - cursor = wlr_cursor_create(); - wlr_cursor_attach_output_layout(cursor, output_layout); - - /* Creates an xcursor manager, another wlroots utility which loads up - * Xcursor themes to source cursor images from and makes sure that cursor - * images are available at all scale factors on the screen (necessary for - * HiDPI support). Scaled cursors will be loaded with each output. */ - 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 - * 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 - * https://drewdevault.com/2018/07/17/Input-handling-in-wlroots.html - * - * And more comments are sprinkled throughout the notify functions above. - */ - 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 - * operates the computer. This conceptually includes up to one keyboard, - * pointer, touch, and drawing tablet device. We also rig up a listener to - * let us know when new input devices are available on the backend. - */ - LISTEN_STATIC(&backend->events.new_input, inputdevice); - virtual_keyboard_mgr = wlr_virtual_keyboard_manager_v1_create(dpy); - LISTEN_STATIC(&virtual_keyboard_mgr->events.new_virtual_keyboard, virtualkeyboard); - virtual_pointer_mgr = wlr_virtual_pointer_manager_v1_create(dpy); - LISTEN_STATIC(&virtual_pointer_mgr->events.new_virtual_pointer, virtualpointer); - - seat = wlr_seat_create(dpy, "seat0"); - 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); - - kb_group = createkeyboardgroup(); - wl_list_init(&kb_group->destroy.link); - - output_mgr = wlr_output_manager_v1_create(dpy); - LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply); - LISTEN_STATIC(&output_mgr->events.test, outputmgrtest); - - /* Make sure XWayland clients don't connect to the parent X server, - * e.g when running in the x11 backend or the wayland backend and the - * compositor has Xwayland support */ - unsetenv("DISPLAY"); -#ifdef XWAYLAND - /* - * Initialise the XWayland X server. - * It will be started when the first X client is started. - */ - if ((xwayland = wlr_xwayland_create(dpy, compositor, 1))) { - LISTEN_STATIC(&xwayland->events.ready, xwaylandready); - LISTEN_STATIC(&xwayland->events.new_surface, createnotifyx11); - - setenv("DISPLAY", xwayland->display_name, 1); - } else { - fprintf(stderr, "failed to setup XWayland X server, continuing without it\n"); - } -#endif -} - -void -spawn(const Arg *arg) -{ - if (fork() == 0) { - dup2(STDERR_FILENO, STDOUT_FILENO); - setsid(); - execvp(((char **)arg->v)[0], (char **)arg->v); - die("dwl: execvp %s failed:", ((char **)arg->v)[0]); - } -} - -void -startdrag(struct wl_listener *listener, void *data) -{ - struct wlr_drag *drag = data; - if (!drag->icon) - return; - - drag->icon->data = &wlr_scene_drag_icon_create(drag_icon, drag->icon)->node; - LISTEN_STATIC(&drag->icon->events.destroy, destroydragicon); -} - -void -tag(const Arg *arg) -{ - Client *sel = focustop(selmon); - if (!sel || (arg->ui & TAGMASK) == 0) - return; - - sel->tags = arg->ui & TAGMASK; - focusclient(focustop(selmon), 1); - arrange(selmon); - printstatus(); -} - -void -tagmon(const Arg *arg) -{ - Client *sel = focustop(selmon); - if (sel) - setmon(sel, dirtomon(arg->i), 0); -} - -void -tile(Monitor *m) -{ - unsigned int mw, my, ty; - int i, n = 0; - Client *c; - - wl_list_for_each(c, &clients, link) - if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) - n++; - if (n == 0) - return; - - if (n > m->nmaster) - mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0; - else - mw = m->w.width; - i = my = ty = 0; - wl_list_for_each(c, &clients, link) { - if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) - continue; - if (i < m->nmaster) { - resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw, - .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0); - my += c->geom.height; - } else { - resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty, - .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0); - ty += c->geom.height; - } - i++; - } -} - -void -togglefloating(const Arg *arg) -{ - Client *sel = focustop(selmon); - /* return if fullscreen */ - if (sel && !sel->isfullscreen) - setfloating(sel, !sel->isfloating); -} - -void -togglefullscreen(const Arg *arg) -{ - Client *sel = focustop(selmon); - if (sel) - setfullscreen(sel, !sel->isfullscreen); -} - -void -toggletag(const Arg *arg) -{ - uint32_t newtags; - Client *sel = focustop(selmon); - if (!sel || !(newtags = sel->tags ^ (arg->ui & TAGMASK))) - return; - - sel->tags = newtags; - focusclient(focustop(selmon), 1); - arrange(selmon); - printstatus(); -} - -void -toggleview(const Arg *arg) -{ - uint32_t newtagset; - if (!(newtagset = selmon ? selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK) : 0)) - return; - - selmon->tagset[selmon->seltags] = newtagset; - focusclient(focustop(selmon), 1); - arrange(selmon); - printstatus(); -} - -void -unlocksession(struct wl_listener *listener, void *data) -{ - SessionLock *lock = wl_container_of(listener, lock, unlock); - destroylock(lock, 1); -} - -void -unmaplayersurfacenotify(struct wl_listener *listener, void *data) -{ - LayerSurface *l = wl_container_of(listener, l, unmap); - - l->mapped = 0; - wlr_scene_node_set_enabled(&l->scene->node, 0); - if (l == exclusive_focus) - exclusive_focus = NULL; - if (l->layer_surface->output && (l->mon = l->layer_surface->output->data)) - arrangelayers(l->mon); - if (l->layer_surface->surface == seat->keyboard_state.focused_surface) - focusclient(focustop(selmon), 1); - motionnotify(0, NULL, 0, 0, 0, 0); -} - -void -unmapnotify(struct wl_listener *listener, void *data) -{ - /* Called when the surface is unmapped, and should no longer be shown. */ - Client *c = wl_container_of(listener, c, unmap); - if (c == grabc) { - cursor_mode = CurNormal; - grabc = NULL; - } - - if (client_is_unmanaged(c)) { - if (c == exclusive_focus) { - exclusive_focus = NULL; - focusclient(focustop(selmon), 1); - } - } else { - wl_list_remove(&c->link); - setmon(c, NULL, 0); - wl_list_remove(&c->flink); - } - - wlr_scene_node_destroy(&c->scene->node); - printstatus(); - motionnotify(0, NULL, 0, 0, 0, 0); -} - -void -updatemons(struct wl_listener *listener, void *data) -{ - /* - * Called whenever the output layout changes: adding or removing a - * monitor, changing an output's mode or position, etc. This is where - * the change officially happens and we update geometry, window - * positions, focus, and the stored configuration in wlroots' - * output-manager implementation. - */ - struct wlr_output_configuration_v1 *config - = wlr_output_configuration_v1_create(); - Client *c; - struct wlr_output_configuration_head_v1 *config_head; - Monitor *m; - - /* First remove from the layout the disabled monitors */ - wl_list_for_each(m, &mons, link) { - if (m->wlr_output->enabled || m->asleep) - continue; - config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output); - config_head->state.enabled = 0; - /* Remove this output from the layout to avoid cursor enter inside it */ - wlr_output_layout_remove(output_layout, m->wlr_output); - closemon(m); - m->m = m->w = (struct wlr_box){0}; - } - /* Insert outputs that need to */ - wl_list_for_each(m, &mons, link) { - 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); - - wlr_scene_node_set_position(&root_bg->node, sgeom.x, sgeom.y); - wlr_scene_rect_set_size(root_bg, sgeom.width, sgeom.height); - - /* 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); - - wl_list_for_each(m, &mons, link) { - if (!m->wlr_output->enabled) - continue; - 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); - 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); - wlr_scene_rect_set_size(m->fullscreen_bg, m->m.width, m->m.height); - - if (m->lock_surface) { - struct wlr_scene_tree *scene_tree = m->lock_surface->surface->data; - wlr_scene_node_set_position(&scene_tree->node, m->m.x, m->m.y); - wlr_session_lock_surface_v1_configure(m->lock_surface, m->m.width, 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); - /* make sure fullscreen clients have the right size */ - if ((c = focustop(m)) && c->isfullscreen) - resize(c, m->m, 0); - - /* Try to re-set the gamma LUT when updating monitors, - * it's only really needed when enabling a disabled output, but meh. */ - m->gamma_lut_changed = 1; - - config_head->state.x = m->m.x; - config_head->state.y = m->m.y; - - if (!selmon) { - selmon = m; - } - } - - if (selmon && selmon->wlr_output->enabled) { - wl_list_for_each(c, &clients, link) { - if (!c->mon && client_surface(c)->mapped) - setmon(c, selmon, c->tags); - } - focusclient(focustop(selmon), 1); - if (selmon->lock_surface) { - client_notify_enter(selmon->lock_surface->surface, - wlr_seat_get_keyboard(seat)); - client_activate_surface(selmon->lock_surface->surface, 1); - } - } - - /* 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); -} - -void -updatetitle(struct wl_listener *listener, void *data) -{ - Client *c = wl_container_of(listener, c, set_title); - if (c == focustop(c->mon)) - printstatus(); -} - -void -urgent(struct wl_listener *listener, void *data) -{ - struct wlr_xdg_activation_v1_request_activate_event *event = data; - Client *c = NULL; - toplevel_from_wlr_surface(event->surface, &c, NULL); - if (!c || c == focustop(selmon)) - return; - - c->isurgent = 1; - printstatus(); - - if (client_surface(c)->mapped) - client_set_border_color(c, urgentcolor); -} - -void -view(const Arg *arg) -{ - if (!selmon || (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) - return; - selmon->seltags ^= 1; /* toggle sel tagset */ - if (arg->ui & TAGMASK) - selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; - focusclient(focustop(selmon), 1); - arrange(selmon); - printstatus(); -} - -void -virtualkeyboard(struct wl_listener *listener, void *data) -{ - struct wlr_virtual_keyboard_v1 *kb = data; - /* virtual keyboards shouldn't share keyboard group */ - KeyboardGroup *group = createkeyboardgroup(); - /* Set the keymap to match the group keymap */ - wlr_keyboard_set_keymap(&kb->keyboard, group->wlr_group->keyboard.keymap); - LISTEN(&kb->keyboard.base.events.destroy, &group->destroy, destroykeyboardgroup); - - /* Add the new keyboard to the group */ - wlr_keyboard_group_add_keyboard(group->wlr_group, &kb->keyboard); -} - -void -virtualpointer(struct wl_listener *listener, void *data) -{ - struct wlr_virtual_pointer_v1_new_pointer_event *event = data; - struct wlr_input_device *device = &event->new_pointer->pointer.base; - - wlr_cursor_attach_input_device(cursor, device); - if (event->suggested_output) - wlr_cursor_map_input_to_output(cursor, device, event->suggested_output); -} - -Monitor * -xytomon(double x, double y) -{ - struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y); - return o ? o->data : NULL; -} - -void -xytonode(double x, double y, struct wlr_surface **psurface, - Client **pc, LayerSurface **pl, double *nx, double *ny) -{ - struct wlr_scene_node *node, *pnode; - struct wlr_surface *surface = NULL; - Client *c = NULL; - LayerSurface *l = NULL; - int layer; - - for (layer = NUM_LAYERS - 1; !surface && layer >= 0; layer--) { - if (!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny))) - continue; - - if (node->type == WLR_SCENE_NODE_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) - c = pnode->data; - if (c && c->type == LayerShell) { - c = NULL; - l = pnode->data; - } - } - - if (psurface) *psurface = surface; - if (pc) *pc = c; - if (pl) *pl = l; -} - -void -zoom(const Arg *arg) -{ - Client *c, *sel = focustop(selmon); - - if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange || sel->isfloating) - return; - - /* Search for the first tiled window that is not sel, marking sel as - * NULL if we pass it along the way */ - wl_list_for_each(c, &clients, link) { - if (VISIBLEON(c, selmon) && !c->isfloating) { - if (c != sel) - break; - sel = NULL; - } - } - - /* Return if no other tiled window was found */ - if (&c->link == &clients) - return; - - /* If we passed sel, move c to the front; otherwise, move sel to the - * front */ - if (!sel) - sel = c; - wl_list_remove(&sel->link); - wl_list_insert(&clients, &sel->link); - - focusclient(sel, 1); - arrange(selmon); -} - -#ifdef XWAYLAND -void -activatex11(struct wl_listener *listener, void *data) -{ - Client *c = wl_container_of(listener, c, activate); - - /* Only "managed" windows can be activated */ - if (!client_is_unmanaged(c)) - 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) -{ - Client *c = wl_container_of(listener, c, configure); - struct wlr_xwayland_surface_configure_event *event = data; - /* TODO: figure out if there is another way to do this */ - if (!c->mon) { - wlr_xwayland_surface_configure(c->surface.xwayland, - event->x, event->y, event->width, event->height); - return; - } - if (c->isfloating || client_is_unmanaged(c)) - resize(c, (struct wlr_box){.x = event->x, .y = event->y, - .width = event->width + c->bw * 2, .height = event->height + c->bw * 2}, 0); - else - arrange(c->mon); -} - -void -createnotifyx11(struct wl_listener *listener, void *data) -{ - struct wlr_xwayland_surface *xsurface = data; - Client *c; - - /* Allocate a Client for this surface */ - c = xsurface->data = ecalloc(1, sizeof(*c)); - c->surface.xwayland = xsurface; - c->type = X11; - c->bw = client_is_unmanaged(c) ? 0 : borderpx; - - /* Listen to the various events it can emit */ - LISTEN(&xsurface->events.associate, &c->associate, associatex11); - LISTEN(&xsurface->events.destroy, &c->destroy, destroynotify); - 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.request_fullscreen, &c->fullscreen, fullscreennotify); - LISTEN(&xsurface->events.set_hints, &c->set_hints, sethints); - LISTEN(&xsurface->events.set_title, &c->set_title, updatetitle); -} - -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) -{ - xcb_atom_t atom = 0; - xcb_intern_atom_reply_t *reply; - xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xc, 0, strlen(name), name); - if ((reply = xcb_intern_atom_reply(xc, cookie, NULL))) - atom = reply->atom; - free(reply); - - return atom; -} - -void -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); - printstatus(); - - if (c->isurgent && surface && surface->mapped) - client_set_border_color(c, urgentcolor); -} - -void -xwaylandready(struct wl_listener *listener, void *data) -{ - struct wlr_xcursor *xcursor; - xcb_connection_t *xc = xcb_connect(xwayland->display_name, NULL); - int err = xcb_connection_has_error(xc); - if (err) { - fprintf(stderr, "xcb_connect to X server failed with code %d\n. Continuing with degraded functionality.\n", err); - return; - } - - /* Collect atoms we are interested in. If getatom returns 0, we will - * not detect that window type. */ - netatom[NetWMWindowTypeDialog] = getatom(xc, "_NET_WM_WINDOW_TYPE_DIALOG"); - netatom[NetWMWindowTypeSplash] = getatom(xc, "_NET_WM_WINDOW_TYPE_SPLASH"); - netatom[NetWMWindowTypeToolbar] = getatom(xc, "_NET_WM_WINDOW_TYPE_TOOLBAR"); - netatom[NetWMWindowTypeUtility] = getatom(xc, "_NET_WM_WINDOW_TYPE_UTILITY"); - - /* assign the one and only seat */ - 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, "default", 1))) - wlr_xwayland_set_cursor(xwayland, - xcursor->images[0]->buffer, xcursor->images[0]->width * 4, - xcursor->images[0]->width, xcursor->images[0]->height, - xcursor->images[0]->hotspot_x, xcursor->images[0]->hotspot_y); - - xcb_disconnect(xc); -} -#endif - -int -main(int argc, char *argv[]) -{ - char *startup_cmd = NULL; - int c; - - while ((c = getopt(argc, argv, "s:hdv")) != -1) { - if (c == 's') - startup_cmd = optarg; - else if (c == 'd') - log_level = WLR_DEBUG; - else if (c == 'v') - die("dwl " VERSION); - else - goto usage; - } - if (optind < argc) - goto usage; - - /* Wayland requires XDG_RUNTIME_DIR for creating its communications socket */ - if (!getenv("XDG_RUNTIME_DIR")) - die("XDG_RUNTIME_DIR must be set"); - setup(); - run(startup_cmd); - cleanup(); - return EXIT_SUCCESS; - -usage: - die("Usage: %s [-v] [-d] [-s startup command]", argv[0]); -} diff --git a/dwl/dwl-v0.7/dwl.desktop b/dwl/dwl-v0.7/dwl.desktop deleted file mode 100644 index e1380f7a..00000000 --- a/dwl/dwl-v0.7/dwl.desktop +++ /dev/null @@ -1,5 +0,0 @@ -[Desktop Entry] -Name=dwl -Comment=dwm for Wayland -Exec=dwl -Type=Application diff --git a/dwl/dwl-v0.7/dwl.o b/dwl/dwl-v0.7/dwl.o deleted file mode 100644 index dffbb4f6..00000000 Binary files a/dwl/dwl-v0.7/dwl.o and /dev/null differ diff --git a/dwl/dwl-v0.7/pointer-constraints-unstable-v1-protocol.h b/dwl/dwl-v0.7/pointer-constraints-unstable-v1-protocol.h deleted file mode 100644 index 27c715ba..00000000 --- a/dwl/dwl-v0.7/pointer-constraints-unstable-v1-protocol.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Generated by wayland-scanner 1.24.0 */ - -#ifndef POINTER_CONSTRAINTS_UNSTABLE_V1_ENUM_PROTOCOL_H -#define POINTER_CONSTRAINTS_UNSTABLE_V1_ENUM_PROTOCOL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef ZWP_POINTER_CONSTRAINTS_V1_ERROR_ENUM -#define ZWP_POINTER_CONSTRAINTS_V1_ERROR_ENUM -/** - * @ingroup iface_zwp_pointer_constraints_v1 - * wp_pointer_constraints error values - * - * These errors can be emitted in response to wp_pointer_constraints - * requests. - */ -enum zwp_pointer_constraints_v1_error { - /** - * pointer constraint already requested on that surface - */ - ZWP_POINTER_CONSTRAINTS_V1_ERROR_ALREADY_CONSTRAINED = 1, -}; -#endif /* ZWP_POINTER_CONSTRAINTS_V1_ERROR_ENUM */ - -#ifndef ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ENUM -#define ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ENUM -/** - * @ingroup iface_zwp_pointer_constraints_v1 - * constraint lifetime - * - * These values represent different lifetime semantics. They are passed - * as arguments to the factory requests to specify how the constraint - * lifetimes should be managed. - */ -enum zwp_pointer_constraints_v1_lifetime { - /** - * the pointer constraint is defunct once deactivated - * - * A oneshot pointer constraint will never reactivate once it has - * been deactivated. See the corresponding deactivation event - * (wp_locked_pointer.unlocked and wp_confined_pointer.unconfined) - * for details. - */ - ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT = 1, - /** - * the pointer constraint may reactivate - * - * A persistent pointer constraint may again reactivate once it - * has been deactivated. See the corresponding deactivation event - * (wp_locked_pointer.unlocked and wp_confined_pointer.unconfined) - * for details. - */ - ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT = 2, -}; -#endif /* ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ENUM */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/dwl/dwl-v0.7/protocols/wlr-layer-shell-unstable-v1.xml b/dwl/dwl-v0.7/protocols/wlr-layer-shell-unstable-v1.xml deleted file mode 100644 index d62fd51e..00000000 --- a/dwl/dwl-v0.7/protocols/wlr-layer-shell-unstable-v1.xml +++ /dev/null @@ -1,390 +0,0 @@ - - - - Copyright © 2017 Drew DeVault - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that copyright notice and this permission - notice appear in supporting documentation, and that the name of - the copyright holders not be used in advertising or publicity - pertaining to distribution of the software without specific, - written prior permission. The copyright holders make no - representations about the suitability of this software for any - purpose. It is provided "as is" without express or implied - warranty. - - THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - THIS SOFTWARE. - - - - - Clients can use this interface to assign the surface_layer role to - wl_surfaces. Such surfaces are assigned to a "layer" of the output and - rendered with a defined z-depth respective to each other. They may also be - anchored to the edges and corners of a screen and specify input handling - semantics. This interface should be suitable for the implementation of - many desktop shell components, and a broad number of other applications - that interact with the desktop. - - - - - Create a layer surface for an existing surface. This assigns the role of - layer_surface, or raises a protocol error if another role is already - assigned. - - Creating a layer surface from a wl_surface which has a buffer attached - or committed is a client error, and any attempts by a client to attach - or manipulate a buffer prior to the first layer_surface.configure call - must also be treated as errors. - - After creating a layer_surface object and setting it up, the client - must perform an initial commit without any buffer attached. - The compositor will reply with a layer_surface.configure event. - The client must acknowledge it and is then allowed to attach a buffer - to map the surface. - - You may pass NULL for output to allow the compositor to decide which - output to use. Generally this will be the one that the user most - recently interacted with. - - Clients can specify a namespace that defines the purpose of the layer - surface. - - - - - - - - - - - - - - - - - These values indicate which layers a surface can be rendered in. They - are ordered by z depth, bottom-most first. Traditional shell surfaces - will typically be rendered between the bottom and top layers. - Fullscreen shell surfaces are typically rendered at the top layer. - Multiple surfaces can share a single layer, and ordering within a - single layer is undefined. - - - - - - - - - - - - - This request indicates that the client will not use the layer_shell - object any more. Objects that have been created through this instance - are not affected. - - - - - - - An interface that may be implemented by a wl_surface, for surfaces that - are designed to be rendered as a layer of a stacked desktop-like - environment. - - Layer surface state (layer, size, anchor, exclusive zone, - margin, interactivity) is double-buffered, and will be applied at the - time wl_surface.commit of the corresponding wl_surface is called. - - Attaching a null buffer to a layer surface unmaps it. - - Unmapping a layer_surface means that the surface cannot be shown by the - compositor until it is explicitly mapped again. The layer_surface - returns to the state it had right after layer_shell.get_layer_surface. - The client can re-map the surface by performing a commit without any - buffer attached, waiting for a configure event and handling it as usual. - - - - - Sets the size of the surface in surface-local coordinates. The - compositor will display the surface centered with respect to its - anchors. - - If you pass 0 for either value, the compositor will assign it and - inform you of the assignment in the configure event. You must set your - anchor to opposite edges in the dimensions you omit; not doing so is a - protocol error. Both values are 0 by default. - - Size is double-buffered, see wl_surface.commit. - - - - - - - - Requests that the compositor anchor the surface to the specified edges - and corners. If two orthogonal edges are specified (e.g. 'top' and - 'left'), then the anchor point will be the intersection of the edges - (e.g. the top left corner of the output); otherwise the anchor point - will be centered on that edge, or in the center if none is specified. - - Anchor is double-buffered, see wl_surface.commit. - - - - - - - Requests that the compositor avoids occluding an area with other - surfaces. The compositor's use of this information is - implementation-dependent - do not assume that this region will not - actually be occluded. - - A positive value is only meaningful if the surface is anchored to one - edge or an edge and both perpendicular edges. If the surface is not - anchored, anchored to only two perpendicular edges (a corner), anchored - to only two parallel edges or anchored to all edges, a positive value - will be treated the same as zero. - - A positive zone is the distance from the edge in surface-local - coordinates to consider exclusive. - - Surfaces that do not wish to have an exclusive zone may instead specify - how they should interact with surfaces that do. If set to zero, the - surface indicates that it would like to be moved to avoid occluding - surfaces with a positive exclusive zone. If set to -1, the surface - indicates that it would not like to be moved to accommodate for other - surfaces, and the compositor should extend it all the way to the edges - it is anchored to. - - For example, a panel might set its exclusive zone to 10, so that - maximized shell surfaces are not shown on top of it. A notification - might set its exclusive zone to 0, so that it is moved to avoid - occluding the panel, but shell surfaces are shown underneath it. A - wallpaper or lock screen might set their exclusive zone to -1, so that - they stretch below or over the panel. - - The default value is 0. - - Exclusive zone is double-buffered, see wl_surface.commit. - - - - - - - Requests that the surface be placed some distance away from the anchor - point on the output, in surface-local coordinates. Setting this value - for edges you are not anchored to has no effect. - - The exclusive zone includes the margin. - - Margin is double-buffered, see wl_surface.commit. - - - - - - - - - - Types of keyboard interaction possible for layer shell surfaces. The - rationale for this is twofold: (1) some applications are not interested - in keyboard events and not allowing them to be focused can improve the - desktop experience; (2) some applications will want to take exclusive - keyboard focus. - - - - - This value indicates that this surface is not interested in keyboard - events and the compositor should never assign it the keyboard focus. - - This is the default value, set for newly created layer shell surfaces. - - This is useful for e.g. desktop widgets that display information or - only have interaction with non-keyboard input devices. - - - - - Request exclusive keyboard focus if this surface is above the shell surface layer. - - For the top and overlay layers, the seat will always give - exclusive keyboard focus to the top-most layer which has keyboard - interactivity set to exclusive. If this layer contains multiple - surfaces with keyboard interactivity set to exclusive, the compositor - determines the one receiving keyboard events in an implementation- - defined manner. In this case, no guarantee is made when this surface - will receive keyboard focus (if ever). - - For the bottom and background layers, the compositor is allowed to use - normal focus semantics. - - This setting is mainly intended for applications that need to ensure - they receive all keyboard events, such as a lock screen or a password - prompt. - - - - - This requests the compositor to allow this surface to be focused and - unfocused by the user in an implementation-defined manner. The user - should be able to unfocus this surface even regardless of the layer - it is on. - - Typically, the compositor will want to use its normal mechanism to - manage keyboard focus between layer shell surfaces with this setting - and regular toplevels on the desktop layer (e.g. click to focus). - Nevertheless, it is possible for a compositor to require a special - interaction to focus or unfocus layer shell surfaces (e.g. requiring - a click even if focus follows the mouse normally, or providing a - keybinding to switch focus between layers). - - This setting is mainly intended for desktop shell components (e.g. - panels) that allow keyboard interaction. Using this option can allow - implementing a desktop shell that can be fully usable without the - mouse. - - - - - - - Set how keyboard events are delivered to this surface. By default, - layer shell surfaces do not receive keyboard events; this request can - be used to change this. - - This setting is inherited by child surfaces set by the get_popup - request. - - Layer surfaces receive pointer, touch, and tablet events normally. If - you do not want to receive them, set the input region on your surface - to an empty region. - - Keyboard interactivity is double-buffered, see wl_surface.commit. - - - - - - - This assigns an xdg_popup's parent to this layer_surface. This popup - should have been created via xdg_surface::get_popup with the parent set - to NULL, and this request must be invoked before committing the popup's - initial state. - - See the documentation of xdg_popup for more details about what an - xdg_popup is and how it is used. - - - - - - - When a configure event is received, if a client commits the - surface in response to the configure event, then the client - must make an ack_configure request sometime before the commit - request, passing along the serial of the configure event. - - If the client receives multiple configure events before it - can respond to one, it only has to ack the last configure event. - - A client is not required to commit immediately after sending - an ack_configure request - it may even ack_configure several times - before its next surface commit. - - A client may send multiple ack_configure requests before committing, but - only the last request sent before a commit indicates which configure - event the client really is responding to. - - - - - - - This request destroys the layer surface. - - - - - - The configure event asks the client to resize its surface. - - Clients should arrange their surface for the new states, and then send - an ack_configure request with the serial sent in this configure event at - some point before committing the new surface. - - The client is free to dismiss all but the last configure event it - received. - - The width and height arguments specify the size of the window in - surface-local coordinates. - - The size is a hint, in the sense that the client is free to ignore it if - it doesn't resize, pick a smaller size (to satisfy aspect ratio or - resize in steps of NxM pixels). If the client picks a smaller size and - is anchored to two opposite anchors (e.g. 'top' and 'bottom'), the - surface will be centered on this axis. - - If the width or height arguments are zero, it means the client should - decide its own window dimension. - - - - - - - - - The closed event is sent by the compositor when the surface will no - longer be shown. The output may have been destroyed or the user may - have asked for it to be removed. Further changes to the surface will be - ignored. The client should destroy the resource after receiving this - event, and create a new surface if they so choose. - - - - - - - - - - - - - - - - - - - - - - Change the layer that the surface is rendered on. - - Layer is double-buffered, see wl_surface.commit. - - - - - diff --git a/dwl/dwl-v0.7/protocols/wlr-output-power-management-unstable-v1.xml b/dwl/dwl-v0.7/protocols/wlr-output-power-management-unstable-v1.xml deleted file mode 100644 index a9778399..00000000 --- a/dwl/dwl-v0.7/protocols/wlr-output-power-management-unstable-v1.xml +++ /dev/null @@ -1,128 +0,0 @@ - - - - Copyright © 2019 Purism SPC - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice (including the next - paragraph) shall be included in all copies or substantial portions of the - Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - - - - This protocol allows clients to control power management modes - of outputs that are currently part of the compositor space. The - intent is to allow special clients like desktop shells to power - down outputs when the system is idle. - - To modify outputs not currently part of the compositor space see - wlr-output-management. - - Warning! The protocol described in this file is experimental and - backward incompatible changes may be made. Backward compatible changes - may be added together with the corresponding interface version bump. - Backward incompatible changes are done by bumping the version number in - the protocol and interface names and resetting the interface version. - Once the protocol is to be declared stable, the 'z' prefix and the - version number in the protocol and interface names are removed and the - interface version number is reset. - - - - - This interface is a manager that allows creating per-output power - management mode controls. - - - - - Create a output power management mode control that can be used to - adjust the power management mode for a given output. - - - - - - - - All objects created by the manager will still remain valid, until their - appropriate destroy request has been called. - - - - - - - This object offers requests to set the power management mode of - an output. - - - - - - - - - - - - - - Set an output's power save mode to the given mode. The mode change - is effective immediately. If the output does not support the given - mode a failed event is sent. - - - - - - - Report the power management mode change of an output. - - The mode event is sent after an output changed its power - management mode. The reason can be a client using set_mode or the - compositor deciding to change an output's mode. - This event is also sent immediately when the object is created - so the client is informed about the current power management mode. - - - - - - - This event indicates that the output power management mode control - is no longer valid. This can happen for a number of reasons, - including: - - The output doesn't support power management - - Another client already has exclusive power management mode control - for this output - - The output disappeared - - Upon receiving this event, the client should destroy this object. - - - - - - Destroys the output power management mode control object. - - - - diff --git a/dwl/dwl-v0.7/swallow.patch b/dwl/dwl-v0.7/swallow.patch deleted file mode 100644 index f9760234..00000000 --- a/dwl/dwl-v0.7/swallow.patch +++ /dev/null @@ -1,350 +0,0 @@ -From 7255d7e2e1b87c0583a202ea20c83fa75466c0fc Mon Sep 17 00:00:00 2001 -From: Nikita Ivanov -Date: Wed, 5 Feb 2025 02:34:39 +0100 -Subject: [PATCH] Swallow: hide the terminal when it spawns a client - ---- - client.h | 12 ++++ - config.def.h | 10 +++- - dwl.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++-- - 3 files changed, 167 insertions(+), 7 deletions(-) - -diff --git a/client.h b/client.h -index 42f225f..bc9cad2 100644 ---- a/client.h -+++ b/client.h -@@ -131,6 +131,18 @@ client_get_appid(Client *c) - return c->surface.xdg->toplevel->app_id; - } - -+static inline int -+client_get_pid(Client *c) -+{ -+ pid_t pid; -+#ifdef XWAYLAND -+ if (client_is_x11(c)) -+ return c->surface.xwayland->pid; -+#endif -+ wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL); -+ return pid; -+} -+ - static inline void - client_get_clip(Client *c, struct wlr_box *clip) - { -diff --git a/config.def.h b/config.def.h -index 22d2171..fb5f8fb 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -13,6 +13,7 @@ static const float focuscolor[] = COLOR(0x005577ff); - static const float urgentcolor[] = COLOR(0xff0000ff); - /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ - static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ -+static int enableautoswallow = 1; /* enables autoswallowing newly spawned clients */ - - /* tagging - TAGCOUNT must be no greater than 31 */ - #define TAGCOUNT (9) -@@ -22,10 +23,11 @@ static int log_level = WLR_ERROR; - - /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ - static const Rule rules[] = { -- /* app_id title tags mask isfloating monitor */ -+ /* app_id title tags mask isfloating isterm noswallow monitor */ - /* examples: */ -- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ -- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ -+ { "foot", NULL, 0, 0, 1, 1, -1 }, -+ { "Gimp_EXAMPLE", NULL, 0, 1, 0, 0, -1 }, /* Start on currently visible tags floating, not tiled */ -+ { "firefox_EXAMPLE", NULL, 1 << 8, 0, 0, 0, -1 }, /* Start on ONLY tag "9" */ - }; - - /* layout(s) */ -@@ -142,6 +144,8 @@ static const Key keys[] = { - { MODKEY, XKB_KEY_space, setlayout, {0} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, - { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, -+ { MODKEY, XKB_KEY_a, toggleswallow, {0} }, -+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_A, toggleautoswallow,{0} }, - { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, - { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, -diff --git a/dwl.c b/dwl.c -index def2562..bbbbe6f 100644 ---- a/dwl.c -+++ b/dwl.c -@@ -73,12 +73,13 @@ - #define MAX(A, B) ((A) > (B) ? (A) : (B)) - #define MIN(A, B) ((A) < (B) ? (A) : (B)) - #define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS) --#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]) && !(C)->swallowedby) - #define LENGTH(X) (sizeof X / sizeof X[0]) - #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 LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0) -+#define BORDERPX(C) (borderpx + ((C)->swallowing ? (C)->swallowing->bw : 0)) - - /* enums */ - enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ -@@ -104,7 +105,8 @@ typedef struct { - } Button; - - typedef struct Monitor Monitor; --typedef struct { -+typedef struct Client Client; -+struct Client { - /* Must keep these three elements in this order */ - unsigned int type; /* XDGShell or X11* */ - struct wlr_box geom; /* layout-relative, includes border */ -@@ -140,8 +142,12 @@ typedef struct { - unsigned int bw; - uint32_t tags; - int isfloating, isurgent, isfullscreen; -+ int isterm, noswallow; - uint32_t resize; /* configure serial of a pending resize */ --} Client; -+ pid_t pid; -+ Client *swallowing; /* client being hidden */ -+ Client *swallowedby; -+}; - - typedef struct { - uint32_t mod; -@@ -230,6 +236,8 @@ typedef struct { - const char *title; - uint32_t tags; - int isfloating; -+ int isterm; -+ int noswallow; - int monitor; - } Rule; - -@@ -311,6 +319,7 @@ static void moveresize(const Arg *arg); - static void outputmgrapply(struct wl_listener *listener, void *data); - static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test); - static void outputmgrtest(struct wl_listener *listener, void *data); -+static pid_t parentpid(pid_t pid); - static void pointerfocus(Client *c, struct wlr_surface *surface, - double sx, double sy, uint32_t time); - static void printstatus(void); -@@ -335,11 +344,15 @@ static void setsel(struct wl_listener *listener, void *data); - static void setup(void); - static void spawn(const Arg *arg); - static void startdrag(struct wl_listener *listener, void *data); -+static void swallow(Client *c, Client *toswallow); - static void tag(const Arg *arg); - static void tagmon(const Arg *arg); -+static Client *termforwin(Client *c); - static void tile(Monitor *m); - static void togglefloating(const Arg *arg); - static void togglefullscreen(const Arg *arg); -+static void toggleswallow(const Arg *arg); -+static void toggleautoswallow(const Arg *arg); - static void toggletag(const Arg *arg); - static void toggleview(const Arg *arg); - static void unlocksession(struct wl_listener *listener, void *data); -@@ -466,11 +479,15 @@ applyrules(Client *c) - if (!(title = client_get_title(c))) - title = broken; - -+ c->pid = client_get_pid(c); -+ - for (r = rules; r < END(rules); r++) { - if ((!r->title || strstr(title, r->title)) - && (!r->id || strstr(appid, r->id))) { - c->isfloating = r->isfloating; - newtags |= r->tags; -+ c->isterm = r->isterm; -+ c->noswallow = r->noswallow; - i = 0; - wl_list_for_each(m, &mons, link) { - if (r->monitor == i++) -@@ -478,6 +495,12 @@ applyrules(Client *c) - } - } - } -+ if (enableautoswallow && !c->noswallow && !c->isfloating && -+ !c->surface.xdg->initial_commit) { -+ Client *p = termforwin(c); -+ if (p) -+ swallow(c, p); -+ } - setmon(c, mon, newtags); - } - -@@ -2006,6 +2029,20 @@ outputmgrtest(struct wl_listener *listener, void *data) - outputmgrapplyortest(config, 1); - } - -+pid_t -+parentpid(pid_t pid) -+{ -+ unsigned int v = 0; -+ FILE *f; -+ char buf[256]; -+ snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)pid); -+ if (!(f = fopen(buf, "r"))) -+ return 0; -+ fscanf(f, "%*u %*s %*c %u", &v); -+ fclose(f); -+ return (pid_t)v; -+} -+ - void - pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, - uint32_t time) -@@ -2326,7 +2363,7 @@ setfullscreen(Client *c, int fullscreen) - c->isfullscreen = fullscreen; - if (!c->mon || !client_surface(c)->mapped) - return; -- c->bw = fullscreen ? 0 : borderpx; -+ c->bw = fullscreen ? 0 : BORDERPX(c); - client_set_fullscreen(c, fullscreen); - wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen - ? LyrFS : c->isfloating ? LyrFloat : LyrTile]); -@@ -2404,6 +2441,9 @@ setmon(Client *c, Monitor *m, uint32_t newtags) - setfloating(c, c->isfloating); - } - focusclient(focustop(selmon), 1); -+ -+ if (c->swallowing) -+ setmon(c->swallowing, m, newtags); - } - - void -@@ -2669,6 +2709,44 @@ startdrag(struct wl_listener *listener, void *data) - LISTEN_STATIC(&drag->icon->events.destroy, destroydragicon); - } - -+void -+swallow(Client *c, Client *toswallow) -+{ -+ /* Do not allow a client to swallow itself */ -+ if (c == toswallow) -+ return; -+ -+ /* Swallow */ -+ if (toswallow && !c->swallowing) { -+ c->swallowing = toswallow; -+ toswallow->swallowedby = c; -+ toswallow->mon = c->mon; -+ toswallow->mon = c->mon; -+ wl_list_remove(&c->link); -+ wl_list_insert(&c->swallowing->link, &c->link); -+ wl_list_remove(&c->flink); -+ wl_list_insert(&c->swallowing->flink, &c->flink); -+ c->bw = BORDERPX(c); -+ c->tags = toswallow->tags; -+ c->isfloating = toswallow->isfloating; -+ c->geom = toswallow->geom; -+ setfullscreen(toswallow, 0); -+ } -+ -+ /* Unswallow */ -+ else if (c->swallowing) { -+ wl_list_remove(&c->swallowing->link); -+ wl_list_insert(&c->link, &c->swallowing->link); -+ wl_list_remove(&c->swallowing->flink); -+ wl_list_insert(&c->flink, &c->swallowing->flink); -+ c->swallowing->tags = c->tags; -+ c->swallowing->swallowedby = NULL; -+ c->swallowing = NULL; -+ c->bw = BORDERPX(c); -+ setfullscreen(c, 0); -+ } -+} -+ - void - tag(const Arg *arg) - { -@@ -2690,6 +2768,40 @@ tagmon(const Arg *arg) - setmon(sel, dirtomon(arg->i), 0); - } - -+Client * -+termforwin(Client *c) -+{ -+ Client *p; -+ pid_t pid; -+ pid_t pids[32]; -+ size_t i, pids_len; -+ -+ if (!c->pid || c->isterm) -+ return NULL; -+ -+ /* Get all parent pids */ -+ pids_len = 0; -+ pid = c->pid; -+ while (pids_len < LENGTH(pids)) { -+ pid = parentpid(pid); -+ if (!pid) -+ break; -+ pids[pids_len++] = pid; -+ } -+ -+ /* Find closest parent */ -+ for (i = 0; i < pids_len; i++) { -+ wl_list_for_each(p, &clients, link) { -+ if (!p->pid || !p->isterm || p->swallowedby) -+ continue; -+ if (pids[i] == p->pid) -+ return p; -+ } -+ } -+ -+ return NULL; -+} -+ - void - tile(Monitor *m) - { -@@ -2741,6 +2853,32 @@ togglefullscreen(const Arg *arg) - setfullscreen(sel, !sel->isfullscreen); - } - -+void -+toggleswallow(const Arg *arg) -+{ -+ Client *c, *sel = focustop(selmon); -+ if (!sel) -+ return; -+ -+ if (sel->swallowing) { -+ swallow(sel, NULL); -+ } else { -+ wl_list_for_each(c, &sel->flink, flink) { -+ if (&c->flink == &fstack) -+ continue; /* wrap past the sentinel node */ -+ if (VISIBLEON(c, selmon)) -+ break; /* found it */ -+ } -+ swallow(sel, c); -+ } -+} -+ -+void -+toggleautoswallow(const Arg *arg) -+{ -+ enableautoswallow = !enableautoswallow; -+} -+ - void - toggletag(const Arg *arg) - { -@@ -2801,6 +2939,12 @@ unmapnotify(struct wl_listener *listener, void *data) - grabc = NULL; - } - -+ if (c->swallowing) { -+ swallow(c, NULL); -+ } else if (c->swallowedby) { -+ swallow(c->swallowedby, NULL); -+ } -+ - if (client_is_unmanaged(c)) { - if (c == exclusive_focus) { - exclusive_focus = NULL; --- -2.48.1 - diff --git a/dwl/dwl-v0.7/util.c b/dwl/dwl-v0.7/util.c deleted file mode 100644 index 51130af0..00000000 --- a/dwl/dwl-v0.7/util.c +++ /dev/null @@ -1,51 +0,0 @@ -/* See LICENSE.dwm file for copyright and license details. */ -#include -#include -#include -#include -#include - -#include "util.h" - -void -die(const char *fmt, ...) { - va_list ap; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - if (fmt[0] && fmt[strlen(fmt)-1] == ':') { - fputc(' ', stderr); - perror(NULL); - } else { - fputc('\n', stderr); - } - - exit(1); -} - -void * -ecalloc(size_t nmemb, size_t size) -{ - void *p; - - if (!(p = calloc(nmemb, size))) - die("calloc:"); - return p; -} - -int -fd_set_nonblock(int fd) { - int flags = fcntl(fd, F_GETFL); - if (flags < 0) { - perror("fcntl(F_GETFL):"); - return -1; - } - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { - perror("fcntl(F_SETFL):"); - return -1; - } - - return 0; -} diff --git a/dwl/dwl-v0.7/util.h b/dwl/dwl-v0.7/util.h deleted file mode 100644 index 226980de..00000000 --- a/dwl/dwl-v0.7/util.h +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE.dwm file for copyright and license details. */ - -void die(const char *fmt, ...); -void *ecalloc(size_t nmemb, size_t size); -int fd_set_nonblock(int fd); diff --git a/dwl/dwl-v0.7/util.o b/dwl/dwl-v0.7/util.o deleted file mode 100644 index c1969d5e..00000000 Binary files a/dwl/dwl-v0.7/util.o and /dev/null differ diff --git a/dwl/dwl-v0.7/wlr-layer-shell-unstable-v1-protocol.h b/dwl/dwl-v0.7/wlr-layer-shell-unstable-v1-protocol.h deleted file mode 100644 index d7e4b331..00000000 --- a/dwl/dwl-v0.7/wlr-layer-shell-unstable-v1-protocol.h +++ /dev/null @@ -1,177 +0,0 @@ -/* Generated by wayland-scanner 1.24.0 */ - -#ifndef WLR_LAYER_SHELL_UNSTABLE_V1_ENUM_PROTOCOL_H -#define WLR_LAYER_SHELL_UNSTABLE_V1_ENUM_PROTOCOL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef ZWLR_LAYER_SHELL_V1_ERROR_ENUM -#define ZWLR_LAYER_SHELL_V1_ERROR_ENUM -enum zwlr_layer_shell_v1_error { - /** - * wl_surface has another role - */ - ZWLR_LAYER_SHELL_V1_ERROR_ROLE = 0, - /** - * layer value is invalid - */ - ZWLR_LAYER_SHELL_V1_ERROR_INVALID_LAYER = 1, - /** - * wl_surface has a buffer attached or committed - */ - ZWLR_LAYER_SHELL_V1_ERROR_ALREADY_CONSTRUCTED = 2, -}; -#endif /* ZWLR_LAYER_SHELL_V1_ERROR_ENUM */ - -#ifndef ZWLR_LAYER_SHELL_V1_LAYER_ENUM -#define ZWLR_LAYER_SHELL_V1_LAYER_ENUM -/** - * @ingroup iface_zwlr_layer_shell_v1 - * available layers for surfaces - * - * These values indicate which layers a surface can be rendered in. They - * are ordered by z depth, bottom-most first. Traditional shell surfaces - * will typically be rendered between the bottom and top layers. - * Fullscreen shell surfaces are typically rendered at the top layer. - * Multiple surfaces can share a single layer, and ordering within a - * single layer is undefined. - */ -enum zwlr_layer_shell_v1_layer { - ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND = 0, - ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM = 1, - ZWLR_LAYER_SHELL_V1_LAYER_TOP = 2, - ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY = 3, -}; -#endif /* ZWLR_LAYER_SHELL_V1_LAYER_ENUM */ - -#ifndef ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ENUM -#define ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ENUM -/** - * @ingroup iface_zwlr_layer_surface_v1 - * types of keyboard interaction possible for a layer shell surface - * - * Types of keyboard interaction possible for layer shell surfaces. The - * rationale for this is twofold: (1) some applications are not interested - * in keyboard events and not allowing them to be focused can improve the - * desktop experience; (2) some applications will want to take exclusive - * keyboard focus. - */ -enum zwlr_layer_surface_v1_keyboard_interactivity { - /** - * no keyboard focus is possible - * - * This value indicates that this surface is not interested in - * keyboard events and the compositor should never assign it the - * keyboard focus. - * - * This is the default value, set for newly created layer shell - * surfaces. - * - * This is useful for e.g. desktop widgets that display information - * or only have interaction with non-keyboard input devices. - */ - ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE = 0, - /** - * request exclusive keyboard focus - * - * Request exclusive keyboard focus if this surface is above the - * shell surface layer. - * - * For the top and overlay layers, the seat will always give - * exclusive keyboard focus to the top-most layer which has - * keyboard interactivity set to exclusive. If this layer contains - * multiple surfaces with keyboard interactivity set to exclusive, - * the compositor determines the one receiving keyboard events in - * an implementation- defined manner. In this case, no guarantee is - * made when this surface will receive keyboard focus (if ever). - * - * For the bottom and background layers, the compositor is allowed - * to use normal focus semantics. - * - * This setting is mainly intended for applications that need to - * ensure they receive all keyboard events, such as a lock screen - * or a password prompt. - */ - ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE = 1, - /** - * request regular keyboard focus semantics - * - * This requests the compositor to allow this surface to be - * focused and unfocused by the user in an implementation-defined - * manner. The user should be able to unfocus this surface even - * regardless of the layer it is on. - * - * Typically, the compositor will want to use its normal mechanism - * to manage keyboard focus between layer shell surfaces with this - * setting and regular toplevels on the desktop layer (e.g. click - * to focus). Nevertheless, it is possible for a compositor to - * require a special interaction to focus or unfocus layer shell - * surfaces (e.g. requiring a click even if focus follows the mouse - * normally, or providing a keybinding to switch focus between - * layers). - * - * This setting is mainly intended for desktop shell components - * (e.g. panels) that allow keyboard interaction. Using this option - * can allow implementing a desktop shell that can be fully usable - * without the mouse. - * @since 4 - */ - ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND = 2, -}; -/** - * @ingroup iface_zwlr_layer_surface_v1 - */ -#define ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND_SINCE_VERSION 4 -#endif /* ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ENUM */ - -#ifndef ZWLR_LAYER_SURFACE_V1_ERROR_ENUM -#define ZWLR_LAYER_SURFACE_V1_ERROR_ENUM -enum zwlr_layer_surface_v1_error { - /** - * provided surface state is invalid - */ - ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_SURFACE_STATE = 0, - /** - * size is invalid - */ - ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_SIZE = 1, - /** - * anchor bitfield is invalid - */ - ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_ANCHOR = 2, - /** - * keyboard interactivity is invalid - */ - ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_KEYBOARD_INTERACTIVITY = 3, -}; -#endif /* ZWLR_LAYER_SURFACE_V1_ERROR_ENUM */ - -#ifndef ZWLR_LAYER_SURFACE_V1_ANCHOR_ENUM -#define ZWLR_LAYER_SURFACE_V1_ANCHOR_ENUM -enum zwlr_layer_surface_v1_anchor { - /** - * the top edge of the anchor rectangle - */ - ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP = 1, - /** - * the bottom edge of the anchor rectangle - */ - ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM = 2, - /** - * the left edge of the anchor rectangle - */ - ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT = 4, - /** - * the right edge of the anchor rectangle - */ - ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT = 8, -}; -#endif /* ZWLR_LAYER_SURFACE_V1_ANCHOR_ENUM */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/dwl/dwl-v0.7/wlr-output-power-management-unstable-v1-protocol.h b/dwl/dwl-v0.7/wlr-output-power-management-unstable-v1-protocol.h deleted file mode 100644 index 7977a976..00000000 --- a/dwl/dwl-v0.7/wlr-output-power-management-unstable-v1-protocol.h +++ /dev/null @@ -1,285 +0,0 @@ -/* Generated by wayland-scanner 1.24.0 */ - -#ifndef WLR_OUTPUT_POWER_MANAGEMENT_UNSTABLE_V1_SERVER_PROTOCOL_H -#define WLR_OUTPUT_POWER_MANAGEMENT_UNSTABLE_V1_SERVER_PROTOCOL_H - -#include -#include -#include "wayland-server.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct wl_client; -struct wl_resource; - -/** - * @page page_wlr_output_power_management_unstable_v1 The wlr_output_power_management_unstable_v1 protocol - * Control power management modes of outputs - * - * @section page_desc_wlr_output_power_management_unstable_v1 Description - * - * This protocol allows clients to control power management modes - * of outputs that are currently part of the compositor space. The - * intent is to allow special clients like desktop shells to power - * down outputs when the system is idle. - * - * To modify outputs not currently part of the compositor space see - * wlr-output-management. - * - * Warning! The protocol described in this file is experimental and - * backward incompatible changes may be made. Backward compatible changes - * may be added together with the corresponding interface version bump. - * Backward incompatible changes are done by bumping the version number in - * the protocol and interface names and resetting the interface version. - * Once the protocol is to be declared stable, the 'z' prefix and the - * version number in the protocol and interface names are removed and the - * interface version number is reset. - * - * @section page_ifaces_wlr_output_power_management_unstable_v1 Interfaces - * - @subpage page_iface_zwlr_output_power_manager_v1 - manager to create per-output power management - * - @subpage page_iface_zwlr_output_power_v1 - adjust power management mode for an output - * @section page_copyright_wlr_output_power_management_unstable_v1 Copyright - *
- *
- * Copyright © 2019 Purism SPC
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- * 
- */ -struct wl_output; -struct zwlr_output_power_manager_v1; -struct zwlr_output_power_v1; - -#ifndef ZWLR_OUTPUT_POWER_MANAGER_V1_INTERFACE -#define ZWLR_OUTPUT_POWER_MANAGER_V1_INTERFACE -/** - * @page page_iface_zwlr_output_power_manager_v1 zwlr_output_power_manager_v1 - * @section page_iface_zwlr_output_power_manager_v1_desc Description - * - * This interface is a manager that allows creating per-output power - * management mode controls. - * @section page_iface_zwlr_output_power_manager_v1_api API - * See @ref iface_zwlr_output_power_manager_v1. - */ -/** - * @defgroup iface_zwlr_output_power_manager_v1 The zwlr_output_power_manager_v1 interface - * - * This interface is a manager that allows creating per-output power - * management mode controls. - */ -extern const struct wl_interface zwlr_output_power_manager_v1_interface; -#endif -#ifndef ZWLR_OUTPUT_POWER_V1_INTERFACE -#define ZWLR_OUTPUT_POWER_V1_INTERFACE -/** - * @page page_iface_zwlr_output_power_v1 zwlr_output_power_v1 - * @section page_iface_zwlr_output_power_v1_desc Description - * - * This object offers requests to set the power management mode of - * an output. - * @section page_iface_zwlr_output_power_v1_api API - * See @ref iface_zwlr_output_power_v1. - */ -/** - * @defgroup iface_zwlr_output_power_v1 The zwlr_output_power_v1 interface - * - * This object offers requests to set the power management mode of - * an output. - */ -extern const struct wl_interface zwlr_output_power_v1_interface; -#endif - -/** - * @ingroup iface_zwlr_output_power_manager_v1 - * @struct zwlr_output_power_manager_v1_interface - */ -struct zwlr_output_power_manager_v1_interface { - /** - * get a power management for an output - * - * Create a output power management mode control that can be used - * to adjust the power management mode for a given output. - */ - void (*get_output_power)(struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *output); - /** - * destroy the manager - * - * All objects created by the manager will still remain valid, - * until their appropriate destroy request has been called. - */ - void (*destroy)(struct wl_client *client, - struct wl_resource *resource); -}; - - -/** - * @ingroup iface_zwlr_output_power_manager_v1 - */ -#define ZWLR_OUTPUT_POWER_MANAGER_V1_GET_OUTPUT_POWER_SINCE_VERSION 1 -/** - * @ingroup iface_zwlr_output_power_manager_v1 - */ -#define ZWLR_OUTPUT_POWER_MANAGER_V1_DESTROY_SINCE_VERSION 1 - -#ifndef ZWLR_OUTPUT_POWER_V1_MODE_ENUM -#define ZWLR_OUTPUT_POWER_V1_MODE_ENUM -enum zwlr_output_power_v1_mode { - /** - * Output is turned off. - */ - ZWLR_OUTPUT_POWER_V1_MODE_OFF = 0, - /** - * Output is turned on, no power saving - */ - ZWLR_OUTPUT_POWER_V1_MODE_ON = 1, -}; -#endif /* ZWLR_OUTPUT_POWER_V1_MODE_ENUM */ - -#ifndef ZWLR_OUTPUT_POWER_V1_MODE_ENUM_IS_VALID -#define ZWLR_OUTPUT_POWER_V1_MODE_ENUM_IS_VALID -/** - * @ingroup iface_zwlr_output_power_v1 - * Validate a zwlr_output_power_v1 mode value. - * - * @return true on success, false on error. - * @ref zwlr_output_power_v1_mode - */ -static inline bool -zwlr_output_power_v1_mode_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case ZWLR_OUTPUT_POWER_V1_MODE_OFF: - return version >= 1; - case ZWLR_OUTPUT_POWER_V1_MODE_ON: - return version >= 1; - default: - return false; - } -} -#endif /* ZWLR_OUTPUT_POWER_V1_MODE_ENUM_IS_VALID */ - -#ifndef ZWLR_OUTPUT_POWER_V1_ERROR_ENUM -#define ZWLR_OUTPUT_POWER_V1_ERROR_ENUM -enum zwlr_output_power_v1_error { - /** - * inexistent power save mode - */ - ZWLR_OUTPUT_POWER_V1_ERROR_INVALID_MODE = 1, -}; -#endif /* ZWLR_OUTPUT_POWER_V1_ERROR_ENUM */ - -#ifndef ZWLR_OUTPUT_POWER_V1_ERROR_ENUM_IS_VALID -#define ZWLR_OUTPUT_POWER_V1_ERROR_ENUM_IS_VALID -/** - * @ingroup iface_zwlr_output_power_v1 - * Validate a zwlr_output_power_v1 error value. - * - * @return true on success, false on error. - * @ref zwlr_output_power_v1_error - */ -static inline bool -zwlr_output_power_v1_error_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case ZWLR_OUTPUT_POWER_V1_ERROR_INVALID_MODE: - return version >= 1; - default: - return false; - } -} -#endif /* ZWLR_OUTPUT_POWER_V1_ERROR_ENUM_IS_VALID */ - -/** - * @ingroup iface_zwlr_output_power_v1 - * @struct zwlr_output_power_v1_interface - */ -struct zwlr_output_power_v1_interface { - /** - * Set an outputs power save mode - * - * Set an output's power save mode to the given mode. The mode - * change is effective immediately. If the output does not support - * the given mode a failed event is sent. - * @param mode the power save mode to set - */ - void (*set_mode)(struct wl_client *client, - struct wl_resource *resource, - uint32_t mode); - /** - * destroy this power management - * - * Destroys the output power management mode control object. - */ - void (*destroy)(struct wl_client *client, - struct wl_resource *resource); -}; - -#define ZWLR_OUTPUT_POWER_V1_MODE 0 -#define ZWLR_OUTPUT_POWER_V1_FAILED 1 - -/** - * @ingroup iface_zwlr_output_power_v1 - */ -#define ZWLR_OUTPUT_POWER_V1_MODE_SINCE_VERSION 1 -/** - * @ingroup iface_zwlr_output_power_v1 - */ -#define ZWLR_OUTPUT_POWER_V1_FAILED_SINCE_VERSION 1 - -/** - * @ingroup iface_zwlr_output_power_v1 - */ -#define ZWLR_OUTPUT_POWER_V1_SET_MODE_SINCE_VERSION 1 -/** - * @ingroup iface_zwlr_output_power_v1 - */ -#define ZWLR_OUTPUT_POWER_V1_DESTROY_SINCE_VERSION 1 - -/** - * @ingroup iface_zwlr_output_power_v1 - * Sends an mode event to the client owning the resource. - * @param resource_ The client's resource - * @param mode the output's new power management mode - */ -static inline void -zwlr_output_power_v1_send_mode(struct wl_resource *resource_, uint32_t mode) -{ - wl_resource_post_event(resource_, ZWLR_OUTPUT_POWER_V1_MODE, mode); -} - -/** - * @ingroup iface_zwlr_output_power_v1 - * Sends an failed event to the client owning the resource. - * @param resource_ The client's resource - */ -static inline void -zwlr_output_power_v1_send_failed(struct wl_resource *resource_) -{ - wl_resource_post_event(resource_, ZWLR_OUTPUT_POWER_V1_FAILED); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/dwl/dwl-v0.7/xdg-shell-protocol.h b/dwl/dwl-v0.7/xdg-shell-protocol.h deleted file mode 100644 index 8c11cd0b..00000000 --- a/dwl/dwl-v0.7/xdg-shell-protocol.h +++ /dev/null @@ -1,2374 +0,0 @@ -/* Generated by wayland-scanner 1.24.0 */ - -#ifndef XDG_SHELL_SERVER_PROTOCOL_H -#define XDG_SHELL_SERVER_PROTOCOL_H - -#include -#include -#include "wayland-server.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct wl_client; -struct wl_resource; - -/** - * @page page_xdg_shell The xdg_shell protocol - * @section page_ifaces_xdg_shell Interfaces - * - @subpage page_iface_xdg_wm_base - create desktop-style surfaces - * - @subpage page_iface_xdg_positioner - child surface positioner - * - @subpage page_iface_xdg_surface - desktop user interface surface base interface - * - @subpage page_iface_xdg_toplevel - toplevel surface - * - @subpage page_iface_xdg_popup - short-lived, popup surfaces for menus - * @section page_copyright_xdg_shell Copyright - *
- *
- * Copyright © 2008-2013 Kristian Høgsberg
- * Copyright © 2013      Rafael Antognolli
- * Copyright © 2013      Jasper St. Pierre
- * Copyright © 2010-2013 Intel Corporation
- * Copyright © 2015-2017 Samsung Electronics Co., Ltd
- * Copyright © 2015-2017 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- * 
- */ -struct wl_output; -struct wl_seat; -struct wl_surface; -struct xdg_popup; -struct xdg_positioner; -struct xdg_surface; -struct xdg_toplevel; -struct xdg_wm_base; - -#ifndef XDG_WM_BASE_INTERFACE -#define XDG_WM_BASE_INTERFACE -/** - * @page page_iface_xdg_wm_base xdg_wm_base - * @section page_iface_xdg_wm_base_desc Description - * - * The xdg_wm_base interface is exposed as a global object enabling clients - * to turn their wl_surfaces into windows in a desktop environment. It - * defines the basic functionality needed for clients and the compositor to - * create windows that can be dragged, resized, maximized, etc, as well as - * creating transient windows such as popup menus. - * @section page_iface_xdg_wm_base_api API - * See @ref iface_xdg_wm_base. - */ -/** - * @defgroup iface_xdg_wm_base The xdg_wm_base interface - * - * The xdg_wm_base interface is exposed as a global object enabling clients - * to turn their wl_surfaces into windows in a desktop environment. It - * defines the basic functionality needed for clients and the compositor to - * create windows that can be dragged, resized, maximized, etc, as well as - * creating transient windows such as popup menus. - */ -extern const struct wl_interface xdg_wm_base_interface; -#endif -#ifndef XDG_POSITIONER_INTERFACE -#define XDG_POSITIONER_INTERFACE -/** - * @page page_iface_xdg_positioner xdg_positioner - * @section page_iface_xdg_positioner_desc Description - * - * The xdg_positioner provides a collection of rules for the placement of a - * child surface relative to a parent surface. Rules can be defined to ensure - * the child surface remains within the visible area's borders, and to - * specify how the child surface changes its position, such as sliding along - * an axis, or flipping around a rectangle. These positioner-created rules are - * constrained by the requirement that a child surface must intersect with or - * be at least partially adjacent to its parent surface. - * - * See the various requests for details about possible rules. - * - * At the time of the request, the compositor makes a copy of the rules - * specified by the xdg_positioner. Thus, after the request is complete the - * xdg_positioner object can be destroyed or reused; further changes to the - * object will have no effect on previous usages. - * - * For an xdg_positioner object to be considered complete, it must have a - * non-zero size set by set_size, and a non-zero anchor rectangle set by - * set_anchor_rect. Passing an incomplete xdg_positioner object when - * positioning a surface raises an invalid_positioner error. - * @section page_iface_xdg_positioner_api API - * See @ref iface_xdg_positioner. - */ -/** - * @defgroup iface_xdg_positioner The xdg_positioner interface - * - * The xdg_positioner provides a collection of rules for the placement of a - * child surface relative to a parent surface. Rules can be defined to ensure - * the child surface remains within the visible area's borders, and to - * specify how the child surface changes its position, such as sliding along - * an axis, or flipping around a rectangle. These positioner-created rules are - * constrained by the requirement that a child surface must intersect with or - * be at least partially adjacent to its parent surface. - * - * See the various requests for details about possible rules. - * - * At the time of the request, the compositor makes a copy of the rules - * specified by the xdg_positioner. Thus, after the request is complete the - * xdg_positioner object can be destroyed or reused; further changes to the - * object will have no effect on previous usages. - * - * For an xdg_positioner object to be considered complete, it must have a - * non-zero size set by set_size, and a non-zero anchor rectangle set by - * set_anchor_rect. Passing an incomplete xdg_positioner object when - * positioning a surface raises an invalid_positioner error. - */ -extern const struct wl_interface xdg_positioner_interface; -#endif -#ifndef XDG_SURFACE_INTERFACE -#define XDG_SURFACE_INTERFACE -/** - * @page page_iface_xdg_surface xdg_surface - * @section page_iface_xdg_surface_desc Description - * - * An interface that may be implemented by a wl_surface, for - * implementations that provide a desktop-style user interface. - * - * It provides a base set of functionality required to construct user - * interface elements requiring management by the compositor, such as - * toplevel windows, menus, etc. The types of functionality are split into - * xdg_surface roles. - * - * Creating an xdg_surface does not set the role for a wl_surface. In order - * to map an xdg_surface, the client must create a role-specific object - * using, e.g., get_toplevel, get_popup. The wl_surface for any given - * xdg_surface can have at most one role, and may not be assigned any role - * not based on xdg_surface. - * - * A role must be assigned before any other requests are made to the - * xdg_surface object. - * - * The client must call wl_surface.commit on the corresponding wl_surface - * for the xdg_surface state to take effect. - * - * Creating an xdg_surface from a wl_surface which has a buffer attached or - * committed is a client error, and any attempts by a client to attach or - * manipulate a buffer prior to the first xdg_surface.configure call must - * also be treated as errors. - * - * After creating a role-specific object and setting it up (e.g. by sending - * the title, app ID, size constraints, parent, etc), the client must - * perform an initial commit without any buffer attached. The compositor - * will reply with initial wl_surface state such as - * wl_surface.preferred_buffer_scale followed by an xdg_surface.configure - * event. The client must acknowledge it and is then allowed to attach a - * buffer to map the surface. - * - * Mapping an xdg_surface-based role surface is defined as making it - * possible for the surface to be shown by the compositor. Note that - * a mapped surface is not guaranteed to be visible once it is mapped. - * - * For an xdg_surface to be mapped by the compositor, the following - * conditions must be met: - * (1) the client has assigned an xdg_surface-based role to the surface - * (2) the client has set and committed the xdg_surface state and the - * role-dependent state to the surface - * (3) the client has committed a buffer to the surface - * - * A newly-unmapped surface is considered to have met condition (1) out - * of the 3 required conditions for mapping a surface if its role surface - * has not been destroyed, i.e. the client must perform the initial commit - * again before attaching a buffer. - * @section page_iface_xdg_surface_api API - * See @ref iface_xdg_surface. - */ -/** - * @defgroup iface_xdg_surface The xdg_surface interface - * - * An interface that may be implemented by a wl_surface, for - * implementations that provide a desktop-style user interface. - * - * It provides a base set of functionality required to construct user - * interface elements requiring management by the compositor, such as - * toplevel windows, menus, etc. The types of functionality are split into - * xdg_surface roles. - * - * Creating an xdg_surface does not set the role for a wl_surface. In order - * to map an xdg_surface, the client must create a role-specific object - * using, e.g., get_toplevel, get_popup. The wl_surface for any given - * xdg_surface can have at most one role, and may not be assigned any role - * not based on xdg_surface. - * - * A role must be assigned before any other requests are made to the - * xdg_surface object. - * - * The client must call wl_surface.commit on the corresponding wl_surface - * for the xdg_surface state to take effect. - * - * Creating an xdg_surface from a wl_surface which has a buffer attached or - * committed is a client error, and any attempts by a client to attach or - * manipulate a buffer prior to the first xdg_surface.configure call must - * also be treated as errors. - * - * After creating a role-specific object and setting it up (e.g. by sending - * the title, app ID, size constraints, parent, etc), the client must - * perform an initial commit without any buffer attached. The compositor - * will reply with initial wl_surface state such as - * wl_surface.preferred_buffer_scale followed by an xdg_surface.configure - * event. The client must acknowledge it and is then allowed to attach a - * buffer to map the surface. - * - * Mapping an xdg_surface-based role surface is defined as making it - * possible for the surface to be shown by the compositor. Note that - * a mapped surface is not guaranteed to be visible once it is mapped. - * - * For an xdg_surface to be mapped by the compositor, the following - * conditions must be met: - * (1) the client has assigned an xdg_surface-based role to the surface - * (2) the client has set and committed the xdg_surface state and the - * role-dependent state to the surface - * (3) the client has committed a buffer to the surface - * - * A newly-unmapped surface is considered to have met condition (1) out - * of the 3 required conditions for mapping a surface if its role surface - * has not been destroyed, i.e. the client must perform the initial commit - * again before attaching a buffer. - */ -extern const struct wl_interface xdg_surface_interface; -#endif -#ifndef XDG_TOPLEVEL_INTERFACE -#define XDG_TOPLEVEL_INTERFACE -/** - * @page page_iface_xdg_toplevel xdg_toplevel - * @section page_iface_xdg_toplevel_desc Description - * - * This interface defines an xdg_surface role which allows a surface to, - * among other things, set window-like properties such as maximize, - * fullscreen, and minimize, set application-specific metadata like title and - * id, and well as trigger user interactive operations such as interactive - * resize and move. - * - * A xdg_toplevel by default is responsible for providing the full intended - * visual representation of the toplevel, which depending on the window - * state, may mean things like a title bar, window controls and drop shadow. - * - * Unmapping an xdg_toplevel means that the surface cannot be shown - * by the compositor until it is explicitly mapped again. - * All active operations (e.g., move, resize) are canceled and all - * attributes (e.g. title, state, stacking, ...) are discarded for - * an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to - * the state it had right after xdg_surface.get_toplevel. The client - * can re-map the toplevel by performing a commit without any buffer - * attached, waiting for a configure event and handling it as usual (see - * xdg_surface description). - * - * Attaching a null buffer to a toplevel unmaps the surface. - * @section page_iface_xdg_toplevel_api API - * See @ref iface_xdg_toplevel. - */ -/** - * @defgroup iface_xdg_toplevel The xdg_toplevel interface - * - * This interface defines an xdg_surface role which allows a surface to, - * among other things, set window-like properties such as maximize, - * fullscreen, and minimize, set application-specific metadata like title and - * id, and well as trigger user interactive operations such as interactive - * resize and move. - * - * A xdg_toplevel by default is responsible for providing the full intended - * visual representation of the toplevel, which depending on the window - * state, may mean things like a title bar, window controls and drop shadow. - * - * Unmapping an xdg_toplevel means that the surface cannot be shown - * by the compositor until it is explicitly mapped again. - * All active operations (e.g., move, resize) are canceled and all - * attributes (e.g. title, state, stacking, ...) are discarded for - * an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to - * the state it had right after xdg_surface.get_toplevel. The client - * can re-map the toplevel by performing a commit without any buffer - * attached, waiting for a configure event and handling it as usual (see - * xdg_surface description). - * - * Attaching a null buffer to a toplevel unmaps the surface. - */ -extern const struct wl_interface xdg_toplevel_interface; -#endif -#ifndef XDG_POPUP_INTERFACE -#define XDG_POPUP_INTERFACE -/** - * @page page_iface_xdg_popup xdg_popup - * @section page_iface_xdg_popup_desc Description - * - * A popup surface is a short-lived, temporary surface. It can be used to - * implement for example menus, popovers, tooltips and other similar user - * interface concepts. - * - * A popup can be made to take an explicit grab. See xdg_popup.grab for - * details. - * - * When the popup is dismissed, a popup_done event will be sent out, and at - * the same time the surface will be unmapped. See the xdg_popup.popup_done - * event for details. - * - * Explicitly destroying the xdg_popup object will also dismiss the popup and - * unmap the surface. Clients that want to dismiss the popup when another - * surface of their own is clicked should dismiss the popup using the destroy - * request. - * - * A newly created xdg_popup will be stacked on top of all previously created - * xdg_popup surfaces associated with the same xdg_toplevel. - * - * The parent of an xdg_popup must be mapped (see the xdg_surface - * description) before the xdg_popup itself. - * - * The client must call wl_surface.commit on the corresponding wl_surface - * for the xdg_popup state to take effect. - * @section page_iface_xdg_popup_api API - * See @ref iface_xdg_popup. - */ -/** - * @defgroup iface_xdg_popup The xdg_popup interface - * - * A popup surface is a short-lived, temporary surface. It can be used to - * implement for example menus, popovers, tooltips and other similar user - * interface concepts. - * - * A popup can be made to take an explicit grab. See xdg_popup.grab for - * details. - * - * When the popup is dismissed, a popup_done event will be sent out, and at - * the same time the surface will be unmapped. See the xdg_popup.popup_done - * event for details. - * - * Explicitly destroying the xdg_popup object will also dismiss the popup and - * unmap the surface. Clients that want to dismiss the popup when another - * surface of their own is clicked should dismiss the popup using the destroy - * request. - * - * A newly created xdg_popup will be stacked on top of all previously created - * xdg_popup surfaces associated with the same xdg_toplevel. - * - * The parent of an xdg_popup must be mapped (see the xdg_surface - * description) before the xdg_popup itself. - * - * The client must call wl_surface.commit on the corresponding wl_surface - * for the xdg_popup state to take effect. - */ -extern const struct wl_interface xdg_popup_interface; -#endif - -#ifndef XDG_WM_BASE_ERROR_ENUM -#define XDG_WM_BASE_ERROR_ENUM -enum xdg_wm_base_error { - /** - * given wl_surface has another role - */ - XDG_WM_BASE_ERROR_ROLE = 0, - /** - * xdg_wm_base was destroyed before children - */ - XDG_WM_BASE_ERROR_DEFUNCT_SURFACES = 1, - /** - * the client tried to map or destroy a non-topmost popup - */ - XDG_WM_BASE_ERROR_NOT_THE_TOPMOST_POPUP = 2, - /** - * the client specified an invalid popup parent surface - */ - XDG_WM_BASE_ERROR_INVALID_POPUP_PARENT = 3, - /** - * the client provided an invalid surface state - */ - XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE = 4, - /** - * the client provided an invalid positioner - */ - XDG_WM_BASE_ERROR_INVALID_POSITIONER = 5, - /** - * the client didn’t respond to a ping event in time - */ - XDG_WM_BASE_ERROR_UNRESPONSIVE = 6, -}; -#endif /* XDG_WM_BASE_ERROR_ENUM */ - -#ifndef XDG_WM_BASE_ERROR_ENUM_IS_VALID -#define XDG_WM_BASE_ERROR_ENUM_IS_VALID -/** - * @ingroup iface_xdg_wm_base - * Validate a xdg_wm_base error value. - * - * @return true on success, false on error. - * @ref xdg_wm_base_error - */ -static inline bool -xdg_wm_base_error_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case XDG_WM_BASE_ERROR_ROLE: - return version >= 1; - case XDG_WM_BASE_ERROR_DEFUNCT_SURFACES: - return version >= 1; - case XDG_WM_BASE_ERROR_NOT_THE_TOPMOST_POPUP: - return version >= 1; - case XDG_WM_BASE_ERROR_INVALID_POPUP_PARENT: - return version >= 1; - case XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE: - return version >= 1; - case XDG_WM_BASE_ERROR_INVALID_POSITIONER: - return version >= 1; - case XDG_WM_BASE_ERROR_UNRESPONSIVE: - return version >= 1; - default: - return false; - } -} -#endif /* XDG_WM_BASE_ERROR_ENUM_IS_VALID */ - -/** - * @ingroup iface_xdg_wm_base - * @struct xdg_wm_base_interface - */ -struct xdg_wm_base_interface { - /** - * destroy xdg_wm_base - * - * Destroy this xdg_wm_base object. - * - * Destroying a bound xdg_wm_base object while there are surfaces - * still alive created by this xdg_wm_base object instance is - * illegal and will result in a defunct_surfaces error. - */ - void (*destroy)(struct wl_client *client, - struct wl_resource *resource); - /** - * create a positioner object - * - * Create a positioner object. A positioner object is used to - * position surfaces relative to some parent surface. See the - * interface description and xdg_surface.get_popup for details. - */ - void (*create_positioner)(struct wl_client *client, - struct wl_resource *resource, - uint32_t id); - /** - * create a shell surface from a surface - * - * This creates an xdg_surface for the given surface. While - * xdg_surface itself is not a role, the corresponding surface may - * only be assigned a role extending xdg_surface, such as - * xdg_toplevel or xdg_popup. It is illegal to create an - * xdg_surface for a wl_surface which already has an assigned role - * and this will result in a role error. - * - * This creates an xdg_surface for the given surface. An - * xdg_surface is used as basis to define a role to a given - * surface, such as xdg_toplevel or xdg_popup. It also manages - * functionality shared between xdg_surface based surface roles. - * - * See the documentation of xdg_surface for more details about what - * an xdg_surface is and how it is used. - */ - void (*get_xdg_surface)(struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *surface); - /** - * respond to a ping event - * - * A client must respond to a ping event with a pong request or - * the client may be deemed unresponsive. See xdg_wm_base.ping and - * xdg_wm_base.error.unresponsive. - * @param serial serial of the ping event - */ - void (*pong)(struct wl_client *client, - struct wl_resource *resource, - uint32_t serial); -}; - -#define XDG_WM_BASE_PING 0 - -/** - * @ingroup iface_xdg_wm_base - */ -#define XDG_WM_BASE_PING_SINCE_VERSION 1 - -/** - * @ingroup iface_xdg_wm_base - */ -#define XDG_WM_BASE_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_wm_base - */ -#define XDG_WM_BASE_CREATE_POSITIONER_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_wm_base - */ -#define XDG_WM_BASE_GET_XDG_SURFACE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_wm_base - */ -#define XDG_WM_BASE_PONG_SINCE_VERSION 1 - -/** - * @ingroup iface_xdg_wm_base - * Sends an ping event to the client owning the resource. - * @param resource_ The client's resource - * @param serial pass this to the pong request - */ -static inline void -xdg_wm_base_send_ping(struct wl_resource *resource_, uint32_t serial) -{ - wl_resource_post_event(resource_, XDG_WM_BASE_PING, serial); -} - -#ifndef XDG_POSITIONER_ERROR_ENUM -#define XDG_POSITIONER_ERROR_ENUM -enum xdg_positioner_error { - /** - * invalid input provided - */ - XDG_POSITIONER_ERROR_INVALID_INPUT = 0, -}; -#endif /* XDG_POSITIONER_ERROR_ENUM */ - -#ifndef XDG_POSITIONER_ERROR_ENUM_IS_VALID -#define XDG_POSITIONER_ERROR_ENUM_IS_VALID -/** - * @ingroup iface_xdg_positioner - * Validate a xdg_positioner error value. - * - * @return true on success, false on error. - * @ref xdg_positioner_error - */ -static inline bool -xdg_positioner_error_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case XDG_POSITIONER_ERROR_INVALID_INPUT: - return version >= 1; - default: - return false; - } -} -#endif /* XDG_POSITIONER_ERROR_ENUM_IS_VALID */ - -#ifndef XDG_POSITIONER_ANCHOR_ENUM -#define XDG_POSITIONER_ANCHOR_ENUM -enum xdg_positioner_anchor { - XDG_POSITIONER_ANCHOR_NONE = 0, - XDG_POSITIONER_ANCHOR_TOP = 1, - XDG_POSITIONER_ANCHOR_BOTTOM = 2, - XDG_POSITIONER_ANCHOR_LEFT = 3, - XDG_POSITIONER_ANCHOR_RIGHT = 4, - XDG_POSITIONER_ANCHOR_TOP_LEFT = 5, - XDG_POSITIONER_ANCHOR_BOTTOM_LEFT = 6, - XDG_POSITIONER_ANCHOR_TOP_RIGHT = 7, - XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT = 8, -}; -#endif /* XDG_POSITIONER_ANCHOR_ENUM */ - -#ifndef XDG_POSITIONER_ANCHOR_ENUM_IS_VALID -#define XDG_POSITIONER_ANCHOR_ENUM_IS_VALID -/** - * @ingroup iface_xdg_positioner - * Validate a xdg_positioner anchor value. - * - * @return true on success, false on error. - * @ref xdg_positioner_anchor - */ -static inline bool -xdg_positioner_anchor_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case XDG_POSITIONER_ANCHOR_NONE: - return version >= 1; - case XDG_POSITIONER_ANCHOR_TOP: - return version >= 1; - case XDG_POSITIONER_ANCHOR_BOTTOM: - return version >= 1; - case XDG_POSITIONER_ANCHOR_LEFT: - return version >= 1; - case XDG_POSITIONER_ANCHOR_RIGHT: - return version >= 1; - case XDG_POSITIONER_ANCHOR_TOP_LEFT: - return version >= 1; - case XDG_POSITIONER_ANCHOR_BOTTOM_LEFT: - return version >= 1; - case XDG_POSITIONER_ANCHOR_TOP_RIGHT: - return version >= 1; - case XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT: - return version >= 1; - default: - return false; - } -} -#endif /* XDG_POSITIONER_ANCHOR_ENUM_IS_VALID */ - -#ifndef XDG_POSITIONER_GRAVITY_ENUM -#define XDG_POSITIONER_GRAVITY_ENUM -enum xdg_positioner_gravity { - XDG_POSITIONER_GRAVITY_NONE = 0, - XDG_POSITIONER_GRAVITY_TOP = 1, - XDG_POSITIONER_GRAVITY_BOTTOM = 2, - XDG_POSITIONER_GRAVITY_LEFT = 3, - XDG_POSITIONER_GRAVITY_RIGHT = 4, - XDG_POSITIONER_GRAVITY_TOP_LEFT = 5, - XDG_POSITIONER_GRAVITY_BOTTOM_LEFT = 6, - XDG_POSITIONER_GRAVITY_TOP_RIGHT = 7, - XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT = 8, -}; -#endif /* XDG_POSITIONER_GRAVITY_ENUM */ - -#ifndef XDG_POSITIONER_GRAVITY_ENUM_IS_VALID -#define XDG_POSITIONER_GRAVITY_ENUM_IS_VALID -/** - * @ingroup iface_xdg_positioner - * Validate a xdg_positioner gravity value. - * - * @return true on success, false on error. - * @ref xdg_positioner_gravity - */ -static inline bool -xdg_positioner_gravity_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case XDG_POSITIONER_GRAVITY_NONE: - return version >= 1; - case XDG_POSITIONER_GRAVITY_TOP: - return version >= 1; - case XDG_POSITIONER_GRAVITY_BOTTOM: - return version >= 1; - case XDG_POSITIONER_GRAVITY_LEFT: - return version >= 1; - case XDG_POSITIONER_GRAVITY_RIGHT: - return version >= 1; - case XDG_POSITIONER_GRAVITY_TOP_LEFT: - return version >= 1; - case XDG_POSITIONER_GRAVITY_BOTTOM_LEFT: - return version >= 1; - case XDG_POSITIONER_GRAVITY_TOP_RIGHT: - return version >= 1; - case XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT: - return version >= 1; - default: - return false; - } -} -#endif /* XDG_POSITIONER_GRAVITY_ENUM_IS_VALID */ - -#ifndef XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM -#define XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM -/** - * @ingroup iface_xdg_positioner - * constraint adjustments - * - * The constraint adjustment value define ways the compositor will adjust - * the position of the surface, if the unadjusted position would result - * in the surface being partly constrained. - * - * Whether a surface is considered 'constrained' is left to the compositor - * to determine. For example, the surface may be partly outside the - * compositor's defined 'work area', thus necessitating the child surface's - * position be adjusted until it is entirely inside the work area. - * - * The adjustments can be combined, according to a defined precedence: 1) - * Flip, 2) Slide, 3) Resize. - */ -enum xdg_positioner_constraint_adjustment { - /** - * don't move the child surface when constrained - * - * Don't alter the surface position even if it is constrained on - * some axis, for example partially outside the edge of an output. - */ - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_NONE = 0, - /** - * move along the x axis until unconstrained - * - * Slide the surface along the x axis until it is no longer - * constrained. - * - * First try to slide towards the direction of the gravity on the x - * axis until either the edge in the opposite direction of the - * gravity is unconstrained or the edge in the direction of the - * gravity is constrained. - * - * Then try to slide towards the opposite direction of the gravity - * on the x axis until either the edge in the direction of the - * gravity is unconstrained or the edge in the opposite direction - * of the gravity is constrained. - */ - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X = 1, - /** - * move along the y axis until unconstrained - * - * Slide the surface along the y axis until it is no longer - * constrained. - * - * First try to slide towards the direction of the gravity on the y - * axis until either the edge in the opposite direction of the - * gravity is unconstrained or the edge in the direction of the - * gravity is constrained. - * - * Then try to slide towards the opposite direction of the gravity - * on the y axis until either the edge in the direction of the - * gravity is unconstrained or the edge in the opposite direction - * of the gravity is constrained. - */ - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y = 2, - /** - * invert the anchor and gravity on the x axis - * - * Invert the anchor and gravity on the x axis if the surface is - * constrained on the x axis. For example, if the left edge of the - * surface is constrained, the gravity is 'left' and the anchor is - * 'left', change the gravity to 'right' and the anchor to 'right'. - * - * If the adjusted position also ends up being constrained, the - * resulting position of the flip_x adjustment will be the one - * before the adjustment. - */ - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X = 4, - /** - * invert the anchor and gravity on the y axis - * - * Invert the anchor and gravity on the y axis if the surface is - * constrained on the y axis. For example, if the bottom edge of - * the surface is constrained, the gravity is 'bottom' and the - * anchor is 'bottom', change the gravity to 'top' and the anchor - * to 'top'. - * - * The adjusted position is calculated given the original anchor - * rectangle and offset, but with the new flipped anchor and - * gravity values. - * - * If the adjusted position also ends up being constrained, the - * resulting position of the flip_y adjustment will be the one - * before the adjustment. - */ - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y = 8, - /** - * horizontally resize the surface - * - * Resize the surface horizontally so that it is completely - * unconstrained. - */ - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X = 16, - /** - * vertically resize the surface - * - * Resize the surface vertically so that it is completely - * unconstrained. - */ - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y = 32, -}; -#endif /* XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM */ - -#ifndef XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM_IS_VALID -#define XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM_IS_VALID -/** - * @ingroup iface_xdg_positioner - * Validate a xdg_positioner constraint_adjustment value. - * - * @return true on success, false on error. - * @ref xdg_positioner_constraint_adjustment - */ -static inline bool -xdg_positioner_constraint_adjustment_is_valid(uint32_t value, uint32_t version) { - uint32_t valid = 0; - if (version >= 1) - valid |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_NONE; - if (version >= 1) - valid |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X; - if (version >= 1) - valid |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y; - if (version >= 1) - valid |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X; - if (version >= 1) - valid |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y; - if (version >= 1) - valid |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X; - if (version >= 1) - valid |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y; - return (value & ~valid) == 0; -} -#endif /* XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM_IS_VALID */ - -/** - * @ingroup iface_xdg_positioner - * @struct xdg_positioner_interface - */ -struct xdg_positioner_interface { - /** - * destroy the xdg_positioner object - * - * Notify the compositor that the xdg_positioner will no longer - * be used. - */ - void (*destroy)(struct wl_client *client, - struct wl_resource *resource); - /** - * set the size of the to-be positioned rectangle - * - * Set the size of the surface that is to be positioned with the - * positioner object. The size is in surface-local coordinates and - * corresponds to the window geometry. See - * xdg_surface.set_window_geometry. - * - * If a zero or negative size is set the invalid_input error is - * raised. - * @param width width of positioned rectangle - * @param height height of positioned rectangle - */ - void (*set_size)(struct wl_client *client, - struct wl_resource *resource, - int32_t width, - int32_t height); - /** - * set the anchor rectangle within the parent surface - * - * Specify the anchor rectangle within the parent surface that - * the child surface will be placed relative to. The rectangle is - * relative to the window geometry as defined by - * xdg_surface.set_window_geometry of the parent surface. - * - * When the xdg_positioner object is used to position a child - * surface, the anchor rectangle may not extend outside the window - * geometry of the positioned child's parent surface. - * - * If a negative size is set the invalid_input error is raised. - * @param x x position of anchor rectangle - * @param y y position of anchor rectangle - * @param width width of anchor rectangle - * @param height height of anchor rectangle - */ - void (*set_anchor_rect)(struct wl_client *client, - struct wl_resource *resource, - int32_t x, - int32_t y, - int32_t width, - int32_t height); - /** - * set anchor rectangle anchor - * - * Defines the anchor point for the anchor rectangle. The - * specified anchor is used derive an anchor point that the child - * surface will be positioned relative to. If a corner anchor is - * set (e.g. 'top_left' or 'bottom_right'), the anchor point will - * be at the specified corner; otherwise, the derived anchor point - * will be centered on the specified edge, or in the center of the - * anchor rectangle if no edge is specified. - * @param anchor anchor - */ - void (*set_anchor)(struct wl_client *client, - struct wl_resource *resource, - uint32_t anchor); - /** - * set child surface gravity - * - * Defines in what direction a surface should be positioned, - * relative to the anchor point of the parent surface. If a corner - * gravity is specified (e.g. 'bottom_right' or 'top_left'), then - * the child surface will be placed towards the specified gravity; - * otherwise, the child surface will be centered over the anchor - * point on any axis that had no gravity specified. If the gravity - * is not in the ‘gravity’ enum, an invalid_input error is - * raised. - * @param gravity gravity direction - */ - void (*set_gravity)(struct wl_client *client, - struct wl_resource *resource, - uint32_t gravity); - /** - * set the adjustment to be done when constrained - * - * Specify how the window should be positioned if the originally - * intended position caused the surface to be constrained, meaning - * at least partially outside positioning boundaries set by the - * compositor. The adjustment is set by constructing a bitmask - * describing the adjustment to be made when the surface is - * constrained on that axis. - * - * If no bit for one axis is set, the compositor will assume that - * the child surface should not change its position on that axis - * when constrained. - * - * If more than one bit for one axis is set, the order of how - * adjustments are applied is specified in the corresponding - * adjustment descriptions. - * - * The default adjustment is none. - * @param constraint_adjustment bit mask of constraint adjustments - */ - void (*set_constraint_adjustment)(struct wl_client *client, - struct wl_resource *resource, - uint32_t constraint_adjustment); - /** - * set surface position offset - * - * Specify the surface position offset relative to the position - * of the anchor on the anchor rectangle and the anchor on the - * surface. For example if the anchor of the anchor rectangle is at - * (x, y), the surface has the gravity bottom|right, and the offset - * is (ox, oy), the calculated surface position will be (x + ox, y - * + oy). The offset position of the surface is the one used for - * constraint testing. See set_constraint_adjustment. - * - * An example use case is placing a popup menu on top of a user - * interface element, while aligning the user interface element of - * the parent surface with some user interface element placed - * somewhere in the popup surface. - * @param x surface position x offset - * @param y surface position y offset - */ - void (*set_offset)(struct wl_client *client, - struct wl_resource *resource, - int32_t x, - int32_t y); - /** - * continuously reconstrain the surface - * - * When set reactive, the surface is reconstrained if the - * conditions used for constraining changed, e.g. the parent window - * moved. - * - * If the conditions changed and the popup was reconstrained, an - * xdg_popup.configure event is sent with updated geometry, - * followed by an xdg_surface.configure event. - * @since 3 - */ - void (*set_reactive)(struct wl_client *client, - struct wl_resource *resource); - /** - * - * - * Set the parent window geometry the compositor should use when - * positioning the popup. The compositor may use this information - * to determine the future state the popup should be constrained - * using. If this doesn't match the dimension of the parent the - * popup is eventually positioned against, the behavior is - * undefined. - * - * The arguments are given in the surface-local coordinate space. - * @param parent_width future window geometry width of parent - * @param parent_height future window geometry height of parent - * @since 3 - */ - void (*set_parent_size)(struct wl_client *client, - struct wl_resource *resource, - int32_t parent_width, - int32_t parent_height); - /** - * set parent configure this is a response to - * - * Set the serial of an xdg_surface.configure event this - * positioner will be used in response to. The compositor may use - * this information together with set_parent_size to determine what - * future state the popup should be constrained using. - * @param serial serial of parent configure event - * @since 3 - */ - void (*set_parent_configure)(struct wl_client *client, - struct wl_resource *resource, - uint32_t serial); -}; - - -/** - * @ingroup iface_xdg_positioner - */ -#define XDG_POSITIONER_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_positioner - */ -#define XDG_POSITIONER_SET_SIZE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_positioner - */ -#define XDG_POSITIONER_SET_ANCHOR_RECT_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_positioner - */ -#define XDG_POSITIONER_SET_ANCHOR_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_positioner - */ -#define XDG_POSITIONER_SET_GRAVITY_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_positioner - */ -#define XDG_POSITIONER_SET_CONSTRAINT_ADJUSTMENT_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_positioner - */ -#define XDG_POSITIONER_SET_OFFSET_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_positioner - */ -#define XDG_POSITIONER_SET_REACTIVE_SINCE_VERSION 3 -/** - * @ingroup iface_xdg_positioner - */ -#define XDG_POSITIONER_SET_PARENT_SIZE_SINCE_VERSION 3 -/** - * @ingroup iface_xdg_positioner - */ -#define XDG_POSITIONER_SET_PARENT_CONFIGURE_SINCE_VERSION 3 - -#ifndef XDG_SURFACE_ERROR_ENUM -#define XDG_SURFACE_ERROR_ENUM -enum xdg_surface_error { - /** - * Surface was not fully constructed - */ - XDG_SURFACE_ERROR_NOT_CONSTRUCTED = 1, - /** - * Surface was already constructed - */ - XDG_SURFACE_ERROR_ALREADY_CONSTRUCTED = 2, - /** - * Attaching a buffer to an unconfigured surface - */ - XDG_SURFACE_ERROR_UNCONFIGURED_BUFFER = 3, - /** - * Invalid serial number when acking a configure event - */ - XDG_SURFACE_ERROR_INVALID_SERIAL = 4, - /** - * Width or height was zero or negative - */ - XDG_SURFACE_ERROR_INVALID_SIZE = 5, - /** - * Surface was destroyed before its role object - */ - XDG_SURFACE_ERROR_DEFUNCT_ROLE_OBJECT = 6, -}; -#endif /* XDG_SURFACE_ERROR_ENUM */ - -#ifndef XDG_SURFACE_ERROR_ENUM_IS_VALID -#define XDG_SURFACE_ERROR_ENUM_IS_VALID -/** - * @ingroup iface_xdg_surface - * Validate a xdg_surface error value. - * - * @return true on success, false on error. - * @ref xdg_surface_error - */ -static inline bool -xdg_surface_error_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case XDG_SURFACE_ERROR_NOT_CONSTRUCTED: - return version >= 1; - case XDG_SURFACE_ERROR_ALREADY_CONSTRUCTED: - return version >= 1; - case XDG_SURFACE_ERROR_UNCONFIGURED_BUFFER: - return version >= 1; - case XDG_SURFACE_ERROR_INVALID_SERIAL: - return version >= 1; - case XDG_SURFACE_ERROR_INVALID_SIZE: - return version >= 1; - case XDG_SURFACE_ERROR_DEFUNCT_ROLE_OBJECT: - return version >= 1; - default: - return false; - } -} -#endif /* XDG_SURFACE_ERROR_ENUM_IS_VALID */ - -/** - * @ingroup iface_xdg_surface - * @struct xdg_surface_interface - */ -struct xdg_surface_interface { - /** - * destroy the xdg_surface - * - * Destroy the xdg_surface object. An xdg_surface must only be - * destroyed after its role object has been destroyed, otherwise a - * defunct_role_object error is raised. - */ - void (*destroy)(struct wl_client *client, - struct wl_resource *resource); - /** - * assign the xdg_toplevel surface role - * - * This creates an xdg_toplevel object for the given xdg_surface - * and gives the associated wl_surface the xdg_toplevel role. - * - * See the documentation of xdg_toplevel for more details about - * what an xdg_toplevel is and how it is used. - */ - void (*get_toplevel)(struct wl_client *client, - struct wl_resource *resource, - uint32_t id); - /** - * assign the xdg_popup surface role - * - * This creates an xdg_popup object for the given xdg_surface and - * gives the associated wl_surface the xdg_popup role. - * - * If null is passed as a parent, a parent surface must be - * specified using some other protocol, before committing the - * initial state. - * - * See the documentation of xdg_popup for more details about what - * an xdg_popup is and how it is used. - */ - void (*get_popup)(struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *parent, - struct wl_resource *positioner); - /** - * set the new window geometry - * - * The window geometry of a surface is its "visible bounds" from - * the user's perspective. Client-side decorations often have - * invisible portions like drop-shadows which should be ignored for - * the purposes of aligning, placing and constraining windows. Note - * that in some situations, compositors may clip rendering to the - * window geometry, so the client should avoid putting functional - * elements outside of it. - * - * The window geometry is double-buffered state, see - * wl_surface.commit. - * - * When maintaining a position, the compositor should treat the (x, - * y) coordinate of the window geometry as the top left corner of - * the window. A client changing the (x, y) window geometry - * coordinate should in general not alter the position of the - * window. - * - * Once the window geometry of the surface is set, it is not - * possible to unset it, and it will remain the same until - * set_window_geometry is called again, even if a new subsurface or - * buffer is attached. - * - * If never set, the value is the full bounds of the surface, - * including any subsurfaces. This updates dynamically on every - * commit. This unset is meant for extremely simple clients. - * - * The arguments are given in the surface-local coordinate space of - * the wl_surface associated with this xdg_surface, and may extend - * outside of the wl_surface itself to mark parts of the subsurface - * tree as part of the window geometry. - * - * When applied, the effective window geometry will be the set - * window geometry clamped to the bounding rectangle of the - * combined geometry of the surface of the xdg_surface and the - * associated subsurfaces. - * - * The effective geometry will not be recalculated unless a new - * call to set_window_geometry is done and the new pending surface - * state is subsequently applied. - * - * The width and height of the effective window geometry must be - * greater than zero. Setting an invalid size will raise an - * invalid_size error. - */ - void (*set_window_geometry)(struct wl_client *client, - struct wl_resource *resource, - int32_t x, - int32_t y, - int32_t width, - int32_t height); - /** - * ack a configure event - * - * When a configure event is received, if a client commits the - * surface in response to the configure event, then the client must - * make an ack_configure request sometime before the commit - * request, passing along the serial of the configure event. - * - * For instance, for toplevel surfaces the compositor might use - * this information to move a surface to the top left only when the - * client has drawn itself for the maximized or fullscreen state. - * - * If the client receives multiple configure events before it can - * respond to one, it only has to ack the last configure event. - * Acking a configure event that was never sent raises an - * invalid_serial error. - * - * A client is not required to commit immediately after sending an - * ack_configure request - it may even ack_configure several times - * before its next surface commit. - * - * A client may send multiple ack_configure requests before - * committing, but only the last request sent before a commit - * indicates which configure event the client really is responding - * to. - * - * Sending an ack_configure request consumes the serial number sent - * with the request, as well as serial numbers sent by all - * configure events sent on this xdg_surface prior to the configure - * event referenced by the committed serial. - * - * It is an error to issue multiple ack_configure requests - * referencing a serial from the same configure event, or to issue - * an ack_configure request referencing a serial from a configure - * event issued before the event identified by the last - * ack_configure request for the same xdg_surface. Doing so will - * raise an invalid_serial error. - * @param serial the serial from the configure event - */ - void (*ack_configure)(struct wl_client *client, - struct wl_resource *resource, - uint32_t serial); -}; - -#define XDG_SURFACE_CONFIGURE 0 - -/** - * @ingroup iface_xdg_surface - */ -#define XDG_SURFACE_CONFIGURE_SINCE_VERSION 1 - -/** - * @ingroup iface_xdg_surface - */ -#define XDG_SURFACE_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_surface - */ -#define XDG_SURFACE_GET_TOPLEVEL_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_surface - */ -#define XDG_SURFACE_GET_POPUP_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_surface - */ -#define XDG_SURFACE_SET_WINDOW_GEOMETRY_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_surface - */ -#define XDG_SURFACE_ACK_CONFIGURE_SINCE_VERSION 1 - -/** - * @ingroup iface_xdg_surface - * Sends an configure event to the client owning the resource. - * @param resource_ The client's resource - * @param serial serial of the configure event - */ -static inline void -xdg_surface_send_configure(struct wl_resource *resource_, uint32_t serial) -{ - wl_resource_post_event(resource_, XDG_SURFACE_CONFIGURE, serial); -} - -#ifndef XDG_TOPLEVEL_ERROR_ENUM -#define XDG_TOPLEVEL_ERROR_ENUM -enum xdg_toplevel_error { - /** - * provided value is not a valid variant of the resize_edge enum - */ - XDG_TOPLEVEL_ERROR_INVALID_RESIZE_EDGE = 0, - /** - * invalid parent toplevel - */ - XDG_TOPLEVEL_ERROR_INVALID_PARENT = 1, - /** - * client provided an invalid min or max size - */ - XDG_TOPLEVEL_ERROR_INVALID_SIZE = 2, -}; -#endif /* XDG_TOPLEVEL_ERROR_ENUM */ - -#ifndef XDG_TOPLEVEL_ERROR_ENUM_IS_VALID -#define XDG_TOPLEVEL_ERROR_ENUM_IS_VALID -/** - * @ingroup iface_xdg_toplevel - * Validate a xdg_toplevel error value. - * - * @return true on success, false on error. - * @ref xdg_toplevel_error - */ -static inline bool -xdg_toplevel_error_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case XDG_TOPLEVEL_ERROR_INVALID_RESIZE_EDGE: - return version >= 1; - case XDG_TOPLEVEL_ERROR_INVALID_PARENT: - return version >= 1; - case XDG_TOPLEVEL_ERROR_INVALID_SIZE: - return version >= 1; - default: - return false; - } -} -#endif /* XDG_TOPLEVEL_ERROR_ENUM_IS_VALID */ - -#ifndef XDG_TOPLEVEL_RESIZE_EDGE_ENUM -#define XDG_TOPLEVEL_RESIZE_EDGE_ENUM -/** - * @ingroup iface_xdg_toplevel - * edge values for resizing - * - * These values are used to indicate which edge of a surface - * is being dragged in a resize operation. - */ -enum xdg_toplevel_resize_edge { - XDG_TOPLEVEL_RESIZE_EDGE_NONE = 0, - XDG_TOPLEVEL_RESIZE_EDGE_TOP = 1, - XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM = 2, - XDG_TOPLEVEL_RESIZE_EDGE_LEFT = 4, - XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT = 5, - XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT = 6, - XDG_TOPLEVEL_RESIZE_EDGE_RIGHT = 8, - XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT = 9, - XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT = 10, -}; -#endif /* XDG_TOPLEVEL_RESIZE_EDGE_ENUM */ - -#ifndef XDG_TOPLEVEL_RESIZE_EDGE_ENUM_IS_VALID -#define XDG_TOPLEVEL_RESIZE_EDGE_ENUM_IS_VALID -/** - * @ingroup iface_xdg_toplevel - * Validate a xdg_toplevel resize_edge value. - * - * @return true on success, false on error. - * @ref xdg_toplevel_resize_edge - */ -static inline bool -xdg_toplevel_resize_edge_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case XDG_TOPLEVEL_RESIZE_EDGE_NONE: - return version >= 1; - case XDG_TOPLEVEL_RESIZE_EDGE_TOP: - return version >= 1; - case XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM: - return version >= 1; - case XDG_TOPLEVEL_RESIZE_EDGE_LEFT: - return version >= 1; - case XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT: - return version >= 1; - case XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT: - return version >= 1; - case XDG_TOPLEVEL_RESIZE_EDGE_RIGHT: - return version >= 1; - case XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT: - return version >= 1; - case XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT: - return version >= 1; - default: - return false; - } -} -#endif /* XDG_TOPLEVEL_RESIZE_EDGE_ENUM_IS_VALID */ - -#ifndef XDG_TOPLEVEL_STATE_ENUM -#define XDG_TOPLEVEL_STATE_ENUM -/** - * @ingroup iface_xdg_toplevel - * types of state on the surface - * - * The different state values used on the surface. This is designed for - * state values like maximized, fullscreen. It is paired with the - * configure event to ensure that both the client and the compositor - * setting the state can be synchronized. - * - * States set in this way are double-buffered, see wl_surface.commit. - */ -enum xdg_toplevel_state { - /** - * the surface is maximized - * the surface is maximized - * - * The surface is maximized. The window geometry specified in the - * configure event must be obeyed by the client, or the - * xdg_wm_base.invalid_surface_state error is raised. - * - * The client should draw without shadow or other decoration - * outside of the window geometry. - */ - XDG_TOPLEVEL_STATE_MAXIMIZED = 1, - /** - * the surface is fullscreen - * the surface is fullscreen - * - * The surface is fullscreen. The window geometry specified in - * the configure event is a maximum; the client cannot resize - * beyond it. For a surface to cover the whole fullscreened area, - * the geometry dimensions must be obeyed by the client. For more - * details, see xdg_toplevel.set_fullscreen. - */ - XDG_TOPLEVEL_STATE_FULLSCREEN = 2, - /** - * the surface is being resized - * the surface is being resized - * - * The surface is being resized. The window geometry specified in - * the configure event is a maximum; the client cannot resize - * beyond it. Clients that have aspect ratio or cell sizing - * configuration can use a smaller size, however. - */ - XDG_TOPLEVEL_STATE_RESIZING = 3, - /** - * the surface is now activated - * the surface is now activated - * - * Client window decorations should be painted as if the window - * is active. Do not assume this means that the window actually has - * keyboard or pointer focus. - */ - XDG_TOPLEVEL_STATE_ACTIVATED = 4, - /** - * the surface’s left edge is tiled - * - * The window is currently in a tiled layout and the left edge is - * considered to be adjacent to another part of the tiling grid. - * - * The client should draw without shadow or other decoration - * outside of the window geometry on the left edge. - * @since 2 - */ - XDG_TOPLEVEL_STATE_TILED_LEFT = 5, - /** - * the surface’s right edge is tiled - * - * The window is currently in a tiled layout and the right edge - * is considered to be adjacent to another part of the tiling grid. - * - * The client should draw without shadow or other decoration - * outside of the window geometry on the right edge. - * @since 2 - */ - XDG_TOPLEVEL_STATE_TILED_RIGHT = 6, - /** - * the surface’s top edge is tiled - * - * The window is currently in a tiled layout and the top edge is - * considered to be adjacent to another part of the tiling grid. - * - * The client should draw without shadow or other decoration - * outside of the window geometry on the top edge. - * @since 2 - */ - XDG_TOPLEVEL_STATE_TILED_TOP = 7, - /** - * the surface’s bottom edge is tiled - * - * The window is currently in a tiled layout and the bottom edge - * is considered to be adjacent to another part of the tiling grid. - * - * The client should draw without shadow or other decoration - * outside of the window geometry on the bottom edge. - * @since 2 - */ - XDG_TOPLEVEL_STATE_TILED_BOTTOM = 8, - /** - * surface repaint is suspended - * - * The surface is currently not ordinarily being repainted; for - * example because its content is occluded by another window, or - * its outputs are switched off due to screen locking. - * @since 6 - */ - XDG_TOPLEVEL_STATE_SUSPENDED = 9, - /** - * the surface’s left edge is constrained - * - * The left edge of the window is currently constrained, meaning - * it shouldn't attempt to resize from that edge. It can for - * example mean it's tiled next to a monitor edge on the - * constrained side of the window. - * @since 7 - */ - XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT = 10, - /** - * the surface’s right edge is constrained - * - * The right edge of the window is currently constrained, meaning - * it shouldn't attempt to resize from that edge. It can for - * example mean it's tiled next to a monitor edge on the - * constrained side of the window. - * @since 7 - */ - XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT = 11, - /** - * the surface’s top edge is constrained - * - * The top edge of the window is currently constrained, meaning - * it shouldn't attempt to resize from that edge. It can for - * example mean it's tiled next to a monitor edge on the - * constrained side of the window. - * @since 7 - */ - XDG_TOPLEVEL_STATE_CONSTRAINED_TOP = 12, - /** - * the surface’s bottom edge is constrained - * - * The bottom edge of the window is currently constrained, - * meaning it shouldn't attempt to resize from that edge. It can - * for example mean it's tiled next to a monitor edge on the - * constrained side of the window. - * @since 7 - */ - XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM = 13, -}; -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION 2 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION 2 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_STATE_TILED_TOP_SINCE_VERSION 2 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_STATE_TILED_BOTTOM_SINCE_VERSION 2 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION 6 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT_SINCE_VERSION 7 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT_SINCE_VERSION 7 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_STATE_CONSTRAINED_TOP_SINCE_VERSION 7 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM_SINCE_VERSION 7 -#endif /* XDG_TOPLEVEL_STATE_ENUM */ - -#ifndef XDG_TOPLEVEL_STATE_ENUM_IS_VALID -#define XDG_TOPLEVEL_STATE_ENUM_IS_VALID -/** - * @ingroup iface_xdg_toplevel - * Validate a xdg_toplevel state value. - * - * @return true on success, false on error. - * @ref xdg_toplevel_state - */ -static inline bool -xdg_toplevel_state_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case XDG_TOPLEVEL_STATE_MAXIMIZED: - return version >= 1; - case XDG_TOPLEVEL_STATE_FULLSCREEN: - return version >= 1; - case XDG_TOPLEVEL_STATE_RESIZING: - return version >= 1; - case XDG_TOPLEVEL_STATE_ACTIVATED: - return version >= 1; - case XDG_TOPLEVEL_STATE_TILED_LEFT: - return version >= 2; - case XDG_TOPLEVEL_STATE_TILED_RIGHT: - return version >= 2; - case XDG_TOPLEVEL_STATE_TILED_TOP: - return version >= 2; - case XDG_TOPLEVEL_STATE_TILED_BOTTOM: - return version >= 2; - case XDG_TOPLEVEL_STATE_SUSPENDED: - return version >= 6; - case XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT: - return version >= 7; - case XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT: - return version >= 7; - case XDG_TOPLEVEL_STATE_CONSTRAINED_TOP: - return version >= 7; - case XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM: - return version >= 7; - default: - return false; - } -} -#endif /* XDG_TOPLEVEL_STATE_ENUM_IS_VALID */ - -#ifndef XDG_TOPLEVEL_WM_CAPABILITIES_ENUM -#define XDG_TOPLEVEL_WM_CAPABILITIES_ENUM -enum xdg_toplevel_wm_capabilities { - /** - * show_window_menu is available - */ - XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU = 1, - /** - * set_maximized and unset_maximized are available - */ - XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE = 2, - /** - * set_fullscreen and unset_fullscreen are available - */ - XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN = 3, - /** - * set_minimized is available - */ - XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE = 4, -}; -#endif /* XDG_TOPLEVEL_WM_CAPABILITIES_ENUM */ - -#ifndef XDG_TOPLEVEL_WM_CAPABILITIES_ENUM_IS_VALID -#define XDG_TOPLEVEL_WM_CAPABILITIES_ENUM_IS_VALID -/** - * @ingroup iface_xdg_toplevel - * Validate a xdg_toplevel wm_capabilities value. - * - * @return true on success, false on error. - * @ref xdg_toplevel_wm_capabilities - */ -static inline bool -xdg_toplevel_wm_capabilities_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU: - return version >= 1; - case XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE: - return version >= 1; - case XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN: - return version >= 1; - case XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE: - return version >= 1; - default: - return false; - } -} -#endif /* XDG_TOPLEVEL_WM_CAPABILITIES_ENUM_IS_VALID */ - -/** - * @ingroup iface_xdg_toplevel - * @struct xdg_toplevel_interface - */ -struct xdg_toplevel_interface { - /** - * destroy the xdg_toplevel - * - * This request destroys the role surface and unmaps the surface; - * see "Unmapping" behavior in interface section for details. - */ - void (*destroy)(struct wl_client *client, - struct wl_resource *resource); - /** - * set the parent of this surface - * - * Set the "parent" of this surface. This surface should be - * stacked above the parent surface and all other ancestor - * surfaces. - * - * Parent surfaces should be set on dialogs, toolboxes, or other - * "auxiliary" surfaces, so that the parent is raised when the - * dialog is raised. - * - * Setting a null parent for a child surface unsets its parent. - * Setting a null parent for a surface which currently has no - * parent is a no-op. - * - * Only mapped surfaces can have child surfaces. Setting a parent - * which is not mapped is equivalent to setting a null parent. If a - * surface becomes unmapped, its children's parent is set to the - * parent of the now-unmapped surface. If the now-unmapped surface - * has no parent, its children's parent is unset. If the - * now-unmapped surface becomes mapped again, its parent-child - * relationship is not restored. - * - * The parent toplevel must not be one of the child toplevel's - * descendants, and the parent must be different from the child - * toplevel, otherwise the invalid_parent protocol error is raised. - */ - void (*set_parent)(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *parent); - /** - * set surface title - * - * Set a short title for the surface. - * - * This string may be used to identify the surface in a task bar, - * window list, or other user interface elements provided by the - * compositor. - * - * The string must be encoded in UTF-8. - */ - void (*set_title)(struct wl_client *client, - struct wl_resource *resource, - const char *title); - /** - * set application ID - * - * Set an application identifier for the surface. - * - * The app ID identifies the general class of applications to which - * the surface belongs. The compositor can use this to group - * multiple surfaces together, or to determine how to launch a new - * application. - * - * For D-Bus activatable applications, the app ID is used as the - * D-Bus service name. - * - * The compositor shell will try to group application surfaces - * together by their app ID. As a best practice, it is suggested to - * select app ID's that match the basename of the application's - * .desktop file. For example, "org.freedesktop.FooViewer" where - * the .desktop file is "org.freedesktop.FooViewer.desktop". - * - * Like other properties, a set_app_id request can be sent after - * the xdg_toplevel has been mapped to update the property. - * - * See the desktop-entry specification [0] for more details on - * application identifiers and how they relate to well-known D-Bus - * names and .desktop files. - * - * [0] https://standards.freedesktop.org/desktop-entry-spec/ - */ - void (*set_app_id)(struct wl_client *client, - struct wl_resource *resource, - const char *app_id); - /** - * show the window menu - * - * Clients implementing client-side decorations might want to - * show a context menu when right-clicking on the decorations, - * giving the user a menu that they can use to maximize or minimize - * the window. - * - * This request asks the compositor to pop up such a window menu at - * the given position, relative to the local surface coordinates of - * the parent surface. There are no guarantees as to what menu - * items the window menu contains, or even if a window menu will be - * drawn at all. - * - * This request must be used in response to some sort of user - * action like a button press, key press, or touch down event. - * @param seat the wl_seat of the user event - * @param serial the serial of the user event - * @param x the x position to pop up the window menu at - * @param y the y position to pop up the window menu at - */ - void (*show_window_menu)(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *seat, - uint32_t serial, - int32_t x, - int32_t y); - /** - * start an interactive move - * - * Start an interactive, user-driven move of the surface. - * - * This request must be used in response to some sort of user - * action like a button press, key press, or touch down event. The - * passed serial is used to determine the type of interactive move - * (touch, pointer, etc). - * - * The server may ignore move requests depending on the state of - * the surface (e.g. fullscreen or maximized), or if the passed - * serial is no longer valid. - * - * If triggered, the surface will lose the focus of the device - * (wl_pointer, wl_touch, etc) used for the move. It is up to the - * compositor to visually indicate that the move is taking place, - * such as updating a pointer cursor, during the move. There is no - * guarantee that the device focus will return when the move is - * completed. - * @param seat the wl_seat of the user event - * @param serial the serial of the user event - */ - void (*move)(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *seat, - uint32_t serial); - /** - * start an interactive resize - * - * Start a user-driven, interactive resize of the surface. - * - * This request must be used in response to some sort of user - * action like a button press, key press, or touch down event. The - * passed serial is used to determine the type of interactive - * resize (touch, pointer, etc). - * - * The server may ignore resize requests depending on the state of - * the surface (e.g. fullscreen or maximized). - * - * If triggered, the client will receive configure events with the - * "resize" state enum value and the expected sizes. See the - * "resize" enum value for more details about what is required. The - * client must also acknowledge configure events using - * "ack_configure". After the resize is completed, the client will - * receive another "configure" event without the resize state. - * - * If triggered, the surface also will lose the focus of the device - * (wl_pointer, wl_touch, etc) used for the resize. It is up to the - * compositor to visually indicate that the resize is taking place, - * such as updating a pointer cursor, during the resize. There is - * no guarantee that the device focus will return when the resize - * is completed. - * - * The edges parameter specifies how the surface should be resized, - * and is one of the values of the resize_edge enum. Values not - * matching a variant of the enum will cause the - * invalid_resize_edge protocol error. The compositor may use this - * information to update the surface position for example when - * dragging the top left corner. The compositor may also use this - * information to adapt its behavior, e.g. choose an appropriate - * cursor image. - * @param seat the wl_seat of the user event - * @param serial the serial of the user event - * @param edges which edge or corner is being dragged - */ - void (*resize)(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *seat, - uint32_t serial, - uint32_t edges); - /** - * set the maximum size - * - * Set a maximum size for the window. - * - * The client can specify a maximum size so that the compositor - * does not try to configure the window beyond this size. - * - * The width and height arguments are in window geometry - * coordinates. See xdg_surface.set_window_geometry. - * - * Values set in this way are double-buffered, see - * wl_surface.commit. - * - * The compositor can use this information to allow or disallow - * different states like maximize or fullscreen and draw accurate - * animations. - * - * Similarly, a tiling window manager may use this information to - * place and resize client windows in a more effective way. - * - * The client should not rely on the compositor to obey the maximum - * size. The compositor may decide to ignore the values set by the - * client and request a larger size. - * - * If never set, or a value of zero in the request, means that the - * client has no expected maximum size in the given dimension. As a - * result, a client wishing to reset the maximum size to an - * unspecified state can use zero for width and height in the - * request. - * - * Requesting a maximum size to be smaller than the minimum size of - * a surface is illegal and will result in an invalid_size error. - * - * The width and height must be greater than or equal to zero. - * Using strictly negative values for width or height will result - * in a invalid_size error. - */ - void (*set_max_size)(struct wl_client *client, - struct wl_resource *resource, - int32_t width, - int32_t height); - /** - * set the minimum size - * - * Set a minimum size for the window. - * - * The client can specify a minimum size so that the compositor - * does not try to configure the window below this size. - * - * The width and height arguments are in window geometry - * coordinates. See xdg_surface.set_window_geometry. - * - * Values set in this way are double-buffered, see - * wl_surface.commit. - * - * The compositor can use this information to allow or disallow - * different states like maximize or fullscreen and draw accurate - * animations. - * - * Similarly, a tiling window manager may use this information to - * place and resize client windows in a more effective way. - * - * The client should not rely on the compositor to obey the minimum - * size. The compositor may decide to ignore the values set by the - * client and request a smaller size. - * - * If never set, or a value of zero in the request, means that the - * client has no expected minimum size in the given dimension. As a - * result, a client wishing to reset the minimum size to an - * unspecified state can use zero for width and height in the - * request. - * - * Requesting a minimum size to be larger than the maximum size of - * a surface is illegal and will result in an invalid_size error. - * - * The width and height must be greater than or equal to zero. - * Using strictly negative values for width and height will result - * in a invalid_size error. - */ - void (*set_min_size)(struct wl_client *client, - struct wl_resource *resource, - int32_t width, - int32_t height); - /** - * maximize the window - * - * Maximize the surface. - * - * After requesting that the surface should be maximized, the - * compositor will respond by emitting a configure event. Whether - * this configure actually sets the window maximized is subject to - * compositor policies. The client must then update its content, - * drawing in the configured state. The client must also - * acknowledge the configure when committing the new content (see - * ack_configure). - * - * It is up to the compositor to decide how and where to maximize - * the surface, for example which output and what region of the - * screen should be used. - * - * If the surface was already maximized, the compositor will still - * emit a configure event with the "maximized" state. - * - * If the surface is in a fullscreen state, this request has no - * direct effect. It may alter the state the surface is returned to - * when unmaximized unless overridden by the compositor. - */ - void (*set_maximized)(struct wl_client *client, - struct wl_resource *resource); - /** - * unmaximize the window - * - * Unmaximize the surface. - * - * After requesting that the surface should be unmaximized, the - * compositor will respond by emitting a configure event. Whether - * this actually un-maximizes the window is subject to compositor - * policies. If available and applicable, the compositor will - * include the window geometry dimensions the window had prior to - * being maximized in the configure event. The client must then - * update its content, drawing it in the configured state. The - * client must also acknowledge the configure when committing the - * new content (see ack_configure). - * - * It is up to the compositor to position the surface after it was - * unmaximized; usually the position the surface had before - * maximizing, if applicable. - * - * If the surface was already not maximized, the compositor will - * still emit a configure event without the "maximized" state. - * - * If the surface is in a fullscreen state, this request has no - * direct effect. It may alter the state the surface is returned to - * when unmaximized unless overridden by the compositor. - */ - void (*unset_maximized)(struct wl_client *client, - struct wl_resource *resource); - /** - * set the window as fullscreen on an output - * - * Make the surface fullscreen. - * - * After requesting that the surface should be fullscreened, the - * compositor will respond by emitting a configure event. Whether - * the client is actually put into a fullscreen state is subject to - * compositor policies. The client must also acknowledge the - * configure when committing the new content (see ack_configure). - * - * The output passed by the request indicates the client's - * preference as to which display it should be set fullscreen on. - * If this value is NULL, it's up to the compositor to choose which - * display will be used to map this surface. - * - * If the surface doesn't cover the whole output, the compositor - * will position the surface in the center of the output and - * compensate with with border fill covering the rest of the - * output. The content of the border fill is undefined, but should - * be assumed to be in some way that attempts to blend into the - * surrounding area (e.g. solid black). - * - * If the fullscreened surface is not opaque, the compositor must - * make sure that other screen content not part of the same surface - * tree (made up of subsurfaces, popups or similarly coupled - * surfaces) are not visible below the fullscreened surface. - */ - void (*set_fullscreen)(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *output); - /** - * unset the window as fullscreen - * - * Make the surface no longer fullscreen. - * - * After requesting that the surface should be unfullscreened, the - * compositor will respond by emitting a configure event. Whether - * this actually removes the fullscreen state of the client is - * subject to compositor policies. - * - * Making a surface unfullscreen sets states for the surface based - * on the following: * the state(s) it may have had before becoming - * fullscreen * any state(s) decided by the compositor * any - * state(s) requested by the client while the surface was - * fullscreen - * - * The compositor may include the previous window geometry - * dimensions in the configure event, if applicable. - * - * The client must also acknowledge the configure when committing - * the new content (see ack_configure). - */ - void (*unset_fullscreen)(struct wl_client *client, - struct wl_resource *resource); - /** - * set the window as minimized - * - * Request that the compositor minimize your surface. There is no - * way to know if the surface is currently minimized, nor is there - * any way to unset minimization on this surface. - * - * If you are looking to throttle redrawing when minimized, please - * instead use the wl_surface.frame event for this, as this will - * also work with live previews on windows in Alt-Tab, Expose or - * similar compositor features. - */ - void (*set_minimized)(struct wl_client *client, - struct wl_resource *resource); -}; - -#define XDG_TOPLEVEL_CONFIGURE 0 -#define XDG_TOPLEVEL_CLOSE 1 -#define XDG_TOPLEVEL_CONFIGURE_BOUNDS 2 -#define XDG_TOPLEVEL_WM_CAPABILITIES 3 - -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_CONFIGURE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_CLOSE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION 4 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION 5 - -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_SET_PARENT_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_SET_TITLE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_SET_APP_ID_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_SHOW_WINDOW_MENU_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_MOVE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_RESIZE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_SET_MAX_SIZE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_SET_MIN_SIZE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_SET_MAXIMIZED_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_UNSET_MAXIMIZED_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_SET_FULLSCREEN_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_UNSET_FULLSCREEN_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_SET_MINIMIZED_SINCE_VERSION 1 - -/** - * @ingroup iface_xdg_toplevel - * Sends an configure event to the client owning the resource. - * @param resource_ The client's resource - */ -static inline void -xdg_toplevel_send_configure(struct wl_resource *resource_, int32_t width, int32_t height, struct wl_array *states) -{ - wl_resource_post_event(resource_, XDG_TOPLEVEL_CONFIGURE, width, height, states); -} - -/** - * @ingroup iface_xdg_toplevel - * Sends an close event to the client owning the resource. - * @param resource_ The client's resource - */ -static inline void -xdg_toplevel_send_close(struct wl_resource *resource_) -{ - wl_resource_post_event(resource_, XDG_TOPLEVEL_CLOSE); -} - -/** - * @ingroup iface_xdg_toplevel - * Sends an configure_bounds event to the client owning the resource. - * @param resource_ The client's resource - */ -static inline void -xdg_toplevel_send_configure_bounds(struct wl_resource *resource_, int32_t width, int32_t height) -{ - wl_resource_post_event(resource_, XDG_TOPLEVEL_CONFIGURE_BOUNDS, width, height); -} - -/** - * @ingroup iface_xdg_toplevel - * Sends an wm_capabilities event to the client owning the resource. - * @param resource_ The client's resource - * @param capabilities array of 32-bit capabilities - */ -static inline void -xdg_toplevel_send_wm_capabilities(struct wl_resource *resource_, struct wl_array *capabilities) -{ - wl_resource_post_event(resource_, XDG_TOPLEVEL_WM_CAPABILITIES, capabilities); -} - -#ifndef XDG_POPUP_ERROR_ENUM -#define XDG_POPUP_ERROR_ENUM -enum xdg_popup_error { - /** - * tried to grab after being mapped - */ - XDG_POPUP_ERROR_INVALID_GRAB = 0, -}; -#endif /* XDG_POPUP_ERROR_ENUM */ - -#ifndef XDG_POPUP_ERROR_ENUM_IS_VALID -#define XDG_POPUP_ERROR_ENUM_IS_VALID -/** - * @ingroup iface_xdg_popup - * Validate a xdg_popup error value. - * - * @return true on success, false on error. - * @ref xdg_popup_error - */ -static inline bool -xdg_popup_error_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case XDG_POPUP_ERROR_INVALID_GRAB: - return version >= 1; - default: - return false; - } -} -#endif /* XDG_POPUP_ERROR_ENUM_IS_VALID */ - -/** - * @ingroup iface_xdg_popup - * @struct xdg_popup_interface - */ -struct xdg_popup_interface { - /** - * remove xdg_popup interface - * - * This destroys the popup. Explicitly destroying the xdg_popup - * object will also dismiss the popup, and unmap the surface. - * - * If this xdg_popup is not the "topmost" popup, the - * xdg_wm_base.not_the_topmost_popup protocol error will be sent. - */ - void (*destroy)(struct wl_client *client, - struct wl_resource *resource); - /** - * make the popup take an explicit grab - * - * This request makes the created popup take an explicit grab. An - * explicit grab will be dismissed when the user dismisses the - * popup, or when the client destroys the xdg_popup. This can be - * done by the user clicking outside the surface, using the - * keyboard, or even locking the screen through closing the lid or - * a timeout. - * - * If the compositor denies the grab, the popup will be immediately - * dismissed. - * - * This request must be used in response to some sort of user - * action like a button press, key press, or touch down event. The - * serial number of the event should be passed as 'serial'. - * - * The parent of a grabbing popup must either be an xdg_toplevel - * surface or another xdg_popup with an explicit grab. If the - * parent is another xdg_popup it means that the popups are nested, - * with this popup now being the topmost popup. - * - * Nested popups must be destroyed in the reverse order they were - * created in, e.g. the only popup you are allowed to destroy at - * all times is the topmost one. - * - * When compositors choose to dismiss a popup, they may dismiss - * every nested grabbing popup as well. When a compositor dismisses - * popups, it will follow the same dismissing order as required - * from the client. - * - * If the topmost grabbing popup is destroyed, the grab will be - * returned to the parent of the popup, if that parent previously - * had an explicit grab. - * - * If the parent is a grabbing popup which has already been - * dismissed, this popup will be immediately dismissed. If the - * parent is a popup that did not take an explicit grab, an error - * will be raised. - * - * During a popup grab, the client owning the grab will receive - * pointer and touch events for all their surfaces as normal - * (similar to an "owner-events" grab in X11 parlance), while the - * top most grabbing popup will always have keyboard focus. - * @param seat the wl_seat of the user event - * @param serial the serial of the user event - */ - void (*grab)(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *seat, - uint32_t serial); - /** - * recalculate the popup's location - * - * Reposition an already-mapped popup. The popup will be placed - * given the details in the passed xdg_positioner object, and a - * xdg_popup.repositioned followed by xdg_popup.configure and - * xdg_surface.configure will be emitted in response. Any - * parameters set by the previous positioner will be discarded. - * - * The passed token will be sent in the corresponding - * xdg_popup.repositioned event. The new popup position will not - * take effect until the corresponding configure event is - * acknowledged by the client. See xdg_popup.repositioned for - * details. The token itself is opaque, and has no other special - * meaning. - * - * If multiple reposition requests are sent, the compositor may - * skip all but the last one. - * - * If the popup is repositioned in response to a configure event - * for its parent, the client should send an - * xdg_positioner.set_parent_configure and possibly an - * xdg_positioner.set_parent_size request to allow the compositor - * to properly constrain the popup. - * - * If the popup is repositioned together with a parent that is - * being resized, but not in response to a configure event, the - * client should send an xdg_positioner.set_parent_size request. - * @param token reposition request token - * @since 3 - */ - void (*reposition)(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *positioner, - uint32_t token); -}; - -#define XDG_POPUP_CONFIGURE 0 -#define XDG_POPUP_POPUP_DONE 1 -#define XDG_POPUP_REPOSITIONED 2 - -/** - * @ingroup iface_xdg_popup - */ -#define XDG_POPUP_CONFIGURE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_popup - */ -#define XDG_POPUP_POPUP_DONE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_popup - */ -#define XDG_POPUP_REPOSITIONED_SINCE_VERSION 3 - -/** - * @ingroup iface_xdg_popup - */ -#define XDG_POPUP_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_popup - */ -#define XDG_POPUP_GRAB_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_popup - */ -#define XDG_POPUP_REPOSITION_SINCE_VERSION 3 - -/** - * @ingroup iface_xdg_popup - * Sends an configure event to the client owning the resource. - * @param resource_ The client's resource - * @param x x position relative to parent surface window geometry - * @param y y position relative to parent surface window geometry - * @param width window geometry width - * @param height window geometry height - */ -static inline void -xdg_popup_send_configure(struct wl_resource *resource_, int32_t x, int32_t y, int32_t width, int32_t height) -{ - wl_resource_post_event(resource_, XDG_POPUP_CONFIGURE, x, y, width, height); -} - -/** - * @ingroup iface_xdg_popup - * Sends an popup_done event to the client owning the resource. - * @param resource_ The client's resource - */ -static inline void -xdg_popup_send_popup_done(struct wl_resource *resource_) -{ - wl_resource_post_event(resource_, XDG_POPUP_POPUP_DONE); -} - -/** - * @ingroup iface_xdg_popup - * Sends an repositioned event to the client owning the resource. - * @param resource_ The client's resource - * @param token reposition request token - */ -static inline void -xdg_popup_send_repositioned(struct wl_resource *resource_, uint32_t token) -{ - wl_resource_post_event(resource_, XDG_POPUP_REPOSITIONED, token); -} - -#ifdef __cplusplus -} -#endif - -#endif