summaryrefslogtreecommitdiff
path: root/dwl.c
diff options
context:
space:
mode:
Diffstat (limited to 'dwl.c')
-rw-r--r--dwl.c150
1 files changed, 85 insertions, 65 deletions
diff --git a/dwl.c b/dwl.c
index 06db9f4..9890a6c 100644
--- a/dwl.c
+++ b/dwl.c
@@ -82,7 +82,7 @@
/* enums */
enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
enum { XDGShell, LayerShell, X11 }; /* client types */
-enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrFS, LyrTop, 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 */
@@ -160,6 +160,7 @@ typedef struct {
struct wl_listener modifiers;
struct wl_listener key;
+ struct wl_listener destroy;
} KeyboardGroup;
typedef struct {
@@ -260,6 +261,7 @@ static void commitpopup(struct wl_listener *listener, void *data);
static void createdecoration(struct wl_listener *listener, void *data);
static void createidleinhibitor(struct wl_listener *listener, void *data);
static void createkeyboard(struct wlr_keyboard *keyboard);
+static KeyboardGroup *createkeyboardgroup(void);
static void createlayersurface(struct wl_listener *listener, void *data);
static void createlocksurface(struct wl_listener *listener, void *data);
static void createmon(struct wl_listener *listener, void *data);
@@ -280,6 +282,7 @@ static void destroynotify(struct wl_listener *listener, void *data);
static void destroypointerconstraint(struct wl_listener *listener, void *data);
static void destroysessionlock(struct wl_listener *listener, void *data);
static void destroysessionmgr(struct wl_listener *listener, void *data);
+static void destroykeyboardgroup(struct wl_listener *listener, void *data);
static Monitor *dirtomon(enum wlr_direction dir);
static void focusclient(Client *c, int lift);
static void focusmon(const Arg *arg);
@@ -397,8 +400,7 @@ static struct wlr_session_lock_v1 *cur_lock;
static struct wl_listener lock_listener = {.notify = locksession};
static struct wlr_seat *seat;
-static KeyboardGroup kb_group = {0};
-static KeyboardGroup vkb_group = {0};
+static KeyboardGroup *kb_group;
static struct wlr_surface *held_grab;
static unsigned int cursor_mode;
static Client *grabc;
@@ -497,6 +499,20 @@ arrange(Monitor *m)
strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol));
+ /* We move all clients (except fullscreen and unmanaged) to LyrTile while
+ * in floating layout to avoid "real" floating clients be always on top */
+ wl_list_for_each(c, &clients, link) {
+ if (c->mon != m || c->isfullscreen)
+ continue;
+
+ wlr_scene_node_reparent(&c->scene->node,
+ (!m->lt[m->sellt]->arrange && c->isfloating)
+ ? layers[LyrTile]
+ : (m->lt[m->sellt]->arrange && c->isfloating)
+ ? layers[LyrFloat]
+ : c->scene->node.parent);
+ }
+
if (m->lt[m->sellt]->arrange)
m->lt[m->sellt]->arrange(m);
motionnotify(0, NULL, 0, 0, 0, 0);
@@ -670,9 +686,7 @@ cleanup(void)
}
wlr_xcursor_manager_destroy(cursor_mgr);
- /* Remove event source that use the dpy event loop before destroying dpy */
- wl_event_source_remove(kb_group.key_repeat_source);
- wl_event_source_remove(vkb_group.key_repeat_source);
+ destroykeyboardgroup(&kb_group->destroy, NULL);
/* If it's not destroyed manually it will cause a use-after-free of wlr_seat.
* Destroy it until it's fixed in the wlroots side */
@@ -843,11 +857,47 @@ void
createkeyboard(struct wlr_keyboard *keyboard)
{
/* Set the keymap to match the group keymap */
- wlr_keyboard_set_keymap(keyboard, kb_group.wlr_group->keyboard.keymap);
- wlr_keyboard_set_repeat_info(keyboard, repeat_rate, repeat_delay);
+ wlr_keyboard_set_keymap(keyboard, kb_group->wlr_group->keyboard.keymap);
/* Add the new keyboard to the group */
- wlr_keyboard_group_add_keyboard(kb_group.wlr_group, keyboard);
+ wlr_keyboard_group_add_keyboard(kb_group->wlr_group, keyboard);
+}
+
+KeyboardGroup *
+createkeyboardgroup(void)
+{
+ KeyboardGroup *group = ecalloc(1, sizeof(*group));
+ struct xkb_context *context;
+ struct xkb_keymap *keymap;
+
+ group->wlr_group = wlr_keyboard_group_create();
+ group->wlr_group->data = group;
+
+ /* Prepare an XKB keymap and assign it to the keyboard group. */
+ context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
+ if (!(keymap = xkb_keymap_new_from_names(context, &xkb_rules,
+ XKB_KEYMAP_COMPILE_NO_FLAGS)))
+ die("failed to compile keymap");
+
+ wlr_keyboard_set_keymap(&group->wlr_group->keyboard, keymap);
+ xkb_keymap_unref(keymap);
+ xkb_context_unref(context);
+
+ wlr_keyboard_set_repeat_info(&group->wlr_group->keyboard, repeat_rate, repeat_delay);
+
+ /* Set up listeners for keyboard events */
+ LISTEN(&group->wlr_group->keyboard.events.key, &group->key, keypress);
+ LISTEN(&group->wlr_group->keyboard.events.modifiers, &group->modifiers, keypressmod);
+
+ group->key_repeat_source = wl_event_loop_add_timer(event_loop, keyrepeat, group);
+
+ /* A seat can only have one keyboard, but this is a limitation of the
+ * Wayland protocol - not wlroots. We assign all connected keyboards to the
+ * same wlr_keyboard_group, which provides a single wlr_keyboard interface for
+ * all of them. Set this combined wlr_keyboard as the seat keyboard.
+ */
+ wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard);
+ return group;
}
void
@@ -970,14 +1020,14 @@ createmon(struct wl_listener *listener, void *data)
m->fullscreen_bg = wlr_scene_rect_create(layers[LyrFS], 0, 0, fullscreen_bg);
wlr_scene_node_set_enabled(&m->fullscreen_bg->node, 0);
- /* Adds this to the output layout in the order it was configured in.
+ /* Adds this to the output layout in the order it was configured.
*
* The output layout utility automatically adds a wl_output global to the
* display, which Wayland clients can see to find out information about the
* output (such as DPI, scale factor, manufacturer, etc).
*/
m->scene_output = wlr_scene_output_create(scene, wlr_output);
- if (m->m.x < 0 || m->m.y < 0)
+ if (m->m.x == -1 && m->m.y == -1)
wlr_output_layout_add_auto(output_layout, wlr_output);
else
wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y);
@@ -1242,6 +1292,18 @@ destroysessionmgr(struct wl_listener *listener, void *data)
wl_list_remove(&listener->link);
}
+void
+destroykeyboardgroup(struct wl_listener *listener, void *data)
+{
+ KeyboardGroup *group = wl_container_of(listener, group, destroy);
+ wl_event_source_remove(group->key_repeat_source);
+ wlr_keyboard_group_destroy(group->wlr_group);
+ wl_list_remove(&group->key.link);
+ wl_list_remove(&group->modifiers.link);
+ wl_list_remove(&group->destroy.link);
+ free(group);
+}
+
Monitor *
dirtomon(enum wlr_direction dir)
{
@@ -1447,7 +1509,7 @@ inputdevice(struct wl_listener *listener, void *data)
* there are no pointer devices, so we always include that capability. */
/* TODO do we actually require a cursor? */
caps = WL_SEAT_CAPABILITY_POINTER;
- if (!wl_list_empty(&kb_group.wlr_group->devices))
+ if (!wl_list_empty(&kb_group->wlr_group->devices))
caps |= WL_SEAT_CAPABILITY_KEYBOARD;
wlr_seat_set_capabilities(seat, caps);
}
@@ -1908,7 +1970,7 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
{
struct timespec now;
- if ((!active_constraint || active_constraint->surface != surface) &&
+ if (surface != seat->pointer_state.focused_surface &&
sloppyfocus && time && c && !client_is_unmanaged(c))
focusclient(c, 0);
@@ -2176,7 +2238,8 @@ setfloating(Client *c, int floating)
{
Client *p = client_get_parent(c);
c->isfloating = floating;
- if (!c->mon)
+ /* If in floating layout do not change the client's layer */
+ if (!c->mon || !c->mon->lt[c->mon->sellt]->arrange)
return;
wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen ||
(p && p->isfullscreen) ? LyrFS
@@ -2296,9 +2359,6 @@ setsel(struct wl_listener *listener, void *data)
void
setup(void)
{
- struct xkb_context *context;
- struct xkb_keymap *keymap;
-
int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE};
struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = handlesig};
sigemptyset(&sa.sa_mask);
@@ -2484,50 +2544,8 @@ setup(void)
LISTEN_STATIC(&seat->events.request_start_drag, requeststartdrag);
LISTEN_STATIC(&seat->events.start_drag, startdrag);
- /*
- * Configures a keyboard group, which will keep track of all connected
- * keyboards, keep their modifier and LED states in sync, and handle
- * keypresses
- */
- kb_group.wlr_group = wlr_keyboard_group_create();
- kb_group.wlr_group->data = &kb_group;
-
- /*
- * Virtual keyboards need to be in a different group
- * https://codeberg.org/dwl/dwl/issues/554
- */
- vkb_group.wlr_group = wlr_keyboard_group_create();
- vkb_group.wlr_group->data = &vkb_group;
-
- /* Prepare an XKB keymap and assign it to the keyboard group. */
- context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- if (!(keymap = xkb_keymap_new_from_names(context, &xkb_rules,
- XKB_KEYMAP_COMPILE_NO_FLAGS)))
- die("failed to compile keymap");
-
- wlr_keyboard_set_keymap(&kb_group.wlr_group->keyboard, keymap);
- wlr_keyboard_set_keymap(&vkb_group.wlr_group->keyboard, keymap);
- xkb_keymap_unref(keymap);
- xkb_context_unref(context);
-
- wlr_keyboard_set_repeat_info(&kb_group.wlr_group->keyboard, repeat_rate, repeat_delay);
- wlr_keyboard_set_repeat_info(&vkb_group.wlr_group->keyboard, repeat_rate, repeat_delay);
-
- /* Set up listeners for keyboard events */
- LISTEN(&kb_group.wlr_group->keyboard.events.key, &kb_group.key, keypress);
- LISTEN(&kb_group.wlr_group->keyboard.events.modifiers, &kb_group.modifiers, keypressmod);
- LISTEN(&vkb_group.wlr_group->keyboard.events.key, &vkb_group.key, keypress);
- LISTEN(&vkb_group.wlr_group->keyboard.events.modifiers, &vkb_group.modifiers, keypressmod);
-
- kb_group.key_repeat_source = wl_event_loop_add_timer(event_loop, keyrepeat, &kb_group);
- vkb_group.key_repeat_source = wl_event_loop_add_timer(event_loop, keyrepeat, &vkb_group);
-
- /* A seat can only have one keyboard, but this is a limitation of the
- * Wayland protocol - not wlroots. We assign all connected keyboards to the
- * same wlr_keyboard_group, which provides a single wlr_keyboard interface for
- * all of them. Set this combined wlr_keyboard as the seat keyboard.
- */
- wlr_seat_set_keyboard(seat, &kb_group.wlr_group->keyboard);
+ kb_group = createkeyboardgroup();
+ wl_list_init(&kb_group->destroy.link);
output_mgr = wlr_output_manager_v1_create(dpy);
LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply);
@@ -2865,13 +2883,15 @@ view(const Arg *arg)
void
virtualkeyboard(struct wl_listener *listener, void *data)
{
- struct wlr_virtual_keyboard_v1 *keyboard = data;
+ struct wlr_virtual_keyboard_v1 *kb = data;
+ /* virtual keyboards shouldn't share keyboard group */
+ KeyboardGroup *group = createkeyboardgroup();
/* Set the keymap to match the group keymap */
- wlr_keyboard_set_keymap(&keyboard->keyboard, vkb_group.wlr_group->keyboard.keymap);
- wlr_keyboard_set_repeat_info(&keyboard->keyboard, repeat_rate, repeat_delay);
+ wlr_keyboard_set_keymap(&kb->keyboard, group->wlr_group->keyboard.keymap);
+ LISTEN(&kb->keyboard.base.events.destroy, &group->destroy, destroykeyboardgroup);
/* Add the new keyboard to the group */
- wlr_keyboard_group_add_keyboard(vkb_group.wlr_group, &keyboard->keyboard);
+ wlr_keyboard_group_add_keyboard(group->wlr_group, &kb->keyboard);
}
void