This commit is contained in:
Mahesh Asolkar 2024-06-09 16:24:39 -07:00
commit 9512cb560e
2 changed files with 87 additions and 66 deletions

View File

@ -36,6 +36,8 @@ static const Layout layouts[] = {
}; };
/* monitors */ /* monitors */
/* (x=-1, y=-1) is reserved as an "autoconfigure" monitor position indicator */
/* WARNING: negative values other than (-1, -1) cause problems with xwayland clients' menus */
/* NOTE: ALWAYS add a fallback rule, even if you are completely sure it won't be used */ /* NOTE: ALWAYS add a fallback rule, even if you are completely sure it won't be used */
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 */

151
dwl.c
View File

@ -166,6 +166,7 @@ typedef struct {
struct wl_listener modifiers; struct wl_listener modifiers;
struct wl_listener key; struct wl_listener key;
struct wl_listener destroy;
} KeyboardGroup; } KeyboardGroup;
typedef struct { typedef struct {
@ -266,6 +267,7 @@ static void commitnotify(struct wl_listener *listener, void *data);
static void createdecoration(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 createidleinhibitor(struct wl_listener *listener, void *data);
static void createkeyboard(struct wlr_keyboard *keyboard); static void createkeyboard(struct wlr_keyboard *keyboard);
static KeyboardGroup *createkeyboardgroup(void);
static void createlayersurface(struct wl_listener *listener, void *data); static void createlayersurface(struct wl_listener *listener, void *data);
static void createlocksurface(struct wl_listener *listener, void *data); static void createlocksurface(struct wl_listener *listener, void *data);
static void createmon(struct wl_listener *listener, void *data); static void createmon(struct wl_listener *listener, void *data);
@ -285,6 +287,7 @@ 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 destroysessionmgr(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 dwl_ipc_manager_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id); static void dwl_ipc_manager_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id);
static void dwl_ipc_manager_destroy(struct wl_resource *resource); static void dwl_ipc_manager_destroy(struct wl_resource *resource);
@ -415,8 +418,7 @@ static struct wlr_session_lock_v1 *cur_lock;
static struct wl_listener lock_listener = {.notify = locksession}; static struct wl_listener lock_listener = {.notify = locksession};
static struct wlr_seat *seat; static struct wlr_seat *seat;
static KeyboardGroup kb_group = {0}; static KeyboardGroup *kb_group;
static KeyboardGroup vkb_group = {0};
static struct wlr_surface *held_grab; static struct wlr_surface *held_grab;
static unsigned int cursor_mode; static unsigned int cursor_mode;
static Client *grabc; static Client *grabc;
@ -515,6 +517,20 @@ arrange(Monitor *m)
strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); 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) if (m->lt[m->sellt]->arrange)
m->lt[m->sellt]->arrange(m); m->lt[m->sellt]->arrange(m);
motionnotify(0, NULL, 0, 0, 0, 0); motionnotify(0, NULL, 0, 0, 0, 0);
@ -689,9 +705,7 @@ cleanup(void)
wlr_xcursor_manager_destroy(cursor_mgr); wlr_xcursor_manager_destroy(cursor_mgr);
wlr_output_layout_destroy(output_layout); wlr_output_layout_destroy(output_layout);
/* Remove event source that use the dpy event loop before destroying dpy */ destroykeyboardgroup(&kb_group->destroy, NULL);
wl_event_source_remove(kb_group.key_repeat_source);
wl_event_source_remove(vkb_group.key_repeat_source);
wl_display_destroy(dpy); wl_display_destroy(dpy);
/* Destroy after the wayland display (when the monitors are already destroyed) /* Destroy after the wayland display (when the monitors are already destroyed)
@ -815,11 +829,48 @@ void
createkeyboard(struct wlr_keyboard *keyboard) createkeyboard(struct wlr_keyboard *keyboard)
{ {
/* Set the keymap to match the group keymap */ /* Set the keymap to match the group keymap */
wlr_keyboard_set_keymap(keyboard, kb_group.wlr_group->keyboard.keymap); wlr_keyboard_set_keymap(keyboard, kb_group->wlr_group->keyboard.keymap);
wlr_keyboard_set_repeat_info(keyboard, repeat_rate, repeat_delay);
/* Add the new keyboard to the group */ /* 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(
wl_display_get_event_loop(dpy), 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 void
@ -954,14 +1005,14 @@ createmon(struct wl_listener *listener, void *data)
m->fullscreen_bg = wlr_scene_rect_create(layers[LyrFS], 0, 0, fullscreen_bg); m->fullscreen_bg = wlr_scene_rect_create(layers[LyrFS], 0, 0, fullscreen_bg);
wlr_scene_node_set_enabled(&m->fullscreen_bg->node, 0); 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 * The output layout utility automatically adds a wl_output global to the
* display, which Wayland clients can see to find out information about the * display, which Wayland clients can see to find out information about the
* output (such as DPI, scale factor, manufacturer, etc). * output (such as DPI, scale factor, manufacturer, etc).
*/ */
m->scene_output = wlr_scene_output_create(scene, wlr_output); m->scene_output = wlr_scene_output_create(scene, wlr_output);
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); wlr_output_layout_add_auto(output_layout, wlr_output);
else else
wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y); wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y);
@ -1244,6 +1295,18 @@ destroysessionmgr(struct wl_listener *listener, void *data)
wl_list_remove(&listener->link); wl_list_remove(&listener->link);
} }
void
destroykeyboardgroup(struct wl_listener *listener, void *data)
{
KeyboardGroup *group = wl_container_of(listener, group, destroy);
wl_event_source_remove(group->key_repeat_source);
wlr_keyboard_group_destroy(group->wlr_group);
wl_list_remove(&group->key.link);
wl_list_remove(&group->modifiers.link);
wl_list_remove(&group->destroy.link);
free(group);
}
Monitor * Monitor *
dirtomon(enum wlr_direction dir) dirtomon(enum wlr_direction dir)
{ {
@ -1656,7 +1719,7 @@ inputdevice(struct wl_listener *listener, void *data)
* there are no pointer devices, so we always include that capability. */ * there are no pointer devices, so we always include that capability. */
/* TODO do we actually require a cursor? */ /* TODO do we actually require a cursor? */
caps = WL_SEAT_CAPABILITY_POINTER; 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; caps |= WL_SEAT_CAPABILITY_KEYBOARD;
wlr_seat_set_capabilities(seat, caps); wlr_seat_set_capabilities(seat, caps);
} }
@ -2117,7 +2180,7 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
{ {
struct timespec now; struct timespec now;
if ((!active_constraint || active_constraint->surface != surface) && if (surface != seat->pointer_state.focused_surface &&
sloppyfocus && time && c && !client_is_unmanaged(c)) sloppyfocus && time && c && !client_is_unmanaged(c))
focusclient(c, 0); focusclient(c, 0);
@ -2384,7 +2447,8 @@ setfloating(Client *c, int floating)
{ {
Client *p = client_get_parent(c); Client *p = client_get_parent(c);
c->isfloating = floating; 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; return;
wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen || wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen ||
(p && p->isfullscreen) ? LyrFS (p && p->isfullscreen) ? LyrFS
@ -2504,9 +2568,6 @@ setsel(struct wl_listener *listener, void *data)
void void
setup(void) setup(void)
{ {
struct xkb_context *context;
struct xkb_keymap *keymap;
int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE}; int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE};
struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = handlesig}; struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = handlesig};
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
@ -2688,52 +2749,8 @@ setup(void)
LISTEN_STATIC(&seat->events.request_start_drag, requeststartdrag); LISTEN_STATIC(&seat->events.request_start_drag, requeststartdrag);
LISTEN_STATIC(&seat->events.start_drag, startdrag); LISTEN_STATIC(&seat->events.start_drag, startdrag);
/* kb_group = createkeyboardgroup();
* Configures a keyboard group, which will keep track of all connected wl_list_init(&kb_group->destroy.link);
* 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(
wl_display_get_event_loop(dpy), keyrepeat, &kb_group);
vkb_group.key_repeat_source = wl_event_loop_add_timer(
wl_display_get_event_loop(dpy), 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);
output_mgr = wlr_output_manager_v1_create(dpy); output_mgr = wlr_output_manager_v1_create(dpy);
LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply); LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply);
@ -3082,13 +3099,15 @@ view(const Arg *arg)
void void
virtualkeyboard(struct wl_listener *listener, void *data) 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 */ /* Set the keymap to match the group keymap */
wlr_keyboard_set_keymap(&keyboard->keyboard, vkb_group.wlr_group->keyboard.keymap); wlr_keyboard_set_keymap(&kb->keyboard, group->wlr_group->keyboard.keymap);
wlr_keyboard_set_repeat_info(&keyboard->keyboard, repeat_rate, repeat_delay); LISTEN(&kb->keyboard.base.events.destroy, &group->destroy, destroykeyboardgroup);
/* Add the new keyboard to the group */ /* 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 void