forked from mirror/dwl
Merge remote-tracking branch 'upstream/main' into wlroots-next
This commit is contained in:
commit
bf5a6be73c
2 changed files with 191 additions and 142 deletions
2
client.h
2
client.h
|
@ -352,7 +352,7 @@ client_set_tiled(Client *c, uint32_t edges)
|
||||||
if (client_is_x11(c))
|
if (client_is_x11(c))
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
if (wl_resource_get_version(c->surface.xdg->resource)
|
if (wl_resource_get_version(c->surface.xdg->toplevel->resource)
|
||||||
>= XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) {
|
>= XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) {
|
||||||
wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, edges);
|
wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, edges);
|
||||||
} else {
|
} else {
|
||||||
|
|
331
dwl.c
331
dwl.c
|
@ -28,6 +28,7 @@
|
||||||
#include <wlr/types/wlr_idle_notify_v1.h>
|
#include <wlr/types/wlr_idle_notify_v1.h>
|
||||||
#include <wlr/types/wlr_input_device.h>
|
#include <wlr/types/wlr_input_device.h>
|
||||||
#include <wlr/types/wlr_keyboard.h>
|
#include <wlr/types/wlr_keyboard.h>
|
||||||
|
#include <wlr/types/wlr_keyboard_group.h>
|
||||||
#include <wlr/types/wlr_layer_shell_v1.h>
|
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||||
#include <wlr/types/wlr_linux_dmabuf_v1.h>
|
#include <wlr/types/wlr_linux_dmabuf_v1.h>
|
||||||
#include <wlr/types/wlr_output.h>
|
#include <wlr/types/wlr_output.h>
|
||||||
|
@ -110,6 +111,7 @@ typedef struct {
|
||||||
struct wlr_xdg_surface *xdg;
|
struct wlr_xdg_surface *xdg;
|
||||||
struct wlr_xwayland_surface *xwayland;
|
struct wlr_xwayland_surface *xwayland;
|
||||||
} surface;
|
} surface;
|
||||||
|
struct wlr_xdg_toplevel_decoration_v1 *decoration;
|
||||||
struct wl_listener commit;
|
struct wl_listener commit;
|
||||||
struct wl_listener map;
|
struct wl_listener map;
|
||||||
struct wl_listener maximize;
|
struct wl_listener maximize;
|
||||||
|
@ -117,6 +119,8 @@ typedef struct {
|
||||||
struct wl_listener destroy;
|
struct wl_listener destroy;
|
||||||
struct wl_listener set_title;
|
struct wl_listener set_title;
|
||||||
struct wl_listener fullscreen;
|
struct wl_listener fullscreen;
|
||||||
|
struct wl_listener set_decoration_mode;
|
||||||
|
struct wl_listener destroy_decoration;
|
||||||
struct wlr_box prev; /* layout-relative, includes border */
|
struct wlr_box prev; /* layout-relative, includes border */
|
||||||
struct wlr_box bounds;
|
struct wlr_box bounds;
|
||||||
#ifdef XWAYLAND
|
#ifdef XWAYLAND
|
||||||
|
@ -141,7 +145,7 @@ typedef struct {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
struct wlr_keyboard *wlr_keyboard;
|
struct wlr_keyboard_group *wlr_group;
|
||||||
|
|
||||||
int nsyms;
|
int nsyms;
|
||||||
const xkb_keysym_t *keysyms; /* invalid if nsyms == 0 */
|
const xkb_keysym_t *keysyms; /* invalid if nsyms == 0 */
|
||||||
|
@ -150,8 +154,7 @@ typedef struct {
|
||||||
|
|
||||||
struct wl_listener modifiers;
|
struct wl_listener modifiers;
|
||||||
struct wl_listener key;
|
struct wl_listener key;
|
||||||
struct wl_listener destroy;
|
} KeyboardGroup;
|
||||||
} Keyboard;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* Must keep these three elements in this order */
|
/* Must keep these three elements in this order */
|
||||||
|
@ -238,7 +241,6 @@ static void buttonpress(struct wl_listener *listener, void *data);
|
||||||
static void chvt(const Arg *arg);
|
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 cleanupkeyboard(struct wl_listener *listener, void *data);
|
|
||||||
static void cleanupmon(struct wl_listener *listener, void *data);
|
static void cleanupmon(struct wl_listener *listener, void *data);
|
||||||
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);
|
||||||
|
@ -253,6 +255,7 @@ static void createnotify(struct wl_listener *listener, void *data);
|
||||||
static void createpointer(struct wlr_pointer *pointer);
|
static void createpointer(struct wlr_pointer *pointer);
|
||||||
static void createpopup(struct wl_listener *listener, void *data);
|
static void createpopup(struct wl_listener *listener, void *data);
|
||||||
static void cursorframe(struct wl_listener *listener, void *data);
|
static void cursorframe(struct wl_listener *listener, void *data);
|
||||||
|
static void destroydecoration(struct wl_listener *listener, void *data);
|
||||||
static void destroydragicon(struct wl_listener *listener, void *data);
|
static void destroydragicon(struct wl_listener *listener, void *data);
|
||||||
static void destroyidleinhibitor(struct wl_listener *listener, void *data);
|
static void destroyidleinhibitor(struct wl_listener *listener, void *data);
|
||||||
static void destroylayersurfacenotify(struct wl_listener *listener, void *data);
|
static void destroylayersurfacenotify(struct wl_listener *listener, void *data);
|
||||||
|
@ -292,6 +295,7 @@ static void pointerfocus(Client *c, struct wlr_surface *surface,
|
||||||
static void printstatus(void);
|
static void printstatus(void);
|
||||||
static void quit(const Arg *arg);
|
static void quit(const Arg *arg);
|
||||||
static void rendermon(struct wl_listener *listener, void *data);
|
static void rendermon(struct wl_listener *listener, void *data);
|
||||||
|
static void requestdecorationmode(struct wl_listener *listener, void *data);
|
||||||
static void requeststartdrag(struct wl_listener *listener, void *data);
|
static void requeststartdrag(struct wl_listener *listener, void *data);
|
||||||
static void requestmonstate(struct wl_listener *listener, void *data);
|
static void requestmonstate(struct wl_listener *listener, void *data);
|
||||||
static void resize(Client *c, struct wlr_box geo, int interact);
|
static void resize(Client *c, struct wlr_box geo, int interact);
|
||||||
|
@ -369,7 +373,8 @@ 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 struct wl_list keyboards;
|
static KeyboardGroup kb_group = {0};
|
||||||
|
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;
|
||||||
|
@ -438,9 +443,10 @@ applyrules(Client *c)
|
||||||
c->isfloating = r->isfloating;
|
c->isfloating = r->isfloating;
|
||||||
newtags |= r->tags;
|
newtags |= r->tags;
|
||||||
i = 0;
|
i = 0;
|
||||||
wl_list_for_each(m, &mons, link)
|
wl_list_for_each(m, &mons, link) {
|
||||||
if (r->monitor == i++)
|
if (r->monitor == i++)
|
||||||
mon = m;
|
mon = m;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wlr_scene_node_reparent(&c->scene->node, layers[c->isfloating ? LyrFloat : LyrTile]);
|
wlr_scene_node_reparent(&c->scene->node, layers[c->isfloating ? LyrFloat : LyrTile]);
|
||||||
|
@ -477,9 +483,8 @@ 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;
|
||||||
struct wlr_layer_surface_v1_state *state = &layer_surface->current;
|
|
||||||
|
|
||||||
if (exclusive != (state->exclusive_zone > 0))
|
if (exclusive != (layer_surface->current.exclusive_zone > 0))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
wlr_scene_layer_surface_v1_configure(l->scene_layer, &full_area, usable_area);
|
wlr_scene_layer_surface_v1_configure(l->scene_layer, &full_area, usable_area);
|
||||||
|
@ -636,25 +641,17 @@ cleanup(void)
|
||||||
waitpid(child_pid, NULL, 0);
|
waitpid(child_pid, NULL, 0);
|
||||||
}
|
}
|
||||||
wlr_xcursor_manager_destroy(cursor_mgr);
|
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);
|
||||||
|
|
||||||
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)
|
||||||
to avoid destroying them with an invalid scene output. */
|
to avoid destroying them with an invalid scene output. */
|
||||||
wlr_scene_node_destroy(&scene->tree.node);
|
wlr_scene_node_destroy(&scene->tree.node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
cleanupkeyboard(struct wl_listener *listener, void *data)
|
|
||||||
{
|
|
||||||
Keyboard *kb = wl_container_of(listener, kb, destroy);
|
|
||||||
|
|
||||||
wl_event_source_remove(kb->key_repeat_source);
|
|
||||||
wl_list_remove(&kb->link);
|
|
||||||
wl_list_remove(&kb->modifiers.link);
|
|
||||||
wl_list_remove(&kb->key.link);
|
|
||||||
wl_list_remove(&kb->destroy.link);
|
|
||||||
free(kb);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
cleanupmon(struct wl_listener *listener, void *data)
|
cleanupmon(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
|
@ -663,9 +660,10 @@ cleanupmon(struct wl_listener *listener, void *data)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* m->layers[i] are intentionally not unlinked */
|
/* m->layers[i] are intentionally not unlinked */
|
||||||
for (i = 0; i < LENGTH(m->layers); i++)
|
for (i = 0; i < LENGTH(m->layers); i++) {
|
||||||
wl_list_for_each_safe(l, tmp, &m->layers[i], link)
|
wl_list_for_each_safe(l, tmp, &m->layers[i], link)
|
||||||
wlr_layer_surface_v1_destroy(l->layer_surface);
|
wlr_layer_surface_v1_destroy(l->layer_surface);
|
||||||
|
}
|
||||||
|
|
||||||
wl_list_remove(&m->destroy.link);
|
wl_list_remove(&m->destroy.link);
|
||||||
wl_list_remove(&m->frame.link);
|
wl_list_remove(&m->frame.link);
|
||||||
|
@ -686,10 +684,10 @@ closemon(Monitor *m)
|
||||||
/* update selmon if needed and
|
/* update selmon if needed and
|
||||||
* move closed monitor's clients to the focused one */
|
* move closed monitor's clients to the focused one */
|
||||||
Client *c;
|
Client *c;
|
||||||
if (wl_list_empty(&mons)) {
|
int i = 0, nmons = wl_list_length(&mons);
|
||||||
|
if (!nmons) {
|
||||||
selmon = NULL;
|
selmon = NULL;
|
||||||
} else if (m == selmon) {
|
} else if (m == selmon) {
|
||||||
int nmons = wl_list_length(&mons), i = 0;
|
|
||||||
do /* don't switch to disabled mons */
|
do /* don't switch to disabled mons */
|
||||||
selmon = wl_container_of(mons.next, selmon, link);
|
selmon = wl_container_of(mons.next, selmon, link);
|
||||||
while (!selmon->wlr_output->enabled && i++ < nmons);
|
while (!selmon->wlr_output->enabled && i++ < nmons);
|
||||||
|
@ -698,7 +696,7 @@ closemon(Monitor *m)
|
||||||
wl_list_for_each(c, &clients, link) {
|
wl_list_for_each(c, &clients, link) {
|
||||||
if (c->isfloating && c->geom.x > m->m.width)
|
if (c->isfloating && c->geom.x > m->m.width)
|
||||||
resize(c, (struct wlr_box){.x = c->geom.x - m->w.width, .y = c->geom.y,
|
resize(c, (struct wlr_box){.x = c->geom.x - m->w.width, .y = c->geom.y,
|
||||||
.width = c->geom.width, .height = c->geom.height}, 0);
|
.width = c->geom.width, .height = c->geom.height}, 0);
|
||||||
if (c->mon == m)
|
if (c->mon == m)
|
||||||
setmon(c, selmon, c->tags);
|
setmon(c, selmon, c->tags);
|
||||||
}
|
}
|
||||||
|
@ -758,8 +756,14 @@ commitnotify(struct wl_listener *listener, void *data)
|
||||||
void
|
void
|
||||||
createdecoration(struct wl_listener *listener, void *data)
|
createdecoration(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
struct wlr_xdg_toplevel_decoration_v1 *dec = data;
|
struct wlr_xdg_toplevel_decoration_v1 *deco = data;
|
||||||
wlr_xdg_toplevel_decoration_v1_set_mode(dec, WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
Client *c = deco->toplevel->base->data;
|
||||||
|
c->decoration = deco;
|
||||||
|
|
||||||
|
LISTEN(&deco->events.request_mode, &c->set_decoration_mode, requestdecorationmode);
|
||||||
|
LISTEN(&deco->events.destroy, &c->destroy_decoration, destroydecoration);
|
||||||
|
|
||||||
|
requestdecorationmode(&c->set_decoration_mode, deco);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -774,35 +778,12 @@ createidleinhibitor(struct wl_listener *listener, void *data)
|
||||||
void
|
void
|
||||||
createkeyboard(struct wlr_keyboard *keyboard)
|
createkeyboard(struct wlr_keyboard *keyboard)
|
||||||
{
|
{
|
||||||
struct xkb_context *context;
|
/* Set the keymap to match the group keymap */
|
||||||
struct xkb_keymap *keymap;
|
wlr_keyboard_set_keymap(keyboard, kb_group.wlr_group->keyboard.keymap);
|
||||||
Keyboard *kb = keyboard->data = ecalloc(1, sizeof(*kb));
|
|
||||||
kb->wlr_keyboard = keyboard;
|
|
||||||
|
|
||||||
/* Prepare an XKB keymap and assign it to the keyboard. */
|
|
||||||
context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
|
||||||
keymap = xkb_keymap_new_from_names(context, &xkb_rules,
|
|
||||||
XKB_KEYMAP_COMPILE_NO_FLAGS);
|
|
||||||
if (!keymap)
|
|
||||||
die("createkeyboard: failed to compile keymap");
|
|
||||||
|
|
||||||
wlr_keyboard_set_keymap(keyboard, keymap);
|
|
||||||
xkb_keymap_unref(keymap);
|
|
||||||
xkb_context_unref(context);
|
|
||||||
wlr_keyboard_set_repeat_info(keyboard, repeat_rate, repeat_delay);
|
wlr_keyboard_set_repeat_info(keyboard, repeat_rate, repeat_delay);
|
||||||
|
|
||||||
/* Here we set up listeners for keyboard events. */
|
/* Add the new keyboard to the group */
|
||||||
LISTEN(&keyboard->events.modifiers, &kb->modifiers, keypressmod);
|
wlr_keyboard_group_add_keyboard(kb_group.wlr_group, keyboard);
|
||||||
LISTEN(&keyboard->events.key, &kb->key, keypress);
|
|
||||||
LISTEN(&keyboard->base.events.destroy, &kb->destroy, cleanupkeyboard);
|
|
||||||
|
|
||||||
wlr_seat_set_keyboard(seat, keyboard);
|
|
||||||
|
|
||||||
kb->key_repeat_source = wl_event_loop_add_timer(
|
|
||||||
wl_display_get_event_loop(dpy), keyrepeat, kb);
|
|
||||||
|
|
||||||
/* And add the keyboard to our list of keyboards */
|
|
||||||
wl_list_insert(&keyboards, &kb->link);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -844,8 +825,8 @@ createlocksurface(struct wl_listener *listener, void *data)
|
||||||
SessionLock *lock = wl_container_of(listener, lock, new_surface);
|
SessionLock *lock = wl_container_of(listener, lock, new_surface);
|
||||||
struct wlr_session_lock_surface_v1 *lock_surface = data;
|
struct wlr_session_lock_surface_v1 *lock_surface = data;
|
||||||
Monitor *m = lock_surface->output->data;
|
Monitor *m = lock_surface->output->data;
|
||||||
struct wlr_scene_tree *scene_tree = lock_surface->surface->data =
|
struct wlr_scene_tree *scene_tree = lock_surface->surface->data
|
||||||
wlr_scene_subsurface_tree_create(lock->scene, lock_surface->surface);
|
= wlr_scene_subsurface_tree_create(lock->scene, lock_surface->surface);
|
||||||
m->lock_surface = lock_surface;
|
m->lock_surface = lock_surface;
|
||||||
|
|
||||||
wlr_scene_node_set_position(&scene_tree->node, m->m.x, m->m.y);
|
wlr_scene_node_set_position(&scene_tree->node, m->m.x, m->m.y);
|
||||||
|
@ -961,40 +942,41 @@ createnotify(struct wl_listener *listener, void *data)
|
||||||
void
|
void
|
||||||
createpointer(struct wlr_pointer *pointer)
|
createpointer(struct wlr_pointer *pointer)
|
||||||
{
|
{
|
||||||
if (wlr_input_device_is_libinput(&pointer->base)) {
|
struct libinput_device *device;
|
||||||
struct libinput_device *libinput_device = wlr_libinput_get_device_handle(&pointer->base);
|
if (wlr_input_device_is_libinput(&pointer->base)
|
||||||
|
&& (device = wlr_libinput_get_device_handle(&pointer->base))) {
|
||||||
|
|
||||||
if (libinput_device_config_tap_get_finger_count(libinput_device)) {
|
if (libinput_device_config_tap_get_finger_count(device)) {
|
||||||
libinput_device_config_tap_set_enabled(libinput_device, tap_to_click);
|
libinput_device_config_tap_set_enabled(device, tap_to_click);
|
||||||
libinput_device_config_tap_set_drag_enabled(libinput_device, tap_and_drag);
|
libinput_device_config_tap_set_drag_enabled(device, tap_and_drag);
|
||||||
libinput_device_config_tap_set_drag_lock_enabled(libinput_device, drag_lock);
|
libinput_device_config_tap_set_drag_lock_enabled(device, drag_lock);
|
||||||
libinput_device_config_tap_set_button_map(libinput_device, button_map);
|
libinput_device_config_tap_set_button_map(device, button_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (libinput_device_config_scroll_has_natural_scroll(libinput_device))
|
if (libinput_device_config_scroll_has_natural_scroll(device))
|
||||||
libinput_device_config_scroll_set_natural_scroll_enabled(libinput_device, natural_scrolling);
|
libinput_device_config_scroll_set_natural_scroll_enabled(device, natural_scrolling);
|
||||||
|
|
||||||
if (libinput_device_config_dwt_is_available(libinput_device))
|
if (libinput_device_config_dwt_is_available(device))
|
||||||
libinput_device_config_dwt_set_enabled(libinput_device, disable_while_typing);
|
libinput_device_config_dwt_set_enabled(device, disable_while_typing);
|
||||||
|
|
||||||
if (libinput_device_config_left_handed_is_available(libinput_device))
|
if (libinput_device_config_left_handed_is_available(device))
|
||||||
libinput_device_config_left_handed_set(libinput_device, left_handed);
|
libinput_device_config_left_handed_set(device, left_handed);
|
||||||
|
|
||||||
if (libinput_device_config_middle_emulation_is_available(libinput_device))
|
if (libinput_device_config_middle_emulation_is_available(device))
|
||||||
libinput_device_config_middle_emulation_set_enabled(libinput_device, middle_button_emulation);
|
libinput_device_config_middle_emulation_set_enabled(device, middle_button_emulation);
|
||||||
|
|
||||||
if (libinput_device_config_scroll_get_methods(libinput_device) != LIBINPUT_CONFIG_SCROLL_NO_SCROLL)
|
if (libinput_device_config_scroll_get_methods(device) != LIBINPUT_CONFIG_SCROLL_NO_SCROLL)
|
||||||
libinput_device_config_scroll_set_method (libinput_device, scroll_method);
|
libinput_device_config_scroll_set_method (device, scroll_method);
|
||||||
|
|
||||||
if (libinput_device_config_click_get_methods(libinput_device) != LIBINPUT_CONFIG_CLICK_METHOD_NONE)
|
if (libinput_device_config_click_get_methods(device) != LIBINPUT_CONFIG_CLICK_METHOD_NONE)
|
||||||
libinput_device_config_click_set_method (libinput_device, click_method);
|
libinput_device_config_click_set_method (device, click_method);
|
||||||
|
|
||||||
if (libinput_device_config_send_events_get_modes(libinput_device))
|
if (libinput_device_config_send_events_get_modes(device))
|
||||||
libinput_device_config_send_events_set_mode(libinput_device, send_events_mode);
|
libinput_device_config_send_events_set_mode(device, send_events_mode);
|
||||||
|
|
||||||
if (libinput_device_config_accel_is_available(libinput_device)) {
|
if (libinput_device_config_accel_is_available(device)) {
|
||||||
libinput_device_config_accel_set_profile(libinput_device, accel_profile);
|
libinput_device_config_accel_set_profile(device, accel_profile);
|
||||||
libinput_device_config_accel_set_speed(libinput_device, accel_speed);
|
libinput_device_config_accel_set_speed(device, accel_speed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1036,6 +1018,15 @@ cursorframe(struct wl_listener *listener, void *data)
|
||||||
wlr_seat_pointer_notify_frame(seat);
|
wlr_seat_pointer_notify_frame(seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
destroydecoration(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
Client *c = wl_container_of(listener, c, destroy_decoration);
|
||||||
|
|
||||||
|
wl_list_remove(&c->destroy_decoration.link);
|
||||||
|
wl_list_remove(&c->set_decoration_mode.link);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
destroydragicon(struct wl_listener *listener, void *data)
|
destroydragicon(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
|
@ -1245,10 +1236,11 @@ void
|
||||||
focusmon(const Arg *arg)
|
focusmon(const Arg *arg)
|
||||||
{
|
{
|
||||||
int i = 0, nmons = wl_list_length(&mons);
|
int i = 0, nmons = wl_list_length(&mons);
|
||||||
if (nmons)
|
if (nmons) {
|
||||||
do /* don't switch to disabled mons */
|
do /* don't switch to disabled mons */
|
||||||
selmon = dirtomon(arg->i);
|
selmon = dirtomon(arg->i);
|
||||||
while (!selmon->wlr_output->enabled && i++ < nmons);
|
while (!selmon->wlr_output->enabled && i++ < nmons);
|
||||||
|
}
|
||||||
focusclient(focustop(selmon), 1);
|
focusclient(focustop(selmon), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1285,9 +1277,10 @@ Client *
|
||||||
focustop(Monitor *m)
|
focustop(Monitor *m)
|
||||||
{
|
{
|
||||||
Client *c;
|
Client *c;
|
||||||
wl_list_for_each(c, &fstack, flink)
|
wl_list_for_each(c, &fstack, flink) {
|
||||||
if (VISIBLEON(c, m))
|
if (VISIBLEON(c, m))
|
||||||
return c;
|
return c;
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1353,7 +1346,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(&keyboards))
|
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);
|
||||||
}
|
}
|
||||||
|
@ -1369,8 +1362,8 @@ keybinding(uint32_t mods, xkb_keysym_t sym)
|
||||||
int handled = 0;
|
int handled = 0;
|
||||||
const Key *k;
|
const Key *k;
|
||||||
for (k = keys; k < END(keys); k++) {
|
for (k = keys; k < END(keys); k++) {
|
||||||
if (CLEANMASK(mods) == CLEANMASK(k->mod) &&
|
if (CLEANMASK(mods) == CLEANMASK(k->mod)
|
||||||
sym == k->keysym && k->func) {
|
&& sym == k->keysym && k->func) {
|
||||||
k->func(&k->arg);
|
k->func(&k->arg);
|
||||||
handled = 1;
|
handled = 1;
|
||||||
}
|
}
|
||||||
|
@ -1383,7 +1376,7 @@ keypress(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
/* This event is raised when a key is pressed or released. */
|
/* This event is raised when a key is pressed or released. */
|
||||||
Keyboard *kb = wl_container_of(listener, kb, key);
|
KeyboardGroup *group = wl_container_of(listener, group, key);
|
||||||
struct wlr_keyboard_key_event *event = data;
|
struct wlr_keyboard_key_event *event = data;
|
||||||
|
|
||||||
/* Translate libinput keycode -> xkbcommon */
|
/* Translate libinput keycode -> xkbcommon */
|
||||||
|
@ -1391,10 +1384,10 @@ keypress(struct wl_listener *listener, void *data)
|
||||||
/* Get a list of keysyms based on the keymap for this keyboard */
|
/* Get a list of keysyms based on the keymap for this keyboard */
|
||||||
const xkb_keysym_t *syms;
|
const xkb_keysym_t *syms;
|
||||||
int nsyms = xkb_state_key_get_syms(
|
int nsyms = xkb_state_key_get_syms(
|
||||||
kb->wlr_keyboard->xkb_state, keycode, &syms);
|
group->wlr_group->keyboard.xkb_state, keycode, &syms);
|
||||||
|
|
||||||
int handled = 0;
|
int handled = 0;
|
||||||
uint32_t mods = wlr_keyboard_get_modifiers(kb->wlr_keyboard);
|
uint32_t mods = wlr_keyboard_get_modifiers(&group->wlr_group->keyboard);
|
||||||
|
|
||||||
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
||||||
|
|
||||||
|
@ -1404,24 +1397,24 @@ keypress(struct wl_listener *listener, void *data)
|
||||||
for (i = 0; i < nsyms; i++)
|
for (i = 0; i < nsyms; i++)
|
||||||
handled = keybinding(mods, syms[i]) || handled;
|
handled = keybinding(mods, syms[i]) || handled;
|
||||||
|
|
||||||
if (handled && kb->wlr_keyboard->repeat_info.delay > 0) {
|
if (handled && group->wlr_group->keyboard.repeat_info.delay > 0) {
|
||||||
kb->mods = mods;
|
group->mods = mods;
|
||||||
kb->keysyms = syms;
|
group->keysyms = syms;
|
||||||
kb->nsyms = nsyms;
|
group->nsyms = nsyms;
|
||||||
wl_event_source_timer_update(kb->key_repeat_source,
|
wl_event_source_timer_update(group->key_repeat_source,
|
||||||
kb->wlr_keyboard->repeat_info.delay);
|
group->wlr_group->keyboard.repeat_info.delay);
|
||||||
} else {
|
} else {
|
||||||
kb->nsyms = 0;
|
group->nsyms = 0;
|
||||||
wl_event_source_timer_update(kb->key_repeat_source, 0);
|
wl_event_source_timer_update(group->key_repeat_source, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handled)
|
if (handled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard);
|
||||||
/* Pass unhandled keycodes along to the client. */
|
/* Pass unhandled keycodes along to the client. */
|
||||||
wlr_seat_set_keyboard(seat, kb->wlr_keyboard);
|
|
||||||
wlr_seat_keyboard_notify_key(seat, event->time_msec,
|
wlr_seat_keyboard_notify_key(seat, event->time_msec,
|
||||||
event->keycode, event->state);
|
event->keycode, event->state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1429,32 +1422,27 @@ keypressmod(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
/* This event is raised when a modifier key, such as shift or alt, is
|
/* This event is raised when a modifier key, such as shift or alt, is
|
||||||
* pressed. We simply communicate this to the client. */
|
* pressed. We simply communicate this to the client. */
|
||||||
Keyboard *kb = wl_container_of(listener, kb, modifiers);
|
KeyboardGroup *group = wl_container_of(listener, group, modifiers);
|
||||||
/*
|
|
||||||
* A seat can only have one keyboard, but this is a limitation of the
|
wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard);
|
||||||
* Wayland protocol - not wlroots. We assign all connected keyboards to the
|
|
||||||
* same seat. You can swap out the underlying wlr_keyboard like this and
|
|
||||||
* wlr_seat handles this transparently.
|
|
||||||
*/
|
|
||||||
wlr_seat_set_keyboard(seat, kb->wlr_keyboard);
|
|
||||||
/* Send modifiers to the client. */
|
/* Send modifiers to the client. */
|
||||||
wlr_seat_keyboard_notify_modifiers(seat,
|
wlr_seat_keyboard_notify_modifiers(seat,
|
||||||
&kb->wlr_keyboard->modifiers);
|
&group->wlr_group->keyboard.modifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
keyrepeat(void *data)
|
keyrepeat(void *data)
|
||||||
{
|
{
|
||||||
Keyboard *kb = data;
|
KeyboardGroup *group = data;
|
||||||
int i;
|
int i;
|
||||||
if (!kb->nsyms || kb->wlr_keyboard->repeat_info.rate <= 0)
|
if (!group->nsyms || group->wlr_group->keyboard.repeat_info.rate <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
wl_event_source_timer_update(kb->key_repeat_source,
|
wl_event_source_timer_update(group->key_repeat_source,
|
||||||
1000 / kb->wlr_keyboard->repeat_info.rate);
|
1000 / group->wlr_group->keyboard.repeat_info.rate);
|
||||||
|
|
||||||
for (i = 0; i < kb->nsyms; i++)
|
for (i = 0; i < group->nsyms; i++)
|
||||||
keybinding(kb->mods, kb->keysyms[i]);
|
keybinding(group->mods, group->keysyms[i]);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1520,7 +1508,7 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||||
/* Unmanaged clients always are floating */
|
/* Unmanaged clients always are floating */
|
||||||
wlr_scene_node_reparent(&c->scene->node, layers[LyrFloat]);
|
wlr_scene_node_reparent(&c->scene->node, layers[LyrFloat]);
|
||||||
wlr_scene_node_set_position(&c->scene->node, c->geom.x + borderpx,
|
wlr_scene_node_set_position(&c->scene->node, c->geom.x + borderpx,
|
||||||
c->geom.y + borderpx);
|
c->geom.y + borderpx);
|
||||||
if (client_wants_focus(c)) {
|
if (client_wants_focus(c)) {
|
||||||
focusclient(c, 1);
|
focusclient(c, 1);
|
||||||
exclusive_focus = c;
|
exclusive_focus = c;
|
||||||
|
@ -1547,7 +1535,7 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||||
* 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 than its parent, if not
|
* we set the same tags and monitor than its parent, if not
|
||||||
* try to apply rules for them */
|
* try to apply rules for them */
|
||||||
/* TODO: https://github.com/djpohly/dwl/pull/334#issuecomment-1330166324 */
|
/* TODO: https://github.com/djpohly/dwl/pull/334#issuecomment-1330166324 */
|
||||||
if (c->type == XDGShell && (p = client_get_parent(c))) {
|
if (c->type == XDGShell && (p = client_get_parent(c))) {
|
||||||
c->isfloating = 1;
|
c->isfloating = 1;
|
||||||
wlr_scene_node_reparent(&c->scene->node, layers[LyrFloat]);
|
wlr_scene_node_reparent(&c->scene->node, layers[LyrFloat]);
|
||||||
|
@ -1559,9 +1547,10 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||||
|
|
||||||
unset_fullscreen:
|
unset_fullscreen:
|
||||||
m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y);
|
m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y);
|
||||||
wl_list_for_each(w, &clients, link)
|
wl_list_for_each(w, &clients, link) {
|
||||||
if (w != c && w->isfullscreen && m == w->mon && (w->tags & c->tags))
|
if (w != c && w->isfullscreen && m == w->mon && (w->tags & c->tags))
|
||||||
setfullscreen(w, 0);
|
setfullscreen(w, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1576,7 +1565,7 @@ maximizenotify(struct wl_listener *listener, void *data)
|
||||||
* protocol version
|
* protocol version
|
||||||
* wlr_xdg_surface_schedule_configure() is used to send an empty reply. */
|
* wlr_xdg_surface_schedule_configure() is used to send an empty reply. */
|
||||||
Client *c = wl_container_of(listener, c, maximize);
|
Client *c = wl_container_of(listener, c, maximize);
|
||||||
if (wl_resource_get_version(c->surface.xdg->resource)
|
if (wl_resource_get_version(c->surface.xdg->toplevel->resource)
|
||||||
< XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION)
|
< XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION)
|
||||||
wlr_xdg_surface_schedule_configure(c->surface.xdg);
|
wlr_xdg_surface_schedule_configure(c->surface.xdg);
|
||||||
}
|
}
|
||||||
|
@ -1784,9 +1773,8 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
|
||||||
uint32_t time)
|
uint32_t time)
|
||||||
{
|
{
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
int internal_call = !time;
|
|
||||||
|
|
||||||
if (sloppyfocus && !internal_call && c && !client_is_unmanaged(c))
|
if (sloppyfocus && time && c && !client_is_unmanaged(c))
|
||||||
focusclient(c, 0);
|
focusclient(c, 0);
|
||||||
|
|
||||||
/* If surface is NULL, clear pointer focus */
|
/* If surface is NULL, clear pointer focus */
|
||||||
|
@ -1795,7 +1783,7 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (internal_call) {
|
if (!time) {
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
time = now.tv_sec * 1000 + now.tv_nsec / 1000000;
|
time = now.tv_sec * 1000 + now.tv_nsec / 1000000;
|
||||||
}
|
}
|
||||||
|
@ -1842,8 +1830,8 @@ printstatus(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%s selmon %u\n", m->wlr_output->name, m == selmon);
|
printf("%s selmon %u\n", m->wlr_output->name, m == selmon);
|
||||||
printf("%s tags %u %u %u %u\n", m->wlr_output->name, occ, m->tagset[m->seltags],
|
printf("%s tags %u %u %u %u\n", m->wlr_output->name, occ,
|
||||||
sel, urg);
|
m->tagset[m->seltags], sel, urg);
|
||||||
printf("%s layout %s\n", m->wlr_output->name, m->ltsymbol);
|
printf("%s layout %s\n", m->wlr_output->name, m->ltsymbol);
|
||||||
}
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
@ -1868,9 +1856,10 @@ rendermon(struct wl_listener *listener, void *data)
|
||||||
|
|
||||||
/* Render if no XDG clients have an outstanding resize and are visible on
|
/* Render if no XDG clients have an outstanding resize and are visible on
|
||||||
* this monitor. */
|
* this monitor. */
|
||||||
wl_list_for_each(c, &clients, link)
|
wl_list_for_each(c, &clients, link) {
|
||||||
if (c->resize && !c->isfloating && client_is_rendered_on_mon(c, m) && !client_is_stopped(c))
|
if (c->resize && !c->isfloating && client_is_rendered_on_mon(c, m) && !client_is_stopped(c))
|
||||||
goto skip;
|
goto skip;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* HACK: The "correct" way to set the gamma is to commit it together with
|
* HACK: The "correct" way to set the gamma is to commit it together with
|
||||||
|
@ -1881,7 +1870,8 @@ rendermon(struct wl_listener *listener, void *data)
|
||||||
* the gamma can not be committed).
|
* the gamma can not be committed).
|
||||||
*/
|
*/
|
||||||
if (m->gamma_lut_changed) {
|
if (m->gamma_lut_changed) {
|
||||||
gamma_control = wlr_gamma_control_manager_v1_get_control(gamma_control_mgr, m->wlr_output);
|
gamma_control
|
||||||
|
= wlr_gamma_control_manager_v1_get_control(gamma_control_mgr, m->wlr_output);
|
||||||
m->gamma_lut_changed = 0;
|
m->gamma_lut_changed = 0;
|
||||||
|
|
||||||
if (!wlr_gamma_control_v1_apply(gamma_control, &pending))
|
if (!wlr_gamma_control_v1_apply(gamma_control, &pending))
|
||||||
|
@ -1905,6 +1895,14 @@ skip:
|
||||||
wlr_output_state_finish(&pending);
|
wlr_output_state_finish(&pending);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
requestdecorationmode(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
Client *c = wl_container_of(listener, c, set_decoration_mode);
|
||||||
|
wlr_xdg_toplevel_decoration_v1_set_mode(c->decoration,
|
||||||
|
WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
requeststartdrag(struct wl_listener *listener, void *data)
|
requeststartdrag(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
|
@ -2035,7 +2033,7 @@ setcursorshape(struct wl_listener *listener, void *data)
|
||||||
* 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)
|
||||||
wlr_cursor_set_xcursor(cursor, cursor_mgr,
|
wlr_cursor_set_xcursor(cursor, cursor_mgr,
|
||||||
wlr_cursor_shape_v1_name(event->shape));
|
wlr_cursor_shape_v1_name(event->shape));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2159,6 +2157,9 @@ 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);
|
||||||
|
@ -2280,7 +2281,7 @@ setup(void)
|
||||||
/* Use decoration protocols to negotiate server-side decorations */
|
/* Use decoration protocols to negotiate server-side decorations */
|
||||||
wlr_server_decoration_manager_set_default_mode(
|
wlr_server_decoration_manager_set_default_mode(
|
||||||
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);
|
||||||
LISTEN_STATIC(&xdg_decoration_mgr->events.new_toplevel_decoration, createdecoration);
|
LISTEN_STATIC(&xdg_decoration_mgr->events.new_toplevel_decoration, createdecoration);
|
||||||
|
|
||||||
|
@ -2323,7 +2324,6 @@ 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_list_init(&keyboards);
|
|
||||||
LISTEN_STATIC(&backend->events.new_input, inputdevice);
|
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);
|
||||||
LISTEN_STATIC(&virtual_keyboard_mgr->events.new_virtual_keyboard, virtualkeyboard);
|
LISTEN_STATIC(&virtual_keyboard_mgr->events.new_virtual_keyboard, virtualkeyboard);
|
||||||
|
@ -2334,6 +2334,53 @@ 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);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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(
|
||||||
|
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);
|
||||||
LISTEN_STATIC(&output_mgr->events.test, outputmgrtest);
|
LISTEN_STATIC(&output_mgr->events.test, outputmgrtest);
|
||||||
|
@ -2345,8 +2392,7 @@ setup(void)
|
||||||
* Initialise the XWayland X server.
|
* Initialise the XWayland X server.
|
||||||
* It will be started when the first X client is started.
|
* It will be started when the first X client is started.
|
||||||
*/
|
*/
|
||||||
xwayland = wlr_xwayland_create(dpy, compositor, 1);
|
if ((xwayland = wlr_xwayland_create(dpy, compositor, 1))) {
|
||||||
if (xwayland) {
|
|
||||||
LISTEN_STATIC(&xwayland->events.ready, xwaylandready);
|
LISTEN_STATIC(&xwayland->events.ready, xwaylandready);
|
||||||
LISTEN_STATIC(&xwayland->events.new_surface, createnotifyx11);
|
LISTEN_STATIC(&xwayland->events.new_surface, createnotifyx11);
|
||||||
|
|
||||||
|
@ -2455,10 +2501,7 @@ toggletag(const Arg *arg)
|
||||||
{
|
{
|
||||||
uint32_t newtags;
|
uint32_t newtags;
|
||||||
Client *sel = focustop(selmon);
|
Client *sel = focustop(selmon);
|
||||||
if (!sel)
|
if (!sel || !(newtags = sel->tags ^ (arg->ui & TAGMASK)))
|
||||||
return;
|
|
||||||
newtags = sel->tags ^ (arg->ui & TAGMASK);
|
|
||||||
if (!newtags)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sel->tags = newtags;
|
sel->tags = newtags;
|
||||||
|
@ -2470,9 +2513,8 @@ toggletag(const Arg *arg)
|
||||||
void
|
void
|
||||||
toggleview(const Arg *arg)
|
toggleview(const Arg *arg)
|
||||||
{
|
{
|
||||||
uint32_t newtagset = selmon ? selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK) : 0;
|
uint32_t newtagset;
|
||||||
|
if (!(newtagset = selmon ? selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK) : 0))
|
||||||
if (!newtagset)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
selmon->tagset[selmon->seltags] = newtagset;
|
selmon->tagset[selmon->seltags] = newtagset;
|
||||||
|
@ -2540,8 +2582,8 @@ updatemons(struct wl_listener *listener, void *data)
|
||||||
* positions, focus, and the stored configuration in wlroots'
|
* positions, focus, and the stored configuration in wlroots'
|
||||||
* output-manager implementation.
|
* output-manager implementation.
|
||||||
*/
|
*/
|
||||||
struct wlr_output_configuration_v1 *config =
|
struct wlr_output_configuration_v1 *config
|
||||||
wlr_output_configuration_v1_create();
|
= wlr_output_configuration_v1_create();
|
||||||
Client *c;
|
Client *c;
|
||||||
struct wlr_output_configuration_head_v1 *config_head;
|
struct wlr_output_configuration_head_v1 *config_head;
|
||||||
Monitor *m;
|
Monitor *m;
|
||||||
|
@ -2609,9 +2651,10 @@ updatemons(struct wl_listener *listener, void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selmon && selmon->wlr_output->enabled) {
|
if (selmon && selmon->wlr_output->enabled) {
|
||||||
wl_list_for_each(c, &clients, link)
|
wl_list_for_each(c, &clients, link) {
|
||||||
if (!c->mon && client_surface(c)->mapped)
|
if (!c->mon && client_surface(c)->mapped)
|
||||||
setmon(c, selmon, c->tags);
|
setmon(c, selmon, c->tags);
|
||||||
|
}
|
||||||
focusclient(focustop(selmon), 1);
|
focusclient(focustop(selmon), 1);
|
||||||
if (selmon->lock_surface) {
|
if (selmon->lock_surface) {
|
||||||
client_notify_enter(selmon->lock_surface->surface,
|
client_notify_enter(selmon->lock_surface->surface,
|
||||||
|
@ -2671,7 +2714,12 @@ 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 *keyboard = data;
|
||||||
createkeyboard(&keyboard->keyboard);
|
/* 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);
|
||||||
|
|
||||||
|
/* Add the new keyboard to the group */
|
||||||
|
wlr_keyboard_group_add_keyboard(vkb_group.wlr_group, &keyboard->keyboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
Monitor *
|
Monitor *
|
||||||
|
@ -2722,12 +2770,13 @@ zoom(const Arg *arg)
|
||||||
|
|
||||||
/* Search for the first tiled window that is not sel, marking sel as
|
/* Search for the first tiled window that is not sel, marking sel as
|
||||||
* NULL if we pass it along the way */
|
* NULL if we pass it along the way */
|
||||||
wl_list_for_each(c, &clients, link)
|
wl_list_for_each(c, &clients, link) {
|
||||||
if (VISIBLEON(c, selmon) && !c->isfloating) {
|
if (VISIBLEON(c, selmon) && !c->isfloating) {
|
||||||
if (c != sel)
|
if (c != sel)
|
||||||
break;
|
break;
|
||||||
sel = NULL;
|
sel = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Return if no other tiled window was found */
|
/* Return if no other tiled window was found */
|
||||||
if (&c->link == &clients)
|
if (&c->link == &clients)
|
||||||
|
|
Loading…
Reference in a new issue