dotfiles

my shiny new dotfiles
git clone git://git.jakekoroman.com/dotfiles
Log | Files | Refs | README

dwl.c (124348B)


      1 /*
      2  * See LICENSE file for copyright and license details.
      3  */
      4 #include <getopt.h>
      5 #include <libinput.h>
      6 #include <linux/input-event-codes.h>
      7 #include <signal.h>
      8 #include <stdio.h>
      9 #include <stdlib.h>
     10 #include <sys/wait.h>
     11 #include <time.h>
     12 #include <unistd.h>
     13 #include <wayland-server-core.h>
     14 #include <wlr/backend.h>
     15 #include <wlr/backend/libinput.h>
     16 #include <wlr/render/allocator.h>
     17 #include <wlr/render/wlr_renderer.h>
     18 #include <wlr/types/wlr_compositor.h>
     19 #include <wlr/types/wlr_cursor.h>
     20 #include <wlr/types/wlr_cursor_shape_v1.h>
     21 #include <wlr/types/wlr_data_control_v1.h>
     22 #include <wlr/types/wlr_data_device.h>
     23 #include <wlr/types/wlr_drm.h>
     24 #include <wlr/types/wlr_export_dmabuf_v1.h>
     25 #include <wlr/types/wlr_fractional_scale_v1.h>
     26 #include <wlr/types/wlr_gamma_control_v1.h>
     27 #include <wlr/types/wlr_idle_inhibit_v1.h>
     28 #include <wlr/types/wlr_idle_notify_v1.h>
     29 #include <wlr/types/wlr_input_device.h>
     30 #include <wlr/types/wlr_keyboard.h>
     31 #include <wlr/types/wlr_keyboard_group.h>
     32 #include <wlr/types/wlr_layer_shell_v1.h>
     33 #include <wlr/types/wlr_linux_dmabuf_v1.h>
     34 #include <wlr/types/wlr_output.h>
     35 #include <wlr/types/wlr_output_layout.h>
     36 #include <wlr/types/wlr_output_management_v1.h>
     37 #include <wlr/types/wlr_pointer.h>
     38 #include <wlr/types/wlr_pointer_constraints_v1.h>
     39 #include <wlr/types/wlr_presentation_time.h>
     40 #include <wlr/types/wlr_primary_selection.h>
     41 #include <wlr/types/wlr_primary_selection_v1.h>
     42 #include <wlr/types/wlr_relative_pointer_v1.h>
     43 #include <wlr/types/wlr_scene.h>
     44 #include <wlr/types/wlr_screencopy_v1.h>
     45 #include <wlr/types/wlr_seat.h>
     46 #include <wlr/types/wlr_server_decoration.h>
     47 #include <wlr/types/wlr_session_lock_v1.h>
     48 #include <wlr/types/wlr_single_pixel_buffer_v1.h>
     49 #include <wlr/types/wlr_subcompositor.h>
     50 #include <wlr/types/wlr_viewporter.h>
     51 #include <wlr/types/wlr_virtual_keyboard_v1.h>
     52 #include <wlr/types/wlr_virtual_pointer_v1.h>
     53 #include <wlr/types/wlr_xcursor_manager.h>
     54 #include <wlr/types/wlr_xdg_activation_v1.h>
     55 #include <wlr/types/wlr_xdg_decoration_v1.h>
     56 #include <wlr/types/wlr_xdg_output_v1.h>
     57 #include <wlr/types/wlr_xdg_shell.h>
     58 #include <wlr/util/log.h>
     59 #include <wlr/util/region.h>
     60 #include <xkbcommon/xkbcommon.h>
     61 #ifdef XWAYLAND
     62 #include <wlr/xwayland.h>
     63 #include <xcb/xcb.h>
     64 #include <xcb/xcb_icccm.h>
     65 #endif
     66 
     67 #include "dwl-ipc-unstable-v2-protocol.h"
     68 #include "util.h"
     69 
     70 /* macros */
     71 #define MAX(A, B)               ((A) > (B) ? (A) : (B))
     72 #define MIN(A, B)               ((A) < (B) ? (A) : (B))
     73 #define ROUND(X)                ((int)((X < 0) ? (X - 0.5) : (X + 0.5)))
     74 #define CLEANMASK(mask)         (mask & ~WLR_MODIFIER_CAPS)
     75 #define VISIBLEON(C, M)         ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags]))
     76 #define LENGTH(X)               (sizeof X / sizeof X[0])
     77 #define END(A)                  ((A) + LENGTH(A))
     78 #define TAGMASK                 ((1u << TAGCOUNT) - 1)
     79 #define LISTEN(E, L, H)         wl_signal_add((E), ((L)->notify = (H), (L)))
     80 #define LISTEN_STATIC(E, H)     do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0)
     81 
     82 /* enums */
     83 enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
     84 enum { XDGShell, LayerShell, X11 }; /* client types */
     85 enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrFS, LyrTop, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */
     86 #ifdef XWAYLAND
     87 enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar,
     88     NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */
     89 #endif
     90 
     91 typedef union {
     92     int i;
     93     uint32_t ui;
     94     float f;
     95     const void *v;
     96 } Arg;
     97 
     98 typedef struct {
     99     unsigned int mod;
    100     unsigned int button;
    101     void (*func)(const Arg *);
    102     const Arg arg;
    103 } Button;
    104 
    105 typedef struct Monitor Monitor;
    106 typedef struct Client Client;
    107 struct Client {
    108     /* Must keep these three elements in this order */
    109     unsigned int type; /* XDGShell or X11* */
    110     struct wlr_box geom; /* layout-relative, includes border */
    111     Monitor *mon;
    112     struct wlr_scene_tree *scene;
    113     struct wlr_scene_rect *border[4]; /* top, bottom, left, right */
    114     struct wlr_scene_tree *scene_surface;
    115     struct wl_list link;
    116     struct wl_list flink;
    117     union {
    118         struct wlr_xdg_surface *xdg;
    119         struct wlr_xwayland_surface *xwayland;
    120     } surface;
    121     struct wlr_xdg_toplevel_decoration_v1 *decoration;
    122     struct wl_listener commit;
    123     struct wl_listener map;
    124     struct wl_listener maximize;
    125     struct wl_listener unmap;
    126     struct wl_listener destroy;
    127     struct wl_listener set_title;
    128     struct wl_listener fullscreen;
    129     struct wl_listener set_decoration_mode;
    130     struct wl_listener destroy_decoration;
    131     struct wlr_box prev; /* layout-relative, includes border */
    132     struct wlr_box bounds;
    133 #ifdef XWAYLAND
    134     struct wl_listener activate;
    135     struct wl_listener associate;
    136     struct wl_listener dissociate;
    137     struct wl_listener configure;
    138     struct wl_listener set_hints;
    139 #endif
    140     unsigned int bw;
    141     uint32_t tags;
    142     int isfloating, isurgent, isfullscreen, isterm, noswallow;
    143     uint32_t resize; /* configure serial of a pending resize */
    144     pid_t pid;
    145     Client *swallowing, *swallowedby;
    146 };
    147 
    148 typedef struct {
    149     struct wl_list link;
    150     struct wl_resource *resource;
    151     Monitor *mon;
    152 } DwlIpcOutput;
    153 
    154 typedef struct {
    155     uint32_t mod;
    156     xkb_keysym_t keysym;
    157     void (*func)(const Arg *);
    158     const Arg arg;
    159 } Key;
    160 
    161 typedef struct {
    162     struct wl_list link;
    163     struct wlr_keyboard_group *wlr_group;
    164 
    165     int nsyms;
    166     const xkb_keysym_t *keysyms; /* invalid if nsyms == 0 */
    167     uint32_t mods; /* invalid if nsyms == 0 */
    168     struct wl_event_source *key_repeat_source;
    169 
    170     struct wl_listener modifiers;
    171     struct wl_listener key;
    172 } KeyboardGroup;
    173 
    174 typedef struct {
    175     /* Must keep these three elements in this order */
    176     unsigned int type; /* LayerShell */
    177     struct wlr_box geom;
    178     Monitor *mon;
    179     struct wlr_scene_tree *scene;
    180     struct wlr_scene_tree *popups;
    181     struct wlr_scene_layer_surface_v1 *scene_layer;
    182     struct wl_list link;
    183     int mapped;
    184     struct wlr_layer_surface_v1 *layer_surface;
    185 
    186     struct wl_listener destroy;
    187     struct wl_listener map;
    188     struct wl_listener unmap;
    189     struct wl_listener surface_commit;
    190 } LayerSurface;
    191 
    192 typedef struct {
    193     const char *symbol;
    194     void (*arrange)(Monitor *);
    195 } Layout;
    196 
    197 struct Monitor {
    198     struct wl_list link;
    199     struct wl_list dwl_ipc_outputs;
    200     struct wlr_output *wlr_output;
    201     struct wlr_scene_output *scene_output;
    202     struct wlr_scene_rect *fullscreen_bg; /* See createmon() for info */
    203     struct wl_listener frame;
    204     struct wl_listener destroy;
    205     struct wl_listener request_state;
    206     struct wl_listener destroy_lock_surface;
    207     struct wlr_session_lock_surface_v1 *lock_surface;
    208     struct wlr_box m; /* monitor area, layout-relative */
    209     struct wlr_box w; /* window area, layout-relative */
    210     struct wl_list layers[4]; /* LayerSurface.link */
    211     const Layout *lt[2];
    212     int gaps;
    213     unsigned int seltags;
    214     unsigned int sellt;
    215     uint32_t tagset[2];
    216     float mfact;
    217     int gamma_lut_changed;
    218     int nmaster;
    219     char ltsymbol[16];
    220 };
    221 
    222 typedef struct {
    223     const char *name;
    224     float mfact;
    225     int nmaster;
    226     float scale;
    227     const Layout *lt;
    228     enum wl_output_transform rr;
    229     int x, y;
    230     int resx;
    231     int resy;
    232     float rate;
    233     int mode;
    234     int adaptive;
    235 } MonitorRule;
    236 
    237 typedef struct {
    238     struct wlr_pointer_constraint_v1 *constraint;
    239     struct wl_listener destroy;
    240 } PointerConstraint;
    241 
    242 typedef struct {
    243     const char *id;
    244     const char *title;
    245     uint32_t tags;
    246     int isfloating;
    247     int isterm;
    248     int noswallow;
    249     int monitor;
    250 } Rule;
    251 
    252 typedef struct {
    253     struct wlr_scene_tree *scene;
    254 
    255     struct wlr_session_lock_v1 *lock;
    256     struct wl_listener new_surface;
    257     struct wl_listener unlock;
    258     struct wl_listener destroy;
    259 } SessionLock;
    260 
    261 /* function declarations */
    262 static void applybounds(Client *c, struct wlr_box *bbox);
    263 static void applyrules(Client *c);
    264 static void arrange(Monitor *m);
    265 static void arrangelayer(Monitor *m, struct wl_list *list,
    266         struct wlr_box *usable_area, int exclusive);
    267 static void arrangelayers(Monitor *m);
    268 static void autostartexec(void);
    269 static void axisnotify(struct wl_listener *listener, void *data);
    270 static void buttonpress(struct wl_listener *listener, void *data);
    271 static void centeredmaster(Monitor *m);
    272 static void chvt(const Arg *arg);
    273 static void checkidleinhibitor(struct wlr_surface *exclude);
    274 static void cleanup(void);
    275 static void cleanupmon(struct wl_listener *listener, void *data);
    276 static void closemon(Monitor *m);
    277 static void commitlayersurfacenotify(struct wl_listener *listener, void *data);
    278 static void commitnotify(struct wl_listener *listener, void *data);
    279 static void createdecoration(struct wl_listener *listener, void *data);
    280 static void createidleinhibitor(struct wl_listener *listener, void *data);
    281 static void createkeyboard(struct wlr_keyboard *keyboard);
    282 static void createlayersurface(struct wl_listener *listener, void *data);
    283 static void createlocksurface(struct wl_listener *listener, void *data);
    284 static void createmon(struct wl_listener *listener, void *data);
    285 static void createnotify(struct wl_listener *listener, void *data);
    286 static void createpointer(struct wlr_pointer *pointer);
    287 static void createpointerconstraint(struct wl_listener *listener, void *data);
    288 static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint);
    289 static void cursorframe(struct wl_listener *listener, void *data);
    290 static void cursorwarptocenter(void);
    291 static void cursorwarptohint(void);
    292 static void destroydecoration(struct wl_listener *listener, void *data);
    293 static void destroydragicon(struct wl_listener *listener, void *data);
    294 static void destroyidleinhibitor(struct wl_listener *listener, void *data);
    295 static void destroylayersurfacenotify(struct wl_listener *listener, void *data);
    296 static void destroylock(SessionLock *lock, int unlocked);
    297 static void destroylocksurface(struct wl_listener *listener, void *data);
    298 static void destroynotify(struct wl_listener *listener, void *data);
    299 static void destroypointerconstraint(struct wl_listener *listener, void *data);
    300 static void destroysessionlock(struct wl_listener *listener, void *data);
    301 static void destroysessionmgr(struct wl_listener *listener, void *data);
    302 static Monitor *dirtomon(enum wlr_direction dir);
    303 static void dwl_ipc_manager_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id);
    304 static void dwl_ipc_manager_destroy(struct wl_resource *resource);
    305 static void dwl_ipc_manager_get_output(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *output);
    306 static void dwl_ipc_manager_release(struct wl_client *client, struct wl_resource *resource);
    307 static void dwl_ipc_output_destroy(struct wl_resource *resource);
    308 static void dwl_ipc_output_printstatus(Monitor *monitor);
    309 static void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output);
    310 static void dwl_ipc_output_set_client_tags(struct wl_client *client, struct wl_resource *resource, uint32_t and_tags, uint32_t xor_tags);
    311 static void dwl_ipc_output_set_layout(struct wl_client *client, struct wl_resource *resource, uint32_t index);
    312 static void dwl_ipc_output_set_tags(struct wl_client *client, struct wl_resource *resource, uint32_t tagmask, uint32_t toggle_tagset);
    313 static void dwl_ipc_output_release(struct wl_client *client, struct wl_resource *resource);
    314 static void focusclient(Client *c, int lift);
    315 static void focusmon(const Arg *arg);
    316 static void focusstack(const Arg *arg);
    317 static Client *focustop(Monitor *m);
    318 static void fullscreennotify(struct wl_listener *listener, void *data);
    319 static void handlesig(int signo);
    320 static void incnmaster(const Arg *arg);
    321 static void inputdevice(struct wl_listener *listener, void *data);
    322 static int keybinding(uint32_t mods, xkb_keysym_t sym);
    323 static void keypress(struct wl_listener *listener, void *data);
    324 static void keypressmod(struct wl_listener *listener, void *data);
    325 static int keyrepeat(void *data);
    326 static void killclient(const Arg *arg);
    327 static void locksession(struct wl_listener *listener, void *data);
    328 static void maplayersurfacenotify(struct wl_listener *listener, void *data);
    329 static void mapnotify(struct wl_listener *listener, void *data);
    330 static void maximizenotify(struct wl_listener *listener, void *data);
    331 static void monocle(Monitor *m);
    332 static void movestack(const Arg *arg);
    333 static void motionabsolute(struct wl_listener *listener, void *data);
    334 static void motionnotify(uint32_t time, struct wlr_input_device *device, double sx,
    335         double sy, double sx_unaccel, double sy_unaccel);
    336 static void motionrelative(struct wl_listener *listener, void *data);
    337 static void moveresize(const Arg *arg);
    338 static void outputmgrapply(struct wl_listener *listener, void *data);
    339 static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test);
    340 static void outputmgrtest(struct wl_listener *listener, void *data);
    341 static void pointerfocus(Client *c, struct wlr_surface *surface,
    342         double sx, double sy, uint32_t time);
    343 static void printstatus(void);
    344 static void quit(const Arg *arg);
    345 static void rendermon(struct wl_listener *listener, void *data);
    346 static void requestdecorationmode(struct wl_listener *listener, void *data);
    347 static void requeststartdrag(struct wl_listener *listener, void *data);
    348 static void requestmonstate(struct wl_listener *listener, void *data);
    349 static void resize(Client *c, struct wlr_box geo, int interact);
    350 static void run(char *startup_cmd);
    351 static void setcursor(struct wl_listener *listener, void *data);
    352 static void setcursorshape(struct wl_listener *listener, void *data);
    353 static void setfloating(Client *c, int floating);
    354 static void setfullscreen(Client *c, int fullscreen);
    355 static void setgamma(struct wl_listener *listener, void *data);
    356 static void setlayout(const Arg *arg);
    357 static void setmfact(const Arg *arg);
    358 static void setmon(Client *c, Monitor *m, uint32_t newtags);
    359 static void setpsel(struct wl_listener *listener, void *data);
    360 static void setsel(struct wl_listener *listener, void *data);
    361 static void setup(void);
    362 static void spawn(const Arg *arg);
    363 static void startdrag(struct wl_listener *listener, void *data);
    364 static void tag(const Arg *arg);
    365 static void tagmon(const Arg *arg);
    366 static void tile(Monitor *m);
    367 static void togglebar(const Arg *arg);
    368 static void togglefloating(const Arg *arg);
    369 static void togglefullscreen(const Arg *arg);
    370 static void togglegaps(const Arg *arg);
    371 static void toggletag(const Arg *arg);
    372 static void toggleview(const Arg *arg);
    373 static void unlocksession(struct wl_listener *listener, void *data);
    374 static void unmaplayersurfacenotify(struct wl_listener *listener, void *data);
    375 static void unmapnotify(struct wl_listener *listener, void *data);
    376 static void updatemons(struct wl_listener *listener, void *data);
    377 static void updatetitle(struct wl_listener *listener, void *data);
    378 static void urgent(struct wl_listener *listener, void *data);
    379 static void view(const Arg *arg);
    380 static void virtualkeyboard(struct wl_listener *listener, void *data);
    381 static void virtualpointer(struct wl_listener *listener, void *data);
    382 static Monitor *xytomon(double x, double y);
    383 static void xytonode(double x, double y, struct wlr_surface **psurface,
    384         Client **pc, LayerSurface **pl, double *nx, double *ny);
    385 static void zoom(const Arg *arg);
    386 static pid_t getparentprocess(pid_t p);
    387 static int isdescprocess(pid_t p, pid_t c);
    388 static Client *termforwin(Client *w);
    389 static void swallow(Client *c, Client *w);
    390 
    391 /* variables */
    392 static const char broken[] = "broken";
    393 static pid_t child_pid = -1;
    394 static int locked;
    395 static void *exclusive_focus;
    396 static struct wl_display *dpy;
    397 static struct wlr_backend *backend;
    398 static struct wlr_scene *scene;
    399 static struct wlr_scene_tree *layers[NUM_LAYERS];
    400 static struct wlr_scene_tree *drag_icon;
    401 /* Map from ZWLR_LAYER_SHELL_* constants to Lyr* enum */
    402 static const int layermap[] = { LyrBg, LyrBottom, LyrTop, LyrOverlay };
    403 static struct wlr_renderer *drw;
    404 static struct wlr_allocator *alloc;
    405 static struct wlr_compositor *compositor;
    406 static struct wlr_session *session;
    407 
    408 static struct wlr_xdg_shell *xdg_shell;
    409 static struct wlr_xdg_activation_v1 *activation;
    410 static struct wlr_xdg_decoration_manager_v1 *xdg_decoration_mgr;
    411 static struct wl_list clients; /* tiling order */
    412 static struct wl_list fstack;  /* focus order */
    413 static struct wlr_idle_notifier_v1 *idle_notifier;
    414 static struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr;
    415 static struct wlr_layer_shell_v1 *layer_shell;
    416 static struct wlr_output_manager_v1 *output_mgr;
    417 static struct wlr_gamma_control_manager_v1 *gamma_control_mgr;
    418 static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr;
    419 static struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr;
    420 static struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr;
    421 
    422 static struct wlr_pointer_constraints_v1 *pointer_constraints;
    423 static struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr;
    424 static struct wlr_pointer_constraint_v1 *active_constraint;
    425 
    426 static struct wlr_cursor *cursor;
    427 static struct wlr_xcursor_manager *cursor_mgr;
    428 
    429 static struct wlr_scene_rect *root_bg;
    430 static struct wlr_session_lock_manager_v1 *session_lock_mgr;
    431 static struct wlr_scene_rect *locked_bg;
    432 static struct wlr_session_lock_v1 *cur_lock;
    433 static struct wl_listener lock_listener = {.notify = locksession};
    434 
    435 static struct wlr_seat *seat;
    436 static KeyboardGroup kb_group = {0};
    437 static KeyboardGroup vkb_group = {0};
    438 static struct wlr_surface *held_grab;
    439 static unsigned int cursor_mode;
    440 static Client *grabc;
    441 static int grabcx, grabcy; /* client-relative */
    442 
    443 static struct wlr_output_layout *output_layout;
    444 static struct wlr_box sgeom;
    445 static struct wl_list mons;
    446 static Monitor *selmon;
    447 
    448 static struct zdwl_ipc_manager_v2_interface dwl_manager_implementation = {.release = dwl_ipc_manager_release, .get_output = dwl_ipc_manager_get_output};
    449 static struct zdwl_ipc_output_v2_interface dwl_output_implementation = {.release = dwl_ipc_output_release, .set_tags = dwl_ipc_output_set_tags, .set_layout = dwl_ipc_output_set_layout, .set_client_tags = dwl_ipc_output_set_client_tags};
    450 
    451 #ifdef XWAYLAND
    452 static void activatex11(struct wl_listener *listener, void *data);
    453 static void associatex11(struct wl_listener *listener, void *data);
    454 static void configurex11(struct wl_listener *listener, void *data);
    455 static void createnotifyx11(struct wl_listener *listener, void *data);
    456 static void dissociatex11(struct wl_listener *listener, void *data);
    457 static xcb_atom_t getatom(xcb_connection_t *xc, const char *name);
    458 static void sethints(struct wl_listener *listener, void *data);
    459 static void xwaylandready(struct wl_listener *listener, void *data);
    460 static struct wlr_xwayland *xwayland;
    461 static xcb_atom_t netatom[NetLast];
    462 #endif
    463 
    464 /* configuration, allows nested code to access above variables */
    465 #include "config.h"
    466 #include "device.h"
    467 
    468 /* attempt to encapsulate suck into one file */
    469 #include "client.h"
    470 
    471 static pid_t *autostart_pids;
    472 static size_t autostart_len;
    473 
    474 /* function implementations */
    475 void
    476 applybounds(Client *c, struct wlr_box *bbox)
    477 {
    478     /* set minimum possible */
    479     c->geom.width = MAX(1 + 2 * (int)c->bw, c->geom.width);
    480     c->geom.height = MAX(1 + 2 * (int)c->bw, c->geom.height);
    481 
    482     if (c->geom.x >= bbox->x + bbox->width)
    483         c->geom.x = bbox->x + bbox->width - c->geom.width;
    484     if (c->geom.y >= bbox->y + bbox->height)
    485         c->geom.y = bbox->y + bbox->height - c->geom.height;
    486     if (c->geom.x + c->geom.width <= bbox->x)
    487         c->geom.x = bbox->x;
    488     if (c->geom.y + c->geom.height <= bbox->y)
    489         c->geom.y = bbox->y;
    490 }
    491 
    492 void
    493 applyrules(Client *c)
    494 {
    495     /* rule matching */
    496     const char *appid, *title;
    497     uint32_t newtags = 0;
    498     int i;
    499     const Rule *r;
    500     Monitor *mon = selmon, *m;
    501 
    502     c->isfloating = client_is_float_type(c);
    503     if (!(appid = client_get_appid(c)))
    504         appid = broken;
    505     if (!(title = client_get_title(c)))
    506         title = broken;
    507 
    508     c->pid = client_get_pid(c);
    509 
    510     for (r = rules; r < END(rules); r++) {
    511         if ((!r->title || strstr(title, r->title))
    512                 && (!r->id || strstr(appid, r->id))) {
    513             c->isfloating = r->isfloating;
    514             c->isterm     = r->isterm;
    515             c->noswallow  = r->noswallow;
    516             newtags |= r->tags;
    517             i = 0;
    518             wl_list_for_each(m, &mons, link) {
    519                 if (r->monitor == i++)
    520                     mon = m;
    521             }
    522         }
    523     }
    524 
    525     if (!c->noswallow && !client_is_float_type(c)) {
    526         Client *p = termforwin(c);
    527         if (p) {
    528             c->swallowedby = p;
    529             p->swallowing  = c;
    530             wl_list_remove(&c->link);
    531             wl_list_remove(&c->flink);
    532             swallow(c,p);
    533             wl_list_remove(&p->link);
    534             wl_list_remove(&p->flink);
    535             mon = p->mon;
    536             newtags = p->tags;
    537         }
    538     }
    539 
    540     if (mon) {
    541         c->geom.x = (mon->w.width - c->geom.width) / 2 + mon->m.x;
    542         c->geom.y = (mon->w.height - c->geom.height) / 2 + mon->m.y;
    543     }
    544 
    545     setmon(c, mon, newtags);
    546 }
    547 
    548 void
    549 arrange(Monitor *m)
    550 {
    551     Client *c;
    552 
    553     if (!m->wlr_output->enabled)
    554         return;
    555 
    556     wl_list_for_each(c, &clients, link) {
    557         if (c->mon == m) {
    558             wlr_scene_node_set_enabled(&c->scene->node, VISIBLEON(c, m));
    559             client_set_suspended(c, !VISIBLEON(c, m));
    560         }
    561     }
    562 
    563     wlr_scene_node_set_enabled(&m->fullscreen_bg->node,
    564             (c = focustop(m)) && c->isfullscreen);
    565 
    566     strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol));
    567 
    568 	/* We move all clients (except fullscreen and unmanaged) to LyrTile while
    569 	 * in floating layout to avoid "real" floating clients be always on top */
    570 	wl_list_for_each(c, &clients, link) {
    571 		if (c->mon != m || c->scene->node.parent == layers[LyrFS])
    572 			continue;
    573 
    574 		wlr_scene_node_reparent(&c->scene->node,
    575 				(!m->lt[m->sellt]->arrange && c->isfloating)
    576 						? layers[LyrTile]
    577 						: (m->lt[m->sellt]->arrange && c->isfloating)
    578 								? layers[LyrFloat]
    579 								: c->scene->node.parent);
    580 	}
    581 
    582     if (m->lt[m->sellt]->arrange)
    583         m->lt[m->sellt]->arrange(m);
    584     motionnotify(0, NULL, 0, 0, 0, 0);
    585     checkidleinhibitor(NULL);
    586 }
    587 
    588 void
    589 arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, int exclusive)
    590 {
    591     LayerSurface *l;
    592     struct wlr_box full_area = m->m;
    593 
    594     wl_list_for_each(l, list, link) {
    595         struct wlr_layer_surface_v1 *layer_surface = l->layer_surface;
    596 
    597         if (exclusive != (layer_surface->current.exclusive_zone > 0))
    598             continue;
    599 
    600         wlr_scene_layer_surface_v1_configure(l->scene_layer, &full_area, usable_area);
    601         wlr_scene_node_set_position(&l->popups->node, l->scene->node.x, l->scene->node.y);
    602         l->geom.x = l->scene->node.x;
    603         l->geom.y = l->scene->node.y;
    604     }
    605 }
    606 
    607 void
    608 arrangelayers(Monitor *m)
    609 {
    610     int i;
    611     struct wlr_box usable_area = m->m;
    612     LayerSurface *l;
    613     uint32_t layers_above_shell[] = {
    614         ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY,
    615         ZWLR_LAYER_SHELL_V1_LAYER_TOP,
    616     };
    617     if (!m->wlr_output->enabled)
    618         return;
    619 
    620     /* Arrange exclusive surfaces from top->bottom */
    621     for (i = 3; i >= 0; i--)
    622         arrangelayer(m, &m->layers[i], &usable_area, 1);
    623 
    624     if (!wlr_box_equal(&usable_area, &m->w)) {
    625         m->w = usable_area;
    626         arrange(m);
    627     }
    628 
    629     /* Arrange non-exlusive surfaces from top->bottom */
    630     for (i = 3; i >= 0; i--)
    631         arrangelayer(m, &m->layers[i], &usable_area, 0);
    632 
    633     /* Find topmost keyboard interactive layer, if such a layer exists */
    634     for (i = 0; i < (int)LENGTH(layers_above_shell); i++) {
    635         wl_list_for_each_reverse(l, &m->layers[layers_above_shell[i]], link) {
    636             if (locked || !l->layer_surface->current.keyboard_interactive || !l->mapped)
    637                 continue;
    638             /* Deactivate the focused client. */
    639             focusclient(NULL, 0);
    640             exclusive_focus = l;
    641             client_notify_enter(l->layer_surface->surface, wlr_seat_get_keyboard(seat));
    642             return;
    643         }
    644     }
    645 }
    646 
    647 void
    648 autostartexec(void) {
    649     const char *const *p;
    650     size_t i = 0;
    651 
    652     /* count entries */
    653     for (p = autostart; *p; autostart_len++, p++)
    654         while (*++p);
    655 
    656     autostart_pids = calloc(autostart_len, sizeof(pid_t));
    657     for (p = autostart; *p; i++, p++) {
    658         if ((autostart_pids[i] = fork()) == 0) {
    659             setsid();
    660             execvp(*p, (char *const *)p);
    661             die("dwl: execvp %s:", *p);
    662         }
    663         /* skip arguments */
    664         while (*++p);
    665     }
    666 }
    667 
    668 void
    669 axisnotify(struct wl_listener *listener, void *data)
    670 {
    671     /* This event is forwarded by the cursor when a pointer emits an axis event,
    672      * for example when you move the scroll wheel. */
    673     struct wlr_pointer_axis_event *event = data;
    674     wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
    675     /* TODO: allow usage of scroll whell for mousebindings, it can be implemented
    676      * checking the event's orientation and the delta of the event */
    677     /* Notify the client with pointer focus of the axis event. */
    678     wlr_seat_pointer_notify_axis(seat,
    679             event->time_msec, event->orientation, event->delta,
    680             event->delta_discrete, event->source);
    681 }
    682 
    683 void
    684 buttonpress(struct wl_listener *listener, void *data)
    685 {
    686     struct wlr_pointer_button_event *event = data;
    687     struct wlr_keyboard *keyboard;
    688     uint32_t mods;
    689     Client *c;
    690     const Button *b;
    691 
    692     wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
    693 
    694     switch (event->state) {
    695     case WLR_BUTTON_PRESSED:
    696         cursor_mode = CurPressed;
    697         held_grab = seat->pointer_state.focused_surface;
    698         if (locked)
    699             break;
    700 
    701         /* Change focus if the button was _pressed_ over a client */
    702         xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL);
    703         if (c && (!client_is_unmanaged(c) || client_wants_focus(c)))
    704             focusclient(c, 1);
    705 
    706         keyboard = wlr_seat_get_keyboard(seat);
    707         mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
    708         for (b = buttons; b < END(buttons); b++) {
    709             if (CLEANMASK(mods) == CLEANMASK(b->mod) &&
    710                     event->button == b->button && b->func) {
    711                 b->func(&b->arg);
    712                 return;
    713             }
    714         }
    715         break;
    716     case WLR_BUTTON_RELEASED:
    717         held_grab = NULL;
    718         /* If you released any buttons, we exit interactive move/resize mode. */
    719         /* TODO should reset to the pointer focus's current setcursor */
    720         if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) {
    721             wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
    722             cursor_mode = CurNormal;
    723             /* Drop the window off on its new monitor */
    724             selmon = xytomon(cursor->x, cursor->y);
    725             setmon(grabc, selmon, 0);
    726             return;
    727         } else {
    728             cursor_mode = CurNormal;
    729         }
    730         break;
    731     }
    732     /* If the event wasn't handled by the compositor, notify the client with
    733      * pointer focus that a button press has occurred */
    734     wlr_seat_pointer_notify_button(seat,
    735             event->time_msec, event->button, event->state);
    736 }
    737 
    738 void
    739 centeredmaster(Monitor *m)
    740 {
    741     int i, n, h, mw, mx, my, oty, ety, tw;
    742     Client *c;
    743 
    744     n = 0;
    745     wl_list_for_each(c, &clients, link)
    746         if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen)
    747             n++;
    748     if (n == 0)
    749         return;
    750 
    751     /* initialize areas */
    752     mw = m->w.width;
    753     mx = 0;
    754     my = 0;
    755     tw = mw;
    756 
    757     if (n > m->nmaster) {
    758         /* go mfact box in the center if more than nmaster clients */
    759         mw = m->nmaster ? (int) (m->w.width * m->mfact) : 0;
    760         tw = m->w.width - mw;
    761 
    762         if (n - m->nmaster > 1) {
    763             /* only one client */
    764             mx = (m->w.width - mw) / 2;
    765             tw = (m->w.width - mw) / 2;
    766         }
    767     }
    768 
    769     i = 0;
    770     oty = 0;
    771     ety = 0;
    772     wl_list_for_each(c, &clients, link) {
    773         if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
    774             continue;
    775         if (i < m->nmaster) {
    776             /* nmaster clients are stacked vertically, in the center
    777              * of the screen */
    778             h = (m->w.height - my) / (MIN(n, m->nmaster) - i);
    779             resize(c, (struct wlr_box){.x = m->w.x + mx, .y = m->w.y + my, .width = mw,
    780                    .height = h}, 0);
    781             my += c->geom.height;
    782         } else {
    783             /* stack clients are stacked vertically */
    784             if ((i - m->nmaster) % 2) {
    785                 h = (m->w.height - ety) / ( (1 + n - i) / 2);
    786                 resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + ety, .width = tw,
    787                        .height = h}, 0);
    788                 ety += c->geom.height;
    789             } else {
    790                 h = (m->w.height - oty) / ((1 + n - i) / 2);
    791                 resize(c, (struct wlr_box){.x = m->w.x + mx + mw, .y = m->w.y + oty, .width = tw,
    792                        .height = h}, 0);
    793                 oty += c->geom.height;
    794             }
    795         }
    796         i++;
    797     }
    798 }
    799 
    800 void
    801 chvt(const Arg *arg)
    802 {
    803     wlr_session_change_vt(session, arg->ui);
    804 }
    805 
    806 void
    807 checkidleinhibitor(struct wlr_surface *exclude)
    808 {
    809     int inhibited = 0, unused_lx, unused_ly;
    810     struct wlr_idle_inhibitor_v1 *inhibitor;
    811     wl_list_for_each(inhibitor, &idle_inhibit_mgr->inhibitors, link) {
    812         struct wlr_surface *surface = wlr_surface_get_root_surface(inhibitor->surface);
    813         struct wlr_scene_tree *tree = surface->data;
    814         if (exclude != surface && (bypass_surface_visibility || (!tree
    815                 || wlr_scene_node_coords(&tree->node, &unused_lx, &unused_ly)))) {
    816             inhibited = 1;
    817             break;
    818         }
    819     }
    820 
    821     wlr_idle_notifier_v1_set_inhibited(idle_notifier, inhibited);
    822 }
    823 
    824 void
    825 cleanup(void)
    826 {
    827     size_t i;
    828 #ifdef XWAYLAND
    829     wlr_xwayland_destroy(xwayland);
    830     xwayland = NULL;
    831 #endif
    832     wl_display_destroy_clients(dpy);
    833 
    834     /* kill child processes */
    835     for (i = 0; i < autostart_len; i++) {
    836         if (0 < autostart_pids[i]) {
    837             kill(autostart_pids[i], SIGTERM);
    838             waitpid(autostart_pids[i], NULL, 0);
    839         }
    840     }
    841 
    842     if (child_pid > 0) {
    843         kill(child_pid, SIGTERM);
    844         waitpid(child_pid, NULL, 0);
    845     }
    846     wlr_xcursor_manager_destroy(cursor_mgr);
    847     wlr_output_layout_destroy(output_layout);
    848 
    849     /* Remove event source that use the dpy event loop before destroying dpy */
    850     wl_event_source_remove(kb_group.key_repeat_source);
    851     wl_event_source_remove(vkb_group.key_repeat_source);
    852 
    853     wl_display_destroy(dpy);
    854     /* Destroy after the wayland display (when the monitors are already destroyed)
    855        to avoid destroying them with an invalid scene output. */
    856     wlr_scene_node_destroy(&scene->tree.node);
    857 }
    858 
    859 void
    860 cleanupmon(struct wl_listener *listener, void *data)
    861 {
    862     Monitor *m = wl_container_of(listener, m, destroy);
    863     LayerSurface *l, *tmp;
    864     size_t i;
    865 
    866     DwlIpcOutput *ipc_output, *ipc_output_tmp;
    867     wl_list_for_each_safe(ipc_output, ipc_output_tmp, &m->dwl_ipc_outputs, link)
    868         wl_resource_destroy(ipc_output->resource);
    869 
    870     /* m->layers[i] are intentionally not unlinked */
    871     for (i = 0; i < LENGTH(m->layers); i++) {
    872         wl_list_for_each_safe(l, tmp, &m->layers[i], link)
    873             wlr_layer_surface_v1_destroy(l->layer_surface);
    874     }
    875 
    876     wl_list_remove(&m->destroy.link);
    877     wl_list_remove(&m->frame.link);
    878     wl_list_remove(&m->link);
    879     wl_list_remove(&m->request_state.link);
    880     m->wlr_output->data = NULL;
    881     wlr_output_layout_remove(output_layout, m->wlr_output);
    882     wlr_scene_output_destroy(m->scene_output);
    883 
    884     closemon(m);
    885     wlr_scene_node_destroy(&m->fullscreen_bg->node);
    886     free(m);
    887 }
    888 
    889 void
    890 closemon(Monitor *m)
    891 {
    892     /* update selmon if needed and
    893      * move closed monitor's clients to the focused one */
    894     Client *c;
    895     int i = 0, nmons = wl_list_length(&mons);
    896     if (!nmons) {
    897         selmon = NULL;
    898     } else if (m == selmon) {
    899         do /* don't switch to disabled mons */
    900             selmon = wl_container_of(mons.next, selmon, link);
    901         while (!selmon->wlr_output->enabled && i++ < nmons);
    902     }
    903 
    904     wl_list_for_each(c, &clients, link) {
    905         if (c->isfloating && c->geom.x > m->m.width)
    906             resize(c, (struct wlr_box){.x = c->geom.x - m->w.width, .y = c->geom.y,
    907                     .width = c->geom.width, .height = c->geom.height}, 0);
    908         if (c->mon == m)
    909             setmon(c, selmon, c->tags);
    910     }
    911     focusclient(focustop(selmon), 1);
    912     printstatus();
    913 }
    914 
    915 void
    916 commitlayersurfacenotify(struct wl_listener *listener, void *data)
    917 {
    918     LayerSurface *l = wl_container_of(listener, l, surface_commit);
    919     struct wlr_layer_surface_v1 *layer_surface = l->layer_surface;
    920     struct wlr_scene_tree *scene_layer = layers[layermap[layer_surface->current.layer]];
    921 
    922     if (layer_surface->current.committed == 0 && l->mapped == layer_surface->surface->mapped)
    923         return;
    924     l->mapped = layer_surface->surface->mapped;
    925 
    926     if (scene_layer != l->scene->node.parent) {
    927         wlr_scene_node_reparent(&l->scene->node, scene_layer);
    928         wl_list_remove(&l->link);
    929         wl_list_insert(&l->mon->layers[layer_surface->current.layer], &l->link);
    930         wlr_scene_node_reparent(&l->popups->node, (layer_surface->current.layer
    931                 < ZWLR_LAYER_SHELL_V1_LAYER_TOP ? layers[LyrTop] : scene_layer));
    932     }
    933 
    934     arrangelayers(l->mon);
    935 }
    936 
    937 void
    938 commitnotify(struct wl_listener *listener, void *data)
    939 {
    940     Client *c = wl_container_of(listener, c, commit);
    941 
    942     if (client_surface(c)->mapped && c->mon)
    943         resize(c, c->geom, (c->isfloating && !c->isfullscreen));
    944 
    945     /* mark a pending resize as completed */
    946     if (c->resize && c->resize <= c->surface.xdg->current.configure_serial)
    947         c->resize = 0;
    948 }
    949 
    950 void
    951 createdecoration(struct wl_listener *listener, void *data)
    952 {
    953     struct wlr_xdg_toplevel_decoration_v1 *deco = data;
    954     Client *c = deco->toplevel->base->data;
    955     c->decoration = deco;
    956 
    957     LISTEN(&deco->events.request_mode, &c->set_decoration_mode, requestdecorationmode);
    958     LISTEN(&deco->events.destroy, &c->destroy_decoration, destroydecoration);
    959 
    960     requestdecorationmode(&c->set_decoration_mode, deco);
    961 }
    962 
    963 void
    964 createidleinhibitor(struct wl_listener *listener, void *data)
    965 {
    966     struct wlr_idle_inhibitor_v1 *idle_inhibitor = data;
    967     LISTEN_STATIC(&idle_inhibitor->events.destroy, destroyidleinhibitor);
    968 
    969     checkidleinhibitor(NULL);
    970 }
    971 
    972 void
    973 createkeyboard(struct wlr_keyboard *keyboard)
    974 {
    975     /* Set the keymap to match the group keymap */
    976     wlr_keyboard_set_keymap(keyboard, kb_group.wlr_group->keyboard.keymap);
    977     wlr_keyboard_set_repeat_info(keyboard, repeat_rate, repeat_delay);
    978 
    979     /* Add the new keyboard to the group */
    980     wlr_keyboard_group_add_keyboard(kb_group.wlr_group, keyboard);
    981 }
    982 
    983 void
    984 createlayersurface(struct wl_listener *listener, void *data)
    985 {
    986     struct wlr_layer_surface_v1 *layer_surface = data;
    987     LayerSurface *l;
    988     struct wlr_surface *surface = layer_surface->surface;
    989     struct wlr_scene_tree *scene_layer = layers[layermap[layer_surface->pending.layer]];
    990     struct wlr_layer_surface_v1_state old_state;
    991 
    992     if (!layer_surface->output
    993             && !(layer_surface->output = selmon ? selmon->wlr_output : NULL)) {
    994         wlr_layer_surface_v1_destroy(layer_surface);
    995         return;
    996     }
    997 
    998     l = layer_surface->data = ecalloc(1, sizeof(*l));
    999     l->type = LayerShell;
   1000     LISTEN(&surface->events.commit, &l->surface_commit, commitlayersurfacenotify);
   1001     LISTEN(&surface->events.map, &l->map, maplayersurfacenotify);
   1002     LISTEN(&surface->events.unmap, &l->unmap, unmaplayersurfacenotify);
   1003     LISTEN(&layer_surface->events.destroy, &l->destroy, destroylayersurfacenotify);
   1004 
   1005     l->layer_surface = layer_surface;
   1006     l->mon = layer_surface->output->data;
   1007     l->scene_layer = wlr_scene_layer_surface_v1_create(scene_layer, layer_surface);
   1008     l->scene = l->scene_layer->tree;
   1009     l->popups = surface->data = wlr_scene_tree_create(layer_surface->current.layer
   1010             < ZWLR_LAYER_SHELL_V1_LAYER_TOP ? layers[LyrTop] : scene_layer);
   1011     l->scene->node.data = l->popups->node.data = l;
   1012 
   1013     wl_list_insert(&l->mon->layers[layer_surface->pending.layer],&l->link);
   1014     wlr_surface_send_enter(surface, layer_surface->output);
   1015 
   1016     /* Temporarily set the layer's current state to pending
   1017      * so that we can easily arrange it
   1018      */
   1019     old_state = layer_surface->current;
   1020     layer_surface->current = layer_surface->pending;
   1021     l->mapped = 1;
   1022     arrangelayers(l->mon);
   1023     layer_surface->current = old_state;
   1024 }
   1025 
   1026 void
   1027 createlocksurface(struct wl_listener *listener, void *data)
   1028 {
   1029     SessionLock *lock = wl_container_of(listener, lock, new_surface);
   1030     struct wlr_session_lock_surface_v1 *lock_surface = data;
   1031     Monitor *m = lock_surface->output->data;
   1032     struct wlr_scene_tree *scene_tree = lock_surface->surface->data
   1033             = wlr_scene_subsurface_tree_create(lock->scene, lock_surface->surface);
   1034     m->lock_surface = lock_surface;
   1035 
   1036     wlr_scene_node_set_position(&scene_tree->node, m->m.x, m->m.y);
   1037     wlr_session_lock_surface_v1_configure(lock_surface, m->m.width, m->m.height);
   1038 
   1039     LISTEN(&lock_surface->events.destroy, &m->destroy_lock_surface, destroylocksurface);
   1040 
   1041     if (m == selmon)
   1042         client_notify_enter(lock_surface->surface, wlr_seat_get_keyboard(seat));
   1043 }
   1044 
   1045 void
   1046 createmon(struct wl_listener *listener, void *data)
   1047 {
   1048     /* This event is raised by the backend when a new output (aka a display or
   1049      * monitor) becomes available. */
   1050     struct wlr_output *wlr_output = data;
   1051     struct wlr_output_mode *mode = wl_container_of(wlr_output->modes.next, mode, link);
   1052     const MonitorRule *r;
   1053     size_t i;
   1054     struct wlr_output_state state;
   1055     Monitor *m;
   1056 
   1057     if (!wlr_output_init_render(wlr_output, alloc, drw))
   1058         return;
   1059 
   1060     m = wlr_output->data = ecalloc(1, sizeof(*m));
   1061     m->wlr_output = wlr_output;
   1062 
   1063     wl_list_init(&m->dwl_ipc_outputs);
   1064 
   1065     for (i = 0; i < LENGTH(m->layers); i++)
   1066         wl_list_init(&m->layers[i]);
   1067 
   1068     wlr_output_state_init(&state);
   1069     /* Initialize monitor state using configured rules */
   1070     m->gaps = gaps;
   1071 
   1072     m->tagset[0] = m->tagset[1] = 1;
   1073     for (r = monrules; r < END(monrules); r++) {
   1074         if (!r->name || strstr(wlr_output->name, r->name) || strstr(wlr_output->description, r->name)) {
   1075             m->m.x = r->x;
   1076             m->m.y = r->y;
   1077             m->mfact = r->mfact;
   1078             m->nmaster = r->nmaster;
   1079             m->lt[0] = r->lt;
   1080             m->lt[1] = &layouts[LENGTH(layouts) > 1 && r->lt != &layouts[1]];
   1081             strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol));
   1082             wlr_output_state_set_scale(&state, r->scale);
   1083             wlr_output_state_set_transform(&state, r->rr);
   1084 
   1085             wlr_output_state_set_adaptive_sync_enabled(&state, r->adaptive);
   1086 
   1087             if(r->mode == -1)
   1088                 wlr_output_state_set_custom_mode(&state, r->resx, r->resy,
   1089                 (int) (r->rate > 0 ? r->rate * 1000 : 0));
   1090             else if (!wl_list_empty(&wlr_output->modes)) {
   1091                 for (int j = 0; j < r->mode; j++) {
   1092                     mode = wl_container_of(mode->link.next, mode, link);
   1093                 }
   1094                 wlr_output_state_set_mode(&state, mode);
   1095             }
   1096 
   1097             break;
   1098         }
   1099     }
   1100 
   1101     wlr_output_init_render(wlr_output, alloc, drw);
   1102 
   1103     /* Set up event listeners */
   1104     LISTEN(&wlr_output->events.frame, &m->frame, rendermon);
   1105     LISTEN(&wlr_output->events.destroy, &m->destroy, cleanupmon);
   1106     LISTEN(&wlr_output->events.request_state, &m->request_state, requestmonstate);
   1107 
   1108     wlr_output_state_set_enabled(&state, 1);
   1109     wlr_output_commit_state(wlr_output, &state);
   1110     wlr_output_state_finish(&state);
   1111 
   1112     wl_list_insert(&mons, &m->link);
   1113     printstatus();
   1114 
   1115     /* The xdg-protocol specifies:
   1116      *
   1117      * If the fullscreened surface is not opaque, the compositor must make
   1118      * sure that other screen content not part of the same surface tree (made
   1119      * up of subsurfaces, popups or similarly coupled surfaces) are not
   1120      * visible below the fullscreened surface.
   1121      *
   1122      */
   1123     /* updatemons() will resize and set correct position */
   1124     m->fullscreen_bg = wlr_scene_rect_create(layers[LyrFS], 0, 0, fullscreen_bg);
   1125     wlr_scene_node_set_enabled(&m->fullscreen_bg->node, 0);
   1126 
   1127     /* Adds this to the output layout in the order it was configured in.
   1128      *
   1129      * The output layout utility automatically adds a wl_output global to the
   1130      * display, which Wayland clients can see to find out information about the
   1131      * output (such as DPI, scale factor, manufacturer, etc).
   1132      */
   1133     m->scene_output = wlr_scene_output_create(scene, wlr_output);
   1134     if (m->m.x < 0 || m->m.y < 0)
   1135         wlr_output_layout_add_auto(output_layout, wlr_output);
   1136     else
   1137         wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y);
   1138 }
   1139 
   1140 void
   1141 createnotify(struct wl_listener *listener, void *data)
   1142 {
   1143     /* This event is raised when wlr_xdg_shell receives a new xdg surface from a
   1144      * client, either a toplevel (application window) or popup,
   1145      * or when wlr_layer_shell receives a new popup from a layer.
   1146      * If you want to do something tricky with popups you should check if
   1147      * its parent is wlr_xdg_shell or wlr_layer_shell */
   1148     struct wlr_xdg_surface *xdg_surface = data;
   1149     Client *c = NULL;
   1150     LayerSurface *l = NULL;
   1151 
   1152     if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
   1153         struct wlr_xdg_popup *popup = xdg_surface->popup;
   1154         struct wlr_box box;
   1155         if (toplevel_from_wlr_surface(popup->base->surface, &c, &l) < 0)
   1156             return;
   1157         popup->base->surface->data = wlr_scene_xdg_surface_create(
   1158                 popup->parent->data, popup->base);
   1159         if ((l && !l->mon) || (c && !c->mon))
   1160             return;
   1161         box = l ? l->mon->m : c->mon->w;
   1162         box.x -= (l ? l->geom.x : c->geom.x);
   1163         box.y -= (l ? l->geom.y : c->geom.y);
   1164         wlr_xdg_popup_unconstrain_from_box(popup, &box);
   1165         return;
   1166     } else if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_NONE)
   1167         return;
   1168 
   1169     /* Allocate a Client for this surface */
   1170     c = xdg_surface->data = ecalloc(1, sizeof(*c));
   1171     c->surface.xdg = xdg_surface;
   1172     c->bw = borderpx;
   1173 
   1174     wlr_xdg_toplevel_set_wm_capabilities(xdg_surface->toplevel,
   1175             WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
   1176 
   1177     LISTEN(&xdg_surface->events.destroy, &c->destroy, destroynotify);
   1178     LISTEN(&xdg_surface->surface->events.commit, &c->commit, commitnotify);
   1179     LISTEN(&xdg_surface->surface->events.map, &c->map, mapnotify);
   1180     LISTEN(&xdg_surface->surface->events.unmap, &c->unmap, unmapnotify);
   1181     LISTEN(&xdg_surface->toplevel->events.request_fullscreen, &c->fullscreen,
   1182             fullscreennotify);
   1183     LISTEN(&xdg_surface->toplevel->events.request_maximize, &c->maximize,
   1184             maximizenotify);
   1185     LISTEN(&xdg_surface->toplevel->events.set_title, &c->set_title, updatetitle);
   1186 }
   1187 
   1188 void
   1189 createpointer(struct wlr_pointer *pointer)
   1190 {
   1191     struct libinput_device *device;
   1192     if (wlr_input_device_is_libinput(&pointer->base)
   1193             && (device = wlr_libinput_get_device_handle(&pointer->base))) {
   1194 
   1195         if (libinput_device_config_tap_get_finger_count(device)) {
   1196             libinput_device_config_tap_set_enabled(device, tap_to_click);
   1197             libinput_device_config_tap_set_drag_enabled(device, tap_and_drag);
   1198             libinput_device_config_tap_set_drag_lock_enabled(device, drag_lock);
   1199             libinput_device_config_tap_set_button_map(device, button_map);
   1200         }
   1201 
   1202         if (libinput_device_config_scroll_has_natural_scroll(device))
   1203             libinput_device_config_scroll_set_natural_scroll_enabled(device, natural_scrolling);
   1204 
   1205         if (libinput_device_config_dwt_is_available(device))
   1206             libinput_device_config_dwt_set_enabled(device, disable_while_typing);
   1207 
   1208         if (libinput_device_config_left_handed_is_available(device))
   1209             libinput_device_config_left_handed_set(device, left_handed);
   1210 
   1211         if (libinput_device_config_middle_emulation_is_available(device))
   1212             libinput_device_config_middle_emulation_set_enabled(device, middle_button_emulation);
   1213 
   1214         if (libinput_device_config_scroll_get_methods(device) != LIBINPUT_CONFIG_SCROLL_NO_SCROLL)
   1215             libinput_device_config_scroll_set_method (device, scroll_method);
   1216 
   1217         if (libinput_device_config_click_get_methods(device) != LIBINPUT_CONFIG_CLICK_METHOD_NONE)
   1218             libinput_device_config_click_set_method (device, click_method);
   1219 
   1220         if (libinput_device_config_send_events_get_modes(device))
   1221             libinput_device_config_send_events_set_mode(device, send_events_mode);
   1222 
   1223         if (libinput_device_config_accel_is_available(device)) {
   1224             libinput_device_config_accel_set_profile(device, accel_profile);
   1225             libinput_device_config_accel_set_speed(device, accel_speed);
   1226         }
   1227     }
   1228 
   1229     wlr_cursor_attach_input_device(cursor, &pointer->base);
   1230 }
   1231 
   1232 void
   1233 createpointerconstraint(struct wl_listener *listener, void *data)
   1234 {
   1235     PointerConstraint *pointer_constraint = ecalloc(1, sizeof(*pointer_constraint));
   1236     pointer_constraint->constraint = data;
   1237     LISTEN(&pointer_constraint->constraint->events.destroy,
   1238             &pointer_constraint->destroy, destroypointerconstraint);
   1239 }
   1240 
   1241 void
   1242 cursorconstrain(struct wlr_pointer_constraint_v1 *constraint)
   1243 {
   1244     if (active_constraint == constraint)
   1245         return;
   1246 
   1247     if (active_constraint)
   1248         wlr_pointer_constraint_v1_send_deactivated(active_constraint);
   1249 
   1250     active_constraint = constraint;
   1251     wlr_pointer_constraint_v1_send_activated(constraint);
   1252 }
   1253 
   1254 void
   1255 cursorframe(struct wl_listener *listener, void *data)
   1256 {
   1257     /* This event is forwarded by the cursor when a pointer emits an frame
   1258      * event. Frame events are sent after regular pointer events to group
   1259      * multiple events together. For instance, two axis events may happen at the
   1260      * same time, in which case a frame event won't be sent in between. */
   1261     /* Notify the client with pointer focus of the frame event. */
   1262     wlr_seat_pointer_notify_frame(seat);
   1263 }
   1264 
   1265 void cursorwarptocenter(void)
   1266 {
   1267     wlr_cursor_warp_closest(cursor, NULL,
   1268                             selmon->w.x + selmon->w.width / 2,
   1269                             selmon->w.y + selmon->w.height / 2);
   1270 }
   1271 
   1272 void
   1273 cursorwarptohint(void)
   1274 {
   1275     Client *c = NULL;
   1276     double sx = active_constraint->current.cursor_hint.x;
   1277     double sy = active_constraint->current.cursor_hint.y;
   1278 
   1279     toplevel_from_wlr_surface(active_constraint->surface, &c, NULL);
   1280     /* TODO: wlroots 0.18: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4478 */
   1281     if (c && (active_constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT )) {
   1282         wlr_cursor_warp(cursor, NULL, sx + c->geom.x + c->bw, sy + c->geom.y + c->bw);
   1283         wlr_seat_pointer_warp(active_constraint->seat, sx, sy);
   1284     }
   1285 }
   1286 
   1287 void
   1288 destroydecoration(struct wl_listener *listener, void *data)
   1289 {
   1290     Client *c = wl_container_of(listener, c, destroy_decoration);
   1291 
   1292     wl_list_remove(&c->destroy_decoration.link);
   1293     wl_list_remove(&c->set_decoration_mode.link);
   1294 }
   1295 
   1296 void
   1297 destroydragicon(struct wl_listener *listener, void *data)
   1298 {
   1299     /* Focus enter isn't sent during drag, so refocus the focused node. */
   1300     focusclient(focustop(selmon), 1);
   1301     motionnotify(0, NULL, 0, 0, 0, 0);
   1302 }
   1303 
   1304 void
   1305 destroyidleinhibitor(struct wl_listener *listener, void *data)
   1306 {
   1307     /* `data` is the wlr_surface of the idle inhibitor being destroyed,
   1308      * at this point the idle inhibitor is still in the list of the manager */
   1309     checkidleinhibitor(wlr_surface_get_root_surface(data));
   1310 }
   1311 
   1312 void
   1313 destroylayersurfacenotify(struct wl_listener *listener, void *data)
   1314 {
   1315     LayerSurface *l = wl_container_of(listener, l, destroy);
   1316 
   1317     wl_list_remove(&l->link);
   1318     wl_list_remove(&l->destroy.link);
   1319     wl_list_remove(&l->map.link);
   1320     wl_list_remove(&l->unmap.link);
   1321     wl_list_remove(&l->surface_commit.link);
   1322     wlr_scene_node_destroy(&l->scene->node);
   1323     wlr_scene_node_destroy(&l->popups->node);
   1324     free(l);
   1325 }
   1326 
   1327 void
   1328 destroylock(SessionLock *lock, int unlock)
   1329 {
   1330     wlr_seat_keyboard_notify_clear_focus(seat);
   1331     if ((locked = !unlock))
   1332         goto destroy;
   1333 
   1334     wlr_scene_node_set_enabled(&locked_bg->node, 0);
   1335 
   1336     focusclient(focustop(selmon), 0);
   1337     motionnotify(0, NULL, 0, 0, 0, 0);
   1338 
   1339 destroy:
   1340     wl_list_remove(&lock->new_surface.link);
   1341     wl_list_remove(&lock->unlock.link);
   1342     wl_list_remove(&lock->destroy.link);
   1343 
   1344     wlr_scene_node_destroy(&lock->scene->node);
   1345     cur_lock = NULL;
   1346     free(lock);
   1347 }
   1348 
   1349 void
   1350 destroylocksurface(struct wl_listener *listener, void *data)
   1351 {
   1352     Monitor *m = wl_container_of(listener, m, destroy_lock_surface);
   1353     struct wlr_session_lock_surface_v1 *surface, *lock_surface = m->lock_surface;
   1354 
   1355     m->lock_surface = NULL;
   1356     wl_list_remove(&m->destroy_lock_surface.link);
   1357 
   1358     if (lock_surface->surface != seat->keyboard_state.focused_surface)
   1359         return;
   1360 
   1361     if (locked && cur_lock && !wl_list_empty(&cur_lock->surfaces)) {
   1362         surface = wl_container_of(cur_lock->surfaces.next, surface, link);
   1363         client_notify_enter(surface->surface, wlr_seat_get_keyboard(seat));
   1364     } else if (!locked) {
   1365         focusclient(focustop(selmon), 1);
   1366     } else {
   1367         wlr_seat_keyboard_clear_focus(seat);
   1368     }
   1369 }
   1370 
   1371 void
   1372 destroynotify(struct wl_listener *listener, void *data)
   1373 {
   1374     /* Called when the xdg_toplevel is destroyed. */
   1375     Client *c = wl_container_of(listener, c, destroy);
   1376     wl_list_remove(&c->destroy.link);
   1377     wl_list_remove(&c->set_title.link);
   1378     wl_list_remove(&c->fullscreen.link);
   1379 #ifdef XWAYLAND
   1380     if (c->type != XDGShell) {
   1381         wl_list_remove(&c->activate.link);
   1382         wl_list_remove(&c->associate.link);
   1383         wl_list_remove(&c->configure.link);
   1384         wl_list_remove(&c->dissociate.link);
   1385         wl_list_remove(&c->set_hints.link);
   1386     } else
   1387 #endif
   1388     {
   1389         wl_list_remove(&c->commit.link);
   1390         wl_list_remove(&c->map.link);
   1391         wl_list_remove(&c->unmap.link);
   1392     }
   1393     free(c);
   1394 }
   1395 
   1396 void
   1397 destroypointerconstraint(struct wl_listener *listener, void *data)
   1398 {
   1399     PointerConstraint *pointer_constraint = wl_container_of(listener, pointer_constraint, destroy);
   1400 
   1401     if (active_constraint == pointer_constraint->constraint) {
   1402         cursorwarptohint();
   1403         active_constraint = NULL;
   1404     }
   1405 
   1406     wl_list_remove(&pointer_constraint->destroy.link);
   1407     free(pointer_constraint);
   1408 }
   1409 
   1410 void
   1411 destroysessionlock(struct wl_listener *listener, void *data)
   1412 {
   1413     SessionLock *lock = wl_container_of(listener, lock, destroy);
   1414     destroylock(lock, 0);
   1415 }
   1416 
   1417 void
   1418 destroysessionmgr(struct wl_listener *listener, void *data)
   1419 {
   1420     wl_list_remove(&lock_listener.link);
   1421     wl_list_remove(&listener->link);
   1422 }
   1423 
   1424 Monitor *
   1425 dirtomon(enum wlr_direction dir)
   1426 {
   1427     struct wlr_output *next;
   1428     if (!wlr_output_layout_get(output_layout, selmon->wlr_output))
   1429         return selmon;
   1430     if ((next = wlr_output_layout_adjacent_output(output_layout,
   1431             dir, selmon->wlr_output, selmon->m.x, selmon->m.y)))
   1432         return next->data;
   1433     if ((next = wlr_output_layout_farthest_output(output_layout,
   1434             dir ^ (WLR_DIRECTION_LEFT|WLR_DIRECTION_RIGHT),
   1435             selmon->wlr_output, selmon->m.x, selmon->m.y)))
   1436         return next->data;
   1437     return selmon;
   1438 }
   1439 
   1440 void
   1441 dwl_ipc_manager_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
   1442 {
   1443     struct wl_resource *manager_resource = wl_resource_create(client, &zdwl_ipc_manager_v2_interface, version, id);
   1444     if (!manager_resource) {
   1445         wl_client_post_no_memory(client);
   1446         return;
   1447     }
   1448     wl_resource_set_implementation(manager_resource, &dwl_manager_implementation, NULL, dwl_ipc_manager_destroy);
   1449 
   1450     zdwl_ipc_manager_v2_send_tags(manager_resource, TAGCOUNT);
   1451 
   1452     for (unsigned int i = 0; i < LENGTH(layouts); i++)
   1453         zdwl_ipc_manager_v2_send_layout(manager_resource, layouts[i].symbol);
   1454 }
   1455 
   1456 void
   1457 dwl_ipc_manager_destroy(struct wl_resource *resource)
   1458 {
   1459     /* No state to destroy */
   1460 }
   1461 
   1462 void
   1463 dwl_ipc_manager_get_output(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *output)
   1464 {
   1465     DwlIpcOutput *ipc_output;
   1466     Monitor *monitor = wlr_output_from_resource(output)->data;
   1467     struct wl_resource *output_resource = wl_resource_create(client, &zdwl_ipc_output_v2_interface, wl_resource_get_version(resource), id);
   1468     if (!output_resource)
   1469         return;
   1470 
   1471     ipc_output = ecalloc(1, sizeof(*ipc_output));
   1472     ipc_output->resource = output_resource;
   1473     ipc_output->mon = monitor;
   1474     wl_resource_set_implementation(output_resource, &dwl_output_implementation, ipc_output, dwl_ipc_output_destroy);
   1475     wl_list_insert(&monitor->dwl_ipc_outputs, &ipc_output->link);
   1476     dwl_ipc_output_printstatus_to(ipc_output);
   1477 }
   1478 
   1479 void
   1480 dwl_ipc_manager_release(struct wl_client *client, struct wl_resource *resource)
   1481 {
   1482     wl_resource_destroy(resource);
   1483 }
   1484 
   1485 static void
   1486 dwl_ipc_output_destroy(struct wl_resource *resource)
   1487 {
   1488     DwlIpcOutput *ipc_output = wl_resource_get_user_data(resource);
   1489     wl_list_remove(&ipc_output->link);
   1490     free(ipc_output);
   1491 }
   1492 
   1493 void
   1494 dwl_ipc_output_printstatus(Monitor *monitor)
   1495 {
   1496     DwlIpcOutput *ipc_output;
   1497     wl_list_for_each(ipc_output, &monitor->dwl_ipc_outputs, link)
   1498         dwl_ipc_output_printstatus_to(ipc_output);
   1499 }
   1500 
   1501 void
   1502 dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output)
   1503 {
   1504     Monitor *monitor = ipc_output->mon;
   1505     Client *c, *focused;
   1506     int tagmask, state, numclients, focused_client, tag;
   1507     const char *title, *appid;
   1508     focused = focustop(monitor);
   1509     zdwl_ipc_output_v2_send_active(ipc_output->resource, monitor == selmon);
   1510 
   1511     for (tag = 0 ; tag < TAGCOUNT; tag++) {
   1512         numclients = state = focused_client = 0;
   1513         tagmask = 1 << tag;
   1514         if ((tagmask & monitor->tagset[monitor->seltags]) != 0)
   1515             state |= ZDWL_IPC_OUTPUT_V2_TAG_STATE_ACTIVE;
   1516 
   1517         wl_list_for_each(c, &clients, link) {
   1518             if (c->mon != monitor)
   1519                 continue;
   1520             if (!(c->tags & tagmask))
   1521                 continue;
   1522             if (c == focused)
   1523                 focused_client = 1;
   1524             if (c->isurgent)
   1525                 state |= ZDWL_IPC_OUTPUT_V2_TAG_STATE_URGENT;
   1526 
   1527             numclients++;
   1528         }
   1529         zdwl_ipc_output_v2_send_tag(ipc_output->resource, tag, state, numclients, focused_client);
   1530     }
   1531     title = focused ? client_get_title(focused) : "";
   1532     appid = focused ? client_get_appid(focused) : "";
   1533 
   1534     zdwl_ipc_output_v2_send_layout(ipc_output->resource, monitor->lt[monitor->sellt] - layouts);
   1535     zdwl_ipc_output_v2_send_title(ipc_output->resource, title ? title : broken);
   1536     zdwl_ipc_output_v2_send_appid(ipc_output->resource, appid ? appid : broken);
   1537     zdwl_ipc_output_v2_send_layout_symbol(ipc_output->resource, monitor->ltsymbol);
   1538     if (wl_resource_get_version(ipc_output->resource) >= ZDWL_IPC_OUTPUT_V2_FULLSCREEN_SINCE_VERSION) {
   1539         zdwl_ipc_output_v2_send_fullscreen(ipc_output->resource, focused ? focused->isfullscreen : 0);
   1540     }
   1541     if (wl_resource_get_version(ipc_output->resource) >= ZDWL_IPC_OUTPUT_V2_FLOATING_SINCE_VERSION) {
   1542         zdwl_ipc_output_v2_send_floating(ipc_output->resource, focused ? focused->isfloating : 0);
   1543     }
   1544     zdwl_ipc_output_v2_send_frame(ipc_output->resource);
   1545 }
   1546 
   1547 void
   1548 dwl_ipc_output_set_client_tags(struct wl_client *client, struct wl_resource *resource, uint32_t and_tags, uint32_t xor_tags)
   1549 {
   1550     DwlIpcOutput *ipc_output;
   1551     Monitor *monitor;
   1552     Client *selected_client;
   1553     unsigned int newtags = 0;
   1554 
   1555     ipc_output = wl_resource_get_user_data(resource);
   1556     if (!ipc_output)
   1557         return;
   1558 
   1559     monitor = ipc_output->mon;
   1560     selected_client = focustop(monitor);
   1561     if (!selected_client)
   1562         return;
   1563 
   1564     newtags = (selected_client->tags & and_tags) ^ xor_tags;
   1565     if (!newtags)
   1566         return;
   1567 
   1568     selected_client->tags = newtags;
   1569     focusclient(focustop(selmon), 1);
   1570     arrange(selmon);
   1571     printstatus();
   1572 }
   1573 
   1574 void
   1575 dwl_ipc_output_set_layout(struct wl_client *client, struct wl_resource *resource, uint32_t index)
   1576 {
   1577     DwlIpcOutput *ipc_output;
   1578     Monitor *monitor;
   1579 
   1580     ipc_output = wl_resource_get_user_data(resource);
   1581     if (!ipc_output)
   1582         return;
   1583 
   1584     monitor = ipc_output->mon;
   1585     if (index >= LENGTH(layouts))
   1586         return;
   1587     if (index != monitor->lt[monitor->sellt] - layouts)
   1588         monitor->sellt ^= 1;
   1589 
   1590     monitor->lt[monitor->sellt] = &layouts[index];
   1591     arrange(monitor);
   1592     printstatus();
   1593 }
   1594 
   1595 void
   1596 dwl_ipc_output_set_tags(struct wl_client *client, struct wl_resource *resource, uint32_t tagmask, uint32_t toggle_tagset)
   1597 {
   1598     DwlIpcOutput *ipc_output;
   1599     Monitor *monitor;
   1600     unsigned int newtags = tagmask & TAGMASK;
   1601 
   1602     ipc_output = wl_resource_get_user_data(resource);
   1603     if (!ipc_output)
   1604         return;
   1605     monitor = ipc_output->mon;
   1606 
   1607     if (!newtags || newtags == monitor->tagset[monitor->seltags])
   1608         return;
   1609     if (toggle_tagset)
   1610         monitor->seltags ^= 1;
   1611 
   1612     monitor->tagset[monitor->seltags] = newtags;
   1613     focusclient(focustop(monitor), 1);
   1614     arrange(monitor);
   1615     printstatus();
   1616 }
   1617 
   1618 void
   1619 dwl_ipc_output_release(struct wl_client *client, struct wl_resource *resource)
   1620 {
   1621     wl_resource_destroy(resource);
   1622 }
   1623 
   1624 void
   1625 focusclient(Client *c, int lift)
   1626 {
   1627     struct wlr_surface *old = seat->keyboard_state.focused_surface;
   1628     int unused_lx, unused_ly, old_client_type;
   1629     Client *old_c = NULL;
   1630     LayerSurface *old_l = NULL;
   1631 
   1632     if (locked)
   1633         return;
   1634 
   1635     /* Raise client in stacking order if requested */
   1636     if (c && lift)
   1637         wlr_scene_node_raise_to_top(&c->scene->node);
   1638 
   1639     if (c && client_surface(c) == old)
   1640         return;
   1641 
   1642     if ((old_client_type = toplevel_from_wlr_surface(old, &old_c, &old_l)) == XDGShell) {
   1643         struct wlr_xdg_popup *popup, *tmp;
   1644         wl_list_for_each_safe(popup, tmp, &old_c->surface.xdg->popups, link)
   1645             wlr_xdg_popup_destroy(popup);
   1646     }
   1647 
   1648     /* Put the new client atop the focus stack and select its monitor */
   1649     if (c && !client_is_unmanaged(c)) {
   1650         wl_list_remove(&c->flink);
   1651         wl_list_insert(&fstack, &c->flink);
   1652         selmon = c->mon;
   1653         c->isurgent = 0;
   1654         client_restack_surface(c);
   1655 
   1656         /* Don't change border color if there is an exclusive focus or we are
   1657          * handling a drag operation */
   1658         if (!exclusive_focus && !seat->drag)
   1659             client_set_border_color(c, focuscolor);
   1660     }
   1661 
   1662     /* Deactivate old client if focus is changing */
   1663     if (old && (!c || client_surface(c) != old)) {
   1664         /* If an overlay is focused, don't focus or activate the client,
   1665          * but only update its position in fstack to render its border with focuscolor
   1666          * and focus it after the overlay is closed. */
   1667         if (old_client_type == LayerShell && wlr_scene_node_coords(
   1668                     &old_l->scene->node, &unused_lx, &unused_ly)
   1669                 && old_l->layer_surface->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) {
   1670             return;
   1671         } else if (old_c && old_c == exclusive_focus && client_wants_focus(old_c)) {
   1672             return;
   1673         /* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg
   1674          * and probably other clients */
   1675         } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) {
   1676             client_set_border_color(old_c, bordercolor);
   1677 
   1678             client_activate_surface(old, 0);
   1679         }
   1680     }
   1681     printstatus();
   1682 
   1683     if (!c) {
   1684         /* With no client, all we have left is to clear focus */
   1685         wlr_seat_keyboard_notify_clear_focus(seat);
   1686         return;
   1687     }
   1688 
   1689     /* Change cursor surface */
   1690     motionnotify(0, NULL, 0, 0, 0, 0);
   1691 
   1692     /* Have a client, so focus its top-level wlr_surface */
   1693     client_notify_enter(client_surface(c), wlr_seat_get_keyboard(seat));
   1694 
   1695     /* Activate the new client */
   1696     client_activate_surface(client_surface(c), 1);
   1697 }
   1698 
   1699 void
   1700 focusmon(const Arg *arg)
   1701 {
   1702     int i = 0, nmons = wl_list_length(&mons);
   1703     if (nmons) {
   1704         do /* don't switch to disabled mons */
   1705             selmon = dirtomon(arg->i);
   1706         while (!selmon->wlr_output->enabled && i++ < nmons);
   1707     }
   1708     cursorwarptocenter();
   1709     focusclient(focustop(selmon), 1);
   1710 }
   1711 
   1712 void
   1713 focusstack(const Arg *arg)
   1714 {
   1715     /* Focus the next or previous client (in tiling order) on selmon */
   1716     Client *c, *sel = focustop(selmon);
   1717     if (!sel || (sel->isfullscreen && !client_has_children(sel)))
   1718         return;
   1719     if (arg->i > 0) {
   1720         wl_list_for_each(c, &sel->link, link) {
   1721             if (&c->link == &clients)
   1722                 continue; /* wrap past the sentinel node */
   1723             if (VISIBLEON(c, selmon))
   1724                 break; /* found it */
   1725         }
   1726     } else {
   1727         wl_list_for_each_reverse(c, &sel->link, link) {
   1728             if (&c->link == &clients)
   1729                 continue; /* wrap past the sentinel node */
   1730             if (VISIBLEON(c, selmon))
   1731                 break; /* found it */
   1732         }
   1733     }
   1734     /* If only one client is visible on selmon, then c == sel */
   1735     focusclient(c, 1);
   1736 }
   1737 
   1738 /* We probably should change the name of this, it sounds like
   1739  * will focus the topmost client of this mon, when actually will
   1740  * only return that client */
   1741 Client *
   1742 focustop(Monitor *m)
   1743 {
   1744     Client *c;
   1745     wl_list_for_each(c, &fstack, flink) {
   1746         if (VISIBLEON(c, m))
   1747             return c;
   1748     }
   1749     return NULL;
   1750 }
   1751 
   1752 void
   1753 fullscreennotify(struct wl_listener *listener, void *data)
   1754 {
   1755     Client *c = wl_container_of(listener, c, fullscreen);
   1756     setfullscreen(c, client_wants_fullscreen(c));
   1757 }
   1758 
   1759 void
   1760 handlesig(int signo)
   1761 {
   1762     if (signo == SIGCHLD) {
   1763         siginfo_t in;
   1764         /* wlroots expects to reap the XWayland process itself, so we
   1765          * use WNOWAIT to keep the child waitable until we know it's not
   1766          * XWayland.
   1767          */
   1768         while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid
   1769 #ifdef XWAYLAND
   1770                && (!xwayland || in.si_pid != xwayland->server->pid)
   1771 #endif
   1772                ) {
   1773             pid_t *p, *lim;
   1774             waitpid(in.si_pid, NULL, 0);
   1775             if (in.si_pid == child_pid)
   1776                 child_pid = -1;
   1777             if (!(p = autostart_pids))
   1778                 continue;
   1779             lim = &p[autostart_len];
   1780 
   1781             for (; p < lim; p++) {
   1782                 if (*p == in.si_pid) {
   1783                     *p = -1;
   1784                     break;
   1785                 }
   1786             }
   1787         }
   1788     } else if (signo == SIGINT || signo == SIGTERM) {
   1789         quit(NULL);
   1790     }
   1791 }
   1792 
   1793 pid_t
   1794 getparentprocess(pid_t p)
   1795 {
   1796     unsigned int v = 0;
   1797 
   1798     FILE *f;
   1799     char buf[256];
   1800     snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p);
   1801 
   1802     if (!(f = fopen(buf, "r")))
   1803         return 0;
   1804 
   1805     fscanf(f, "%*u %*s %*c %u", &v);
   1806     fclose(f);
   1807 
   1808     return (pid_t)v;
   1809 }
   1810 
   1811 int
   1812 isdescprocess(pid_t p, pid_t c)
   1813 {
   1814     while (p != c && c != 0)
   1815         c = getparentprocess(c);
   1816 
   1817     return (int)c;
   1818 }
   1819 
   1820 Client *
   1821 termforwin(Client *w)
   1822 {
   1823     Client *c;
   1824 
   1825     if (!w->pid || w->isterm || w->noswallow)
   1826         return NULL;
   1827 
   1828     wl_list_for_each(c, &fstack, flink)
   1829         if (c->isterm && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid))
   1830             return c;
   1831 
   1832     return NULL;
   1833 }
   1834 
   1835 void
   1836 swallow(Client *c, Client *w)
   1837 {
   1838     c->bw = w->bw;
   1839     c->isfloating = w->isfloating;
   1840     c->isurgent = w->isurgent;
   1841     c->isfullscreen = w->isfullscreen;
   1842     c->tags = w->tags;
   1843     c->geom = w->geom;
   1844     wl_list_insert(&w->link, &c->link);
   1845     wl_list_insert(&w->flink, &c->flink);
   1846     wlr_scene_node_set_enabled(&w->scene->node, 0);
   1847     wlr_scene_node_set_enabled(&c->scene->node, 1);
   1848 }
   1849 
   1850 void
   1851 incnmaster(const Arg *arg)
   1852 {
   1853     if (!arg || !selmon)
   1854         return;
   1855     selmon->nmaster = MAX(selmon->nmaster + arg->i, 0);
   1856     arrange(selmon);
   1857 }
   1858 
   1859 void
   1860 inputdevice(struct wl_listener *listener, void *data)
   1861 {
   1862     /* This event is raised by the backend when a new input device becomes
   1863      * available. */
   1864     struct wlr_input_device *device = data;
   1865     uint32_t caps;
   1866 
   1867     switch (device->type) {
   1868     case WLR_INPUT_DEVICE_KEYBOARD:
   1869         createkeyboard(wlr_keyboard_from_input_device(device));
   1870         break;
   1871     case WLR_INPUT_DEVICE_POINTER:
   1872         createpointer(wlr_pointer_from_input_device(device));
   1873         break;
   1874     default:
   1875         /* TODO handle other input device types */
   1876         break;
   1877     }
   1878 
   1879     /* We need to let the wlr_seat know what our capabilities are, which is
   1880      * communiciated to the client. In dwl we always have a cursor, even if
   1881      * there are no pointer devices, so we always include that capability. */
   1882     /* TODO do we actually require a cursor? */
   1883     caps = WL_SEAT_CAPABILITY_POINTER;
   1884     if (!wl_list_empty(&kb_group.wlr_group->devices))
   1885         caps |= WL_SEAT_CAPABILITY_KEYBOARD;
   1886     wlr_seat_set_capabilities(seat, caps);
   1887 }
   1888 
   1889 int
   1890 keybinding(uint32_t mods, xkb_keysym_t sym)
   1891 {
   1892     /*
   1893      * Here we handle compositor keybindings. This is when the compositor is
   1894      * processing keys, rather than passing them on to the client for its own
   1895      * processing.
   1896      */
   1897     const Key *k;
   1898     for (k = keys; k < END(keys); k++) {
   1899         if (CLEANMASK(mods) == CLEANMASK(k->mod)
   1900                 && sym == k->keysym && k->func) {
   1901             k->func(&k->arg);
   1902             return 1;
   1903         }
   1904     }
   1905     return 0;
   1906 }
   1907 
   1908 void
   1909 keypress(struct wl_listener *listener, void *data)
   1910 {
   1911     int i;
   1912     /* This event is raised when a key is pressed or released. */
   1913     KeyboardGroup *group = wl_container_of(listener, group, key);
   1914     struct wlr_keyboard_key_event *event = data;
   1915 
   1916     /* Translate libinput keycode -> xkbcommon */
   1917     uint32_t keycode = event->keycode + 8;
   1918     /* Get a list of keysyms based on the keymap for this keyboard */
   1919     const xkb_keysym_t *syms;
   1920     int nsyms = xkb_state_key_get_syms(
   1921             group->wlr_group->keyboard.xkb_state, keycode, &syms);
   1922 
   1923     int handled = 0;
   1924     uint32_t mods = wlr_keyboard_get_modifiers(&group->wlr_group->keyboard);
   1925 
   1926     wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
   1927 
   1928     /* On _press_ if there is no active screen locker,
   1929      * attempt to process a compositor keybinding. */
   1930     if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
   1931         for (i = 0; i < nsyms; i++)
   1932             handled = keybinding(mods, syms[i]) || handled;
   1933     }
   1934 
   1935     if (handled && group->wlr_group->keyboard.repeat_info.delay > 0) {
   1936         group->mods = mods;
   1937         group->keysyms = syms;
   1938         group->nsyms = nsyms;
   1939         wl_event_source_timer_update(group->key_repeat_source,
   1940                 group->wlr_group->keyboard.repeat_info.delay);
   1941     } else {
   1942         group->nsyms = 0;
   1943         wl_event_source_timer_update(group->key_repeat_source, 0);
   1944     }
   1945 
   1946     if (handled)
   1947         return;
   1948 
   1949     wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard);
   1950     /* Pass unhandled keycodes along to the client. */
   1951     wlr_seat_keyboard_notify_key(seat, event->time_msec,
   1952             event->keycode, event->state);
   1953 }
   1954 
   1955 void
   1956 keypressmod(struct wl_listener *listener, void *data)
   1957 {
   1958     /* This event is raised when a modifier key, such as shift or alt, is
   1959      * pressed. We simply communicate this to the client. */
   1960     KeyboardGroup *group = wl_container_of(listener, group, modifiers);
   1961 
   1962     wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard);
   1963     /* Send modifiers to the client. */
   1964     wlr_seat_keyboard_notify_modifiers(seat,
   1965             &group->wlr_group->keyboard.modifiers);
   1966 }
   1967 
   1968 int
   1969 keyrepeat(void *data)
   1970 {
   1971     KeyboardGroup *group = data;
   1972     int i;
   1973     if (!group->nsyms || group->wlr_group->keyboard.repeat_info.rate <= 0)
   1974         return 0;
   1975 
   1976     wl_event_source_timer_update(group->key_repeat_source,
   1977             1000 / group->wlr_group->keyboard.repeat_info.rate);
   1978 
   1979     for (i = 0; i < group->nsyms; i++)
   1980         keybinding(group->mods, group->keysyms[i]);
   1981 
   1982     return 0;
   1983 }
   1984 
   1985 void
   1986 killclient(const Arg *arg)
   1987 {
   1988     Client *sel = focustop(selmon);
   1989     if (sel)
   1990         client_send_close(sel);
   1991 }
   1992 
   1993 void
   1994 locksession(struct wl_listener *listener, void *data)
   1995 {
   1996     struct wlr_session_lock_v1 *session_lock = data;
   1997     SessionLock *lock;
   1998     wlr_scene_node_set_enabled(&locked_bg->node, 1);
   1999     if (cur_lock) {
   2000         wlr_session_lock_v1_destroy(session_lock);
   2001         return;
   2002     }
   2003     lock = session_lock->data = ecalloc(1, sizeof(*lock));
   2004     focusclient(NULL, 0);
   2005 
   2006     lock->scene = wlr_scene_tree_create(layers[LyrBlock]);
   2007     cur_lock = lock->lock = session_lock;
   2008     locked = 1;
   2009 
   2010     LISTEN(&session_lock->events.new_surface, &lock->new_surface, createlocksurface);
   2011     LISTEN(&session_lock->events.destroy, &lock->destroy, destroysessionlock);
   2012     LISTEN(&session_lock->events.unlock, &lock->unlock, unlocksession);
   2013 
   2014     wlr_session_lock_v1_send_locked(session_lock);
   2015 }
   2016 
   2017 void
   2018 maplayersurfacenotify(struct wl_listener *listener, void *data)
   2019 {
   2020     motionnotify(0, NULL, 0, 0, 0, 0);
   2021 }
   2022 
   2023 void
   2024 mapnotify(struct wl_listener *listener, void *data)
   2025 {
   2026     /* Called when the surface is mapped, or ready to display on-screen. */
   2027     Client *p = NULL;
   2028     Client *w, *c = wl_container_of(listener, c, map);
   2029     Monitor *m;
   2030     int i;
   2031 
   2032     /* Create scene tree for this client and its border */
   2033     c->scene = client_surface(c)->data = wlr_scene_tree_create(layers[LyrTile]);
   2034     wlr_scene_node_set_enabled(&c->scene->node, c->type != XDGShell);
   2035     c->scene_surface = c->type == XDGShell
   2036             ? wlr_scene_xdg_surface_create(c->scene, c->surface.xdg)
   2037             : wlr_scene_subsurface_tree_create(c->scene, client_surface(c));
   2038     c->scene->node.data = c->scene_surface->node.data = c;
   2039 
   2040     client_get_geometry(c, &c->geom);
   2041 
   2042     /* Handle unmanaged clients first so we can return prior create borders */
   2043     if (client_is_unmanaged(c)) {
   2044         /* Unmanaged clients always are floating */
   2045         wlr_scene_node_reparent(&c->scene->node, layers[LyrFloat]);
   2046         wlr_scene_node_set_position(&c->scene->node, c->geom.x + borderpx,
   2047                 c->geom.y + borderpx);
   2048         if (client_wants_focus(c)) {
   2049             focusclient(c, 1);
   2050             exclusive_focus = c;
   2051         }
   2052         goto unset_fullscreen;
   2053     }
   2054 
   2055     for (i = 0; i < 4; i++) {
   2056         c->border[i] = wlr_scene_rect_create(c->scene, 0, 0,
   2057                 c->isurgent ? urgentcolor : bordercolor);
   2058         c->border[i]->node.data = c;
   2059     }
   2060 
   2061     /* Initialize client geometry with room for border */
   2062     client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
   2063     c->geom.width += 2 * c->bw;
   2064     c->geom.height += 2 * c->bw;
   2065 
   2066     /* Insert this client into client lists. */
   2067     wl_list_insert(&clients, &c->link);
   2068     wl_list_insert(&fstack, &c->flink);
   2069 
   2070     /* Set initial monitor, tags, floating status, and focus:
   2071      * we always consider floating, clients that have parent and thus
   2072      * we set the same tags and monitor than its parent, if not
   2073      * try to apply rules for them */
   2074     if ((p = client_get_parent(c))) {
   2075         c->isfloating = 1;
   2076         if (p->mon) {
   2077             c->geom.x = (p->mon->w.width - c->geom.width) / 2 + p->mon->m.x;
   2078             c->geom.y = (p->mon->w.height - c->geom.height) / 2 + p->mon->m.y;
   2079         }
   2080         setmon(c, p->mon, p->tags);
   2081     } else {
   2082         applyrules(c);
   2083     }
   2084     printstatus();
   2085 
   2086 unset_fullscreen:
   2087     m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y);
   2088     wl_list_for_each(w, &clients, link) {
   2089         if (w != c && w != p && w->isfullscreen && m == w->mon && (w->tags & c->tags))
   2090             setfullscreen(w, 0);
   2091     }
   2092 }
   2093 
   2094 void
   2095 maximizenotify(struct wl_listener *listener, void *data)
   2096 {
   2097     /* This event is raised when a client would like to maximize itself,
   2098      * typically because the user clicked on the maximize button on
   2099      * client-side decorations. dwl doesn't support maximization, but
   2100      * to conform to xdg-shell protocol we still must send a configure.
   2101      * Since xdg-shell protocol v5 we should ignore request of unsupported
   2102      * capabilities, just schedule a empty configure when the client uses <5
   2103      * protocol version
   2104      * wlr_xdg_surface_schedule_configure() is used to send an empty reply. */
   2105     Client *c = wl_container_of(listener, c, maximize);
   2106     if (wl_resource_get_version(c->surface.xdg->toplevel->resource)
   2107             < XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION)
   2108         wlr_xdg_surface_schedule_configure(c->surface.xdg);
   2109 }
   2110 
   2111 void
   2112 monocle(Monitor *m)
   2113 {
   2114     Client *c;
   2115     int n = 0;
   2116     unsigned int e = m->gaps;
   2117 
   2118     wl_list_for_each(c, &clients, link) {
   2119         if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
   2120             continue;
   2121         resize(c, (struct wlr_box) { .x = m->w.x + gappx*e, .y = m->w.y + gappx*e,
   2122                                      .width = m->w.width - 2*gappx*e, .height = m->w.height - 2*gappx*e}, 0);
   2123         n++;
   2124     }
   2125     if (n)
   2126         snprintf(m->ltsymbol, LENGTH(m->ltsymbol), "[%d]", n);
   2127     if ((c = focustop(m)))
   2128         wlr_scene_node_raise_to_top(&c->scene->node);
   2129 }
   2130 
   2131 void
   2132 movestack(const Arg *arg)
   2133 {
   2134     Client *c, *sel = focustop(selmon);
   2135 
   2136     if (!sel) {
   2137         return;
   2138     }
   2139 
   2140     if (wl_list_length(&clients) <= 1) {
   2141         return;
   2142     }
   2143 
   2144     if (arg->i > 0) {
   2145         wl_list_for_each(c, &sel->link, link) {
   2146             if (VISIBLEON(c, selmon) || &c->link == &clients) {
   2147                 break; /* found it */
   2148             }
   2149         }
   2150     } else {
   2151         wl_list_for_each_reverse(c, &sel->link, link) {
   2152             if (VISIBLEON(c, selmon) || &c->link == &clients) {
   2153                 break; /* found it */
   2154             }
   2155         }
   2156         /* backup one client */
   2157         c = wl_container_of(c->link.prev, c, link);
   2158     }
   2159 
   2160     wl_list_remove(&sel->link);
   2161     wl_list_insert(&c->link, &sel->link);
   2162     arrange(selmon);
   2163 }
   2164 
   2165 void
   2166 motionabsolute(struct wl_listener *listener, void *data)
   2167 {
   2168     /* This event is forwarded by the cursor when a pointer emits an _absolute_
   2169      * motion event, from 0..1 on each axis. This happens, for example, when
   2170      * wlroots is running under a Wayland window rather than KMS+DRM, and you
   2171      * move the mouse over the window. You could enter the window from any edge,
   2172      * so we have to warp the mouse there. There is also some hardware which
   2173      * emits these events. */
   2174     struct wlr_pointer_motion_absolute_event *event = data;
   2175     double lx, ly, dx, dy;
   2176 
   2177     if (!event->time_msec) /* this is 0 with virtual pointers */
   2178         wlr_cursor_warp_absolute(cursor, &event->pointer->base, event->x, event->y);
   2179 
   2180     wlr_cursor_absolute_to_layout_coords(cursor, &event->pointer->base, event->x, event->y, &lx, &ly);
   2181     dx = lx - cursor->x;
   2182     dy = ly - cursor->y;
   2183     motionnotify(event->time_msec, &event->pointer->base, dx, dy, dx, dy);
   2184 }
   2185 
   2186 void
   2187 motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy,
   2188         double dx_unaccel, double dy_unaccel)
   2189 {
   2190     double sx = 0, sy = 0, sx_confined, sy_confined;
   2191     Client *c = NULL, *w = NULL;
   2192     LayerSurface *l = NULL;
   2193     struct wlr_surface *surface = NULL;
   2194     struct wlr_pointer_constraint_v1 *constraint;
   2195 
   2196     /* time is 0 in internal calls meant to restore pointer focus. */
   2197     if (time) {
   2198         wlr_relative_pointer_manager_v1_send_relative_motion(
   2199                 relative_pointer_mgr, seat, (uint64_t)time * 1000,
   2200                 dx, dy, dx_unaccel, dy_unaccel);
   2201 
   2202         wl_list_for_each(constraint, &pointer_constraints->constraints, link)
   2203             cursorconstrain(constraint);
   2204 
   2205         if (active_constraint && cursor_mode != CurResize && cursor_mode != CurMove) {
   2206             toplevel_from_wlr_surface(active_constraint->surface, &c, NULL);
   2207             if (c && active_constraint->surface == seat->pointer_state.focused_surface) {
   2208                 sx = cursor->x - c->geom.x - c->bw;
   2209                 sy = cursor->y - c->geom.y - c->bw;
   2210                 if (wlr_region_confine(&active_constraint->region, sx, sy,
   2211                         sx + dx, sy + dy, &sx_confined, &sy_confined)) {
   2212                     dx = sx_confined - sx;
   2213                     dy = sy_confined - sy;
   2214                 }
   2215 
   2216                 if (active_constraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED)
   2217                     return;
   2218             }
   2219         }
   2220 
   2221         wlr_cursor_move(cursor, device, dx, dy);
   2222         wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
   2223 
   2224         /* Update selmon (even while dragging a window) */
   2225         if (sloppyfocus)
   2226             selmon = xytomon(cursor->x, cursor->y);
   2227     }
   2228 
   2229     /* Update drag icon's position */
   2230     wlr_scene_node_set_position(&drag_icon->node, ROUND(cursor->x), ROUND(cursor->y));
   2231 
   2232     /* If we are currently grabbing the mouse, handle and return */
   2233     if (cursor_mode == CurMove) {
   2234         /* Move the grabbed client to the new position. */
   2235         resize(grabc, (struct wlr_box){.x = ROUND(cursor->x) - grabcx, .y = ROUND(cursor->y) - grabcy,
   2236             .width = grabc->geom.width, .height = grabc->geom.height}, 1);
   2237         return;
   2238     } else if (cursor_mode == CurResize) {
   2239         resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y,
   2240             .width = ROUND(cursor->x) - grabc->geom.x, .height = ROUND(cursor->y) - grabc->geom.y}, 1);
   2241         return;
   2242     }
   2243 
   2244     /* Find the client under the pointer and send the event along. */
   2245     xytonode(cursor->x, cursor->y, &surface, &c, NULL, &sx, &sy);
   2246 
   2247     if (cursor_mode == CurPressed && !seat->drag && surface != held_grab
   2248             && toplevel_from_wlr_surface(held_grab, &w, &l) >= 0) {
   2249         c = w;
   2250         surface = held_grab;
   2251         sx = cursor->x - (l ? l->geom.x : w->geom.x);
   2252         sy = cursor->y - (l ? l->geom.y : w->geom.y);
   2253     }
   2254 
   2255     /* If there's no client surface under the cursor, set the cursor image to a
   2256      * default. This is what makes the cursor image appear when you move it
   2257      * off of a client or over its border. */
   2258     if (!surface && !seat->drag)
   2259         wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
   2260 
   2261     pointerfocus(c, surface, sx, sy, time);
   2262 }
   2263 
   2264 void
   2265 motionrelative(struct wl_listener *listener, void *data)
   2266 {
   2267     /* This event is forwarded by the cursor when a pointer emits a _relative_
   2268      * pointer motion event (i.e. a delta) */
   2269     struct wlr_pointer_motion_event *event = data;
   2270     /* The cursor doesn't move unless we tell it to. The cursor automatically
   2271      * handles constraining the motion to the output layout, as well as any
   2272      * special configuration applied for the specific input device which
   2273      * generated the event. You can pass NULL for the device if you want to move
   2274      * the cursor around without any input. */
   2275     motionnotify(event->time_msec, &event->pointer->base, event->delta_x, event->delta_y,
   2276             event->unaccel_dx, event->unaccel_dy);
   2277 }
   2278 
   2279 void
   2280 moveresize(const Arg *arg)
   2281 {
   2282     if (cursor_mode != CurNormal && cursor_mode != CurPressed)
   2283         return;
   2284     xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL);
   2285     if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen)
   2286         return;
   2287 
   2288     /* Float the window and tell motionnotify to grab it */
   2289     setfloating(grabc, 1);
   2290     switch (cursor_mode = arg->ui) {
   2291     case CurMove:
   2292         grabcx = ROUND(cursor->x) - grabc->geom.x;
   2293         grabcy = ROUND(cursor->y) - grabc->geom.y;
   2294         wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur");
   2295         break;
   2296     case CurResize:
   2297         /* Doesn't work for X11 output - the next absolute motion event
   2298          * returns the cursor to where it started */
   2299         wlr_cursor_warp_closest(cursor, NULL,
   2300                 grabc->geom.x + grabc->geom.width,
   2301                 grabc->geom.y + grabc->geom.height);
   2302         wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize");
   2303         break;
   2304     }
   2305 }
   2306 
   2307 void
   2308 outputmgrapply(struct wl_listener *listener, void *data)
   2309 {
   2310     struct wlr_output_configuration_v1 *config = data;
   2311     outputmgrapplyortest(config, 0);
   2312 }
   2313 
   2314 void
   2315 outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test)
   2316 {
   2317     /*
   2318      * Called when a client such as wlr-randr requests a change in output
   2319      * configuration. This is only one way that the layout can be changed,
   2320      * so any Monitor information should be updated by updatemons() after an
   2321      * output_layout.change event, not here.
   2322      */
   2323     struct wlr_output_configuration_head_v1 *config_head;
   2324     int ok = 1;
   2325 
   2326     wl_list_for_each(config_head, &config->heads, link) {
   2327         struct wlr_output *wlr_output = config_head->state.output;
   2328         Monitor *m = wlr_output->data;
   2329         struct wlr_output_state state;
   2330 
   2331         wlr_output_state_init(&state);
   2332         wlr_output_state_set_enabled(&state, config_head->state.enabled);
   2333         if (!config_head->state.enabled)
   2334             goto apply_or_test;
   2335 
   2336         if (config_head->state.mode)
   2337             wlr_output_state_set_mode(&state, config_head->state.mode);
   2338         else
   2339             wlr_output_state_set_custom_mode(&state,
   2340                     config_head->state.custom_mode.width,
   2341                     config_head->state.custom_mode.height,
   2342                     config_head->state.custom_mode.refresh);
   2343 
   2344         /* Don't move monitors if position wouldn't change, this to avoid
   2345          * wlroots marking the output as manually configured */
   2346         if (m->m.x != config_head->state.x || m->m.y != config_head->state.y)
   2347             wlr_output_layout_add(output_layout, wlr_output,
   2348                     config_head->state.x, config_head->state.y);
   2349         wlr_output_state_set_transform(&state, config_head->state.transform);
   2350         wlr_output_state_set_scale(&state, config_head->state.scale);
   2351         wlr_output_state_set_adaptive_sync_enabled(&state,
   2352                 config_head->state.adaptive_sync_enabled);
   2353 
   2354 apply_or_test:
   2355         ok &= test ? wlr_output_test_state(wlr_output, &state)
   2356                 : wlr_output_commit_state(wlr_output, &state);
   2357 
   2358         wlr_output_state_finish(&state);
   2359     }
   2360 
   2361     if (ok)
   2362         wlr_output_configuration_v1_send_succeeded(config);
   2363     else
   2364         wlr_output_configuration_v1_send_failed(config);
   2365     wlr_output_configuration_v1_destroy(config);
   2366 
   2367     /* TODO: use a wrapper function? */
   2368     updatemons(NULL, NULL);
   2369 }
   2370 
   2371 void
   2372 outputmgrtest(struct wl_listener *listener, void *data)
   2373 {
   2374     struct wlr_output_configuration_v1 *config = data;
   2375     outputmgrapplyortest(config, 1);
   2376 }
   2377 
   2378 void
   2379 pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
   2380         uint32_t time)
   2381 {
   2382     struct timespec now;
   2383 
   2384     if ((!active_constraint || active_constraint->surface != surface) &&
   2385             sloppyfocus && time && c && !client_is_unmanaged(c))
   2386         focusclient(c, 0);
   2387 
   2388     /* If surface is NULL, clear pointer focus */
   2389     if (!surface) {
   2390         wlr_seat_pointer_notify_clear_focus(seat);
   2391         return;
   2392     }
   2393 
   2394     if (!time) {
   2395         clock_gettime(CLOCK_MONOTONIC, &now);
   2396         time = now.tv_sec * 1000 + now.tv_nsec / 1000000;
   2397     }
   2398 
   2399     /* Let the client know that the mouse cursor has entered one
   2400      * of its surfaces, and make keyboard focus follow if desired.
   2401      * wlroots makes this a no-op if surface is already focused */
   2402     wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
   2403     wlr_seat_pointer_notify_motion(seat, time, sx, sy);
   2404 }
   2405 
   2406 void
   2407 printstatus(void)
   2408 {
   2409     Monitor *m = NULL;
   2410 
   2411     wl_list_for_each(m, &mons, link)
   2412         dwl_ipc_output_printstatus(m);
   2413 }
   2414 
   2415 void
   2416 quit(const Arg *arg)
   2417 {
   2418     wl_display_terminate(dpy);
   2419 }
   2420 
   2421 void
   2422 rendermon(struct wl_listener *listener, void *data)
   2423 {
   2424     /* This function is called every time an output is ready to display a frame,
   2425      * generally at the output's refresh rate (e.g. 60Hz). */
   2426     Monitor *m = wl_container_of(listener, m, frame);
   2427     Client *c;
   2428     struct wlr_output_state pending = {0};
   2429     struct wlr_gamma_control_v1 *gamma_control;
   2430     struct timespec now;
   2431 
   2432     /* Render if no XDG clients have an outstanding resize and are visible on
   2433      * this monitor. */
   2434     wl_list_for_each(c, &clients, link) {
   2435         if (c->resize && !c->isfloating && client_is_rendered_on_mon(c, m) && !client_is_stopped(c))
   2436             goto skip;
   2437     }
   2438 
   2439     /*
   2440      * HACK: The "correct" way to set the gamma is to commit it together with
   2441      * the rest of the state in one go, but to do that we would need to rewrite
   2442      * wlr_scene_output_commit() in order to add the gamma to the pending
   2443      * state before committing, instead try to commit the gamma in one frame,
   2444      * and commit the rest of the state in the next one (or in the same frame if
   2445      * the gamma can not be committed).
   2446      */
   2447     if (m->gamma_lut_changed) {
   2448         gamma_control
   2449                 = wlr_gamma_control_manager_v1_get_control(gamma_control_mgr, m->wlr_output);
   2450         m->gamma_lut_changed = 0;
   2451 
   2452         if (!wlr_gamma_control_v1_apply(gamma_control, &pending))
   2453             goto commit;
   2454 
   2455         if (!wlr_output_test_state(m->wlr_output, &pending)) {
   2456             wlr_gamma_control_v1_send_failed_and_destroy(gamma_control);
   2457             goto commit;
   2458         }
   2459         wlr_output_commit_state(m->wlr_output, &pending);
   2460         wlr_output_schedule_frame(m->wlr_output);
   2461     } else {
   2462 commit:
   2463         wlr_scene_output_commit(m->scene_output, NULL);
   2464     }
   2465 
   2466 skip:
   2467     /* Let clients know a frame has been rendered */
   2468     clock_gettime(CLOCK_MONOTONIC, &now);
   2469     wlr_scene_output_send_frame_done(m->scene_output, &now);
   2470     wlr_output_state_finish(&pending);
   2471 }
   2472 
   2473 void
   2474 requestdecorationmode(struct wl_listener *listener, void *data)
   2475 {
   2476     Client *c = wl_container_of(listener, c, set_decoration_mode);
   2477     wlr_xdg_toplevel_decoration_v1_set_mode(c->decoration,
   2478             WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
   2479 }
   2480 
   2481 void
   2482 requeststartdrag(struct wl_listener *listener, void *data)
   2483 {
   2484     struct wlr_seat_request_start_drag_event *event = data;
   2485 
   2486     if (wlr_seat_validate_pointer_grab_serial(seat, event->origin,
   2487             event->serial))
   2488         wlr_seat_start_pointer_drag(seat, event->drag, event->serial);
   2489     else
   2490         wlr_data_source_destroy(event->drag->source);
   2491 }
   2492 
   2493 void
   2494 requestmonstate(struct wl_listener *listener, void *data)
   2495 {
   2496     struct wlr_output_event_request_state *event = data;
   2497     wlr_output_commit_state(event->output, event->state);
   2498     updatemons(NULL, NULL);
   2499 }
   2500 
   2501 void
   2502 resize(Client *c, struct wlr_box geo, int interact)
   2503 {
   2504     struct wlr_box *bbox = interact ? &sgeom : &c->mon->w;
   2505     struct wlr_box clip;
   2506     client_set_bounds(c, geo.width, geo.height);
   2507     c->geom = geo;
   2508     applybounds(c, bbox);
   2509 
   2510     /* Update scene-graph, including borders */
   2511     wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y);
   2512     wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw);
   2513     wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw);
   2514     wlr_scene_rect_set_size(c->border[1], c->geom.width, c->bw);
   2515     wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - 2 * c->bw);
   2516     wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - 2 * c->bw);
   2517     wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw);
   2518     wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
   2519     wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw);
   2520 
   2521     /* this is a no-op if size hasn't changed */
   2522     c->resize = client_set_size(c, c->geom.width - 2 * c->bw,
   2523                                 c->geom.height - 2 * c->bw);
   2524     client_get_clip(c, &clip);
   2525     wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip);
   2526 }
   2527 
   2528 void
   2529 run(char *startup_cmd)
   2530 {
   2531     /* Add a Unix socket to the Wayland display. */
   2532     const char *socket = wl_display_add_socket_auto(dpy);
   2533     if (!socket)
   2534         die("startup: display_add_socket_auto");
   2535     setenv("WAYLAND_DISPLAY", socket, 1);
   2536 
   2537     /* Start the backend. This will enumerate outputs and inputs, become the DRM
   2538      * master, etc */
   2539     if (!wlr_backend_start(backend))
   2540         die("startup: backend_start");
   2541 
   2542     /* Now that the socket exists and the backend is started, run the startup command */
   2543     autostartexec();
   2544     if (startup_cmd) {
   2545         int piperw[2];
   2546         if (pipe(piperw) < 0)
   2547             die("startup: pipe:");
   2548         if ((child_pid = fork()) < 0)
   2549             die("startup: fork:");
   2550         if (child_pid == 0) {
   2551             dup2(piperw[0], STDIN_FILENO);
   2552             close(piperw[0]);
   2553             close(piperw[1]);
   2554             execl("/bin/sh", "/bin/sh", "-c", startup_cmd, NULL);
   2555             die("startup: execl:");
   2556         }
   2557         dup2(piperw[1], STDOUT_FILENO);
   2558         close(piperw[1]);
   2559         close(piperw[0]);
   2560     }
   2561     printstatus();
   2562 
   2563     /* At this point the outputs are initialized, choose initial selmon based on
   2564      * cursor position, and set default cursor image */
   2565     selmon = xytomon(cursor->x, cursor->y);
   2566 
   2567     /* TODO hack to get cursor to display in its initial location (100, 100)
   2568      * instead of (0, 0) and then jumping. still may not be fully
   2569      * initialized, as the image/coordinates are not transformed for the
   2570      * monitor when displayed here */
   2571     wlr_cursor_warp_closest(cursor, NULL, cursor->x, cursor->y);
   2572     wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
   2573 
   2574     /* Run the Wayland event loop. This does not return until you exit the
   2575      * compositor. Starting the backend rigged up all of the necessary event
   2576      * loop configuration to listen to libinput events, DRM events, generate
   2577      * frame events at the refresh rate, and so on. */
   2578     wl_display_run(dpy);
   2579 }
   2580 
   2581 void
   2582 setcursor(struct wl_listener *listener, void *data)
   2583 {
   2584     /* This event is raised by the seat when a client provides a cursor image */
   2585     struct wlr_seat_pointer_request_set_cursor_event *event = data;
   2586     /* If we're "grabbing" the cursor, don't use the client's image, we will
   2587      * restore it after "grabbing" sending a leave event, followed by a enter
   2588      * event, which will result in the client requesting set the cursor surface */
   2589     if (cursor_mode != CurNormal && cursor_mode != CurPressed)
   2590         return;
   2591     /* This can be sent by any client, so we check to make sure this one is
   2592      * actually has pointer focus first. If so, we can tell the cursor to
   2593      * use the provided surface as the cursor image. It will set the
   2594      * hardware cursor on the output that it's currently on and continue to
   2595      * do so as the cursor moves between outputs. */
   2596     if (event->seat_client == seat->pointer_state.focused_client)
   2597         wlr_cursor_set_surface(cursor, event->surface,
   2598                 event->hotspot_x, event->hotspot_y);
   2599 }
   2600 
   2601 void
   2602 setcursorshape(struct wl_listener *listener, void *data)
   2603 {
   2604     struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data;
   2605     if (cursor_mode != CurNormal && cursor_mode != CurPressed)
   2606         return;
   2607     /* This can be sent by any client, so we check to make sure this one is
   2608      * actually has pointer focus first. If so, we can tell the cursor to
   2609      * use the provided cursor shape. */
   2610     if (event->seat_client == seat->pointer_state.focused_client)
   2611         wlr_cursor_set_xcursor(cursor, cursor_mgr,
   2612                 wlr_cursor_shape_v1_name(event->shape));
   2613 }
   2614 
   2615 void
   2616 setfloating(Client *c, int floating)
   2617 {
   2618     Client *p = client_get_parent(c);
   2619     c->isfloating = floating;
   2620     if (!c->mon)
   2621         return;
   2622     wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen ||
   2623             (p && p->isfullscreen) ? LyrFS
   2624             : c->isfloating ? LyrFloat : LyrTile]);
   2625     arrange(c->mon);
   2626     printstatus();
   2627 }
   2628 
   2629 void
   2630 setfullscreen(Client *c, int fullscreen)
   2631 {
   2632     c->isfullscreen = fullscreen;
   2633     if (!c->mon)
   2634         return;
   2635     c->bw = fullscreen ? 0 : borderpx;
   2636     client_set_fullscreen(c, fullscreen);
   2637     wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen
   2638             ? LyrFS : c->isfloating ? LyrFloat : LyrTile]);
   2639 
   2640     if (fullscreen) {
   2641         c->prev = c->geom;
   2642         resize(c, c->mon->m, 0);
   2643     } else {
   2644         /* restore previous size instead of arrange for floating windows since
   2645          * client positions are set by the user and cannot be recalculated */
   2646         resize(c, c->prev, 0);
   2647     }
   2648     arrange(c->mon);
   2649     printstatus();
   2650 }
   2651 
   2652 void
   2653 setgamma(struct wl_listener *listener, void *data)
   2654 {
   2655     struct wlr_gamma_control_manager_v1_set_gamma_event *event = data;
   2656     Monitor *m = event->output->data;
   2657     if (!m)
   2658         return;
   2659     m->gamma_lut_changed = 1;
   2660     wlr_output_schedule_frame(m->wlr_output);
   2661 }
   2662 
   2663 void
   2664 setlayout(const Arg *arg)
   2665 {
   2666     if (!selmon)
   2667         return;
   2668     if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
   2669         selmon->sellt ^= 1;
   2670     if (arg && arg->v) {
   2671         selmon->lt[selmon->sellt] = (Layout *)arg->v;
   2672     }
   2673     strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol));
   2674     arrange(selmon);
   2675     printstatus();
   2676 }
   2677 
   2678 /* arg > 1.0 will set mfact absolutely */
   2679 void
   2680 setmfact(const Arg *arg)
   2681 {
   2682     float f;
   2683 
   2684     if (!arg || !selmon || !selmon->lt[selmon->sellt]->arrange)
   2685         return;
   2686     f = arg->f < 1.0f ? arg->f + selmon->mfact : arg->f - 1.0f;
   2687     if (f < 0.1 || f > 0.9)
   2688         return;
   2689     selmon->mfact = f;
   2690     arrange(selmon);
   2691 }
   2692 
   2693 void
   2694 setmon(Client *c, Monitor *m, uint32_t newtags)
   2695 {
   2696     Monitor *oldmon = c->mon;
   2697 
   2698     if (oldmon == m)
   2699         return;
   2700     c->mon = m;
   2701     c->prev = c->geom;
   2702 
   2703     /* Scene graph sends surface leave/enter events on move and resize */
   2704     if (oldmon)
   2705         arrange(oldmon);
   2706     if (m) {
   2707         /* Make sure window actually overlaps with the monitor */
   2708         resize(c, c->geom, 0);
   2709         c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */
   2710         setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */
   2711         setfloating(c, c->isfloating);
   2712     }
   2713     focusclient(focustop(selmon), 1);
   2714 }
   2715 
   2716 void
   2717 setpsel(struct wl_listener *listener, void *data)
   2718 {
   2719     /* This event is raised by the seat when a client wants to set the selection,
   2720      * usually when the user copies something. wlroots allows compositors to
   2721      * ignore such requests if they so choose, but in dwl we always honor
   2722      */
   2723     struct wlr_seat_request_set_primary_selection_event *event = data;
   2724     wlr_seat_set_primary_selection(seat, event->source, event->serial);
   2725 }
   2726 
   2727 void
   2728 setsel(struct wl_listener *listener, void *data)
   2729 {
   2730     /* This event is raised by the seat when a client wants to set the selection,
   2731      * usually when the user copies something. wlroots allows compositors to
   2732      * ignore such requests if they so choose, but in dwl we always honor
   2733      */
   2734     struct wlr_seat_request_set_selection_event *event = data;
   2735     wlr_seat_set_selection(seat, event->source, event->serial);
   2736 }
   2737 
   2738 void
   2739 setup(void)
   2740 {
   2741     struct xkb_context *context;
   2742     struct xkb_keymap *keymap;
   2743 
   2744     int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE};
   2745     struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = handlesig};
   2746     sigemptyset(&sa.sa_mask);
   2747 
   2748     for (i = 0; i < (int)LENGTH(sig); i++)
   2749         sigaction(sig[i], &sa, NULL);
   2750 
   2751     wlr_log_init(log_level, NULL);
   2752 
   2753     /* The Wayland display is managed by libwayland. It handles accepting
   2754      * clients from the Unix socket, manging Wayland globals, and so on. */
   2755     dpy = wl_display_create();
   2756 
   2757     /* The backend is a wlroots feature which abstracts the underlying input and
   2758      * output hardware. The autocreate option will choose the most suitable
   2759      * backend based on the current environment, such as opening an X11 window
   2760      * if an X11 server is running. */
   2761     if (!(backend = wlr_backend_autocreate(dpy, &session)))
   2762         die("couldn't create backend");
   2763 
   2764     /* Initialize the scene graph used to lay out windows */
   2765     scene = wlr_scene_create();
   2766     root_bg = wlr_scene_rect_create(&scene->tree, 0, 0, rootcolor);
   2767     for (i = 0; i < NUM_LAYERS; i++)
   2768         layers[i] = wlr_scene_tree_create(&scene->tree);
   2769     drag_icon = wlr_scene_tree_create(&scene->tree);
   2770     wlr_scene_node_place_below(&drag_icon->node, &layers[LyrBlock]->node);
   2771 
   2772     /* Autocreates a renderer, either Pixman, GLES2 or Vulkan for us. The user
   2773      * can also specify a renderer using the WLR_RENDERER env var.
   2774      * The renderer is responsible for defining the various pixel formats it
   2775      * supports for shared memory, this configures that for clients. */
   2776     if (!(drw = wlr_renderer_autocreate(backend)))
   2777         die("couldn't create renderer");
   2778 
   2779     /* Create shm, drm and linux_dmabuf interfaces by ourselves.
   2780      * The simplest way is call:
   2781      *      wlr_renderer_init_wl_display(drw);
   2782      * but we need to create manually the linux_dmabuf interface to integrate it
   2783      * with wlr_scene. */
   2784     wlr_renderer_init_wl_shm(drw, dpy);
   2785 
   2786     if (wlr_renderer_get_dmabuf_texture_formats(drw)) {
   2787         wlr_drm_create(dpy, drw);
   2788         wlr_scene_set_linux_dmabuf_v1(scene,
   2789                 wlr_linux_dmabuf_v1_create_with_renderer(dpy, 4, drw));
   2790     }
   2791 
   2792     /* Autocreates an allocator for us.
   2793      * The allocator is the bridge between the renderer and the backend. It
   2794      * handles the buffer creation, allowing wlroots to render onto the
   2795      * screen */
   2796     if (!(alloc = wlr_allocator_autocreate(backend, drw)))
   2797         die("couldn't create allocator");
   2798 
   2799     /* This creates some hands-off wlroots interfaces. The compositor is
   2800      * necessary for clients to allocate surfaces and the data device manager
   2801      * handles the clipboard. Each of these wlroots interfaces has room for you
   2802      * to dig your fingers in and play with their behavior if you want. Note that
   2803      * the clients cannot set the selection directly without compositor approval,
   2804      * see the setsel() function. */
   2805     compositor = wlr_compositor_create(dpy, 6, drw);
   2806     wlr_subcompositor_create(dpy);
   2807     wlr_data_device_manager_create(dpy);
   2808     wlr_export_dmabuf_manager_v1_create(dpy);
   2809     wlr_screencopy_manager_v1_create(dpy);
   2810     wlr_data_control_manager_v1_create(dpy);
   2811     wlr_primary_selection_v1_device_manager_create(dpy);
   2812     wlr_viewporter_create(dpy);
   2813     wlr_single_pixel_buffer_manager_v1_create(dpy);
   2814     wlr_fractional_scale_manager_v1_create(dpy, 1);
   2815 
   2816     /* Initializes the interface used to implement urgency hints */
   2817     activation = wlr_xdg_activation_v1_create(dpy);
   2818     LISTEN_STATIC(&activation->events.request_activate, urgent);
   2819 
   2820     gamma_control_mgr = wlr_gamma_control_manager_v1_create(dpy);
   2821     LISTEN_STATIC(&gamma_control_mgr->events.set_gamma, setgamma);
   2822 
   2823     /* Creates an output layout, which a wlroots utility for working with an
   2824      * arrangement of screens in a physical layout. */
   2825     output_layout = wlr_output_layout_create();
   2826     LISTEN_STATIC(&output_layout->events.change, updatemons);
   2827     wlr_xdg_output_manager_v1_create(dpy, output_layout);
   2828 
   2829     /* Configure a listener to be notified when new outputs are available on the
   2830      * backend. */
   2831     wl_list_init(&mons);
   2832     LISTEN_STATIC(&backend->events.new_output, createmon);
   2833 
   2834     /* Set up our client lists, the xdg-shell and the layer-shell. The xdg-shell is a
   2835      * Wayland protocol which is used for application windows. For more
   2836      * detail on shells, refer to the article:
   2837      *
   2838      * https://drewdevault.com/2018/07/29/Wayland-shells.html
   2839      */
   2840     wl_list_init(&clients);
   2841     wl_list_init(&fstack);
   2842 
   2843     xdg_shell = wlr_xdg_shell_create(dpy, 6);
   2844     LISTEN_STATIC(&xdg_shell->events.new_surface, createnotify);
   2845 
   2846     layer_shell = wlr_layer_shell_v1_create(dpy, 3);
   2847     LISTEN_STATIC(&layer_shell->events.new_surface, createlayersurface);
   2848 
   2849     idle_notifier = wlr_idle_notifier_v1_create(dpy);
   2850 
   2851     idle_inhibit_mgr = wlr_idle_inhibit_v1_create(dpy);
   2852     LISTEN_STATIC(&idle_inhibit_mgr->events.new_inhibitor, createidleinhibitor);
   2853 
   2854     session_lock_mgr = wlr_session_lock_manager_v1_create(dpy);
   2855     wl_signal_add(&session_lock_mgr->events.new_lock, &lock_listener);
   2856     LISTEN_STATIC(&session_lock_mgr->events.destroy, destroysessionmgr);
   2857     locked_bg = wlr_scene_rect_create(layers[LyrBlock], sgeom.width, sgeom.height,
   2858             (float [4]){0.1f, 0.1f, 0.1f, 1.0f});
   2859     wlr_scene_node_set_enabled(&locked_bg->node, 0);
   2860 
   2861     /* Use decoration protocols to negotiate server-side decorations */
   2862     wlr_server_decoration_manager_set_default_mode(
   2863             wlr_server_decoration_manager_create(dpy),
   2864             WLR_SERVER_DECORATION_MANAGER_MODE_SERVER);
   2865     xdg_decoration_mgr = wlr_xdg_decoration_manager_v1_create(dpy);
   2866     LISTEN_STATIC(&xdg_decoration_mgr->events.new_toplevel_decoration, createdecoration);
   2867 
   2868     pointer_constraints = wlr_pointer_constraints_v1_create(dpy);
   2869     LISTEN_STATIC(&pointer_constraints->events.new_constraint, createpointerconstraint);
   2870 
   2871     relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(dpy);
   2872 
   2873     /*
   2874      * Creates a cursor, which is a wlroots utility for tracking the cursor
   2875      * image shown on screen.
   2876      */
   2877     cursor = wlr_cursor_create();
   2878     wlr_cursor_attach_output_layout(cursor, output_layout);
   2879 
   2880     /* Creates an xcursor manager, another wlroots utility which loads up
   2881      * Xcursor themes to source cursor images from and makes sure that cursor
   2882      * images are available at all scale factors on the screen (necessary for
   2883      * HiDPI support). Scaled cursors will be loaded with each output. */
   2884     cursor_mgr = wlr_xcursor_manager_create(NULL, 24);
   2885     setenv("XCURSOR_SIZE", "24", 1);
   2886 
   2887     /*
   2888      * wlr_cursor *only* displays an image on screen. It does not move around
   2889      * when the pointer moves. However, we can attach input devices to it, and
   2890      * it will generate aggregate events for all of them. In these events, we
   2891      * can choose how we want to process them, forwarding them to clients and
   2892      * moving the cursor around. More detail on this process is described in
   2893      * https://drewdevault.com/2018/07/17/Input-handling-in-wlroots.html
   2894      *
   2895      * And more comments are sprinkled throughout the notify functions above.
   2896      */
   2897     LISTEN_STATIC(&cursor->events.motion, motionrelative);
   2898     LISTEN_STATIC(&cursor->events.motion_absolute, motionabsolute);
   2899     LISTEN_STATIC(&cursor->events.button, buttonpress);
   2900     LISTEN_STATIC(&cursor->events.axis, axisnotify);
   2901     LISTEN_STATIC(&cursor->events.frame, cursorframe);
   2902 
   2903     cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1);
   2904     LISTEN_STATIC(&cursor_shape_mgr->events.request_set_shape, setcursorshape);
   2905 
   2906     /*
   2907      * Configures a seat, which is a single "seat" at which a user sits and
   2908      * operates the computer. This conceptually includes up to one keyboard,
   2909      * pointer, touch, and drawing tablet device. We also rig up a listener to
   2910      * let us know when new input devices are available on the backend.
   2911      */
   2912     LISTEN_STATIC(&backend->events.new_input, inputdevice);
   2913     virtual_keyboard_mgr = wlr_virtual_keyboard_manager_v1_create(dpy);
   2914     LISTEN_STATIC(&virtual_keyboard_mgr->events.new_virtual_keyboard, virtualkeyboard);
   2915     virtual_pointer_mgr = wlr_virtual_pointer_manager_v1_create(dpy);
   2916     LISTEN_STATIC(&virtual_pointer_mgr->events.new_virtual_pointer, virtualpointer);
   2917 
   2918     seat = wlr_seat_create(dpy, "seat0");
   2919     LISTEN_STATIC(&seat->events.request_set_cursor, setcursor);
   2920     LISTEN_STATIC(&seat->events.request_set_selection, setsel);
   2921     LISTEN_STATIC(&seat->events.request_set_primary_selection, setpsel);
   2922     LISTEN_STATIC(&seat->events.request_start_drag, requeststartdrag);
   2923     LISTEN_STATIC(&seat->events.start_drag, startdrag);
   2924 
   2925     /*
   2926      * Configures a keyboard group, which will keep track of all connected
   2927      * keyboards, keep their modifier and LED states in sync, and handle
   2928      * keypresses
   2929      */
   2930     kb_group.wlr_group = wlr_keyboard_group_create();
   2931     kb_group.wlr_group->data = &kb_group;
   2932 
   2933     /*
   2934      * Virtual keyboards need to be in a different group
   2935      * https://codeberg.org/dwl/dwl/issues/554
   2936      */
   2937     vkb_group.wlr_group = wlr_keyboard_group_create();
   2938     vkb_group.wlr_group->data = &vkb_group;
   2939 
   2940     /* Prepare an XKB keymap and assign it to the keyboard group. */
   2941     context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
   2942     if (!(keymap = xkb_keymap_new_from_names(context, &xkb_rules,
   2943                 XKB_KEYMAP_COMPILE_NO_FLAGS)))
   2944         die("failed to compile keymap");
   2945 
   2946     wlr_keyboard_set_keymap(&kb_group.wlr_group->keyboard, keymap);
   2947     wlr_keyboard_set_keymap(&vkb_group.wlr_group->keyboard, keymap);
   2948     xkb_keymap_unref(keymap);
   2949     xkb_context_unref(context);
   2950 
   2951     wlr_keyboard_set_repeat_info(&kb_group.wlr_group->keyboard, repeat_rate, repeat_delay);
   2952     wlr_keyboard_set_repeat_info(&vkb_group.wlr_group->keyboard, repeat_rate, repeat_delay);
   2953 
   2954     /* Set up listeners for keyboard events */
   2955     LISTEN(&kb_group.wlr_group->keyboard.events.key, &kb_group.key, keypress);
   2956     LISTEN(&kb_group.wlr_group->keyboard.events.modifiers, &kb_group.modifiers, keypressmod);
   2957     LISTEN(&vkb_group.wlr_group->keyboard.events.key, &vkb_group.key, keypress);
   2958     LISTEN(&vkb_group.wlr_group->keyboard.events.modifiers, &vkb_group.modifiers, keypressmod);
   2959 
   2960     kb_group.key_repeat_source = wl_event_loop_add_timer(
   2961             wl_display_get_event_loop(dpy), keyrepeat, &kb_group);
   2962     vkb_group.key_repeat_source = wl_event_loop_add_timer(
   2963             wl_display_get_event_loop(dpy), keyrepeat, &vkb_group);
   2964 
   2965     /* A seat can only have one keyboard, but this is a limitation of the
   2966      * Wayland protocol - not wlroots. We assign all connected keyboards to the
   2967      * same wlr_keyboard_group, which provides a single wlr_keyboard interface for
   2968      * all of them. Set this combined wlr_keyboard as the seat keyboard.
   2969      */
   2970     wlr_seat_set_keyboard(seat, &kb_group.wlr_group->keyboard);
   2971 
   2972     output_mgr = wlr_output_manager_v1_create(dpy);
   2973     LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply);
   2974     LISTEN_STATIC(&output_mgr->events.test, outputmgrtest);
   2975 
   2976     wlr_scene_set_presentation(scene, wlr_presentation_create(dpy, backend));
   2977     wl_global_create(dpy, &zdwl_ipc_manager_v2_interface, 2, NULL, dwl_ipc_manager_bind);
   2978 
   2979     /* Make sure XWayland clients don't connect to the parent X server,
   2980      * e.g when running in the x11 backend or the wayland backend and the
   2981      * compositor has Xwayland support */
   2982     unsetenv("DISPLAY");
   2983 #ifdef XWAYLAND
   2984     /*
   2985      * Initialise the XWayland X server.
   2986      * It will be started when the first X client is started.
   2987      */
   2988     if ((xwayland = wlr_xwayland_create(dpy, compositor, 1))) {
   2989         LISTEN_STATIC(&xwayland->events.ready, xwaylandready);
   2990         LISTEN_STATIC(&xwayland->events.new_surface, createnotifyx11);
   2991 
   2992         setenv("DISPLAY", xwayland->display_name, 1);
   2993     } else {
   2994         fprintf(stderr, "failed to setup XWayland X server, continuing without it\n");
   2995     }
   2996 #endif
   2997 }
   2998 
   2999 void
   3000 spawn(const Arg *arg)
   3001 {
   3002     if (fork() == 0) {
   3003         dup2(STDERR_FILENO, STDOUT_FILENO);
   3004         setsid();
   3005         execvp(((char **)arg->v)[0], (char **)arg->v);
   3006         die("dwl: execvp %s failed:", ((char **)arg->v)[0]);
   3007     }
   3008 }
   3009 
   3010 void
   3011 startdrag(struct wl_listener *listener, void *data)
   3012 {
   3013     struct wlr_drag *drag = data;
   3014     if (!drag->icon)
   3015         return;
   3016 
   3017     drag->icon->data = &wlr_scene_drag_icon_create(drag_icon, drag->icon)->node;
   3018     LISTEN_STATIC(&drag->icon->events.destroy, destroydragicon);
   3019 }
   3020 
   3021 void
   3022 tag(const Arg *arg)
   3023 {
   3024     Client *sel = focustop(selmon);
   3025     if (!sel || (arg->ui & TAGMASK) == 0)
   3026         return;
   3027 
   3028     sel->tags = arg->ui & TAGMASK;
   3029     focusclient(focustop(selmon), 1);
   3030     arrange(selmon);
   3031     printstatus();
   3032 }
   3033 
   3034 void
   3035 tagmon(const Arg *arg)
   3036 {
   3037     Client *sel = focustop(selmon);
   3038     if (sel) {
   3039         setmon(sel, dirtomon(arg->i), 0);
   3040         focusmon(arg);
   3041         cursorwarptocenter();
   3042     }
   3043 }
   3044 
   3045 void
   3046 tile(Monitor *m)
   3047 {
   3048     unsigned int h, r, e = m->gaps, mw, my, ty;
   3049     int i, n = 0;
   3050     Client *c;
   3051 
   3052     wl_list_for_each(c, &clients, link)
   3053         if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen)
   3054             n++;
   3055     if (n == 0)
   3056         return;
   3057 
   3058     if (n > m->nmaster)
   3059         mw = m->nmaster ? ROUND((m->w.width + gappx*e) * m->mfact) : 0;
   3060     else
   3061         mw = m->w.width - 2*gappx*e + gappx*e;
   3062     i = 0;
   3063     my = ty = gappx*e;
   3064     wl_list_for_each(c, &clients, link) {
   3065         if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
   3066             continue;
   3067         if (i < m->nmaster) {
   3068             r = MIN(n, m->nmaster) - i;
   3069             h = (m->w.height - my - gappx*e - gappx*e * (r - 1)) / r;
   3070             resize(c, (struct wlr_box){.x = m->w.x + gappx*e, .y = m->w.y + my,
   3071                 .width = mw - gappx*e, .height = h}, 0);
   3072             my += c->geom.height + gappx*e;
   3073         } else {
   3074             r = n - i;
   3075             h = (m->w.height - ty - gappx*e - gappx*e * (r - 1)) / r;
   3076             resize(c, (struct wlr_box){.x = m->w.x + mw + gappx*e, .y = m->w.y + ty,
   3077                 .width = m->w.width - mw - 2*gappx*e, .height = h}, 0);
   3078             ty += c->geom.height + gappx*e;
   3079         }
   3080         i++;
   3081     }
   3082 }
   3083 
   3084 void
   3085 togglebar(const Arg *arg) {
   3086     DwlIpcOutput *ipc_output;
   3087     wl_list_for_each(ipc_output, &selmon->dwl_ipc_outputs, link)
   3088         zdwl_ipc_output_v2_send_toggle_visibility(ipc_output->resource);
   3089 }
   3090 
   3091 void
   3092 togglefloating(const Arg *arg)
   3093 {
   3094     Client *sel = focustop(selmon);
   3095     /* return if fullscreen */
   3096     if (sel && !sel->isfullscreen)
   3097         setfloating(sel, !sel->isfloating);
   3098 }
   3099 
   3100 void
   3101 togglefullscreen(const Arg *arg)
   3102 {
   3103     Client *sel = focustop(selmon);
   3104     if (sel)
   3105         setfullscreen(sel, !sel->isfullscreen);
   3106 }
   3107 
   3108 void
   3109 togglegaps(const Arg *arg)
   3110 {
   3111     selmon->gaps = !selmon->gaps;
   3112     arrange(selmon);
   3113 }
   3114 
   3115 void
   3116 toggletag(const Arg *arg)
   3117 {
   3118     uint32_t newtags;
   3119     Client *sel = focustop(selmon);
   3120     if (!sel || !(newtags = sel->tags ^ (arg->ui & TAGMASK)))
   3121         return;
   3122 
   3123     sel->tags = newtags;
   3124     focusclient(focustop(selmon), 1);
   3125     arrange(selmon);
   3126     printstatus();
   3127 }
   3128 
   3129 void
   3130 toggleview(const Arg *arg)
   3131 {
   3132     uint32_t newtagset;
   3133     if (!(newtagset = selmon ? selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK) : 0))
   3134         return;
   3135 
   3136     selmon->tagset[selmon->seltags] = newtagset;
   3137     focusclient(focustop(selmon), 1);
   3138     arrange(selmon);
   3139     printstatus();
   3140 }
   3141 
   3142 void
   3143 unlocksession(struct wl_listener *listener, void *data)
   3144 {
   3145     SessionLock *lock = wl_container_of(listener, lock, unlock);
   3146     destroylock(lock, 1);
   3147 }
   3148 
   3149 void
   3150 unmaplayersurfacenotify(struct wl_listener *listener, void *data)
   3151 {
   3152     LayerSurface *l = wl_container_of(listener, l, unmap);
   3153 
   3154     l->mapped = 0;
   3155     wlr_scene_node_set_enabled(&l->scene->node, 0);
   3156     if (l == exclusive_focus)
   3157         exclusive_focus = NULL;
   3158     if (l->layer_surface->output && (l->mon = l->layer_surface->output->data))
   3159         arrangelayers(l->mon);
   3160     if (l->layer_surface->surface == seat->keyboard_state.focused_surface)
   3161         focusclient(focustop(selmon), 1);
   3162     motionnotify(0, NULL, 0, 0, 0, 0);
   3163 }
   3164 
   3165 void
   3166 unmapnotify(struct wl_listener *listener, void *data)
   3167 {
   3168     /* Called when the surface is unmapped, and should no longer be shown. */
   3169     Client *c = wl_container_of(listener, c, unmap);
   3170     if (c == grabc) {
   3171         cursor_mode = CurNormal;
   3172         grabc = NULL;
   3173     }
   3174 
   3175     if (c->swallowedby) {
   3176         swallow(c->swallowedby, c);
   3177     }
   3178 
   3179     if (client_is_unmanaged(c)) {
   3180         if (c == exclusive_focus) {
   3181             exclusive_focus = NULL;
   3182             focusclient(focustop(selmon), 1);
   3183         }
   3184     } else {
   3185         if (!c->swallowing)
   3186             wl_list_remove(&c->link);
   3187         setmon(c, NULL, 0);
   3188         if (!c->swallowing)
   3189             wl_list_remove(&c->flink);
   3190     }
   3191 
   3192     if (c->swallowedby) {
   3193         c->swallowedby->prev = c->geom;
   3194         setfullscreen(c->swallowedby, c->isfullscreen);
   3195         c->swallowedby->swallowing = NULL;
   3196         c->swallowedby = NULL;
   3197     }
   3198 
   3199     if (c->swallowing) {
   3200         c->swallowing->swallowedby = NULL;
   3201         c->swallowing = NULL;
   3202     }
   3203 
   3204     wlr_scene_node_destroy(&c->scene->node);
   3205     printstatus();
   3206     motionnotify(0, NULL, 0, 0, 0, 0);
   3207 }
   3208 
   3209 void
   3210 updatemons(struct wl_listener *listener, void *data)
   3211 {
   3212     /*
   3213      * Called whenever the output layout changes: adding or removing a
   3214      * monitor, changing an output's mode or position, etc. This is where
   3215      * the change officially happens and we update geometry, window
   3216      * positions, focus, and the stored configuration in wlroots'
   3217      * output-manager implementation.
   3218      */
   3219     struct wlr_output_configuration_v1 *config
   3220             = wlr_output_configuration_v1_create();
   3221     Client *c;
   3222     struct wlr_output_configuration_head_v1 *config_head;
   3223     Monitor *m;
   3224 
   3225     /* First remove from the layout the disabled monitors */
   3226     wl_list_for_each(m, &mons, link) {
   3227         if (m->wlr_output->enabled)
   3228             continue;
   3229         config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output);
   3230         config_head->state.enabled = 0;
   3231         /* Remove this output from the layout to avoid cursor enter inside it */
   3232         wlr_output_layout_remove(output_layout, m->wlr_output);
   3233         closemon(m);
   3234         m->m = m->w = (struct wlr_box){0};
   3235     }
   3236     /* Insert outputs that need to */
   3237     wl_list_for_each(m, &mons, link) {
   3238         if (m->wlr_output->enabled
   3239                 && !wlr_output_layout_get(output_layout, m->wlr_output))
   3240             wlr_output_layout_add_auto(output_layout, m->wlr_output);
   3241     }
   3242 
   3243     /* Now that we update the output layout we can get its box */
   3244     wlr_output_layout_get_box(output_layout, NULL, &sgeom);
   3245 
   3246     wlr_scene_node_set_position(&root_bg->node, sgeom.x, sgeom.y);
   3247     wlr_scene_rect_set_size(root_bg, sgeom.width, sgeom.height);
   3248 
   3249     /* Make sure the clients are hidden when dwl is locked */
   3250     wlr_scene_node_set_position(&locked_bg->node, sgeom.x, sgeom.y);
   3251     wlr_scene_rect_set_size(locked_bg, sgeom.width, sgeom.height);
   3252 
   3253     wl_list_for_each(m, &mons, link) {
   3254         if (!m->wlr_output->enabled)
   3255             continue;
   3256         config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output);
   3257 
   3258         /* Get the effective monitor geometry to use for surfaces */
   3259         wlr_output_layout_get_box(output_layout, m->wlr_output, &m->m);
   3260         m->w = m->m;
   3261         wlr_scene_output_set_position(m->scene_output, m->m.x, m->m.y);
   3262 
   3263         wlr_scene_node_set_position(&m->fullscreen_bg->node, m->m.x, m->m.y);
   3264         wlr_scene_rect_set_size(m->fullscreen_bg, m->m.width, m->m.height);
   3265 
   3266         if (m->lock_surface) {
   3267             struct wlr_scene_tree *scene_tree = m->lock_surface->surface->data;
   3268             wlr_scene_node_set_position(&scene_tree->node, m->m.x, m->m.y);
   3269             wlr_session_lock_surface_v1_configure(m->lock_surface, m->m.width, m->m.height);
   3270         }
   3271 
   3272         /* Calculate the effective monitor geometry to use for clients */
   3273         arrangelayers(m);
   3274         /* Don't move clients to the left output when plugging monitors */
   3275         arrange(m);
   3276         /* make sure fullscreen clients have the right size */
   3277         if ((c = focustop(m)) && c->isfullscreen)
   3278             resize(c, m->m, 0);
   3279 
   3280         /* Try to re-set the gamma LUT when updating monitors,
   3281          * it's only really needed when enabling a disabled output, but meh. */
   3282         m->gamma_lut_changed = 1;
   3283 
   3284         config_head->state.x = m->m.x;
   3285         config_head->state.y = m->m.y;
   3286     }
   3287 
   3288     if (selmon && selmon->wlr_output->enabled) {
   3289         wl_list_for_each(c, &clients, link) {
   3290             if (!c->mon && client_surface(c)->mapped)
   3291                 setmon(c, selmon, c->tags);
   3292         }
   3293         focusclient(focustop(selmon), 1);
   3294         if (selmon->lock_surface) {
   3295             client_notify_enter(selmon->lock_surface->surface,
   3296                     wlr_seat_get_keyboard(seat));
   3297             client_activate_surface(selmon->lock_surface->surface, 1);
   3298         }
   3299     }
   3300 
   3301     /* FIXME: figure out why the cursor image is at 0,0 after turning all
   3302      * the monitors on.
   3303      * Move the cursor image where it used to be. It does not generate a
   3304      * wl_pointer.motion event for the clients, it's only the image what it's
   3305      * at the wrong position after all. */
   3306     wlr_cursor_move(cursor, NULL, 0, 0);
   3307 
   3308     wlr_output_manager_v1_set_configuration(output_mgr, config);
   3309 }
   3310 
   3311 void
   3312 updatetitle(struct wl_listener *listener, void *data)
   3313 {
   3314     Client *c = wl_container_of(listener, c, set_title);
   3315     if (c == focustop(c->mon))
   3316         printstatus();
   3317 }
   3318 
   3319 void
   3320 urgent(struct wl_listener *listener, void *data)
   3321 {
   3322     struct wlr_xdg_activation_v1_request_activate_event *event = data;
   3323     Client *c = NULL;
   3324     toplevel_from_wlr_surface(event->surface, &c, NULL);
   3325     if (!c || c == focustop(selmon))
   3326         return;
   3327 
   3328     c->isurgent = 1;
   3329     printstatus();
   3330 
   3331     if (client_surface(c)->mapped)
   3332         client_set_border_color(c, urgentcolor);
   3333 }
   3334 
   3335 void
   3336 view(const Arg *arg)
   3337 {
   3338     if (!selmon || (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
   3339         return;
   3340     selmon->seltags ^= 1; /* toggle sel tagset */
   3341     if (arg->ui & TAGMASK)
   3342         selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
   3343     focusclient(focustop(selmon), 1);
   3344     arrange(selmon);
   3345     printstatus();
   3346 }
   3347 
   3348 void
   3349 virtualkeyboard(struct wl_listener *listener, void *data)
   3350 {
   3351     struct wlr_virtual_keyboard_v1 *keyboard = data;
   3352     /* Set the keymap to match the group keymap */
   3353     wlr_keyboard_set_keymap(&keyboard->keyboard, vkb_group.wlr_group->keyboard.keymap);
   3354     wlr_keyboard_set_repeat_info(&keyboard->keyboard, repeat_rate, repeat_delay);
   3355 
   3356     /* Add the new keyboard to the group */
   3357     wlr_keyboard_group_add_keyboard(vkb_group.wlr_group, &keyboard->keyboard);
   3358 }
   3359 
   3360 void
   3361 virtualpointer(struct wl_listener *listener, void *data)
   3362 {
   3363     struct wlr_virtual_pointer_v1_new_pointer_event *event = data;
   3364     struct wlr_pointer pointer = event->new_pointer->pointer;
   3365 
   3366     wlr_cursor_attach_input_device(cursor, &pointer.base);
   3367     if (event->suggested_output)
   3368         wlr_cursor_map_input_to_output(cursor, &pointer.base, event->suggested_output);
   3369 }
   3370 
   3371 Monitor *
   3372 xytomon(double x, double y)
   3373 {
   3374     struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y);
   3375     return o ? o->data : NULL;
   3376 }
   3377 
   3378 void
   3379 xytonode(double x, double y, struct wlr_surface **psurface,
   3380         Client **pc, LayerSurface **pl, double *nx, double *ny)
   3381 {
   3382     struct wlr_scene_node *node, *pnode;
   3383     struct wlr_surface *surface = NULL;
   3384     Client *c = NULL;
   3385     LayerSurface *l = NULL;
   3386     int layer;
   3387 
   3388     for (layer = NUM_LAYERS - 1; !surface && layer >= 0; layer--) {
   3389         if (!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny)))
   3390             continue;
   3391 
   3392         if (node->type == WLR_SCENE_NODE_BUFFER)
   3393             surface = wlr_scene_surface_try_from_buffer(
   3394                     wlr_scene_buffer_from_node(node))->surface;
   3395         /* Walk the tree to find a node that knows the client */
   3396         for (pnode = node; pnode && !c; pnode = &pnode->parent->node)
   3397             c = pnode->data;
   3398         if (c && c->type == LayerShell) {
   3399             c = NULL;
   3400             l = pnode->data;
   3401         }
   3402     }
   3403 
   3404     if (psurface) *psurface = surface;
   3405     if (pc) *pc = c;
   3406     if (pl) *pl = l;
   3407 }
   3408 
   3409 void
   3410 zoom(const Arg *arg)
   3411 {
   3412     Client *c, *sel = focustop(selmon);
   3413 
   3414     if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange || sel->isfloating)
   3415         return;
   3416 
   3417     /* Search for the first tiled window that is not sel, marking sel as
   3418      * NULL if we pass it along the way */
   3419     wl_list_for_each(c, &clients, link) {
   3420         if (VISIBLEON(c, selmon) && !c->isfloating) {
   3421             if (c != sel)
   3422                 break;
   3423             sel = NULL;
   3424         }
   3425     }
   3426 
   3427     /* Return if no other tiled window was found */
   3428     if (&c->link == &clients)
   3429         return;
   3430 
   3431     /* If we passed sel, move c to the front; otherwise, move sel to the
   3432      * front */
   3433     if (!sel)
   3434         sel = c;
   3435     wl_list_remove(&sel->link);
   3436     wl_list_insert(&clients, &sel->link);
   3437 
   3438     focusclient(sel, 1);
   3439     arrange(selmon);
   3440 }
   3441 
   3442 #ifdef XWAYLAND
   3443 void
   3444 activatex11(struct wl_listener *listener, void *data)
   3445 {
   3446     Client *c = wl_container_of(listener, c, activate);
   3447 
   3448     /* Only "managed" windows can be activated */
   3449     if (!client_is_unmanaged(c))
   3450         wlr_xwayland_surface_activate(c->surface.xwayland, 1);
   3451 }
   3452 
   3453 void
   3454 associatex11(struct wl_listener *listener, void *data)
   3455 {
   3456     Client *c = wl_container_of(listener, c, associate);
   3457 
   3458     LISTEN(&client_surface(c)->events.map, &c->map, mapnotify);
   3459     LISTEN(&client_surface(c)->events.unmap, &c->unmap, unmapnotify);
   3460 }
   3461 
   3462 void
   3463 configurex11(struct wl_listener *listener, void *data)
   3464 {
   3465     Client *c = wl_container_of(listener, c, configure);
   3466     struct wlr_xwayland_surface_configure_event *event = data;
   3467     /* TODO: figure out if there is another way to do this */
   3468     if (!c->mon) {
   3469         wlr_xwayland_surface_configure(c->surface.xwayland,
   3470                 event->x, event->y, event->width, event->height);
   3471         return;
   3472     }
   3473     if (c->isfloating || client_is_unmanaged(c))
   3474         resize(c, (struct wlr_box){.x = event->x, .y = event->y,
   3475                 .width = event->width, .height = event->height}, 0);
   3476 
   3477     // NOTE(jake): below causes steam to hard lock up
   3478     // https://codeberg.org/dwl/dwl/issues/573
   3479 #if 0
   3480     else
   3481         arrange(c->mon);
   3482 #endif
   3483 }
   3484 
   3485 void
   3486 createnotifyx11(struct wl_listener *listener, void *data)
   3487 {
   3488     struct wlr_xwayland_surface *xsurface = data;
   3489     Client *c;
   3490 
   3491     /* Allocate a Client for this surface */
   3492     c = xsurface->data = ecalloc(1, sizeof(*c));
   3493     c->surface.xwayland = xsurface;
   3494     c->type = X11;
   3495     c->bw = borderpx;
   3496 
   3497     /* Listen to the various events it can emit */
   3498     LISTEN(&xsurface->events.associate, &c->associate, associatex11);
   3499     LISTEN(&xsurface->events.destroy, &c->destroy, destroynotify);
   3500     LISTEN(&xsurface->events.dissociate, &c->dissociate, dissociatex11);
   3501     LISTEN(&xsurface->events.request_activate, &c->activate, activatex11);
   3502     LISTEN(&xsurface->events.request_configure, &c->configure, configurex11);
   3503     LISTEN(&xsurface->events.request_fullscreen, &c->fullscreen, fullscreennotify);
   3504     LISTEN(&xsurface->events.set_hints, &c->set_hints, sethints);
   3505     LISTEN(&xsurface->events.set_title, &c->set_title, updatetitle);
   3506 }
   3507 
   3508 void
   3509 dissociatex11(struct wl_listener *listener, void *data)
   3510 {
   3511     Client *c = wl_container_of(listener, c, dissociate);
   3512     wl_list_remove(&c->map.link);
   3513     wl_list_remove(&c->unmap.link);
   3514 }
   3515 
   3516 xcb_atom_t
   3517 getatom(xcb_connection_t *xc, const char *name)
   3518 {
   3519     xcb_atom_t atom = 0;
   3520     xcb_intern_atom_reply_t *reply;
   3521     xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xc, 0, strlen(name), name);
   3522     if ((reply = xcb_intern_atom_reply(xc, cookie, NULL)))
   3523         atom = reply->atom;
   3524     free(reply);
   3525 
   3526     return atom;
   3527 }
   3528 
   3529 void
   3530 sethints(struct wl_listener *listener, void *data)
   3531 {
   3532     Client *c = wl_container_of(listener, c, set_hints);
   3533     struct wlr_surface *surface = client_surface(c);
   3534     if (c == focustop(selmon))
   3535         return;
   3536 
   3537     c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints);
   3538     printstatus();
   3539 
   3540     if (c->isurgent && surface && surface->mapped)
   3541         client_set_border_color(c, urgentcolor);
   3542 }
   3543 
   3544 void
   3545 xwaylandready(struct wl_listener *listener, void *data)
   3546 {
   3547     struct wlr_xcursor *xcursor;
   3548     xcb_connection_t *xc = xcb_connect(xwayland->display_name, NULL);
   3549     int err = xcb_connection_has_error(xc);
   3550     if (err) {
   3551         fprintf(stderr, "xcb_connect to X server failed with code %d\n. Continuing with degraded functionality.\n", err);
   3552         return;
   3553     }
   3554 
   3555     /* Collect atoms we are interested in. If getatom returns 0, we will
   3556      * not detect that window type. */
   3557     netatom[NetWMWindowTypeDialog] = getatom(xc, "_NET_WM_WINDOW_TYPE_DIALOG");
   3558     netatom[NetWMWindowTypeSplash] = getatom(xc, "_NET_WM_WINDOW_TYPE_SPLASH");
   3559     netatom[NetWMWindowTypeToolbar] = getatom(xc, "_NET_WM_WINDOW_TYPE_TOOLBAR");
   3560     netatom[NetWMWindowTypeUtility] = getatom(xc, "_NET_WM_WINDOW_TYPE_UTILITY");
   3561 
   3562     /* assign the one and only seat */
   3563     wlr_xwayland_set_seat(xwayland, seat);
   3564 
   3565     /* Set the default XWayland cursor to match the rest of dwl. */
   3566     if ((xcursor = wlr_xcursor_manager_get_xcursor(cursor_mgr, "default", 1)))
   3567         wlr_xwayland_set_cursor(xwayland,
   3568                 xcursor->images[0]->buffer, xcursor->images[0]->width * 4,
   3569                 xcursor->images[0]->width, xcursor->images[0]->height,
   3570                 xcursor->images[0]->hotspot_x, xcursor->images[0]->hotspot_y);
   3571 
   3572     xcb_disconnect(xc);
   3573 }
   3574 #endif
   3575 
   3576 int
   3577 main(int argc, char *argv[])
   3578 {
   3579     char *startup_cmd = NULL;
   3580     int c;
   3581 
   3582     while ((c = getopt(argc, argv, "s:hdv")) != -1) {
   3583         if (c == 's')
   3584             startup_cmd = optarg;
   3585         else if (c == 'd')
   3586             log_level = WLR_DEBUG;
   3587         else if (c == 'v')
   3588             die("dwl " VERSION);
   3589         else
   3590             goto usage;
   3591     }
   3592     if (optind < argc)
   3593         goto usage;
   3594 
   3595     /* Wayland requires XDG_RUNTIME_DIR for creating its communications socket */
   3596     if (!getenv("XDG_RUNTIME_DIR"))
   3597         die("XDG_RUNTIME_DIR must be set");
   3598     setup();
   3599     initenv();
   3600     run(startup_cmd);
   3601     cleanup();
   3602     return EXIT_SUCCESS;
   3603 
   3604 usage:
   3605     die("Usage: %s [-v] [-d] [-s startup command]", argv[0]);
   3606 }