Compare commits
11 Commits
854ab23102
...
630efefd3a
Author | SHA1 | Date | |
---|---|---|---|
630efefd3a | |||
8c9a29b87e | |||
|
c2e7350f2e | ||
|
7570dc0a41 | ||
|
e5a57fb155 | ||
613ee6a3a6 | |||
9512cb560e | |||
|
21205f2f40 | ||
|
8f6fca35d0 | ||
|
bca077b927 | ||
|
0047ff740a |
6
Makefile
6
Makefile
@ -15,8 +15,8 @@ LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(LIBS)
|
|||||||
|
|
||||||
all: dwl
|
all: dwl
|
||||||
dwl: dwl.o util.o dwl-ipc-unstable-v2-protocol.o
|
dwl: dwl.o util.o dwl-ipc-unstable-v2-protocol.o
|
||||||
$(CC) dwl.o util.o $(LDLIBS) $(LDFLAGS) $(DWLCFLAGS) dwl-ipc-unstable-v2-protocol.o -o $@
|
$(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) dwl-ipc-unstable-v2-protocol.o -o $@
|
||||||
dwl.o: dwl.c config.mk config.h client.h cursor-shape-v1-protocol.h pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h xdg-shell-protocol.h dwl-ipc-unstable-v2-protocol.h
|
dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h xdg-shell-protocol.h dwl-ipc-unstable-v2-protocol.h
|
||||||
util.o: util.c util.h
|
util.o: util.c util.h
|
||||||
dwl-ipc-unstable-v2-protocol.o: dwl-ipc-unstable-v2-protocol.h
|
dwl-ipc-unstable-v2-protocol.o: dwl-ipc-unstable-v2-protocol.h
|
||||||
|
|
||||||
@ -73,4 +73,4 @@ uninstall:
|
|||||||
|
|
||||||
.SUFFIXES: .c .o
|
.SUFFIXES: .c .o
|
||||||
.c.o:
|
.c.o:
|
||||||
$(CC) $(CPPFLAGS) $(DWLCFLAGS) -c $<
|
$(CC) $(CPPFLAGS) $(DWLCFLAGS) -o $@ -c $<
|
||||||
|
20
client.h
20
client.h
@ -172,11 +172,11 @@ client_get_parent(Client *c)
|
|||||||
{
|
{
|
||||||
Client *p = NULL;
|
Client *p = NULL;
|
||||||
#ifdef XWAYLAND
|
#ifdef XWAYLAND
|
||||||
if (client_is_x11(c)) {
|
if (client_is_x11(c)) {
|
||||||
if (c->surface.xwayland->parent)
|
if (c->surface.xwayland->parent)
|
||||||
toplevel_from_wlr_surface(c->surface.xwayland->parent->surface, &p, NULL);
|
toplevel_from_wlr_surface(c->surface.xwayland->parent->surface, &p, NULL);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (c->surface.xdg->toplevel->parent)
|
if (c->surface.xdg->toplevel->parent)
|
||||||
toplevel_from_wlr_surface(c->surface.xdg->toplevel->parent->base->surface, &p, NULL);
|
toplevel_from_wlr_surface(c->surface.xdg->toplevel->parent->base->surface, &p, NULL);
|
||||||
@ -187,12 +187,12 @@ static inline int
|
|||||||
client_has_children(Client *c)
|
client_has_children(Client *c)
|
||||||
{
|
{
|
||||||
#ifdef XWAYLAND
|
#ifdef XWAYLAND
|
||||||
if (client_is_x11(c))
|
if (client_is_x11(c))
|
||||||
return !wl_list_empty(&c->surface.xwayland->children);
|
return !wl_list_empty(&c->surface.xwayland->children);
|
||||||
#endif
|
#endif
|
||||||
/* surface.xdg->link is never empty because it always contains at least the
|
/* surface.xdg->link is never empty because it always contains at least the
|
||||||
* surface itself. */
|
* surface itself. */
|
||||||
return wl_list_length(&c->surface.xdg->link) > 1;
|
return wl_list_length(&c->surface.xdg->link) > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline const char *
|
static inline const char *
|
||||||
|
@ -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 */
|
||||||
|
177
dwl.c
177
dwl.c
@ -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 {
|
||||||
@ -268,6 +269,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);
|
||||||
@ -287,6 +289,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);
|
||||||
@ -418,9 +421,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 unsigned int cursor_mode;
|
static unsigned int cursor_mode;
|
||||||
static Client *grabc;
|
static Client *grabc;
|
||||||
static int grabcx, grabcy; /* client-relative */
|
static int grabcx, grabcy; /* client-relative */
|
||||||
@ -518,6 +519,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);
|
||||||
@ -612,7 +627,6 @@ buttonpress(struct wl_listener *listener, void *data)
|
|||||||
switch (event->state) {
|
switch (event->state) {
|
||||||
case WLR_BUTTON_PRESSED:
|
case WLR_BUTTON_PRESSED:
|
||||||
cursor_mode = CurPressed;
|
cursor_mode = CurPressed;
|
||||||
held_grab = seat->pointer_state.focused_surface;
|
|
||||||
if (locked)
|
if (locked)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -632,7 +646,6 @@ buttonpress(struct wl_listener *listener, void *data)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WLR_BUTTON_RELEASED:
|
case WLR_BUTTON_RELEASED:
|
||||||
held_grab = NULL;
|
|
||||||
/* If you released any buttons, we exit interactive move/resize mode. */
|
/* If you released any buttons, we exit interactive move/resize mode. */
|
||||||
/* TODO should reset to the pointer focus's current setcursor */
|
/* TODO should reset to the pointer focus's current setcursor */
|
||||||
if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) {
|
if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) {
|
||||||
@ -692,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)
|
||||||
@ -818,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
|
||||||
@ -957,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);
|
||||||
@ -1262,6 +1310,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)
|
||||||
{
|
{
|
||||||
@ -1674,7 +1734,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);
|
||||||
}
|
}
|
||||||
@ -1947,6 +2007,18 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
|
|||||||
struct wlr_surface *surface = NULL;
|
struct wlr_surface *surface = NULL;
|
||||||
struct wlr_pointer_constraint_v1 *constraint;
|
struct wlr_pointer_constraint_v1 *constraint;
|
||||||
|
|
||||||
|
/* Find the client under the pointer and send the event along. */
|
||||||
|
xytonode(cursor->x, cursor->y, &surface, &c, NULL, &sx, &sy);
|
||||||
|
|
||||||
|
if (cursor_mode == CurPressed && !seat->drag
|
||||||
|
&& surface != seat->pointer_state.focused_surface
|
||||||
|
&& toplevel_from_wlr_surface(seat->pointer_state.focused_surface, &w, &l) >= 0) {
|
||||||
|
c = w;
|
||||||
|
surface = seat->pointer_state.focused_surface;
|
||||||
|
sx = cursor->x - (l ? l->geom.x : w->geom.x);
|
||||||
|
sy = cursor->y - (l ? l->geom.y : w->geom.y);
|
||||||
|
}
|
||||||
|
|
||||||
/* time is 0 in internal calls meant to restore pointer focus. */
|
/* time is 0 in internal calls meant to restore pointer focus. */
|
||||||
if (time) {
|
if (time) {
|
||||||
wlr_relative_pointer_manager_v1_send_relative_motion(
|
wlr_relative_pointer_manager_v1_send_relative_motion(
|
||||||
@ -1995,17 +2067,6 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the client under the pointer and send the event along. */
|
|
||||||
xytonode(cursor->x, cursor->y, &surface, &c, NULL, &sx, &sy);
|
|
||||||
|
|
||||||
if (cursor_mode == CurPressed && !seat->drag && surface != held_grab
|
|
||||||
&& toplevel_from_wlr_surface(held_grab, &w, &l) >= 0) {
|
|
||||||
c = w;
|
|
||||||
surface = held_grab;
|
|
||||||
sx = cursor->x - (l ? l->geom.x : w->geom.x);
|
|
||||||
sy = cursor->y - (l ? l->geom.y : w->geom.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If there's no client surface under the cursor, set the cursor image to a
|
/* If there's no client surface under the cursor, set the cursor image to a
|
||||||
* default. This is what makes the cursor image appear when you move it
|
* default. This is what makes the cursor image appear when you move it
|
||||||
* off of a client or over its border. */
|
* off of a client or over its border. */
|
||||||
@ -2135,7 +2196,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);
|
||||||
|
|
||||||
@ -2402,7 +2463,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
|
||||||
@ -2522,9 +2584,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);
|
||||||
@ -2706,52 +2765,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);
|
||||||
@ -3116,13 +3131,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
|
||||||
|
Loading…
Reference in New Issue
Block a user