4 Commits

Author SHA1 Message Date
Leonardo Hernández Hernández 03fbd67c9c document status output 2025-01-02 20:02:17 -06:00
Leonardo Hernández Hernández 3db89cd5e8 Use a subsection for mouse commands
also add missing ".El", s/Toggles/Toggle/ in second command and add newlines
after a full stop
2025-01-02 20:01:35 -06:00
Leonardo Hernández Hernández 982dcc4133 document mouse button actions
[sevz: commit message is mine. The content was written by scottro11 and shared
in https://codeberg.org/dwl/dwl/issues/697]

Closes: https://codeberg.org/dwl/dwl/issues/697
2024-12-30 22:41:07 -06:00
Leonardo Hernández Hernández a035b0b9f3 drop CAVEATS section from the man page
Since 71f11e6cf6 it is not longer the case
2024-12-30 22:41:07 -06:00
5 changed files with 148 additions and 179 deletions
+5 -7
View File
@@ -15,11 +15,10 @@ philosophy. Like dwm, dwl is:
## Getting Started: ## Getting Started:
### Latest semi-stable [release] ### Latest semi-stable [release]
This is probably where you want to start. This builds against the [wlroots] This is probably where you want to start. This builds against the dependent
versions currently shipping in major distributions. If your packages' versions currently shipping in major distributions. If your
distribution's `wlroots` version is older, use an earlier dwl [release]. distribution's wlroots version is older, use an earlier dwl [release] or [0.x
The `wlroots` version against which a given `dwl` release builds is specified branch].
with each release on the [release] page
### Development branch [main] ### Development branch [main]
Active development progresses on the `main` branch. The `main` branch is built Active development progresses on the `main` branch. The `main` branch is built
@@ -75,7 +74,7 @@ seatd daemon.
When dwl is run with no arguments, it will launch the server and begin handling When dwl is run with no arguments, it will launch the server and begin handling
any shortcuts configured in `config.h`. There is no status bar or other any shortcuts configured in `config.h`. There is no status bar or other
decoration initially; these are instead clients that can be run within the decoration initially; these are instead clients that can be run within the
Wayland session. Do note that the default background color is grey. This can be Wayland session. Do note that the default background color is black. This can be
modified in `config.h`. modified in `config.h`.
If you would like to run a script or command automatically at startup, you can If you would like to run a script or command automatically at startup, you can
@@ -182,7 +181,6 @@ inspiration, and to the various contributors to the project, including:
- Stivvo for output management and fullscreen support, and patch maintenance - Stivvo for output management and fullscreen support, and patch maintenance
[wlroots]: https://gitlab.freedesktop.org/wlroots
[`systemd --user`]: https://wiki.archlinux.org/title/Systemd/User [`systemd --user`]: https://wiki.archlinux.org/title/Systemd/User
[#dwl on Libera Chat]: https://web.libera.chat/?channels=#dwl [#dwl on Libera Chat]: https://web.libera.chat/?channels=#dwl
[0.7-rc1]: https://codeberg.org/dwl/dwl/releases/tag/v0.7-rc1 [0.7-rc1]: https://codeberg.org/dwl/dwl/releases/tag/v0.7-rc1
+9 -8
View File
@@ -213,15 +213,16 @@ client_is_float_type(Client *c)
if (client_is_x11(c)) { if (client_is_x11(c)) {
struct wlr_xwayland_surface *surface = c->surface.xwayland; struct wlr_xwayland_surface *surface = c->surface.xwayland;
xcb_size_hints_t *size_hints = surface->size_hints; xcb_size_hints_t *size_hints = surface->size_hints;
size_t i;
if (surface->modal) if (surface->modal)
return 1; return 1;
if (wlr_xwayland_surface_has_window_type(surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DIALOG) for (i = 0; i < surface->window_type_len; i++)
|| wlr_xwayland_surface_has_window_type(surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_SPLASH) if (surface->window_type[i] == netatom[NetWMWindowTypeDialog]
|| wlr_xwayland_surface_has_window_type(surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_TOOLBAR) || surface->window_type[i] == netatom[NetWMWindowTypeSplash]
|| wlr_xwayland_surface_has_window_type(surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_UTILITY)) { || surface->window_type[i] == netatom[NetWMWindowTypeToolbar]
return 1; || surface->window_type[i] == netatom[NetWMWindowTypeUtility])
} return 1;
return size_hints && size_hints->min_width > 0 && size_hints->min_height > 0 return size_hints && size_hints->min_width > 0 && size_hints->min_height > 0
&& (size_hints->max_width == size_hints->min_width && (size_hints->max_width == size_hints->min_width
@@ -264,8 +265,8 @@ client_is_stopped(Client *c)
wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL); wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL);
if (waitid(P_PID, pid, &in, WNOHANG|WCONTINUED|WSTOPPED|WNOWAIT) < 0) { if (waitid(P_PID, pid, &in, WNOHANG|WCONTINUED|WSTOPPED|WNOWAIT) < 0) {
/* This process is not our child process, while is very unlikely that /* This process is not our child process, while is very unluckely that
* it is stopped, in order to do not skip frames, assume that it is. */ * it is stopped, in order to do not skip frames assume that it is. */
if (errno == ECHILD) if (errno == ECHILD)
return 1; return 1;
} else if (in.si_pid) { } else if (in.si_pid) {
+14 -13
View File
@@ -12,7 +12,7 @@ static const float bordercolor[] = COLOR(0x444444ff);
static const float focuscolor[] = COLOR(0x005577ff); static const float focuscolor[] = COLOR(0x005577ff);
static const float urgentcolor[] = COLOR(0xff0000ff); static const float urgentcolor[] = COLOR(0xff0000ff);
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
static const float fullscreen_bg[] = {0.0f, 0.0f, 0.0f, 1.0f}; /* You can also use glsl colors */ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
/* tagging - TAGCOUNT must be no greater than 31 */ /* tagging - TAGCOUNT must be no greater than 31 */
#define TAGCOUNT (9) #define TAGCOUNT (9)
@@ -20,9 +20,10 @@ static const float fullscreen_bg[] = {0.0f, 0.0f, 0.0f, 1.0f}; /* You ca
/* logging */ /* logging */
static int log_level = WLR_ERROR; static int log_level = WLR_ERROR;
/* AT LEAST ONE rule must exist. Define at least an EXAMPLE rule here. */ /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */
static const Rule rules[] = { static const Rule rules[] = {
/* app_id title tags mask isfloating monitor */ /* app_id title tags mask isfloating monitor */
/* examples: */
{ "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */
{ "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */
}; };
@@ -36,18 +37,18 @@ static const Layout layouts[] = {
}; };
/* monitors */ /* monitors */
/* /* (x=-1, y=-1) is reserved as an "autoconfigure" monitor position indicator
* (x=-1, y=-1) causes a monitor to "autoconfigure" its position * WARNING: negative values other than (-1, -1) cause problems with Xwayland clients
* * https://gitlab.freedesktop.org/xorg/xserver/-/issues/899
* WARNING: Due to https://gitlab.freedesktop.org/xorg/xserver/-/issues/899 */
* negative monitor positions other than (-1, -1) create problems for Xwayland /* NOTE: ALWAYS add a fallback rule, even if you are completely sure it won't be used */
* clients
*
* AT LEAST ONE monitor rule must exist. Define at least a NULL default rule here. */
static const MonitorRule monrules[] = { static const MonitorRule monrules[] = {
/* name mfact nmaster scale layout rotate/reflect x y */ /* name mfact nmaster scale layout rotate/reflect x y */
{ NULL, 0.55f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, /* example of a HiDPI laptop monitor:
{ "eDP-1_EXAMPLE", 0.5f, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, { "eDP-1", 0.5f, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 },
*/
/* defaults */
{ NULL, 0.55f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 },
}; };
/* keyboard */ /* keyboard */
+1 -1
View File
@@ -11,7 +11,7 @@ DATADIR = $(PREFIX)/share
WLR_INCS = `$(PKG_CONFIG) --cflags wlroots-0.19` WLR_INCS = `$(PKG_CONFIG) --cflags wlroots-0.19`
WLR_LIBS = `$(PKG_CONFIG) --libs wlroots-0.19` WLR_LIBS = `$(PKG_CONFIG) --libs wlroots-0.19`
# Allow using an alternative wlroots installation # Allow using an alternative wlroots installations
# This has to have all the includes required by wlroots, e.g: # This has to have all the includes required by wlroots, e.g:
# Assuming wlroots git repo is "${PWD}/wlroots" and you only ran "meson setup build && ninja -C build" # Assuming wlroots git repo is "${PWD}/wlroots" and you only ran "meson setup build && ninja -C build"
#WLR_INCS = -I/usr/include/pixman-1 -I/usr/include/elogind -I/usr/include/libdrm \ #WLR_INCS = -I/usr/include/pixman-1 -I/usr/include/elogind -I/usr/include/libdrm \
+119 -150
View File
@@ -79,12 +79,16 @@
#define END(A) ((A) + LENGTH(A)) #define END(A) ((A) + LENGTH(A))
#define TAGMASK ((1u << TAGCOUNT) - 1) #define TAGMASK ((1u << TAGCOUNT) - 1)
#define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) #define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L)))
#define LISTEN_STATIC(E, H) do { struct wl_listener *_l = ecalloc(1, sizeof(*_l)); _l->notify = (H); wl_signal_add((E), _l); } while (0) #define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0)
/* enums */ /* enums */
enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
enum { XDGShell, LayerShell, X11 }; /* client types */ enum { XDGShell, LayerShell, X11 }; /* client types */
enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */
#ifdef XWAYLAND
enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar,
NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */
#endif
typedef union { typedef union {
int i; int i;
@@ -252,7 +256,6 @@ static void chvt(const Arg *arg);
static void checkidleinhibitor(struct wlr_surface *exclude); static void checkidleinhibitor(struct wlr_surface *exclude);
static void cleanup(void); static void cleanup(void);
static void cleanupmon(struct wl_listener *listener, void *data); static void cleanupmon(struct wl_listener *listener, void *data);
static void cleanuplisteners(void);
static void closemon(Monitor *m); static void closemon(Monitor *m);
static void commitlayersurfacenotify(struct wl_listener *listener, void *data); static void commitlayersurfacenotify(struct wl_listener *listener, void *data);
static void commitnotify(struct wl_listener *listener, void *data); static void commitnotify(struct wl_listener *listener, void *data);
@@ -280,6 +283,7 @@ static void destroylocksurface(struct wl_listener *listener, void *data);
static void destroynotify(struct wl_listener *listener, void *data); static void destroynotify(struct wl_listener *listener, void *data);
static void destroypointerconstraint(struct wl_listener *listener, void *data); static void destroypointerconstraint(struct wl_listener *listener, void *data);
static void destroysessionlock(struct wl_listener *listener, void *data); static void destroysessionlock(struct wl_listener *listener, void *data);
static void destroysessionmgr(struct wl_listener *listener, void *data);
static void destroykeyboardgroup(struct wl_listener *listener, void *data); static void destroykeyboardgroup(struct wl_listener *listener, void *data);
static Monitor *dirtomon(enum wlr_direction dir); static Monitor *dirtomon(enum wlr_direction dir);
static void focusclient(Client *c, int lift); static void focusclient(Client *c, int lift);
@@ -394,6 +398,7 @@ static struct wlr_scene_rect *root_bg;
static struct wlr_session_lock_manager_v1 *session_lock_mgr; static struct wlr_session_lock_manager_v1 *session_lock_mgr;
static struct wlr_scene_rect *locked_bg; static struct wlr_scene_rect *locked_bg;
static struct wlr_session_lock_v1 *cur_lock; static struct wlr_session_lock_v1 *cur_lock;
static struct wl_listener lock_listener = {.notify = locksession};
static struct wlr_seat *seat; static struct wlr_seat *seat;
static KeyboardGroup *kb_group; static KeyboardGroup *kb_group;
@@ -406,47 +411,17 @@ static struct wlr_box sgeom;
static struct wl_list mons; static struct wl_list mons;
static Monitor *selmon; static Monitor *selmon;
/* global event handlers */
static struct wl_listener cursor_axis = {.notify = axisnotify};
static struct wl_listener cursor_button = {.notify = buttonpress};
static struct wl_listener cursor_frame = {.notify = cursorframe};
static struct wl_listener cursor_motion = {.notify = motionrelative};
static struct wl_listener cursor_motion_absolute = {.notify = motionabsolute};
static struct wl_listener gpu_reset = {.notify = gpureset};
static struct wl_listener layout_change = {.notify = updatemons};
static struct wl_listener new_idle_inhibitor = {.notify = createidleinhibitor};
static struct wl_listener new_input_device = {.notify = inputdevice};
static struct wl_listener new_virtual_keyboard = {.notify = virtualkeyboard};
static struct wl_listener new_virtual_pointer = {.notify = virtualpointer};
static struct wl_listener new_pointer_constraint = {.notify = createpointerconstraint};
static struct wl_listener new_output = {.notify = createmon};
static struct wl_listener new_xdg_toplevel = {.notify = createnotify};
static struct wl_listener new_xdg_popup = {.notify = createpopup};
static struct wl_listener new_xdg_decoration = {.notify = createdecoration};
static struct wl_listener new_layer_surface = {.notify = createlayersurface};
static struct wl_listener output_mgr_apply = {.notify = outputmgrapply};
static struct wl_listener output_mgr_test = {.notify = outputmgrtest};
static struct wl_listener output_power_mgr_set_mode = {.notify = powermgrsetmode};
static struct wl_listener request_activate = {.notify = urgent};
static struct wl_listener request_cursor = {.notify = setcursor};
static struct wl_listener request_set_psel = {.notify = setpsel};
static struct wl_listener request_set_sel = {.notify = setsel};
static struct wl_listener request_set_cursor_shape = {.notify = setcursorshape};
static struct wl_listener request_start_drag = {.notify = requeststartdrag};
static struct wl_listener start_drag = {.notify = startdrag};
static struct wl_listener new_session_lock = {.notify = locksession};
#ifdef XWAYLAND #ifdef XWAYLAND
static void activatex11(struct wl_listener *listener, void *data); static void activatex11(struct wl_listener *listener, void *data);
static void associatex11(struct wl_listener *listener, void *data); static void associatex11(struct wl_listener *listener, void *data);
static void configurex11(struct wl_listener *listener, void *data); static void configurex11(struct wl_listener *listener, void *data);
static void createnotifyx11(struct wl_listener *listener, void *data); static void createnotifyx11(struct wl_listener *listener, void *data);
static void dissociatex11(struct wl_listener *listener, void *data); static void dissociatex11(struct wl_listener *listener, void *data);
static xcb_atom_t getatom(xcb_connection_t *xc, const char *name);
static void sethints(struct wl_listener *listener, void *data); static void sethints(struct wl_listener *listener, void *data);
static void xwaylandready(struct wl_listener *listener, void *data); static void xwaylandready(struct wl_listener *listener, void *data);
static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11};
static struct wl_listener xwayland_ready = {.notify = xwaylandready};
static struct wlr_xwayland *xwayland; static struct wlr_xwayland *xwayland;
static xcb_atom_t netatom[NetLast];
#endif #endif
/* configuration, allows nested code to access above variables */ /* configuration, allows nested code to access above variables */
@@ -483,6 +458,7 @@ applyrules(Client *c)
const Rule *r; const Rule *r;
Monitor *mon = selmon, *m; Monitor *mon = selmon, *m;
c->isfloating = client_is_float_type(c);
appid = client_get_appid(c); appid = client_get_appid(c);
title = client_get_title(c); title = client_get_title(c);
@@ -498,8 +474,6 @@ applyrules(Client *c)
} }
} }
} }
c->isfloating |= client_is_float_type(c);
setmon(c, mon, newtags); setmon(c, mon, newtags);
} }
@@ -552,9 +526,6 @@ arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, int
wl_list_for_each(l, list, link) { wl_list_for_each(l, list, link) {
struct wlr_layer_surface_v1 *layer_surface = l->layer_surface; struct wlr_layer_surface_v1 *layer_surface = l->layer_surface;
if (!layer_surface->initialized)
continue;
if (exclusive != (layer_surface->current.exclusive_zone > 0)) if (exclusive != (layer_surface->current.exclusive_zone > 0))
continue; continue;
@@ -610,8 +581,8 @@ axisnotify(struct wl_listener *listener, void *data)
* for example when you move the scroll wheel. */ * for example when you move the scroll wheel. */
struct wlr_pointer_axis_event *event = data; struct wlr_pointer_axis_event *event = data;
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
/* TODO: allow usage of scroll wheel for mousebindings, it can be implemented /* TODO: allow usage of scroll whell for mousebindings, it can be implemented
* by checking the event's orientation and the delta of the event */ * checking the event's orientation and the delta of the event */
/* Notify the client with pointer focus of the axis event. */ /* Notify the client with pointer focus of the axis event. */
wlr_seat_pointer_notify_axis(seat, wlr_seat_pointer_notify_axis(seat,
event->time_msec, event->orientation, event->delta, event->time_msec, event->orientation, event->delta,
@@ -699,7 +670,6 @@ checkidleinhibitor(struct wlr_surface *exclude)
void void
cleanup(void) cleanup(void)
{ {
cleanuplisteners();
#ifdef XWAYLAND #ifdef XWAYLAND
wlr_xwayland_destroy(xwayland); wlr_xwayland_destroy(xwayland);
xwayland = NULL; xwayland = NULL;
@@ -713,8 +683,8 @@ cleanup(void)
destroykeyboardgroup(&kb_group->destroy, NULL); destroykeyboardgroup(&kb_group->destroy, NULL);
/* If it's not destroyed manually, it will cause a use-after-free of wlr_seat. /* If it's not destroyed manually it will cause a use-after-free of wlr_seat.
* Destroy it until it's fixed on the wlroots side */ * Destroy it until it's fixed in the wlroots side */
wlr_backend_destroy(backend); wlr_backend_destroy(backend);
wl_display_destroy(dpy); wl_display_destroy(dpy);
@@ -740,8 +710,6 @@ cleanupmon(struct wl_listener *listener, void *data)
wl_list_remove(&m->frame.link); wl_list_remove(&m->frame.link);
wl_list_remove(&m->link); wl_list_remove(&m->link);
wl_list_remove(&m->request_state.link); wl_list_remove(&m->request_state.link);
if (m->lock_surface)
destroylocksurface(&m->destroy_lock_surface, NULL);
m->wlr_output->data = NULL; m->wlr_output->data = NULL;
wlr_output_layout_remove(output_layout, m->wlr_output); wlr_output_layout_remove(output_layout, m->wlr_output);
wlr_scene_output_destroy(m->scene_output); wlr_scene_output_destroy(m->scene_output);
@@ -751,43 +719,6 @@ cleanupmon(struct wl_listener *listener, void *data)
free(m); free(m);
} }
void
cleanuplisteners(void)
{
wl_list_remove(&cursor_axis.link);
wl_list_remove(&cursor_button.link);
wl_list_remove(&cursor_frame.link);
wl_list_remove(&cursor_motion.link);
wl_list_remove(&cursor_motion_absolute.link);
wl_list_remove(&gpu_reset.link);
wl_list_remove(&new_idle_inhibitor.link);
wl_list_remove(&layout_change.link);
wl_list_remove(&new_input_device.link);
wl_list_remove(&new_virtual_keyboard.link);
wl_list_remove(&new_virtual_pointer.link);
wl_list_remove(&new_pointer_constraint.link);
wl_list_remove(&new_output.link);
wl_list_remove(&new_xdg_toplevel.link);
wl_list_remove(&new_xdg_decoration.link);
wl_list_remove(&new_xdg_popup.link);
wl_list_remove(&new_layer_surface.link);
wl_list_remove(&output_mgr_apply.link);
wl_list_remove(&output_mgr_test.link);
wl_list_remove(&output_power_mgr_set_mode.link);
wl_list_remove(&request_activate.link);
wl_list_remove(&request_cursor.link);
wl_list_remove(&request_set_psel.link);
wl_list_remove(&request_set_sel.link);
wl_list_remove(&request_set_cursor_shape.link);
wl_list_remove(&request_start_drag.link);
wl_list_remove(&start_drag.link);
wl_list_remove(&new_session_lock.link);
#ifdef XWAYLAND
wl_list_remove(&new_xwayland_surface.link);
wl_list_remove(&xwayland_ready.link);
#endif
}
void void
closemon(Monitor *m) closemon(Monitor *m)
{ {
@@ -861,7 +792,7 @@ commitnotify(struct wl_listener *listener, void *data)
/* /*
* Get the monitor this client will be rendered on * Get the monitor this client will be rendered on
* Note that if the user set a rule in which the client is placed on * Note that if the user set a rule in which the client is placed on
* a different monitor based on its title, this will likely select * a different monitor based on its title this will likely select
* a wrong monitor. * a wrong monitor.
*/ */
applyrules(c); applyrules(c);
@@ -912,7 +843,6 @@ commitpopup(struct wl_listener *listener, void *data)
box.y -= (type == LayerShell ? l->scene->node.y : c->geom.y); box.y -= (type == LayerShell ? l->scene->node.y : c->geom.y);
wlr_xdg_popup_unconstrain_from_box(popup, &box); wlr_xdg_popup_unconstrain_from_box(popup, &box);
wl_list_remove(&listener->link); wl_list_remove(&listener->link);
free(listener);
} }
void void
@@ -1215,7 +1145,7 @@ cursorconstrain(struct wlr_pointer_constraint_v1 *constraint)
void void
cursorframe(struct wl_listener *listener, void *data) cursorframe(struct wl_listener *listener, void *data)
{ {
/* This event is forwarded by the cursor when a pointer emits a frame /* This event is forwarded by the cursor when a pointer emits an frame
* event. Frame events are sent after regular pointer events to group * event. Frame events are sent after regular pointer events to group
* multiple events together. For instance, two axis events may happen at the * multiple events together. For instance, two axis events may happen at the
* same time, in which case a frame event won't be sent in between. */ * same time, in which case a frame event won't be sent in between. */
@@ -1252,8 +1182,6 @@ destroydragicon(struct wl_listener *listener, void *data)
/* Focus enter isn't sent during drag, so refocus the focused node. */ /* Focus enter isn't sent during drag, so refocus the focused node. */
focusclient(focustop(selmon), 1); focusclient(focustop(selmon), 1);
motionnotify(0, NULL, 0, 0, 0, 0); motionnotify(0, NULL, 0, 0, 0, 0);
wl_list_remove(&listener->link);
free(listener);
} }
void void
@@ -1262,8 +1190,6 @@ destroyidleinhibitor(struct wl_listener *listener, void *data)
/* `data` is the wlr_surface of the idle inhibitor being destroyed, /* `data` is the wlr_surface of the idle inhibitor being destroyed,
* at this point the idle inhibitor is still in the list of the manager */ * at this point the idle inhibitor is still in the list of the manager */
checkidleinhibitor(wlr_surface_get_root_surface(data)); checkidleinhibitor(wlr_surface_get_root_surface(data));
wl_list_remove(&listener->link);
free(listener);
} }
void void
@@ -1371,15 +1297,22 @@ destroysessionlock(struct wl_listener *listener, void *data)
destroylock(lock, 0); destroylock(lock, 0);
} }
void
destroysessionmgr(struct wl_listener *listener, void *data)
{
wl_list_remove(&lock_listener.link);
wl_list_remove(&listener->link);
}
void void
destroykeyboardgroup(struct wl_listener *listener, void *data) destroykeyboardgroup(struct wl_listener *listener, void *data)
{ {
KeyboardGroup *group = wl_container_of(listener, group, destroy); KeyboardGroup *group = wl_container_of(listener, group, destroy);
wl_event_source_remove(group->key_repeat_source); wl_event_source_remove(group->key_repeat_source);
wlr_keyboard_group_destroy(group->wlr_group);
wl_list_remove(&group->key.link); wl_list_remove(&group->key.link);
wl_list_remove(&group->modifiers.link); wl_list_remove(&group->modifiers.link);
wl_list_remove(&group->destroy.link); wl_list_remove(&group->destroy.link);
wlr_keyboard_group_destroy(group->wlr_group);
free(group); free(group);
} }
@@ -1511,7 +1444,7 @@ focusstack(const Arg *arg)
focusclient(c, 1); focusclient(c, 1);
} }
/* We probably should change the name of this: it sounds like it /* We probably should change the name of this, it sounds like
* will focus the topmost client of this mon, when actually will * will focus the topmost client of this mon, when actually will
* only return that client */ * only return that client */
Client * Client *
@@ -1544,8 +1477,7 @@ gpureset(struct wl_listener *listener, void *data)
if (!(alloc = wlr_allocator_autocreate(backend, drw))) if (!(alloc = wlr_allocator_autocreate(backend, drw)))
die("couldn't recreate allocator"); die("couldn't recreate allocator");
wl_list_remove(&gpu_reset.link); LISTEN_STATIC(&drw->events.lost, gpureset);
wl_signal_add(&drw->events.lost, &gpu_reset);
wlr_compositor_set_renderer(compositor, drw); wlr_compositor_set_renderer(compositor, drw);
@@ -1560,10 +1492,22 @@ gpureset(struct wl_listener *listener, void *data)
void void
handlesig(int signo) handlesig(int signo)
{ {
if (signo == SIGCHLD) if (signo == SIGCHLD) {
#ifdef XWAYLAND
siginfo_t in;
/* wlroots expects to reap the XWayland process itself, so we
* use WNOWAIT to keep the child waitable until we know it's not
* XWayland.
*/
while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid
&& (!xwayland || in.si_pid != xwayland->server->pid))
waitpid(in.si_pid, NULL, 0);
#else
while (waitpid(-1, NULL, WNOHANG) > 0); while (waitpid(-1, NULL, WNOHANG) > 0);
else if (signo == SIGINT || signo == SIGTERM) #endif
} else if (signo == SIGINT || signo == SIGTERM) {
quit(NULL); quit(NULL);
}
} }
void void
@@ -1783,8 +1727,8 @@ mapnotify(struct wl_listener *listener, void *data)
/* Set initial monitor, tags, floating status, and focus: /* Set initial monitor, tags, floating status, and focus:
* we always consider floating, clients that have parent and thus * we always consider floating, clients that have parent and thus
* we set the same tags and monitor as its parent. * we set the same tags and monitor than its parent, if not
* If there is no parent, apply rules */ * try to apply rules for them */
if ((p = client_get_parent(c))) { if ((p = client_get_parent(c))) {
c->isfloating = 1; c->isfloating = 1;
setmon(c, p->mon, p->tags); setmon(c, p->mon, p->tags);
@@ -1844,7 +1788,8 @@ motionabsolute(struct wl_listener *listener, void *data)
* motion event, from 0..1 on each axis. This happens, for example, when * motion event, from 0..1 on each axis. This happens, for example, when
* wlroots is running under a Wayland window rather than KMS+DRM, and you * wlroots is running under a Wayland window rather than KMS+DRM, and you
* move the mouse over the window. You could enter the window from any edge, * move the mouse over the window. You could enter the window from any edge,
* so we have to warp the mouse there. Also, some hardware emits these events. */ * so we have to warp the mouse there. There is also some hardware which
* emits these events. */
struct wlr_pointer_motion_absolute_event *event = data; struct wlr_pointer_motion_absolute_event *event = data;
double lx, ly, dx, dy; double lx, ly, dx, dy;
@@ -1966,7 +1911,7 @@ moveresize(const Arg *arg)
case CurMove: case CurMove:
grabcx = (int)round(cursor->x) - grabc->geom.x; grabcx = (int)round(cursor->x) - grabc->geom.x;
grabcy = (int)round(cursor->y) - grabc->geom.y; grabcy = (int)round(cursor->y) - grabc->geom.y;
wlr_cursor_set_xcursor(cursor, cursor_mgr, "all-scroll"); wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur");
break; break;
case CurResize: case CurResize:
/* Doesn't work for X11 output - the next absolute motion event /* Doesn't work for X11 output - the next absolute motion event
@@ -2029,9 +1974,9 @@ apply_or_test:
ok &= test ? wlr_output_test_state(wlr_output, &state) ok &= test ? wlr_output_test_state(wlr_output, &state)
: wlr_output_commit_state(wlr_output, &state); : wlr_output_commit_state(wlr_output, &state);
/* Don't move monitors if position wouldn't change. This avoids /* Don't move monitors if position wouldn't change, this to avoid
* wlroots marking the output as manually configured. * wlroots marking the output as manually configured.
* wlr_output_layout_add does not like disabled outputs */ * wlr_output_layout_add does not like disabled outputs */
if (!test && wlr_output->enabled && (m->m.x != config_head->state.x || m->m.y != config_head->state.y)) if (!test && wlr_output->enabled && (m->m.x != config_head->state.x || m->m.y != config_head->state.y))
wlr_output_layout_add(output_layout, wlr_output, wlr_output_layout_add(output_layout, wlr_output,
config_head->state.x, config_head->state.y); config_head->state.x, config_head->state.y);
@@ -2268,10 +2213,8 @@ run(char *startup_cmd)
close(piperw[0]); close(piperw[0]);
} }
/* Mark stdout as non-blocking to avoid the startup script /* Mark stdout as non-blocking to avoid people who does not close stdin
* causing dwl to freeze when a user neither closes stdin * nor consumes it in their startup script getting dwl frozen */
* nor consumes standard input in his startup script */
if (fd_set_nonblock(STDOUT_FILENO) < 0) if (fd_set_nonblock(STDOUT_FILENO) < 0)
close(STDOUT_FILENO); close(STDOUT_FILENO);
@@ -2282,7 +2225,7 @@ run(char *startup_cmd)
selmon = xytomon(cursor->x, cursor->y); selmon = xytomon(cursor->x, cursor->y);
/* TODO hack to get cursor to display in its initial location (100, 100) /* TODO hack to get cursor to display in its initial location (100, 100)
* instead of (0, 0) and then jumping. Still may not be fully * instead of (0, 0) and then jumping. still may not be fully
* initialized, as the image/coordinates are not transformed for the * initialized, as the image/coordinates are not transformed for the
* monitor when displayed here */ * monitor when displayed here */
wlr_cursor_warp_closest(cursor, NULL, cursor->x, cursor->y); wlr_cursor_warp_closest(cursor, NULL, cursor->x, cursor->y);
@@ -2305,7 +2248,7 @@ setcursor(struct wl_listener *listener, void *data)
* event, which will result in the client requesting set the cursor surface */ * event, which will result in the client requesting set the cursor surface */
if (cursor_mode != CurNormal && cursor_mode != CurPressed) if (cursor_mode != CurNormal && cursor_mode != CurPressed)
return; return;
/* This can be sent by any client, so we check to make sure this one /* This can be sent by any client, so we check to make sure this one is
* actually has pointer focus first. If so, we can tell the cursor to * actually has pointer focus first. If so, we can tell the cursor to
* use the provided surface as the cursor image. It will set the * use the provided surface as the cursor image. It will set the
* hardware cursor on the output that it's currently on and continue to * hardware cursor on the output that it's currently on and continue to
@@ -2321,7 +2264,7 @@ setcursorshape(struct wl_listener *listener, void *data)
struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data; struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data;
if (cursor_mode != CurNormal && cursor_mode != CurPressed) if (cursor_mode != CurNormal && cursor_mode != CurPressed)
return; return;
/* This can be sent by any client, so we check to make sure this one /* This can be sent by any client, so we check to make sure this one is
* actually has pointer focus first. If so, we can tell the cursor to * actually has pointer focus first. If so, we can tell the cursor to
* use the provided cursor shape. */ * use the provided cursor shape. */
if (event->seat_client == seat->pointer_state.focused_client) if (event->seat_client == seat->pointer_state.focused_client)
@@ -2424,7 +2367,7 @@ setpsel(struct wl_listener *listener, void *data)
{ {
/* This event is raised by the seat when a client wants to set the selection, /* This event is raised by the seat when a client wants to set the selection,
* usually when the user copies something. wlroots allows compositors to * usually when the user copies something. wlroots allows compositors to
* ignore such requests if they so choose, but in dwl we always honor them * ignore such requests if they so choose, but in dwl we always honor
*/ */
struct wlr_seat_request_set_primary_selection_event *event = data; struct wlr_seat_request_set_primary_selection_event *event = data;
wlr_seat_set_primary_selection(seat, event->source, event->serial); wlr_seat_set_primary_selection(seat, event->source, event->serial);
@@ -2435,7 +2378,7 @@ setsel(struct wl_listener *listener, void *data)
{ {
/* This event is raised by the seat when a client wants to set the selection, /* This event is raised by the seat when a client wants to set the selection,
* usually when the user copies something. wlroots allows compositors to * usually when the user copies something. wlroots allows compositors to
* ignore such requests if they so choose, but in dwl we always honor them * ignore such requests if they so choose, but in dwl we always honor
*/ */
struct wlr_seat_request_set_selection_event *event = data; struct wlr_seat_request_set_selection_event *event = data;
wlr_seat_set_selection(seat, event->source, event->serial); wlr_seat_set_selection(seat, event->source, event->serial);
@@ -2479,12 +2422,12 @@ setup(void)
* supports for shared memory, this configures that for clients. */ * supports for shared memory, this configures that for clients. */
if (!(drw = wlr_renderer_autocreate(backend))) if (!(drw = wlr_renderer_autocreate(backend)))
die("couldn't create renderer"); die("couldn't create renderer");
wl_signal_add(&drw->events.lost, &gpu_reset); LISTEN_STATIC(&drw->events.lost, gpureset);
/* Create shm, drm and linux_dmabuf interfaces by ourselves. /* Create shm, drm and linux_dmabuf interfaces by ourselves.
* The simplest way is to call: * The simplest way is call:
* wlr_renderer_init_wl_display(drw); * wlr_renderer_init_wl_display(drw);
* but we need to create the linux_dmabuf interface manually to integrate it * but we need to create manually the linux_dmabuf interface to integrate it
* with wlr_scene. */ * with wlr_scene. */
wlr_renderer_init_wl_shm(drw, dpy); wlr_renderer_init_wl_shm(drw, dpy);
@@ -2526,24 +2469,23 @@ setup(void)
/* Initializes the interface used to implement urgency hints */ /* Initializes the interface used to implement urgency hints */
activation = wlr_xdg_activation_v1_create(dpy); activation = wlr_xdg_activation_v1_create(dpy);
wl_signal_add(&activation->events.request_activate, &request_activate); LISTEN_STATIC(&activation->events.request_activate, urgent);
wlr_scene_set_gamma_control_manager_v1(scene, wlr_gamma_control_manager_v1_create(dpy)); wlr_scene_set_gamma_control_manager_v1(scene, wlr_gamma_control_manager_v1_create(dpy));
power_mgr = wlr_output_power_manager_v1_create(dpy); power_mgr = wlr_output_power_manager_v1_create(dpy);
wl_signal_add(&power_mgr->events.set_mode, &output_power_mgr_set_mode); LISTEN_STATIC(&power_mgr->events.set_mode, powermgrsetmode);
/* Creates an output layout, which is a wlroots utility for working with an /* Creates an output layout, which a wlroots utility for working with an
* arrangement of screens in a physical layout. */ * arrangement of screens in a physical layout. */
output_layout = wlr_output_layout_create(dpy); output_layout = wlr_output_layout_create(dpy);
wl_signal_add(&output_layout->events.change, &layout_change); LISTEN_STATIC(&output_layout->events.change, updatemons);
wlr_xdg_output_manager_v1_create(dpy, output_layout);
wlr_xdg_output_manager_v1_create(dpy, output_layout);
/* Configure a listener to be notified when new outputs are available on the /* Configure a listener to be notified when new outputs are available on the
* backend. */ * backend. */
wl_list_init(&mons); wl_list_init(&mons);
wl_signal_add(&backend->events.new_output, &new_output); LISTEN_STATIC(&backend->events.new_output, createmon);
/* Set up our client lists, the xdg-shell and the layer-shell. The xdg-shell is a /* Set up our client lists, the xdg-shell and the layer-shell. The xdg-shell is a
* Wayland protocol which is used for application windows. For more * Wayland protocol which is used for application windows. For more
@@ -2555,19 +2497,20 @@ setup(void)
wl_list_init(&fstack); wl_list_init(&fstack);
xdg_shell = wlr_xdg_shell_create(dpy, 6); xdg_shell = wlr_xdg_shell_create(dpy, 6);
wl_signal_add(&xdg_shell->events.new_toplevel, &new_xdg_toplevel); LISTEN_STATIC(&xdg_shell->events.new_toplevel, createnotify);
wl_signal_add(&xdg_shell->events.new_popup, &new_xdg_popup); LISTEN_STATIC(&xdg_shell->events.new_popup, createpopup);
layer_shell = wlr_layer_shell_v1_create(dpy, 3); layer_shell = wlr_layer_shell_v1_create(dpy, 3);
wl_signal_add(&layer_shell->events.new_surface, &new_layer_surface); LISTEN_STATIC(&layer_shell->events.new_surface, createlayersurface);
idle_notifier = wlr_idle_notifier_v1_create(dpy); idle_notifier = wlr_idle_notifier_v1_create(dpy);
idle_inhibit_mgr = wlr_idle_inhibit_v1_create(dpy); idle_inhibit_mgr = wlr_idle_inhibit_v1_create(dpy);
wl_signal_add(&idle_inhibit_mgr->events.new_inhibitor, &new_idle_inhibitor); LISTEN_STATIC(&idle_inhibit_mgr->events.new_inhibitor, createidleinhibitor);
session_lock_mgr = wlr_session_lock_manager_v1_create(dpy); session_lock_mgr = wlr_session_lock_manager_v1_create(dpy);
wl_signal_add(&session_lock_mgr->events.new_lock, &new_session_lock); wl_signal_add(&session_lock_mgr->events.new_lock, &lock_listener);
LISTEN_STATIC(&session_lock_mgr->events.destroy, destroysessionmgr);
locked_bg = wlr_scene_rect_create(layers[LyrBlock], sgeom.width, sgeom.height, locked_bg = wlr_scene_rect_create(layers[LyrBlock], sgeom.width, sgeom.height,
(float [4]){0.1f, 0.1f, 0.1f, 1.0f}); (float [4]){0.1f, 0.1f, 0.1f, 1.0f});
wlr_scene_node_set_enabled(&locked_bg->node, 0); wlr_scene_node_set_enabled(&locked_bg->node, 0);
@@ -2577,10 +2520,10 @@ setup(void)
wlr_server_decoration_manager_create(dpy), wlr_server_decoration_manager_create(dpy),
WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); WLR_SERVER_DECORATION_MANAGER_MODE_SERVER);
xdg_decoration_mgr = wlr_xdg_decoration_manager_v1_create(dpy); xdg_decoration_mgr = wlr_xdg_decoration_manager_v1_create(dpy);
wl_signal_add(&xdg_decoration_mgr->events.new_toplevel_decoration, &new_xdg_decoration); LISTEN_STATIC(&xdg_decoration_mgr->events.new_toplevel_decoration, createdecoration);
pointer_constraints = wlr_pointer_constraints_v1_create(dpy); pointer_constraints = wlr_pointer_constraints_v1_create(dpy);
wl_signal_add(&pointer_constraints->events.new_constraint, &new_pointer_constraint); LISTEN_STATIC(&pointer_constraints->events.new_constraint, createpointerconstraint);
relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(dpy); relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(dpy);
@@ -2608,14 +2551,14 @@ setup(void)
* *
* And more comments are sprinkled throughout the notify functions above. * And more comments are sprinkled throughout the notify functions above.
*/ */
wl_signal_add(&cursor->events.motion, &cursor_motion); LISTEN_STATIC(&cursor->events.motion, motionrelative);
wl_signal_add(&cursor->events.motion_absolute, &cursor_motion_absolute); LISTEN_STATIC(&cursor->events.motion_absolute, motionabsolute);
wl_signal_add(&cursor->events.button, &cursor_button); LISTEN_STATIC(&cursor->events.button, buttonpress);
wl_signal_add(&cursor->events.axis, &cursor_axis); LISTEN_STATIC(&cursor->events.axis, axisnotify);
wl_signal_add(&cursor->events.frame, &cursor_frame); LISTEN_STATIC(&cursor->events.frame, cursorframe);
cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1); cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1);
wl_signal_add(&cursor_shape_mgr->events.request_set_shape, &request_set_cursor_shape); LISTEN_STATIC(&cursor_shape_mgr->events.request_set_shape, setcursorshape);
/* /*
* Configures a seat, which is a single "seat" at which a user sits and * Configures a seat, which is a single "seat" at which a user sits and
@@ -2623,27 +2566,25 @@ setup(void)
* pointer, touch, and drawing tablet device. We also rig up a listener to * pointer, touch, and drawing tablet device. We also rig up a listener to
* let us know when new input devices are available on the backend. * let us know when new input devices are available on the backend.
*/ */
wl_signal_add(&backend->events.new_input, &new_input_device); LISTEN_STATIC(&backend->events.new_input, inputdevice);
virtual_keyboard_mgr = wlr_virtual_keyboard_manager_v1_create(dpy); virtual_keyboard_mgr = wlr_virtual_keyboard_manager_v1_create(dpy);
wl_signal_add(&virtual_keyboard_mgr->events.new_virtual_keyboard, LISTEN_STATIC(&virtual_keyboard_mgr->events.new_virtual_keyboard, virtualkeyboard);
&new_virtual_keyboard);
virtual_pointer_mgr = wlr_virtual_pointer_manager_v1_create(dpy); virtual_pointer_mgr = wlr_virtual_pointer_manager_v1_create(dpy);
wl_signal_add(&virtual_pointer_mgr->events.new_virtual_pointer, LISTEN_STATIC(&virtual_pointer_mgr->events.new_virtual_pointer, virtualpointer);
&new_virtual_pointer);
seat = wlr_seat_create(dpy, "seat0"); seat = wlr_seat_create(dpy, "seat0");
wl_signal_add(&seat->events.request_set_cursor, &request_cursor); LISTEN_STATIC(&seat->events.request_set_cursor, setcursor);
wl_signal_add(&seat->events.request_set_selection, &request_set_sel); LISTEN_STATIC(&seat->events.request_set_selection, setsel);
wl_signal_add(&seat->events.request_set_primary_selection, &request_set_psel); LISTEN_STATIC(&seat->events.request_set_primary_selection, setpsel);
wl_signal_add(&seat->events.request_start_drag, &request_start_drag); LISTEN_STATIC(&seat->events.request_start_drag, requeststartdrag);
wl_signal_add(&seat->events.start_drag, &start_drag); LISTEN_STATIC(&seat->events.start_drag, startdrag);
kb_group = createkeyboardgroup(); kb_group = createkeyboardgroup();
wl_list_init(&kb_group->destroy.link); wl_list_init(&kb_group->destroy.link);
output_mgr = wlr_output_manager_v1_create(dpy); output_mgr = wlr_output_manager_v1_create(dpy);
wl_signal_add(&output_mgr->events.apply, &output_mgr_apply); LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply);
wl_signal_add(&output_mgr->events.test, &output_mgr_test); LISTEN_STATIC(&output_mgr->events.test, outputmgrtest);
/* Make sure XWayland clients don't connect to the parent X server, /* Make sure XWayland clients don't connect to the parent X server,
* e.g when running in the x11 backend or the wayland backend and the * e.g when running in the x11 backend or the wayland backend and the
@@ -2655,8 +2596,8 @@ setup(void)
* It will be started when the first X client is started. * It will be started when the first X client is started.
*/ */
if ((xwayland = wlr_xwayland_create(dpy, compositor, 1))) { if ((xwayland = wlr_xwayland_create(dpy, compositor, 1))) {
wl_signal_add(&xwayland->events.ready, &xwayland_ready); LISTEN_STATIC(&xwayland->events.ready, xwaylandready);
wl_signal_add(&xwayland->events.new_surface, &new_xwayland_surface); LISTEN_STATIC(&xwayland->events.new_surface, createnotifyx11);
setenv("DISPLAY", xwayland->display_name, 1); setenv("DISPLAY", xwayland->display_name, 1);
} else { } else {
@@ -3150,12 +3091,25 @@ dissociatex11(struct wl_listener *listener, void *data)
wl_list_remove(&c->unmap.link); wl_list_remove(&c->unmap.link);
} }
xcb_atom_t
getatom(xcb_connection_t *xc, const char *name)
{
xcb_atom_t atom = 0;
xcb_intern_atom_reply_t *reply;
xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xc, 0, strlen(name), name);
if ((reply = xcb_intern_atom_reply(xc, cookie, NULL)))
atom = reply->atom;
free(reply);
return atom;
}
void void
sethints(struct wl_listener *listener, void *data) sethints(struct wl_listener *listener, void *data)
{ {
Client *c = wl_container_of(listener, c, set_hints); Client *c = wl_container_of(listener, c, set_hints);
struct wlr_surface *surface = client_surface(c); struct wlr_surface *surface = client_surface(c);
if (c == focustop(selmon) || !c->surface.xwayland->hints) if (c == focustop(selmon))
return; return;
c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints); c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints);
@@ -3169,6 +3123,19 @@ void
xwaylandready(struct wl_listener *listener, void *data) xwaylandready(struct wl_listener *listener, void *data)
{ {
struct wlr_xcursor *xcursor; struct wlr_xcursor *xcursor;
xcb_connection_t *xc = xcb_connect(xwayland->display_name, NULL);
int err = xcb_connection_has_error(xc);
if (err) {
fprintf(stderr, "xcb_connect to X server failed with code %d\n. Continuing with degraded functionality.\n", err);
return;
}
/* Collect atoms we are interested in. If getatom returns 0, we will
* not detect that window type. */
netatom[NetWMWindowTypeDialog] = getatom(xc, "_NET_WM_WINDOW_TYPE_DIALOG");
netatom[NetWMWindowTypeSplash] = getatom(xc, "_NET_WM_WINDOW_TYPE_SPLASH");
netatom[NetWMWindowTypeToolbar] = getatom(xc, "_NET_WM_WINDOW_TYPE_TOOLBAR");
netatom[NetWMWindowTypeUtility] = getatom(xc, "_NET_WM_WINDOW_TYPE_UTILITY");
/* assign the one and only seat */ /* assign the one and only seat */
wlr_xwayland_set_seat(xwayland, seat); wlr_xwayland_set_seat(xwayland, seat);
@@ -3179,6 +3146,8 @@ xwaylandready(struct wl_listener *listener, void *data)
xcursor->images[0]->buffer, xcursor->images[0]->width * 4, xcursor->images[0]->buffer, xcursor->images[0]->width * 4,
xcursor->images[0]->width, xcursor->images[0]->height, xcursor->images[0]->width, xcursor->images[0]->height,
xcursor->images[0]->hotspot_x, xcursor->images[0]->hotspot_y); xcursor->images[0]->hotspot_x, xcursor->images[0]->hotspot_y);
xcb_disconnect(xc);
} }
#endif #endif