7 Commits
Author SHA1 Message Date
A Frederick Christensen 52c4fb58ec Revert "Post 0.3 release modification"
This reverts commit 38c7bd7ee8.
Accidental commit intended for a testing repository.
2026-03-01 19:54:28 -06:00
A Frederick Christensen 38c7bd7ee8 Post 0.3 release modification 2026-03-01 19:53:43 -06:00
A Frederick Christensen 6e1bfa86c7 Remove trailing whitespace from README
Adapted from PR #1188 by @diegoviola
2026-03-01 19:15:22 -06:00
A Frederick Christensen e32535cf97 Fix typos -- adapted from PR #1189 by @diegoviola 2026-03-01 19:10:43 -06:00
thanatos f4249db613 Updated README to clarify branch roles
This change effectively reverts DWL to the prior development model, where development of DWL itself happens against the current wlroots release, and changes in anticipation of the next wlroots release are made on a separate branch.
2026-02-21 11:51:17 -07:00
thanatos b2d2b701d7 Corrected README 2026-02-21 11:37:48 -07:00
Thanatos 2c9cb2af1b Bumped to 0.9 for wlroots-0.20.0. Updated cursor image buffer handling for xwayland 2026-02-21 11:33:09 -07:00
10 changed files with 271 additions and 1236 deletions
+7 -90
View File
@@ -1,98 +1,12 @@
# Changelog # Changelog
* [0.9](#0.9) * [Unreleased](#unreleased)
* [0.8](#0.8)
* [0.7](#0.7) * [0.7](#0.7)
* [0.6](#0.6) * [0.6](#0.6)
* [0.5](#0.5) * [0.5](#0.5)
## 0.9 ## Unreleased
### Added
* Add axis mouse bindings ([#652][652])
* Add support for the ext-data-control protocol ([#1184][1184])
* Add support for the ext-foreign-toplevel-list protocol ([#1223][1223])
* Add support for the ext-image-copy-capture and ext-image-capture-source protocols (screensharing) ([#1218][1218], [#1223][1223], [#1224][1224])
* Add support for version 4 of the layer shell protocol (on-demand keyboard interactivity) ([#674][674])
* Add support for wlr-text-input and wlr-input-method protocols (IME) ([#1219][1219])
* Snap windows to edges when moving or resizing them ([#608][608])
[1184]: https://codeberg.org/dwl/dwl/pulls/1184
[1218]: https://codeberg.org/dwl/dwl/pulls/1218
[1219]: https://codeberg.org/dwl/dwl/pulls/1219
[1223]: https://codeberg.org/dwl/dwl/pulls/1223
[1224]: https://codeberg.org/dwl/dwl/pulls/1224
[608]: https://codeberg.org/dwl/dwl/pulls/608
[652]: https://codeberg.org/dwl/dwl/pulls/652
[674]: https://codeberg.org/dwl/dwl/pulls/674
### Changed
* Update wlroots to version 0.20 ([#1218][1218])
* Use modifier-independent key symbols in config.h keybindings ([#1075][1075])
[1075]: https://codeberg.org/dwl/dwl/pulls/1075
[1218]: https://codeberg.org/dwl/dwl/pulls/1218
### Fixed
* Apply a minimum window size of 1x1 ([#1231][1231])
* Close Xwayland submenus when changing tag or focus ([#1233][1233])
* Don't make Firefox draw rounded corners when it is opened ([#d1ebf3c][d1ebf3c])
* Don't send key release events to the wrong client ([#1108][1108])
* Fix a crash when closing mpv ([#1220][1220])
* Fix a crash when destroying an idle-inhibitor ([#1214][1214])
* Fix choppy resizing on newer wlroots ([#1280][1280])
* Fix the position of certain sub-menus in Xwayland applications ([#1232][1232])
* Keep the focused border color on the regular client when opening a layer shell surface like wmenu ([#6013835][6013835])
* Let keybindings focus and tag monitors above and below ([#5fd19fe][5fd19fe])
* Preserve asleep disabled outputs in output config ([#1198][1198])
* Respect size hints ([#4de32d2][4de32d2])
* Set seat capabilities for virtual keyboards and pointers when there is no other input device ([#99cdc9a][99cdc9a])
* Show popups in fullscreen Xwayland applications ([#1fe1b4e][1fe1b4e])
* Show the correct cursor after moving and resizing ([#8ad2c92][8ad2c92])
[1108]: https://codeberg.org/dwl/dwl/pulls/1108
[1198]: https://codeberg.org/dwl/dwl/pulls/1198
[1214]: https://codeberg.org/dwl/dwl/pulls/1214
[1220]: https://codeberg.org/dwl/dwl/pulls/1220
[1231]: https://codeberg.org/dwl/dwl/pulls/1231
[1232]: https://codeberg.org/dwl/dwl/pulls/1232
[1233]: https://codeberg.org/dwl/dwl/pulls/1233
[1280]: https://codeberg.org/dwl/dwl/pulls/1280
[1fe1b4e]: https://codeberg.org/dwl/dwl/commit/1fe1b4e
[4de32d2]: https://codeberg.org/dwl/dwl/commit/4de32d2
[5fd19fe]: https://codeberg.org/dwl/dwl/commit/5fd19fe
[6013835]: https://codeberg.org/dwl/dwl/commit/6013835
[8ad2c92]: https://codeberg.org/dwl/dwl/commit/8ad2c92
[99cdc9a]: https://codeberg.org/dwl/dwl/commit/99cdc9a
[d1ebf3c]: https://codeberg.org/dwl/dwl/commit/d1ebf3c
### Contributors
* A Frederick Christensen
* Alex Denes
* Andrea Chiavazza
* Diego Viola
* Guido Cella
* Leonardo Hernández Hernández
* Peter Hofmann
* Siva Mahadevan
* julmajustus
* klim
* save196
* sewn
* thanatos
## 0.8
### Added ### Added
* Support for the linux-drm-syncobj-v1 protocol ([wlroots!4715][wlroots!4715], [#685][685]) * Support for the linux-drm-syncobj-v1 protocol ([wlroots!4715][wlroots!4715], [#685][685])
@@ -103,12 +17,15 @@
[646]: https://codeberg.org/dwl/dwl/pulls/646 [646]: https://codeberg.org/dwl/dwl/pulls/646
### Changed
### Deprecated
### Removed
### Fixed ### Fixed
* Crash when a client is created while all outputs are disabled. * Crash when a client is created while all outputs are disabled.
### Security
Most changes in this release are not listed. See the commits for details. ### Contributors
## 0.7 ## 0.7
+10 -8
View File
@@ -5,7 +5,7 @@ include config.mk
# flags for compiling # flags for compiling
DWLCPPFLAGS = -I. -DWLR_USE_UNSTABLE -D_POSIX_C_SOURCE=200809L \ DWLCPPFLAGS = -I. -DWLR_USE_UNSTABLE -D_POSIX_C_SOURCE=200809L \
-DVERSION=\"$(VERSION)\" $(XWAYLAND) $(CPPFLAGS) -DVERSION=\"$(VERSION)\" $(XWAYLAND)
DWLDEVCFLAGS = -g -Wpedantic -Wall -Wextra -Wdeclaration-after-statement \ DWLDEVCFLAGS = -g -Wpedantic -Wall -Wextra -Wdeclaration-after-statement \
-Wno-unused-parameter -Wshadow -Wunused-macros -Werror=strict-prototypes \ -Wno-unused-parameter -Wshadow -Wunused-macros -Werror=strict-prototypes \
-Werror=implicit -Werror=return-type -Werror=incompatible-pointer-types \ -Werror=implicit -Werror=return-type -Werror=incompatible-pointer-types \
@@ -17,11 +17,12 @@ DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(WLR_INCS) $(DWLCPPFLAGS) $(DWLDEV
LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(WLR_LIBS) -lm $(LIBS) LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(WLR_LIBS) -lm $(LIBS)
all: dwl all: dwl
dwl: dwl.c client.h config.h ime.h util.h config.mk cursor-shape-v1-protocol.h \ dwl: dwl.o util.o
ext-image-copy-capture-v1-protocol.h \ $(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@
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 \ pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \
wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h
$(CC) dwl.c $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ util.o: util.c util.h
# wayland-scanner is a tool which generates C headers and rigging for Wayland # wayland-scanner is a tool which generates C headers and rigging for Wayland
# protocols, which are specified in XML. wlroots requires you to rig these up # protocols, which are specified in XML. wlroots requires you to rig these up
@@ -32,9 +33,6 @@ WAYLAND_PROTOCOLS = `$(PKG_CONFIG) --variable=pkgdatadir wayland-protocols`
cursor-shape-v1-protocol.h: cursor-shape-v1-protocol.h:
$(WAYLAND_SCANNER) enum-header \ $(WAYLAND_SCANNER) enum-header \
$(WAYLAND_PROTOCOLS)/staging/cursor-shape/cursor-shape-v1.xml $@ $(WAYLAND_PROTOCOLS)/staging/cursor-shape/cursor-shape-v1.xml $@
ext-image-copy-capture-v1-protocol.h:
$(WAYLAND_SCANNER) enum-header \
$(WAYLAND_PROTOCOLS)/staging/ext-image-copy-capture/ext-image-copy-capture-v1.xml $@
pointer-constraints-unstable-v1-protocol.h: pointer-constraints-unstable-v1-protocol.h:
$(WAYLAND_SCANNER) enum-header \ $(WAYLAND_SCANNER) enum-header \
$(WAYLAND_PROTOCOLS)/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml $@ $(WAYLAND_PROTOCOLS)/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml $@
@@ -56,7 +54,7 @@ clean:
dist: clean dist: clean
mkdir -p dwl-$(VERSION) mkdir -p dwl-$(VERSION)
cp -R LICENSE* Makefile CHANGELOG.md README.md client.h config.def.h \ cp -R LICENSE* Makefile CHANGELOG.md README.md client.h config.def.h \
config.mk protocols dwl.1 dwl.c ime.h util.h dwl.desktop \ config.mk protocols dwl.1 dwl.c util.c util.h dwl.desktop \
dwl-$(VERSION) dwl-$(VERSION)
tar -caf dwl-$(VERSION).tar.gz dwl-$(VERSION) tar -caf dwl-$(VERSION).tar.gz dwl-$(VERSION)
rm -rf dwl-$(VERSION) rm -rf dwl-$(VERSION)
@@ -75,3 +73,7 @@ install: dwl
uninstall: uninstall:
rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(MANDIR)/man1/dwl.1 \ rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(MANDIR)/man1/dwl.1 \
$(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop
.SUFFIXES: .c .o
.c.o:
$(CC) $(CPPFLAGS) $(DWLCFLAGS) -o $@ -c $<
+5 -5
View File
@@ -10,7 +10,7 @@ primarily in terms of functionality, and secondarily in terms of
philosophy. Like [dwm], dwl is: philosophy. Like [dwm], dwl is:
- Easy to understand, hack on, and extend with patches - Easy to understand, hack on, and extend with patches
- One C source file configurable via `config.h` - One C source file (or a very small number) configurable via `config.h`
- Tied to as few external dependencies as possible - Tied to as few external dependencies as possible
## Getting Started: ## Getting Started:
@@ -153,6 +153,7 @@ given the base on which it is built. Implemented default features are:
- Support screen lockers via ext-session-lock-v1 protocol - Support screen lockers via ext-session-lock-v1 protocol
- Various Wayland protocols - Various Wayland protocols
- XWayland support as provided by wlroots (can be enabled in `config.mk`) - XWayland support as provided by wlroots (can be enabled in `config.mk`)
- Zero flickering - Wayland users naturally expect that "every frame is perfect"
- Layer shell popups (used by Waybar) - Layer shell popups (used by Waybar)
- Damage tracking provided by scenegraph API - Damage tracking provided by scenegraph API
@@ -165,6 +166,9 @@ indiscriminately. We will try to keep the code as small as possible.
Features under consideration (possibly as patches) are: Features under consideration (possibly as patches) are:
- Protocols made trivial by wlroots - Protocols made trivial by wlroots
- Implement the text-input and input-method protocols to support IME once ibus
implements input-method v2 (see https://github.com/ibus/ibus/pull/2256 and
https://codeberg.org/dwl/dwl/pulls/235)
Feature *non-goals* for the main codebase include: Feature *non-goals* for the main codebase include:
@@ -189,10 +193,6 @@ inspiration, and to the various contributors to the project, including:
and for helping to keep the project running and for helping to keep the project running
- Stivvo for output management and fullscreen support, and patch maintenance - Stivvo for output management and fullscreen support, and patch maintenance
Also, thanks to our current lead developers:
- @thanatos
- @guidocella
[wlroots]: https://gitlab.freedesktop.org/wlroots [wlroots]: https://gitlab.freedesktop.org/wlroots
[dwm]: https://dwm.suckless.org/ [dwm]: https://dwm.suckless.org/
+21 -48
View File
@@ -15,32 +15,6 @@ client_is_x11(Client *c)
return 0; return 0;
} }
static inline void
client_get_size_hints(Client *c, struct wlr_box *max, struct wlr_box *min)
{
struct wlr_xdg_toplevel_state *state;
#ifdef XWAYLAND
if (client_is_x11(c)) {
xcb_size_hints_t *size_hints = c->surface.xwayland->size_hints;
if (size_hints) {
max->width = size_hints->max_width;
max->height = size_hints->max_height;
min->width = size_hints->min_width;
min->height = size_hints->min_height;
}
return;
}
#endif
state = &c->surface.xdg->toplevel->current;
max->width = state->max_width;
max->height = state->max_height;
min->width = state->min_width;
min->height = state->min_height;
}
static inline struct wlr_surface * static inline struct wlr_surface *
client_surface(Client *c) client_surface(Client *c)
{ {
@@ -232,12 +206,13 @@ client_get_title(Client *c)
static inline int static inline int
client_is_float_type(Client *c) client_is_float_type(Client *c)
{ {
struct wlr_box min = {0}, max = {0}; struct wlr_xdg_toplevel *toplevel;
client_get_size_hints(c, &max, &min); struct wlr_xdg_toplevel_state state;
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) { if (client_is_x11(c)) {
struct wlr_xwayland_surface *surface = c->surface.xwayland; struct wlr_xwayland_surface *surface = c->surface.xwayland;
xcb_size_hints_t *size_hints = surface->size_hints;
if (surface->modal) if (surface->modal)
return 1; return 1;
@@ -248,13 +223,17 @@ client_is_float_type(Client *c)
return 1; return 1;
} }
return min.width > 0 && min.height > 0 && return size_hints && size_hints->min_width > 0 && size_hints->min_height > 0
(min.width == max.width || min.height == max.height); && (size_hints->max_width == size_hints->min_width
|| size_hints->max_height == size_hints->min_height);
} }
#endif #endif
return c->surface.xdg->toplevel->parent || (min.width > 0 && min.height > 0 && toplevel = c->surface.xdg->toplevel;
(min.width == max.width || min.height == max.height)); state = toplevel->current;
return toplevel->parent || (state.min_width != 0 && state.min_height != 0
&& (state.min_width == state.max_width
|| state.min_height == state.max_height));
} }
static inline int static inline int
@@ -312,18 +291,11 @@ client_is_unmanaged(Client *c)
static inline void static inline void
client_notify_enter(struct wlr_surface *s, struct wlr_keyboard *kb) client_notify_enter(struct wlr_surface *s, struct wlr_keyboard *kb)
{ {
uint32_t filtered[WLR_KEYBOARD_KEYS_CAP]; if (kb)
size_t size = 0; wlr_seat_keyboard_notify_enter(seat, s, kb->keycodes,
if (!kb) { kb->num_keycodes, &kb->modifiers);
else
wlr_seat_keyboard_notify_enter(seat, s, NULL, 0, NULL); wlr_seat_keyboard_notify_enter(seat, s, NULL, 0, NULL);
return;
}
for (size_t i = 0; i < kb->num_keycodes; i++) {
uint32_t key = kb->keycodes[i];
if (!consumed[key])
filtered[size++] = key;
}
wlr_seat_keyboard_notify_enter(seat, s, filtered, size, &kb->modifiers);
} }
static inline void static inline void
@@ -365,19 +337,20 @@ client_set_scale(struct wlr_surface *s, float scale)
wlr_surface_set_preferred_buffer_scale(s, (int32_t)ceilf(scale)); wlr_surface_set_preferred_buffer_scale(s, (int32_t)ceilf(scale));
} }
static inline void static inline uint32_t
client_set_size(Client *c, uint32_t width, uint32_t height) client_set_size(Client *c, uint32_t width, uint32_t height)
{ {
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) { if (client_is_x11(c)) {
wlr_xwayland_surface_configure(c->surface.xwayland, wlr_xwayland_surface_configure(c->surface.xwayland,
c->geom.x + c->bw, c->geom.y + c->bw, width, height); c->geom.x + c->bw, c->geom.y + c->bw, width, height);
return; return 0;
} }
#endif #endif
if ((int32_t)width != c->surface.xdg->toplevel->current.width if ((int32_t)width == c->surface.xdg->toplevel->current.width
|| (int32_t)height != c->surface.xdg->toplevel->current.height) && (int32_t)height == c->surface.xdg->toplevel->current.height)
wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, (int32_t)width, (int32_t)height); return 0;
return wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, (int32_t)width, (int32_t)height);
} }
static inline void static inline void
+18 -23
View File
@@ -7,7 +7,6 @@
static const int sloppyfocus = 1; /* focus follows mouse */ static const int sloppyfocus = 1; /* focus follows mouse */
static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */
static const unsigned int borderpx = 1; /* border pixel of windows */ static const unsigned int borderpx = 1; /* border pixel of windows */
static const unsigned int snap = 32; /* snap pixel */
static const float rootcolor[] = COLOR(0x222222ff); static const float rootcolor[] = COLOR(0x222222ff);
static const float bordercolor[] = COLOR(0x444444ff); static const float bordercolor[] = COLOR(0x444444ff);
static const float focuscolor[] = COLOR(0x005577ff); static const float focuscolor[] = COLOR(0x005577ff);
@@ -106,11 +105,11 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA
/* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */ /* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */
#define MODKEY WLR_MODIFIER_ALT #define MODKEY WLR_MODIFIER_ALT
#define TAGKEYS(KEY,TAG) \ #define TAGKEYS(KEY,SKEY,TAG) \
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \ { MODKEY, KEY, view, {.ui = 1 << TAG} }, \
{ MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \ { MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \
{ MODKEY|WLR_MODIFIER_SHIFT, KEY, tag, {.ui = 1 << TAG} }, \ { MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \
{ MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,KEY,toggletag, {.ui = 1 << TAG} } { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} }
/* helper for spawning shell commands in the pre dwm-5.0 fashion */ /* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
@@ -120,6 +119,7 @@ static const char *termcmd[] = { "foot", NULL };
static const char *menucmd[] = { "wmenu-run", NULL }; static const char *menucmd[] = { "wmenu-run", NULL };
static const Key keys[] = { static const Key keys[] = {
/* Note that Shift changes certain key codes: 2 -> at, etc. */
/* modifier key function argument */ /* modifier key function argument */
{ MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} },
@@ -139,28 +139,28 @@ static const Key keys[] = {
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} }, { MODKEY, XKB_KEY_e, togglefullscreen, {0} },
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} }, { MODKEY, XKB_KEY_0, view, {.ui = ~0} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_0, tag, {.ui = ~0} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
{ MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_comma, tagmon, {.i = WLR_DIRECTION_LEFT} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_period, tagmon, {.i = WLR_DIRECTION_RIGHT} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} },
TAGKEYS( XKB_KEY_1, 0), TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0),
TAGKEYS( XKB_KEY_2, 1), TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1),
TAGKEYS( XKB_KEY_3, 2), TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2),
TAGKEYS( XKB_KEY_4, 3), TAGKEYS( XKB_KEY_4, XKB_KEY_dollar, 3),
TAGKEYS( XKB_KEY_5, 4), TAGKEYS( XKB_KEY_5, XKB_KEY_percent, 4),
TAGKEYS( XKB_KEY_6, 5), TAGKEYS( XKB_KEY_6, XKB_KEY_asciicircum, 5),
TAGKEYS( XKB_KEY_7, 6), TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6),
TAGKEYS( XKB_KEY_8, 7), TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7),
TAGKEYS( XKB_KEY_9, 8), TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8),
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_q, quit, {0} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_q, quit, {0} },
/* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */ /* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */
{ WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_BackSpace, quit, {0} }, { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} },
/* Ctrl-Alt-Fx is used to switch to another VT, if you don't know what a VT is /* Ctrl-Alt-Fx is used to switch to another VT, if you don't know what a VT is
* do not remove them. * do not remove them.
*/ */
#define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_F##n, chvt, {.ui = (n)} } #define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_XF86Switch_VT_##n, chvt, {.ui = (n)} }
CHVT(1), CHVT(2), CHVT(3), CHVT(4), CHVT(5), CHVT(6), CHVT(1), CHVT(2), CHVT(3), CHVT(4), CHVT(5), CHVT(6),
CHVT(7), CHVT(8), CHVT(9), CHVT(10), CHVT(11), CHVT(12), CHVT(7), CHVT(8), CHVT(9), CHVT(10), CHVT(11), CHVT(12),
}; };
@@ -170,8 +170,3 @@ static const Button buttons[] = {
{ MODKEY, BTN_MIDDLE, togglefloating, {0} }, { MODKEY, BTN_MIDDLE, togglefloating, {0} },
{ MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, { MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} },
}; };
static const Axis axes[] = {
{ MODKEY, AxisUp, spawn, SHCMD("volume-up_EXAMPLE") },
{ MODKEY, AxisDown, spawn, SHCMD("volume-down_EXAMPLE") },
};
+5 -5
View File
@@ -1,4 +1,4 @@
_VERSION = 0.10-dev _VERSION = 0.9-dev
VERSION = `git describe --tags --dirty 2>/dev/null || echo $(_VERSION)` VERSION = `git describe --tags --dirty 2>/dev/null || echo $(_VERSION)`
PKG_CONFIG = pkg-config PKG_CONFIG = pkg-config
@@ -17,12 +17,12 @@ WLR_LIBS = `$(PKG_CONFIG) --libs wlroots-0.20`
#WLR_INCS = -I/usr/include/pixman-1 -I/usr/include/elogind -I/usr/include/libdrm \ #WLR_INCS = -I/usr/include/pixman-1 -I/usr/include/elogind -I/usr/include/libdrm \
# -I$(PWD)/wlroots/include # -I$(PWD)/wlroots/include
# Set -rpath to avoid using the wrong library. # Set -rpath to avoid using the wrong library.
#WLR_LIBS = -Wl,-rpath,$(PWD)/wlroots/build -L$(PWD)/wlroots/build -lwlroots-0.20 #WLR_LIBS = -Wl,-rpath,$(PWD)/wlroots/build -L$(PWD)/wlroots/build -lwlroots-0.19
# Assuming you ran "meson setup --prefix ${PWD}/0.20 build && ninja -C build install" # Assuming you ran "meson setup --prefix ${PWD}/0.19 build && ninja -C build install"
#WLR_INCS = -I/usr/include/pixman-1 -I/usr/include/elogind -I/usr/include/libdrm \ #WLR_INCS = -I/usr/include/pixman-1 -I/usr/include/elogind -I/usr/include/libdrm \
# -I$(PWD)/wlroots/0.20/include/wlroots-0.20 # -I$(PWD)/wlroots/0.19/include/wlroots-0.19
#WLR_LIBS = -Wl,-rpath,$(PWD)/wlroots/0.20/lib64 -L$(PWD)/wlroots/0.20/lib64 -lwlroots-0.20 #WLR_LIBS = -Wl,-rpath,$(PWD)/wlroots/0.19/lib64 -L$(PWD)/wlroots/0.19/lib64 -lwlroots-0.19
XWAYLAND = XWAYLAND =
XLIBS = XLIBS =
+145 -344
View File
File diff suppressed because it is too large Load Diff
-639
View File
@@ -1,639 +0,0 @@
#include <wlr/types/wlr_input_method_v2.h>
#include <wlr/types/wlr_text_input_v3.h>
struct input_method_relay {
struct wl_list text_inputs; /* struct text_input.link */
struct wlr_input_method_v2 *input_method;
struct wlr_surface *focused_surface;
struct text_input *active_text_input;
struct wl_list popups; /* input_method_popup.link */
struct wlr_scene_tree *popup_tree;
struct wl_listener new_text_input;
struct wl_listener new_input_method;
struct wl_listener input_method_commit;
struct wl_listener input_method_grab_keyboard;
struct wl_listener input_method_destroy;
struct wl_listener input_method_new_popup_surface;
struct wl_listener keyboard_grab_destroy;
struct wl_listener focused_surface_destroy;
};
struct input_method_popup {
struct wlr_input_popup_surface_v2 *popup_surface;
struct wlr_scene_tree *tree;
struct wlr_scene_tree *scene_surface;
struct input_method_relay *relay;
struct wl_list link; /* input_method_relay.popups */
struct wl_listener destroy;
struct wl_listener commit;
};
struct text_input {
struct input_method_relay *relay;
struct wlr_text_input_v3 *input;
struct wl_list link;
struct wl_listener enable;
struct wl_listener commit;
struct wl_listener disable;
struct wl_listener destroy;
};
struct wlr_input_method_manager_v2 *input_method_manager;
struct wlr_text_input_manager_v3 *text_input_manager;
struct input_method_relay *input_method_relay;
/* functions used in dwl.c */
static int input_method_keyboard_grab_forward_key(
KeyboardGroup *keyboard, struct wlr_keyboard_key_event *event);
static int input_method_keyboard_grab_forward_modifiers(KeyboardGroup *keyboard);
static struct input_method_relay *input_method_relay_create(void);
static void input_method_relay_finish(struct input_method_relay *relay);
static void input_method_relay_set_focus(struct input_method_relay *relay,
struct wlr_surface *surface);
/* internal functions */
static struct text_input *get_active_text_input(struct input_method_relay *relay);
static struct wlr_input_method_keyboard_grab_v2 *get_keyboard_grab(KeyboardGroup *keyboard);
static int keyboard_is_emulated_by_input_method(struct wlr_keyboard *keyboard,
struct wlr_input_method_v2 *input_method);
static void handle_focused_surface_destroy(struct wl_listener *listener, void *data);
static void handle_input_method_commit(struct wl_listener *listener, void *data);
static void handle_input_method_destroy(struct wl_listener *listener, void *data);
static void handle_input_method_grab_keyboard(struct wl_listener *listener, void *data);
static void handle_input_method_new_popup_surface(struct wl_listener *listener, void *data);
static void handle_keyboard_grab_destroy(struct wl_listener *listener, void *data);
static void handle_new_input_method(struct wl_listener *listener, void *data);
static void handle_new_text_input(struct wl_listener *listener, void *data);
static void handle_popup_surface_commit(struct wl_listener *listener, void *data);
static void handle_popup_surface_destroy(struct wl_listener *listener, void *data);
static void handle_text_input_commit(struct wl_listener *listener, void *data);
static void handle_text_input_destroy(struct wl_listener *listener, void *data);
static void handle_text_input_disable(struct wl_listener *listener, void *data);
static void handle_text_input_enable(struct wl_listener *listener, void *data);
static Monitor *output_from_wlr_output(struct wlr_output *wlr_output);
static Monitor *output_nearest_to(int lx, int ly);
static void send_state_to_input_method(struct input_method_relay *relay);
static void update_active_text_input(struct input_method_relay *relay);
static void update_popup_position(struct input_method_popup *popup);
static void update_popups_position(struct input_method_relay *relay);
static void update_text_inputs_focused_surface(struct input_method_relay *relay);
Monitor *
output_from_wlr_output(struct wlr_output *wlr_output)
{
Monitor *m = NULL;
wl_list_for_each(m, &mons, link) {
if (m->wlr_output == wlr_output)
return m;
}
return NULL;
}
Monitor *
output_nearest_to(int lx, int ly)
{
double closest_x, closest_y;
wlr_output_layout_closest_point(output_layout, NULL, lx, ly, &closest_x,
&closest_y);
return output_from_wlr_output(
wlr_output_layout_output_at(output_layout, closest_x, closest_y));
}
int
keyboard_is_emulated_by_input_method(struct wlr_keyboard *keyboard,
struct wlr_input_method_v2 *input_method)
{
struct wlr_virtual_keyboard_v1 *virtual_keyboard;
if (!keyboard || !input_method)
return 0;
virtual_keyboard = wlr_input_device_get_virtual_keyboard(&keyboard->base);
return virtual_keyboard &&
wl_resource_get_client(virtual_keyboard->resource) ==
wl_resource_get_client(input_method->resource);
}
struct wlr_input_method_keyboard_grab_v2 *
get_keyboard_grab(KeyboardGroup *keyboard)
{
struct wlr_input_method_v2 *input_method = input_method_relay->input_method;
if (!input_method || !input_method->keyboard_grab || keyboard != kb_group ||
keyboard_is_emulated_by_input_method(keyboard->virtual_keyboard,
input_method))
return NULL;
return input_method->keyboard_grab;
}
int
input_method_keyboard_grab_forward_modifiers(KeyboardGroup *keyboard)
{
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab =
get_keyboard_grab(keyboard);
struct wlr_keyboard_modifiers *modifiers =
&keyboard->wlr_group->keyboard.modifiers;
if (keyboard_grab) {
wlr_input_method_keyboard_grab_v2_set_keyboard(
keyboard_grab, &keyboard->wlr_group->keyboard);
wlr_input_method_keyboard_grab_v2_send_modifiers(keyboard_grab, modifiers);
return 1;
} else {
return 0;
}
}
int
input_method_keyboard_grab_forward_key(
KeyboardGroup *keyboard, struct wlr_keyboard_key_event *event)
{
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab =
get_keyboard_grab(keyboard);
if (keyboard_grab) {
wlr_input_method_keyboard_grab_v2_set_keyboard(
keyboard_grab, &keyboard->wlr_group->keyboard);
wlr_input_method_keyboard_grab_v2_send_key(keyboard_grab, event->time_msec,
event->keycode, event->state);
return 1;
} else {
return 0;
}
}
struct text_input *
get_active_text_input(struct input_method_relay *relay)
{
struct text_input *text_input;
if (!relay->input_method)
return NULL;
wl_list_for_each(text_input, &relay->text_inputs, link) {
if (text_input->input->focused_surface &&
text_input->input->current_enabled)
return text_input;
}
return NULL;
}
void
update_active_text_input(struct input_method_relay *relay)
{
struct text_input *active_text_input = get_active_text_input(relay);
if (relay->input_method && relay->active_text_input != active_text_input) {
if (active_text_input)
wlr_input_method_v2_send_activate(relay->input_method);
else
wlr_input_method_v2_send_deactivate(relay->input_method);
wlr_input_method_v2_send_done(relay->input_method);
}
relay->active_text_input = active_text_input;
}
void
update_text_inputs_focused_surface(struct input_method_relay *relay)
{
struct text_input *text_input;
wl_list_for_each(text_input, &relay->text_inputs, link) {
struct wlr_text_input_v3 *input = text_input->input;
struct wlr_surface *new_focused_surface;
if (relay->input_method && relay->focused_surface &&
wl_resource_get_client(input->resource) ==
wl_resource_get_client(relay->focused_surface->resource)) {
new_focused_surface = relay->focused_surface;
} else {
new_focused_surface = NULL;
}
if (input->focused_surface == new_focused_surface)
continue;
if (input->focused_surface)
wlr_text_input_v3_send_leave(input);
if (new_focused_surface)
wlr_text_input_v3_send_enter(input, new_focused_surface);
}
}
void
update_popup_position(struct input_method_popup *popup)
{
struct input_method_relay *relay = popup->relay;
struct text_input *text_input = relay->active_text_input;
struct wlr_box cursor_rect;
struct wlr_xdg_surface *xdg_surface;
struct wlr_layer_surface_v1 *layer_surface;
struct wlr_scene_tree *tree;
int lx, ly;
Monitor *output;
struct wlr_box output_box;
struct wlr_xdg_positioner_rules positioner_rules;
struct wlr_box popup_box;
if (!text_input || !relay->focused_surface ||
!popup->popup_surface->surface->mapped)
return;
xdg_surface = wlr_xdg_surface_try_from_wlr_surface(relay->focused_surface);
layer_surface = wlr_layer_surface_v1_try_from_wlr_surface(relay->focused_surface);
if ((text_input->input->current.features &
WLR_TEXT_INPUT_V3_FEATURE_CURSOR_RECTANGLE) &&
(xdg_surface || layer_surface)) {
cursor_rect = text_input->input->current.cursor_rectangle;
tree = relay->focused_surface->data;
wlr_scene_node_coords(&tree->node, &lx, &ly);
cursor_rect.x += lx;
cursor_rect.y += ly;
if (xdg_surface) {
cursor_rect.x -= xdg_surface->geometry.x;
cursor_rect.y -= xdg_surface->geometry.y;
}
} else {
cursor_rect = (struct wlr_box){0};
}
output = output_nearest_to(cursor_rect.x, cursor_rect.y);
if (!output || !output->wlr_output->enabled)
return;
wlr_output_layout_get_box(output_layout, output->wlr_output, &output_box);
positioner_rules = (struct wlr_xdg_positioner_rules) {
.anchor_rect = cursor_rect,
.anchor = XDG_POSITIONER_ANCHOR_BOTTOM_LEFT,
.gravity = XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT,
.size =
{
.width = popup->popup_surface->surface->current.width,
.height = popup->popup_surface->surface->current.height,
},
.constraint_adjustment = XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y |
XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X,
};
wlr_xdg_positioner_rules_get_geometry(&positioner_rules, &popup_box);
wlr_xdg_positioner_rules_unconstrain_box(&positioner_rules, &output_box, &popup_box);
wlr_scene_node_set_position(&popup->tree->node, popup_box.x, popup_box.y);
wlr_scene_node_raise_to_top(&relay->popup_tree->node);
wlr_input_popup_surface_v2_send_text_input_rectangle(
popup->popup_surface, &(struct wlr_box){
.x = cursor_rect.x - popup_box.x,
.y = cursor_rect.y - popup_box.y,
.width = cursor_rect.width,
.height = cursor_rect.height,
});
}
void
update_popups_position(struct input_method_relay *relay)
{
struct input_method_popup *popup;
wl_list_for_each(popup, &relay->popups, link) {
update_popup_position(popup);
}
}
void
handle_input_method_commit(struct wl_listener *listener,
void *data)
{
struct input_method_relay *relay =
wl_container_of(listener, relay, input_method_commit);
struct wlr_input_method_v2 *input_method = relay->input_method;
struct text_input *text_input = relay->active_text_input;
if (!text_input)
return;
if (input_method->current.preedit.text) {
wlr_text_input_v3_send_preedit_string(text_input->input,
input_method->current.preedit.text,
input_method->current.preedit.cursor_begin,
input_method->current.preedit.cursor_end);
}
if (input_method->current.commit_text) {
wlr_text_input_v3_send_commit_string(text_input->input,
input_method->current.commit_text);
}
if (input_method->current.delete.before_length ||
input_method->current.delete.after_length) {
wlr_text_input_v3_send_delete_surrounding_text(text_input->input,
input_method->current.delete.before_length,
input_method->current.delete.after_length);
}
wlr_text_input_v3_send_done(text_input->input);
}
void
handle_keyboard_grab_destroy(struct wl_listener *listener,
void *data)
{
struct input_method_relay *relay =
wl_container_of(listener, relay, keyboard_grab_destroy);
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab =
relay->input_method->keyboard_grab;
wl_list_remove(&relay->keyboard_grab_destroy.link);
if (keyboard_grab->keyboard) {
/* Send modifier state to original client */
wlr_seat_keyboard_notify_modifiers(keyboard_grab->input_method->seat,
&keyboard_grab->keyboard->modifiers);
}
}
void
handle_input_method_grab_keyboard(struct wl_listener *listener,
void *data)
{
struct input_method_relay *relay =
wl_container_of(listener, relay, input_method_grab_keyboard);
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
struct wlr_keyboard *active_keyboard = &kb_group->wlr_group->keyboard;
if (!keyboard_is_emulated_by_input_method(active_keyboard,
relay->input_method)) {
/* Send modifier state to grab */
wlr_input_method_keyboard_grab_v2_set_keyboard(keyboard_grab,
active_keyboard);
}
relay->keyboard_grab_destroy.notify = handle_keyboard_grab_destroy;
wl_signal_add(&keyboard_grab->events.destroy, &relay->keyboard_grab_destroy);
}
void
handle_input_method_destroy(struct wl_listener *listener,
void *data)
{
struct input_method_relay *relay =
wl_container_of(listener, relay, input_method_destroy);
wl_list_remove(&relay->input_method_commit.link);
wl_list_remove(&relay->input_method_grab_keyboard.link);
wl_list_remove(&relay->input_method_new_popup_surface.link);
wl_list_remove(&relay->input_method_destroy.link);
relay->input_method = NULL;
update_text_inputs_focused_surface(relay);
update_active_text_input(relay);
}
void
handle_popup_surface_destroy(struct wl_listener *listener,
void *data)
{
struct input_method_popup *popup = wl_container_of(listener, popup, destroy);
wlr_scene_node_destroy(&popup->tree->node);
wl_list_remove(&popup->destroy.link);
wl_list_remove(&popup->commit.link);
wl_list_remove(&popup->link);
free(popup);
}
void
handle_popup_surface_commit(struct wl_listener *listener,
void *data)
{
struct input_method_popup *popup = wl_container_of(listener, popup, commit);
update_popup_position(popup);
}
void
handle_input_method_new_popup_surface(struct wl_listener *listener,
void *data)
{
struct input_method_relay *relay =
wl_container_of(listener, relay, input_method_new_popup_surface);
struct input_method_popup *popup = ecalloc(1, sizeof(*popup));
popup->popup_surface = data;
popup->relay = relay;
popup->destroy.notify = handle_popup_surface_destroy;
wl_signal_add(&popup->popup_surface->events.destroy, &popup->destroy);
popup->commit.notify = handle_popup_surface_commit;
wl_signal_add(&popup->popup_surface->surface->events.commit, &popup->commit);
popup->tree = wlr_scene_tree_create(layers[LyrIMPopup]);
popup->scene_surface = wlr_scene_subsurface_tree_create(
popup->tree, popup->popup_surface->surface);
popup->scene_surface->node.data = popup;
wl_list_insert(&relay->popups, &popup->link);
update_popup_position(popup);
}
void
handle_new_input_method(struct wl_listener *listener, void *data)
{
struct input_method_relay *relay =
wl_container_of(listener, relay, new_input_method);
struct wlr_input_method_v2 *input_method = data;
if (seat != input_method->seat)
return;
if (relay->input_method) {
wlr_input_method_v2_send_unavailable(input_method);
return;
}
relay->input_method = input_method;
relay->input_method_commit.notify = handle_input_method_commit;
wl_signal_add(&relay->input_method->events.commit,
&relay->input_method_commit);
relay->input_method_grab_keyboard.notify = handle_input_method_grab_keyboard;
wl_signal_add(&relay->input_method->events.grab_keyboard,
&relay->input_method_grab_keyboard);
relay->input_method_destroy.notify = handle_input_method_destroy;
wl_signal_add(&relay->input_method->events.destroy,
&relay->input_method_destroy);
relay->input_method_new_popup_surface.notify =
handle_input_method_new_popup_surface;
wl_signal_add(&relay->input_method->events.new_popup_surface,
&relay->input_method_new_popup_surface);
update_text_inputs_focused_surface(relay);
update_active_text_input(relay);
}
void
send_state_to_input_method(struct input_method_relay *relay)
{
struct wlr_input_method_v2 *input_method = relay->input_method;
struct wlr_text_input_v3 *input = relay->active_text_input->input;
if (input->active_features & WLR_TEXT_INPUT_V3_FEATURE_SURROUNDING_TEXT) {
wlr_input_method_v2_send_surrounding_text(input_method,
input->current.surrounding.text,
input->current.surrounding.cursor,
input->current.surrounding.anchor);
}
wlr_input_method_v2_send_text_change_cause(input_method,
input->current.text_change_cause);
if (input->active_features & WLR_TEXT_INPUT_V3_FEATURE_CONTENT_TYPE) {
wlr_input_method_v2_send_content_type(input_method,
input->current.content_type.hint,
input->current.content_type.purpose);
}
wlr_input_method_v2_send_done(input_method);
}
void
handle_text_input_enable(struct wl_listener *listener, void *data)
{
struct text_input *text_input = wl_container_of(listener, text_input, enable);
struct input_method_relay *relay = text_input->relay;
update_active_text_input(relay);
if (relay->active_text_input == text_input) {
update_popups_position(relay);
send_state_to_input_method(relay);
}
wlr_text_input_v3_send_done(text_input->input);
}
void
handle_text_input_disable(struct wl_listener *listener,
void *data)
{
struct text_input *text_input =
wl_container_of(listener, text_input, disable);
update_active_text_input(text_input->relay);
}
void
handle_text_input_commit(struct wl_listener *listener, void *data)
{
struct text_input *text_input = wl_container_of(listener, text_input, commit);
struct input_method_relay *relay = text_input->relay;
if (relay->active_text_input == text_input) {
update_popups_position(relay);
send_state_to_input_method(relay);
}
}
void
handle_text_input_destroy(struct wl_listener *listener,
void *data)
{
struct text_input *text_input =
wl_container_of(listener, text_input, destroy);
wl_list_remove(&text_input->enable.link);
wl_list_remove(&text_input->disable.link);
wl_list_remove(&text_input->commit.link);
wl_list_remove(&text_input->destroy.link);
wl_list_remove(&text_input->link);
update_active_text_input(text_input->relay);
free(text_input);
}
void
handle_new_text_input(struct wl_listener *listener, void *data)
{
struct input_method_relay *relay =
wl_container_of(listener, relay, new_text_input);
struct wlr_text_input_v3 *wlr_text_input = data;
struct text_input *text_input;
if (seat != wlr_text_input->seat)
return;
text_input = ecalloc(1, sizeof(*text_input));
text_input->input = wlr_text_input;
text_input->relay = relay;
wl_list_insert(&relay->text_inputs, &text_input->link);
text_input->enable.notify = handle_text_input_enable;
wl_signal_add(&text_input->input->events.enable, &text_input->enable);
text_input->disable.notify = handle_text_input_disable;
wl_signal_add(&text_input->input->events.disable, &text_input->disable);
text_input->commit.notify = handle_text_input_commit;
wl_signal_add(&text_input->input->events.commit, &text_input->commit);
text_input->destroy.notify = handle_text_input_destroy;
wl_signal_add(&text_input->input->events.destroy, &text_input->destroy);
update_text_inputs_focused_surface(relay);
}
void
handle_focused_surface_destroy(struct wl_listener *listener,
void *data)
{
struct input_method_relay *relay =
wl_container_of(listener, relay, focused_surface_destroy);
input_method_relay_set_focus(relay, NULL);
}
struct input_method_relay *
input_method_relay_create()
{
struct input_method_relay *relay = ecalloc(1, sizeof(*relay));
wl_list_init(&relay->text_inputs);
wl_list_init(&relay->popups);
relay->popup_tree = wlr_scene_tree_create(&scene->tree);
relay->new_text_input.notify = handle_new_text_input;
wl_signal_add(&text_input_manager->events.new_text_input, &relay->new_text_input);
relay->new_input_method.notify = handle_new_input_method;
wl_signal_add(&input_method_manager->events.new_input_method,
&relay->new_input_method);
relay->focused_surface_destroy.notify = handle_focused_surface_destroy;
return relay;
}
void
input_method_relay_finish(struct input_method_relay *relay)
{
wl_list_remove(&relay->new_text_input.link);
wl_list_remove(&relay->new_input_method.link);
free(relay);
}
void
input_method_relay_set_focus(struct input_method_relay *relay,
struct wlr_surface *surface)
{
if (!relay || relay->focused_surface == surface)
return;
if (relay->focused_surface)
wl_list_remove(&relay->focused_surface_destroy.link);
relay->focused_surface = surface;
if (surface)
wl_signal_add(&surface->events.destroy, &relay->focused_surface_destroy);
update_text_inputs_focused_surface(relay);
update_active_text_input(relay);
}
+51
View File
@@ -0,0 +1,51 @@
/* See LICENSE.dwm file for copyright and license details. */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include "util.h"
void
die(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
fputc(' ', stderr);
perror(NULL);
} else {
fputc('\n', stderr);
}
exit(1);
}
void *
ecalloc(size_t nmemb, size_t size)
{
void *p;
if (!(p = calloc(nmemb, size)))
die("calloc:");
return p;
}
int
fd_set_nonblock(int fd) {
int flags = fcntl(fd, F_GETFL);
if (flags < 0) {
perror("fcntl(F_GETFL):");
return -1;
}
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
perror("fcntl(F_SETFL):");
return -1;
}
return 0;
}
+3 -68
View File
@@ -1,70 +1,5 @@
/* See LICENSE.dwm file for copyright and license details. */ /* See LICENSE.dwm file for copyright and license details. */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <xkbcommon/xkbcommon.h>
#define MAX(A, B) ((A) > (B) ? (A) : (B)) void die(const char *fmt, ...);
#define MIN(A, B) ((A) < (B) ? (A) : (B)) void *ecalloc(size_t nmemb, size_t size);
#define LENGTH(X) (sizeof X / sizeof X[0]) int fd_set_nonblock(int fd);
#define END(A) ((A) + LENGTH(A))
static void die(const char *fmt, ...);
static void *ecalloc(size_t nmemb, size_t size);
static int fd_set_nonblock(int fd);
xkb_keysym_t keymap_get_one_sym_by_level(struct xkb_keymap *keymap,
xkb_keycode_t key, xkb_layout_index_t layout, xkb_level_index_t level);
void
die(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
fputc(' ', stderr);
perror(NULL);
} else {
fputc('\n', stderr);
}
exit(1);
}
void *
ecalloc(size_t nmemb, size_t size)
{
void *p;
if (!(p = calloc(nmemb, size)))
die("calloc:");
return p;
}
int
fd_set_nonblock(int fd) {
int flags = fcntl(fd, F_GETFL);
if (flags < 0) {
perror("fcntl(F_GETFL):");
return -1;
}
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
perror("fcntl(F_SETFL):");
return -1;
}
return 0;
}
xkb_keysym_t
keymap_get_one_sym_by_level(struct xkb_keymap *keymap, xkb_keycode_t key,
xkb_layout_index_t layout, xkb_level_index_t level)
{
const xkb_keysym_t *syms;
int count = xkb_keymap_key_get_syms_by_level(keymap, key, layout, level, &syms);
return count ? syms[0] : XKB_KEY_NoSymbol;
}