42 Commits
Author SHA1 Message Date
julmajustus d16036e690 Fix input_method_relay double allocation
- input_method_relay is allocated inside input_method_relay_create(), which leads the extra allocation to leak memory.
2026-09-18 22:09:39 +03:00
save196 45054a34a4 always apply a minimum size of 1x1
Resizing with the mouse can make the size negative, which makes dwl
crash, and the minimum is 1 because 0 makes some X11 clients crash.
2026-09-18 10:37:27 +02:00
save196 669b26d0a9 let the focus leave an unmanaged surface
Unmanaged clients spawned by a parent window, like menus, would not
close if the user changed workspace or focused another client while the
menu was selected, because the parent was never told that it lost the
focus. This remembers the last managed client and deactivates it on a
focus change, so that it closes the menu itself.

This also fixes a regression introduced by f6e3a28, where menus would
close immediately after being opened.
2026-09-18 09:17:40 +02:00
save196 e451862544 follow the geometry of unmanaged clients and fix formatting 2026-09-17 17:35:49 +00:00
save196 b3223b15e9 fix capturing hidden toplevels 2026-09-17 16:46:41 +00:00
Guido Cella 1fe1b4e66e show popups in fullscreen Xwayland apps
The dialogs opened by clicking items in Xwyland applications' toolbars
are unmanaged clients, so placing them in LyrFloat drew them below their
source client in LyrFS when it is fullscreened.

Add a new dedicated layer for unamanged clients to fix it. Don't put
them in LyrFS to prevent the regular fullscreen client from hiding
unmanaged ones, e.g. by opening dmenu and then clicking the regular
client.

Fixes https://codeberg.org/dwl/dwl/issues/556
2026-09-16 12:47:52 +02:00
Guido Cella 1dae5ba3ed size hints can be -1 2026-09-16 11:50:36 +02:00
Guido Cella 433c325fb2 fix a use-after-free
Prevent a use-after-free when closing a nested dwl with Ctrl+c.

It happened because cleanup() → input_method_relay_finish() frees
input_method_relay, and then closemon() → focusclient() →
input_method_relay_set_focus() uses relay->surface.
2026-09-15 23:29:50 +02:00
Guido Cella 6013835337 keep the focused border color of the old client in certain cases
When focusing an unmanaged client (like dmenu) or a layer shell surface
(like wmenu) keep the focused border color of the regular client, but
still deactivate it. This is consistent with dwm and sway.

This was already done for unmanaged clients but not for layer shell
surfaces.

This is not perfect because you can press MODKEY+j/k or move the cursor
while a program like dmenu is focused and have 2 clients with focused
border color after closing dmenu. But this doesn't work well even in
sway where if you change focus while dmenu is open you can longer focus
it, and after closing a layer shell surface with on-demand keyboard
interactivity all toplevels have the focused border color, so this will
do for now.
2026-09-15 22:17:24 +02:00
Guido Cella f6e3a2826e deactivate the old client when the new one wants focus
I see no issue with winecfg after removing this condition, so I assume
it was fixed upstream.
2026-09-15 22:16:35 +02:00
Guido Cella aa0c1659d3 Reapply "use modifier-independent key symbols in keybindings"
This reverts commit 0f8630282d.
2026-09-15 21:23:47 +02:00
Guido Cella bab3fdadf3 don't run keybindings twice when the shift keysym is the same
For keys like F1-F12 the keysym with the shift is the same as without.
Avoid running keybindings bound to these keys twice.
2026-09-15 21:22:41 +02:00
Guido Cella 0f8630282d Revert "use modifier-independent key symbols in keybindings"
This reverts commit f9c644f0b0.
2026-09-15 20:57:28 +02:00
Guido Cella 4de32d2d5c Reapply "respect size hints"
This reverts commit 31bf1cbaf6.

Fixes https://codeberg.org/dwl/dwl/issues/105
Fixes https://codeberg.org/dwl/dwl/issues/634
Fixes https://codeberg.org/dwl/dwl/issues/1171
2026-09-15 20:03:28 +02:00
Guido Cella 36c80aff03 Revert "don't resize on commit"
This reverts commit 498a0e605c.

Without resizing on every commit the top left of firefox is cropped.
2026-09-15 15:24:45 +02:00
Guido Cella 68c6319e3f Revert "reduce nesting in commitnotify()"
This reverts commit c824886b8c.
2026-09-15 15:24:27 +02:00
Guido Cella c824886b8c reduce nesting in commitnotify() 2026-09-15 12:07:13 +02:00
Guido Cella 498a0e605c don't resize on commit
Fixes https://codeberg.org/dwl/dwl/issues/1229
Reverts 32e66f4

This could be called only on the initial_commit, but it was added to fix
https://github.com/djpohly/dwl/issues/515 which I can't reproduce after
removing it, so let's try to remove it completely.
2026-09-15 12:06:35 +02:00
Guido Cella fec0699985 make client_set_size() return void
The return value is unused since the previous commit.
2026-09-15 12:06:32 +02:00
Guido Cella e7f185ed3e remove c->resize
Unused since 70c33c0.
2026-09-15 09:49:25 +02:00
Andrea ChiavazzaandGuido Cella f9c644f0b0 use modifier-independent key symbols in keybindings
Co-authored-by: Guido Cella <guido@guidocella.xyz>
2026-09-14 17:53:35 +02:00
Leonardo Hernández Hernández dc9a860191 use the new output swapchain manager in outputmgrapplyortest() 2026-09-14 10:45:33 +02:00
Guido Cella d1ebf3c985 fix firefox opening with rounded corners
Fixes https://codeberg.org/dwl/dwl/issues/1169

The c->isfloating check is needed to have the correct floating window
size with e.g. alacritty -o window.dimensions.columns=15
window.dimensions.lines=10.
2026-09-14 10:42:59 +02:00
sewn 8f52e96be4 replicate dwm behavior for snap resize 2026-09-14 02:25:48 +02:00
Guido Cella 5fd19feaff support monitors above and below in focusmon and tagmon
Fixes https://codeberg.org/dwl/dwl/issues/1105
2026-09-13 21:14:10 +02:00
Guido Cella b1c101515a remove zero flickering lie
This isn't true since dwl switched to the scene API in 2021 (1b38801).

The issue is tracked at https://codeberg.org/dwl/dwl/issues/552.
2026-09-13 19:34:27 +02:00
Guido CellaandDreamMaoMao 8ad2c920db use the right cursor after move and resize
Fixes https://codeberg.org/dwl/dwl/issues/1162

Co-authored-by: DreamMaoMao <2523610504@qq.com>
2026-09-13 19:06:54 +02:00
Peter HofmannandGuido Cella e8bf70d639 implement Axis mouse bindings
Co-authored-by: Guido Cella <guido@guidocella.xyz>
2026-09-13 18:14:47 +02:00
Guido Cellaandbrinkpw 99cdc9a825 set seat capabilities for virtual keyboards and pointers
wlr_seat_set_capabilities was never called without a real input device.

Fixes https://codeberg.org/dwl/dwl/issues/1155.

Co-authored-by: brinkpw
2026-09-13 08:38:07 +02:00
Guido Cella 7ba335063f don't crash when clicking an empty area
If l is not initialized, accessing
l->layer_surface->current.keyboard_interactive causes a segmentation
fault. This was hard to see because c above was never initialized but
never caused a crash, and dwl also didn't crash building with ASan.

Also initialize c to be safe.

Fixes 4c54bd8.
Fixes https://codeberg.org/dwl/dwl/issues/1225.
2026-09-13 08:25:20 +02:00
Guido CellaandZuki Air fb4102b5ae support screenshare of single windows
Supersedes https://codeberg.org/dwl/dwl/pulls/1157.

Co-authored-by: Zuki Air <zukirust@gmail.com>
2026-09-12 10:28:05 +02:00
Guido CellaandZuki Air 721f70ea8b implement ext-foreign-toplevel-list
This is used by lswt which lists toplevel ids and titles.
keyd-application-mapper will also support it hopefully.

This will also be needed to support screenshare of single windows
(https://codeberg.org/dwl/dwl/pulls/1157).

Co-authored-by: Zuki Air <zukirust@gmail.com>
2026-09-12 08:02:27 +02:00
0a6dc6d548 add support for layer-shell on-demand keyboard interactivity
Supersedes https://codeberg.org/dwl/dwl/pulls/674

Co-authored-by: Leonardo Hernández Hernández <leohdz172@proton.me>
Co-authored-by: MayOrMayNotBeACat <maybeacat804@gmail.com>
2026-09-12 08:00:20 +02:00
Guido Cella 4c54bd8113 implement xytonode() with toplevel_from_wlr_surface()
xytonode() does not return the layer surface under the cursor because
pnode->data is always NULL. It was not noticed because it is not passed
the LayerSurface argument anywhere. But it is noticeable after
implementing layer shell on-demand keyboard interactivity because layer
shell surfaces are never focused by sloppyfocus.

Rather than figuring out how to fix it, just replace its implementation
with toplevel_from_wlr_surface() which works and also reduces the SLOC.
2026-09-11 23:55:17 +02:00
Guido CellaandDreamMaoMao 2f3fe0671d add IME support
Based on mangowm, which is based on labwc, which is based on sway, so
this should be covered by LICENSE.sway.

Fixes https://codeberg.org/dwl/dwl/issues/6
Fixes https://codeberg.org/dwl/dwl/issues/710
Fixes https://codeberg.org/dwl/dwl/issues/1176
Fixes https://codeberg.org/dwl/dwl/issues/1185

Co-authored-by: DreamMaoMao <2523610504@qq.com>
2026-09-10 22:34:08 +02:00
Andrea Chiavazza f6800e95ee fix some key binding events being passed to clients 2026-09-09 21:50:41 +01:00
Siva Mahadevan 7fb20244c6 move util.c to util.h
This allows single-source compilation and whole-program optimization using something like:

make CFLAGS='-flto -ffunction-sections -fdata-sections -Wl,--gc-sections'

Furthermore, move more compositor-agnostic utility functions/macros to util.h,
similar to the original dwm sources.
2026-09-09 09:37:07 -04:00
A Frederick Christensen 21be76ac80 Formally not lead developers in README
User @guidocella joins dwl as a lead developer
2026-09-08 11:33:59 -05:00
julmajustus 70c33c015a Remove rendermon pending resize frame skip
This is no longer needed as wlroots => 0.19 handles this internally via scene-level surface state tracking and
linux-drm-syncobj explicit sync.

The manual commit skip now causes the c->resize to be stuck on non-zero
state which leads to choppy resizing experience.
2026-09-08 17:28:19 +02:00
Guido Cella ee788f0149 update wlroots version in commented variables 2026-09-08 11:44:44 +02:00
A Frederick Christensen 132606e133 add support for ext-image-copy-capture-v1 and ext-image-capture-source-v1 (wlroots!4545) 2026-09-08 11:44:44 +02:00
Thanatos 49ca434514 Bumped to 0.9 for wlroots-0.20.0. Updated cursor image buffer handling for xwayland 2026-09-08 11:44:44 +02:00
9 changed files with 1140 additions and 268 deletions
+8 -10
View File
@@ -5,7 +5,7 @@ include config.mk
# flags for compiling
DWLCPPFLAGS = -I. -DWLR_USE_UNSTABLE -D_POSIX_C_SOURCE=200809L \
-DVERSION=\"$(VERSION)\" $(XWAYLAND)
-DVERSION=\"$(VERSION)\" $(XWAYLAND) $(CPPFLAGS)
DWLDEVCFLAGS = -g -Wpedantic -Wall -Wextra -Wdeclaration-after-statement \
-Wno-unused-parameter -Wshadow -Wunused-macros -Werror=strict-prototypes \
-Werror=implicit -Werror=return-type -Werror=incompatible-pointer-types \
@@ -17,12 +17,11 @@ DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(WLR_INCS) $(DWLCPPFLAGS) $(DWLDEV
LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(WLR_LIBS) -lm $(LIBS)
all: dwl
dwl: dwl.o util.o
$(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@
dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \
dwl: dwl.c client.h config.h ime.h util.h config.mk cursor-shape-v1-protocol.h \
ext-image-copy-capture-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
util.o: util.c util.h
$(CC) dwl.c $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@
# 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
@@ -33,6 +32,9 @@ WAYLAND_PROTOCOLS = `$(PKG_CONFIG) --variable=pkgdatadir wayland-protocols`
cursor-shape-v1-protocol.h:
$(WAYLAND_SCANNER) enum-header \
$(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:
$(WAYLAND_SCANNER) enum-header \
$(WAYLAND_PROTOCOLS)/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml $@
@@ -54,7 +56,7 @@ clean:
dist: clean
mkdir -p dwl-$(VERSION)
cp -R LICENSE* Makefile CHANGELOG.md README.md client.h config.def.h \
config.mk protocols dwl.1 dwl.c util.c util.h dwl.desktop \
config.mk protocols dwl.1 dwl.c ime.h util.h dwl.desktop \
dwl-$(VERSION)
tar -caf dwl-$(VERSION).tar.gz dwl-$(VERSION)
rm -rf dwl-$(VERSION)
@@ -73,7 +75,3 @@ install: dwl
uninstall:
rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(MANDIR)/man1/dwl.1 \
$(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:
- Easy to understand, hack on, and extend with patches
- One C source file (or a very small number) configurable via `config.h`
- One C source file configurable via `config.h`
- Tied to as few external dependencies as possible
## Getting Started:
@@ -153,7 +153,6 @@ given the base on which it is built. Implemented default features are:
- Support screen lockers via ext-session-lock-v1 protocol
- Various Wayland protocols
- 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)
- Damage tracking provided by scenegraph API
@@ -166,9 +165,6 @@ indiscriminately. We will try to keep the code as small as possible.
Features under consideration (possibly as patches) are:
- 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:
@@ -193,6 +189,10 @@ inspiration, and to the various contributors to the project, including:
and for helping to keep the project running
- 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
[dwm]: https://dwm.suckless.org/
+48 -21
View File
@@ -15,6 +15,32 @@ client_is_x11(Client *c)
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 *
client_surface(Client *c)
{
@@ -206,13 +232,12 @@ client_get_title(Client *c)
static inline int
client_is_float_type(Client *c)
{
struct wlr_xdg_toplevel *toplevel;
struct wlr_xdg_toplevel_state state;
struct wlr_box min = {0}, max = {0};
client_get_size_hints(c, &max, &min);
#ifdef XWAYLAND
if (client_is_x11(c)) {
struct wlr_xwayland_surface *surface = c->surface.xwayland;
xcb_size_hints_t *size_hints = surface->size_hints;
if (surface->modal)
return 1;
@@ -223,17 +248,13 @@ client_is_float_type(Client *c)
return 1;
}
return size_hints && size_hints->min_width > 0 && size_hints->min_height > 0
&& (size_hints->max_width == size_hints->min_width
|| size_hints->max_height == size_hints->min_height);
return min.width > 0 && min.height > 0 &&
(min.width == max.width || min.height == max.height);
}
#endif
toplevel = c->surface.xdg->toplevel;
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));
return c->surface.xdg->toplevel->parent || (min.width > 0 && min.height > 0 &&
(min.width == max.width || min.height == max.height));
}
static inline int
@@ -291,11 +312,18 @@ client_is_unmanaged(Client *c)
static inline void
client_notify_enter(struct wlr_surface *s, struct wlr_keyboard *kb)
{
if (kb)
wlr_seat_keyboard_notify_enter(seat, s, kb->keycodes,
kb->num_keycodes, &kb->modifiers);
else
uint32_t filtered[WLR_KEYBOARD_KEYS_CAP];
size_t size = 0;
if (!kb) {
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
@@ -337,20 +365,19 @@ client_set_scale(struct wlr_surface *s, float scale)
wlr_surface_set_preferred_buffer_scale(s, (int32_t)ceilf(scale));
}
static inline uint32_t
static inline void
client_set_size(Client *c, uint32_t width, uint32_t height)
{
#ifdef XWAYLAND
if (client_is_x11(c)) {
wlr_xwayland_surface_configure(c->surface.xwayland,
c->geom.x + c->bw, c->geom.y + c->bw, width, height);
return 0;
return;
}
#endif
if ((int32_t)width == c->surface.xdg->toplevel->current.width
&& (int32_t)height == c->surface.xdg->toplevel->current.height)
return 0;
return wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, (int32_t)width, (int32_t)height);
if ((int32_t)width != c->surface.xdg->toplevel->current.width
|| (int32_t)height != c->surface.xdg->toplevel->current.height)
wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, (int32_t)width, (int32_t)height);
}
static inline void
+23 -18
View File
@@ -7,6 +7,7 @@
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 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 bordercolor[] = COLOR(0x444444ff);
static const float focuscolor[] = COLOR(0x005577ff);
@@ -105,11 +106,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 */
#define MODKEY WLR_MODIFIER_ALT
#define TAGKEYS(KEY,SKEY,TAG) \
#define TAGKEYS(KEY,TAG) \
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
{ MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \
{ MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \
{ MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} }
{ MODKEY|WLR_MODIFIER_SHIFT, KEY, tag, {.ui = 1 << TAG} }, \
{ MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,KEY,toggletag, {.ui = 1 << TAG} }
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
@@ -119,7 +120,6 @@ static const char *termcmd[] = { "foot", NULL };
static const char *menucmd[] = { "wmenu-run", NULL };
static const Key keys[] = {
/* Note that Shift changes certain key codes: 2 -> at, etc. */
/* modifier key function argument */
{ MODKEY, XKB_KEY_p, spawn, {.v = menucmd} },
{ 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, XKB_KEY_e, togglefullscreen, {0} },
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_0, tag, {.ui = ~0} },
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
{ MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} },
TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0),
TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1),
TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2),
TAGKEYS( XKB_KEY_4, XKB_KEY_dollar, 3),
TAGKEYS( XKB_KEY_5, XKB_KEY_percent, 4),
TAGKEYS( XKB_KEY_6, XKB_KEY_asciicircum, 5),
TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6),
TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7),
TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8),
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_comma, tagmon, {.i = WLR_DIRECTION_LEFT} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_period, tagmon, {.i = WLR_DIRECTION_RIGHT} },
TAGKEYS( XKB_KEY_1, 0),
TAGKEYS( XKB_KEY_2, 1),
TAGKEYS( XKB_KEY_3, 2),
TAGKEYS( XKB_KEY_4, 3),
TAGKEYS( XKB_KEY_5, 4),
TAGKEYS( XKB_KEY_6, 5),
TAGKEYS( XKB_KEY_7, 6),
TAGKEYS( XKB_KEY_8, 7),
TAGKEYS( XKB_KEY_9, 8),
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_q, quit, {0} },
/* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */
{ WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} },
{ WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_BackSpace, quit, {0} },
/* Ctrl-Alt-Fx is used to switch to another VT, if you don't know what a VT is
* do not remove them.
*/
#define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_XF86Switch_VT_##n, chvt, {.ui = (n)} }
#define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_F##n, chvt, {.ui = (n)} }
CHVT(1), CHVT(2), CHVT(3), CHVT(4), CHVT(5), CHVT(6),
CHVT(7), CHVT(8), CHVT(9), CHVT(10), CHVT(11), CHVT(12),
};
@@ -170,3 +170,8 @@ static const Button buttons[] = {
{ MODKEY, BTN_MIDDLE, togglefloating, {0} },
{ MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} },
};
static const Axis axes[] = {
{ MODKEY, AxisUp, spawn, SHCMD("volume-up_EXAMPLE") },
{ MODKEY, AxisDown, spawn, SHCMD("volume-down_EXAMPLE") },
};
+7 -7
View File
@@ -1,4 +1,4 @@
_VERSION = 0.8-dev
_VERSION = 0.9-dev
VERSION = `git describe --tags --dirty 2>/dev/null || echo $(_VERSION)`
PKG_CONFIG = pkg-config
@@ -8,8 +8,8 @@ PREFIX = /usr/local
MANDIR = $(PREFIX)/share/man
DATADIR = $(PREFIX)/share
WLR_INCS = `$(PKG_CONFIG) --cflags wlroots-0.19`
WLR_LIBS = `$(PKG_CONFIG) --libs wlroots-0.19`
WLR_INCS = `$(PKG_CONFIG) --cflags wlroots-0.20`
WLR_LIBS = `$(PKG_CONFIG) --libs wlroots-0.20`
# Allow using an alternative wlroots installation
# This has to have all the includes required by wlroots, e.g:
@@ -17,12 +17,12 @@ WLR_LIBS = `$(PKG_CONFIG) --libs wlroots-0.19`
#WLR_INCS = -I/usr/include/pixman-1 -I/usr/include/elogind -I/usr/include/libdrm \
# -I$(PWD)/wlroots/include
# Set -rpath to avoid using the wrong library.
#WLR_LIBS = -Wl,-rpath,$(PWD)/wlroots/build -L$(PWD)/wlroots/build -lwlroots-0.19
#WLR_LIBS = -Wl,-rpath,$(PWD)/wlroots/build -L$(PWD)/wlroots/build -lwlroots-0.20
# Assuming you ran "meson setup --prefix ${PWD}/0.19 build && ninja -C build install"
# Assuming you ran "meson setup --prefix ${PWD}/0.20 build && ninja -C build install"
#WLR_INCS = -I/usr/include/pixman-1 -I/usr/include/elogind -I/usr/include/libdrm \
# -I$(PWD)/wlroots/0.19/include/wlroots-0.19
#WLR_LIBS = -Wl,-rpath,$(PWD)/wlroots/0.19/lib64 -L$(PWD)/wlroots/0.19/lib64 -lwlroots-0.19
# -I$(PWD)/wlroots/0.20/include/wlroots-0.20
#WLR_LIBS = -Wl,-rpath,$(PWD)/wlroots/0.20/lib64 -L$(PWD)/wlroots/0.20/lib64 -lwlroots-0.20
XWAYLAND =
XLIBS =
+336 -147
View File
File diff suppressed because it is too large Load Diff
+639
View File
@@ -0,0 +1,639 @@
#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
@@ -1,51 +0,0 @@
/* 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;
}
+68 -3
View File
@@ -1,5 +1,70 @@
/* 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>
void die(const char *fmt, ...);
void *ecalloc(size_t nmemb, size_t size);
int fd_set_nonblock(int fd);
#define MAX(A, B) ((A) > (B) ? (A) : (B))
#define MIN(A, B) ((A) < (B) ? (A) : (B))
#define LENGTH(X) (sizeof X / sizeof X[0])
#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;
}