mirror of
https://codeberg.org/dwl/dwl.git
synced 2026-09-22 23:29:10 +00:00
Compare commits
35
Commits
8f52e96be4
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a75ca79630 | ||
|
|
87029e21c0 | ||
|
|
a514a928e4 | ||
|
|
242ffd7a75 | ||
|
|
f22c223cbf | ||
|
|
b83881f881 | ||
|
|
fa400c5d3d | ||
|
|
40b0ae76ae | ||
|
|
2a567195e6 | ||
|
|
cc23250527 | ||
|
|
98bea2c27f | ||
|
|
49837e985e | ||
|
|
d16036e690 | ||
|
|
45054a34a4 | ||
|
|
669b26d0a9 | ||
|
|
e451862544 | ||
|
|
b3223b15e9 | ||
|
|
1fe1b4e66e | ||
|
|
1dae5ba3ed | ||
|
|
433c325fb2 | ||
|
|
6013835337 | ||
|
|
f6e3a2826e | ||
|
|
aa0c1659d3 | ||
|
|
bab3fdadf3 | ||
|
|
0f8630282d | ||
|
|
4de32d2d5c | ||
|
|
36c80aff03 | ||
|
|
68c6319e3f | ||
|
|
c824886b8c | ||
|
|
498a0e605c | ||
|
|
fec0699985 | ||
|
|
e7f185ed3e | ||
|
|
f9c644f0b0 | ||
|
|
dc9a860191 | ||
|
|
d1ebf3c985 |
+90
-7
@@ -1,12 +1,98 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
* [Unreleased](#unreleased)
|
* [0.9](#0.9)
|
||||||
|
* [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)
|
||||||
|
|
||||||
|
|
||||||
## Unreleased
|
## 0.9
|
||||||
|
|
||||||
|
### 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])
|
||||||
@@ -17,15 +103,12 @@
|
|||||||
[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
|
|
||||||
### Contributors
|
Most changes in this release are not listed. See the commits for details.
|
||||||
|
|
||||||
|
|
||||||
## 0.7
|
## 0.7
|
||||||
|
|||||||
@@ -15,6 +15,32 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -163,6 +189,7 @@ client_get_geometry(Client *c, struct wlr_box *geom)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
*geom = c->surface.xdg->geometry;
|
*geom = c->surface.xdg->geometry;
|
||||||
|
geom->x = geom->y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Client *
|
static inline Client *
|
||||||
@@ -206,13 +233,12 @@ 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_xdg_toplevel *toplevel;
|
struct wlr_box min = {0}, max = {0};
|
||||||
struct wlr_xdg_toplevel_state state;
|
client_get_size_hints(c, &max, &min);
|
||||||
|
|
||||||
#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;
|
||||||
|
|
||||||
@@ -223,17 +249,13 @@ client_is_float_type(Client *c)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return size_hints && size_hints->min_width > 0 && size_hints->min_height > 0
|
return min.width > 0 && min.height > 0 &&
|
||||||
&& (size_hints->max_width == size_hints->min_width
|
(min.width == max.width || min.height == max.height);
|
||||||
|| size_hints->max_height == size_hints->min_height);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
toplevel = c->surface.xdg->toplevel;
|
return c->surface.xdg->toplevel->parent || (min.width > 0 && min.height > 0 &&
|
||||||
state = toplevel->current;
|
(min.width == max.width || min.height == max.height));
|
||||||
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
|
||||||
@@ -344,20 +366,17 @@ 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 uint32_t
|
static inline void
|
||||||
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 0;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if ((int32_t)width == c->surface.xdg->toplevel->current.width
|
wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, (int32_t)width, (int32_t)height);
|
||||||
&& (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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
|||||||
+21
-19
@@ -106,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 */
|
/* 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,SKEY,TAG) \
|
#define TAGKEYS(KEY,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, SKEY, tag, {.ui = 1 << TAG} }, \
|
{ MODKEY|WLR_MODIFIER_SHIFT, KEY, tag, {.ui = 1 << TAG} }, \
|
||||||
{ MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.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 */
|
/* 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,7 +120,6 @@ 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} },
|
||||||
@@ -140,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_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_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_less, tagmon, {.i = WLR_DIRECTION_LEFT} },
|
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_comma, tagmon, {.i = WLR_DIRECTION_LEFT} },
|
||||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} },
|
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_period, tagmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||||
TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0),
|
TAGKEYS( XKB_KEY_1, 0),
|
||||||
TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1),
|
TAGKEYS( XKB_KEY_2, 1),
|
||||||
TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2),
|
TAGKEYS( XKB_KEY_3, 2),
|
||||||
TAGKEYS( XKB_KEY_4, XKB_KEY_dollar, 3),
|
TAGKEYS( XKB_KEY_4, 3),
|
||||||
TAGKEYS( XKB_KEY_5, XKB_KEY_percent, 4),
|
TAGKEYS( XKB_KEY_5, 4),
|
||||||
TAGKEYS( XKB_KEY_6, XKB_KEY_asciicircum, 5),
|
TAGKEYS( XKB_KEY_6, 5),
|
||||||
TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6),
|
TAGKEYS( XKB_KEY_7, 6),
|
||||||
TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7),
|
TAGKEYS( XKB_KEY_8, 7),
|
||||||
TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8),
|
TAGKEYS( XKB_KEY_9, 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_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
|
/* 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_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(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),
|
||||||
};
|
};
|
||||||
@@ -173,6 +172,9 @@ static const Button buttons[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const Axis axes[] = {
|
static const Axis axes[] = {
|
||||||
|
/* example of volume control:
|
||||||
{ MODKEY, AxisUp, spawn, SHCMD("volume-up_EXAMPLE") },
|
{ MODKEY, AxisUp, spawn, SHCMD("volume-up_EXAMPLE") },
|
||||||
{ MODKEY, AxisDown, spawn, SHCMD("volume-down_EXAMPLE") },
|
{ MODKEY, AxisDown, spawn, SHCMD("volume-down_EXAMPLE") }, */
|
||||||
|
{ 0, 0, NULL, {0} },
|
||||||
|
/* does nothing, but the array cannot be empty */
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
_VERSION = 0.9-dev
|
_VERSION = 0.10-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
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <libinput.h>
|
#include <libinput.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <linux/input-event-codes.h>
|
#include <linux/input-event-codes.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@@ -15,6 +16,7 @@
|
|||||||
#include <wlr/backend.h>
|
#include <wlr/backend.h>
|
||||||
#include <wlr/backend/libinput.h>
|
#include <wlr/backend/libinput.h>
|
||||||
#include <wlr/render/allocator.h>
|
#include <wlr/render/allocator.h>
|
||||||
|
#include <wlr/render/swapchain.h>
|
||||||
#include <wlr/render/wlr_renderer.h>
|
#include <wlr/render/wlr_renderer.h>
|
||||||
#include <wlr/types/wlr_alpha_modifier_v1.h>
|
#include <wlr/types/wlr_alpha_modifier_v1.h>
|
||||||
#include <wlr/types/wlr_compositor.h>
|
#include <wlr/types/wlr_compositor.h>
|
||||||
@@ -42,6 +44,7 @@
|
|||||||
#include <wlr/types/wlr_output_layout.h>
|
#include <wlr/types/wlr_output_layout.h>
|
||||||
#include <wlr/types/wlr_output_management_v1.h>
|
#include <wlr/types/wlr_output_management_v1.h>
|
||||||
#include <wlr/types/wlr_output_power_management_v1.h>
|
#include <wlr/types/wlr_output_power_management_v1.h>
|
||||||
|
#include <wlr/types/wlr_output_swapchain_manager.h>
|
||||||
#include <wlr/types/wlr_pointer.h>
|
#include <wlr/types/wlr_pointer.h>
|
||||||
#include <wlr/types/wlr_pointer_constraints_v1.h>
|
#include <wlr/types/wlr_pointer_constraints_v1.h>
|
||||||
#include <wlr/types/wlr_presentation_time.h>
|
#include <wlr/types/wlr_presentation_time.h>
|
||||||
@@ -85,7 +88,8 @@
|
|||||||
/* enums */
|
/* enums */
|
||||||
enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
|
enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
|
||||||
enum { XDGShell, LayerShell, X11 }; /* client types */
|
enum { XDGShell, LayerShell, X11 }; /* client types */
|
||||||
enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrIMPopup, LyrBlock, NUM_LAYERS }; /* scene layers */
|
enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrUnmanaged, LyrOverlay,
|
||||||
|
LyrIMPopup, LyrBlock, NUM_LAYERS }; /* scene layers */
|
||||||
enum { AxisUp, AxisRight, AxisDown, AxisLeft };
|
enum { AxisUp, AxisRight, AxisDown, AxisLeft };
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
@@ -149,12 +153,12 @@ typedef struct {
|
|||||||
struct wl_listener associate;
|
struct wl_listener associate;
|
||||||
struct wl_listener dissociate;
|
struct wl_listener dissociate;
|
||||||
struct wl_listener configure;
|
struct wl_listener configure;
|
||||||
|
struct wl_listener set_geometry;
|
||||||
struct wl_listener set_hints;
|
struct wl_listener set_hints;
|
||||||
#endif
|
#endif
|
||||||
unsigned int bw;
|
unsigned int bw;
|
||||||
uint32_t tags;
|
uint32_t tags;
|
||||||
int isfloating, isurgent, isfullscreen;
|
int isfloating, isurgent, isfullscreen;
|
||||||
uint32_t resize; /* configure serial of a pending resize */
|
|
||||||
} Client;
|
} Client;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -168,9 +172,8 @@ typedef struct {
|
|||||||
struct wlr_keyboard_group *wlr_group;
|
struct wlr_keyboard_group *wlr_group;
|
||||||
struct wlr_keyboard *virtual_keyboard;
|
struct wlr_keyboard *virtual_keyboard;
|
||||||
|
|
||||||
int nsyms;
|
xkb_keysym_t keysyms[2];
|
||||||
const xkb_keysym_t *keysyms; /* invalid if nsyms == 0 */
|
uint32_t mods;
|
||||||
uint32_t mods; /* invalid if nsyms == 0 */
|
|
||||||
struct wl_event_source *key_repeat_source;
|
struct wl_event_source *key_repeat_source;
|
||||||
|
|
||||||
struct wl_listener modifiers;
|
struct wl_listener modifiers;
|
||||||
@@ -208,6 +211,7 @@ struct Monitor {
|
|||||||
struct wl_listener frame;
|
struct wl_listener frame;
|
||||||
struct wl_listener destroy;
|
struct wl_listener destroy;
|
||||||
struct wl_listener request_state;
|
struct wl_listener request_state;
|
||||||
|
struct wl_listener commit_lock_surface;
|
||||||
struct wl_listener destroy_lock_surface;
|
struct wl_listener destroy_lock_surface;
|
||||||
struct wlr_session_lock_surface_v1 *lock_surface;
|
struct wlr_session_lock_surface_v1 *lock_surface;
|
||||||
struct wlr_box m; /* monitor area, layout-relative */
|
struct wlr_box m; /* monitor area, layout-relative */
|
||||||
@@ -273,6 +277,7 @@ static void cleanupmon(struct wl_listener *listener, void *data);
|
|||||||
static void cleanuplisteners(void);
|
static void cleanuplisteners(void);
|
||||||
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);
|
||||||
|
static void commitlocksurface(struct wl_listener *listener, void *data);
|
||||||
static void commitnotify(struct wl_listener *listener, void *data);
|
static void commitnotify(struct wl_listener *listener, void *data);
|
||||||
static void commitpopup(struct wl_listener *listener, void *data);
|
static void commitpopup(struct wl_listener *listener, void *data);
|
||||||
static void createdecoration(struct wl_listener *listener, void *data);
|
static void createdecoration(struct wl_listener *listener, void *data);
|
||||||
@@ -300,7 +305,7 @@ static void destroypointerconstraint(struct wl_listener *listener, void *data);
|
|||||||
static void destroysessionlock(struct wl_listener *listener, void *data);
|
static void destroysessionlock(struct wl_listener *listener, void *data);
|
||||||
static void destroykeyboardgroup(struct wl_listener *listener, void *data);
|
static void destroykeyboardgroup(struct wl_listener *listener, void *data);
|
||||||
static Monitor *dirtomon(enum wlr_direction dir);
|
static Monitor *dirtomon(enum wlr_direction dir);
|
||||||
static void focusclient(Client *c, int lift);
|
static void focusclient(Client *c, LayerSurface *l, int lift);
|
||||||
static void focusmon(const Arg *arg);
|
static void focusmon(const Arg *arg);
|
||||||
static void focusstack(const Arg *arg);
|
static void focusstack(const Arg *arg);
|
||||||
static Client *focustop(Monitor *m);
|
static Client *focustop(Monitor *m);
|
||||||
@@ -373,7 +378,7 @@ static void zoom(const Arg *arg);
|
|||||||
/* variables */
|
/* variables */
|
||||||
static pid_t child_pid = -1;
|
static pid_t child_pid = -1;
|
||||||
static int locked;
|
static int locked;
|
||||||
static void *exclusive_focus;
|
static Client *focused_client;
|
||||||
static struct wl_display *dpy;
|
static struct wl_display *dpy;
|
||||||
static struct wl_event_loop *event_loop;
|
static struct wl_event_loop *event_loop;
|
||||||
static struct wlr_backend *backend;
|
static struct wlr_backend *backend;
|
||||||
@@ -464,6 +469,7 @@ static void associatex11(struct wl_listener *listener, void *data);
|
|||||||
static void configurex11(struct wl_listener *listener, void *data);
|
static void configurex11(struct wl_listener *listener, void *data);
|
||||||
static void createnotifyx11(struct wl_listener *listener, void *data);
|
static void createnotifyx11(struct wl_listener *listener, void *data);
|
||||||
static void dissociatex11(struct wl_listener *listener, void *data);
|
static void dissociatex11(struct wl_listener *listener, void *data);
|
||||||
|
static void setgeometryx11(struct wl_listener *listener, void *data);
|
||||||
static void sethints(struct wl_listener *listener, void *data);
|
static void sethints(struct wl_listener *listener, void *data);
|
||||||
static void xwaylandready(struct wl_listener *listener, void *data);
|
static void xwaylandready(struct wl_listener *listener, void *data);
|
||||||
static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11};
|
static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11};
|
||||||
@@ -483,10 +489,23 @@ static struct wlr_xwayland *xwayland;
|
|||||||
void
|
void
|
||||||
applybounds(Client *c, struct wlr_box *bbox)
|
applybounds(Client *c, struct wlr_box *bbox)
|
||||||
{
|
{
|
||||||
/* set minimum possible */
|
/* set minimum client size to 1 */
|
||||||
c->geom.width = MAX(1 + 2 * (int)c->bw, c->geom.width);
|
c->geom.width = MAX(1 + 2 * (int)c->bw, c->geom.width);
|
||||||
c->geom.height = MAX(1 + 2 * (int)c->bw, c->geom.height);
|
c->geom.height = MAX(1 + 2 * (int)c->bw, c->geom.height);
|
||||||
|
|
||||||
|
if (!c->isfullscreen) {
|
||||||
|
struct wlr_box min = {0}, max = {0};
|
||||||
|
client_get_size_hints(c, &max, &min);
|
||||||
|
c->geom.width = MAX(min.width + 2 * (int)c->bw, c->geom.width);
|
||||||
|
c->geom.height = MAX(min.height + 2 * (int)c->bw, c->geom.height);
|
||||||
|
/* Some clients set their max size to INT_MAX, which does not violate the
|
||||||
|
* protocol but it's unnecesary, as they can set their max size to zero. */
|
||||||
|
if (max.width > 0 && 2 * (int)c->bw <= INT_MAX - max.width) /* Checks for overflow */
|
||||||
|
c->geom.width = MIN(max.width + 2 * (int)c->bw, c->geom.width);
|
||||||
|
if (max.height > 0 && 2 * (int)c->bw <= INT_MAX - max.height) /* Checks for overflow */
|
||||||
|
c->geom.height = MIN(max.height + 2 * (int)c->bw, c->geom.height);
|
||||||
|
}
|
||||||
|
|
||||||
if (c->geom.x >= bbox->x + bbox->width)
|
if (c->geom.x >= bbox->x + bbox->width)
|
||||||
c->geom.x = bbox->x + bbox->width - c->geom.width;
|
c->geom.x = bbox->x + bbox->width - c->geom.width;
|
||||||
if (c->geom.y >= bbox->y + bbox->height)
|
if (c->geom.y >= bbox->y + bbox->height)
|
||||||
@@ -538,7 +557,9 @@ arrange(Monitor *m)
|
|||||||
wl_list_for_each(c, &clients, link) {
|
wl_list_for_each(c, &clients, link) {
|
||||||
if (c->mon == m) {
|
if (c->mon == m) {
|
||||||
wlr_scene_node_set_enabled(&c->scene->node, VISIBLEON(c, m));
|
wlr_scene_node_set_enabled(&c->scene->node, VISIBLEON(c, m));
|
||||||
client_set_suspended(c, !VISIBLEON(c, m));
|
client_set_suspended(c, !VISIBLEON(c, m)
|
||||||
|
&& (!c->image_capture_source
|
||||||
|
|| wl_list_empty(&c->image_capture_source->resources)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,9 +643,7 @@ arrangelayers(Monitor *m)
|
|||||||
!l->mapped)
|
!l->mapped)
|
||||||
continue;
|
continue;
|
||||||
/* Deactivate the focused client. */
|
/* Deactivate the focused client. */
|
||||||
focusclient(NULL, 0);
|
focusclient(NULL, l, 0);
|
||||||
exclusive_focus = l;
|
|
||||||
client_notify_enter(l->layer_surface->surface, wlr_seat_get_keyboard(seat));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -643,6 +662,7 @@ axisnotify(struct wl_listener *listener, void *data)
|
|||||||
|
|
||||||
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
||||||
|
|
||||||
|
if (!locked) {
|
||||||
if (event->orientation == WL_POINTER_AXIS_VERTICAL_SCROLL)
|
if (event->orientation == WL_POINTER_AXIS_VERTICAL_SCROLL)
|
||||||
adir = event->delta > 0 ? AxisDown : AxisUp;
|
adir = event->delta > 0 ? AxisDown : AxisUp;
|
||||||
else
|
else
|
||||||
@@ -655,6 +675,7 @@ axisnotify(struct wl_listener *listener, void *data)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Notify the client with pointer focus of the axis event. */
|
/* Notify the client with pointer focus of the axis event. */
|
||||||
wlr_seat_pointer_notify_axis(seat,
|
wlr_seat_pointer_notify_axis(seat,
|
||||||
@@ -685,10 +706,9 @@ buttonpress(struct wl_listener *listener, void *data)
|
|||||||
or a layer surface with on-demand keyboard interactivity */
|
or a layer surface with on-demand keyboard interactivity */
|
||||||
xytonode(cursor->x, cursor->y, NULL, &c, &l, NULL, NULL);
|
xytonode(cursor->x, cursor->y, NULL, &c, &l, NULL, NULL);
|
||||||
if (c && (!client_is_unmanaged(c) || client_wants_focus(c))) {
|
if (c && (!client_is_unmanaged(c) || client_wants_focus(c))) {
|
||||||
focusclient(c, 1);
|
focusclient(c, NULL, 1);
|
||||||
} else if (l && l->layer_surface->current.keyboard_interactive) {
|
} else if (l && l->layer_surface->current.keyboard_interactive) {
|
||||||
focusclient(NULL, 0);
|
focusclient(NULL, l, 0);
|
||||||
client_notify_enter(l->layer_surface->surface, wlr_seat_get_keyboard(seat));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
keyboard = wlr_seat_get_keyboard(seat);
|
keyboard = wlr_seat_get_keyboard(seat);
|
||||||
@@ -738,6 +758,8 @@ capturerequest(struct wl_listener *listener, void *data)
|
|||||||
|
|
||||||
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_accept(
|
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_accept(
|
||||||
request, view->image_capture_source);
|
request, view->image_capture_source);
|
||||||
|
|
||||||
|
client_set_suspended(view, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -782,6 +804,7 @@ cleanup(void)
|
|||||||
destroykeyboardgroup(&kb_group->destroy, NULL);
|
destroykeyboardgroup(&kb_group->destroy, NULL);
|
||||||
|
|
||||||
input_method_relay_finish(input_method_relay);
|
input_method_relay_finish(input_method_relay);
|
||||||
|
input_method_relay = NULL;
|
||||||
|
|
||||||
/* If it's not destroyed manually, it will cause a use-after-free of wlr_seat.
|
/* If it's not destroyed manually, it will cause a use-after-free of wlr_seat.
|
||||||
* Destroy it until it's fixed on the wlroots side */
|
* Destroy it until it's fixed on the wlroots side */
|
||||||
@@ -884,7 +907,7 @@ closemon(Monitor *m)
|
|||||||
if (c->mon == m)
|
if (c->mon == m)
|
||||||
setmon(c, selmon, c->tags);
|
setmon(c, selmon, c->tags);
|
||||||
}
|
}
|
||||||
focusclient(focustop(selmon), 1);
|
focusclient(focustop(selmon), NULL, 1);
|
||||||
printstatus();
|
printstatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -908,11 +931,6 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layer_surface == exclusive_focus
|
|
||||||
&& layer_surface->current.keyboard_interactive !=
|
|
||||||
ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE)
|
|
||||||
exclusive_focus = NULL;
|
|
||||||
|
|
||||||
if (layer_surface->current.committed == 0 && l->mapped == layer_surface->surface->mapped)
|
if (layer_surface->current.committed == 0 && l->mapped == layer_surface->surface->mapped)
|
||||||
return;
|
return;
|
||||||
l->mapped = layer_surface->surface->mapped;
|
l->mapped = layer_surface->surface->mapped;
|
||||||
@@ -928,6 +946,20 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data)
|
|||||||
arrangelayers(l->mon);
|
arrangelayers(l->mon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
commitlocksurface(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
Monitor *m = wl_container_of(listener, m, commit_lock_surface);
|
||||||
|
|
||||||
|
if (!m->lock_surface->surface->mapped)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wl_list_remove(&m->commit_lock_surface.link);
|
||||||
|
wl_list_init(&m->commit_lock_surface.link);
|
||||||
|
|
||||||
|
motionnotify(0, NULL, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
commitnotify(struct wl_listener *listener, void *data)
|
commitnotify(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
@@ -951,14 +983,13 @@ commitnotify(struct wl_listener *listener, void *data)
|
|||||||
if (c->decoration)
|
if (c->decoration)
|
||||||
requestdecorationmode(&c->set_decoration_mode, c->decoration);
|
requestdecorationmode(&c->set_decoration_mode, c->decoration);
|
||||||
wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, 0, 0);
|
wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, 0, 0);
|
||||||
|
if (!c->isfloating)
|
||||||
|
client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT |
|
||||||
|
WLR_EDGE_RIGHT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
resize(c, c->geom, (c->isfloating && !c->isfullscreen));
|
resize(c, c->geom, (c->isfloating && !c->isfullscreen));
|
||||||
|
|
||||||
/* mark a pending resize as completed */
|
|
||||||
if (c->resize && c->resize <= c->surface.xdg->current.configure_serial)
|
|
||||||
c->resize = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1106,6 +1137,7 @@ createlocksurface(struct wl_listener *listener, void *data)
|
|||||||
wlr_session_lock_surface_v1_configure(lock_surface, m->m.width, m->m.height);
|
wlr_session_lock_surface_v1_configure(lock_surface, m->m.width, m->m.height);
|
||||||
|
|
||||||
LISTEN(&lock_surface->events.destroy, &m->destroy_lock_surface, destroylocksurface);
|
LISTEN(&lock_surface->events.destroy, &m->destroy_lock_surface, destroylocksurface);
|
||||||
|
LISTEN(&lock_surface->surface->events.commit, &m->commit_lock_surface, commitlocksurface);
|
||||||
|
|
||||||
if (m == selmon)
|
if (m == selmon)
|
||||||
client_notify_enter(lock_surface->surface, wlr_seat_get_keyboard(seat));
|
client_notify_enter(lock_surface->surface, wlr_seat_get_keyboard(seat));
|
||||||
@@ -1327,7 +1359,7 @@ void
|
|||||||
destroydragicon(struct wl_listener *listener, void *data)
|
destroydragicon(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
/* Focus enter isn't sent during drag, so refocus the focused node. */
|
/* Focus enter isn't sent during drag, so refocus the focused node. */
|
||||||
focusclient(focustop(selmon), 1);
|
focusclient(focustop(selmon), NULL, 1);
|
||||||
motionnotify(0, NULL, 0, 0, 0, 0);
|
motionnotify(0, NULL, 0, 0, 0, 0);
|
||||||
wl_list_remove(&listener->link);
|
wl_list_remove(&listener->link);
|
||||||
free(listener);
|
free(listener);
|
||||||
@@ -1366,7 +1398,7 @@ destroylock(SessionLock *lock, int unlock)
|
|||||||
|
|
||||||
wlr_scene_node_set_enabled(&locked_bg->node, 0);
|
wlr_scene_node_set_enabled(&locked_bg->node, 0);
|
||||||
|
|
||||||
focusclient(focustop(selmon), 0);
|
focusclient(focustop(selmon), NULL, 0);
|
||||||
motionnotify(0, NULL, 0, 0, 0, 0);
|
motionnotify(0, NULL, 0, 0, 0, 0);
|
||||||
|
|
||||||
destroy:
|
destroy:
|
||||||
@@ -1387,6 +1419,7 @@ destroylocksurface(struct wl_listener *listener, void *data)
|
|||||||
|
|
||||||
m->lock_surface = NULL;
|
m->lock_surface = NULL;
|
||||||
wl_list_remove(&m->destroy_lock_surface.link);
|
wl_list_remove(&m->destroy_lock_surface.link);
|
||||||
|
wl_list_remove(&m->commit_lock_surface.link);
|
||||||
|
|
||||||
if (lock_surface->surface != seat->keyboard_state.focused_surface)
|
if (lock_surface->surface != seat->keyboard_state.focused_surface)
|
||||||
return;
|
return;
|
||||||
@@ -1395,7 +1428,7 @@ destroylocksurface(struct wl_listener *listener, void *data)
|
|||||||
surface = wl_container_of(cur_lock->surfaces.next, surface, link);
|
surface = wl_container_of(cur_lock->surfaces.next, surface, link);
|
||||||
client_notify_enter(surface->surface, wlr_seat_get_keyboard(seat));
|
client_notify_enter(surface->surface, wlr_seat_get_keyboard(seat));
|
||||||
} else if (!locked) {
|
} else if (!locked) {
|
||||||
focusclient(focustop(selmon), 1);
|
focusclient(focustop(selmon), NULL, 1);
|
||||||
} else {
|
} else {
|
||||||
wlr_seat_keyboard_clear_focus(seat);
|
wlr_seat_keyboard_clear_focus(seat);
|
||||||
}
|
}
|
||||||
@@ -1415,6 +1448,7 @@ destroynotify(struct wl_listener *listener, void *data)
|
|||||||
wl_list_remove(&c->associate.link);
|
wl_list_remove(&c->associate.link);
|
||||||
wl_list_remove(&c->configure.link);
|
wl_list_remove(&c->configure.link);
|
||||||
wl_list_remove(&c->dissociate.link);
|
wl_list_remove(&c->dissociate.link);
|
||||||
|
wl_list_remove(&c->set_geometry.link);
|
||||||
wl_list_remove(&c->set_hints.link);
|
wl_list_remove(&c->set_hints.link);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
@@ -1482,7 +1516,7 @@ dirtomon(enum wlr_direction dir)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
focusclient(Client *c, int lift)
|
focusclient(Client *c, LayerSurface *l, int lift)
|
||||||
{
|
{
|
||||||
struct wlr_surface *old = seat->keyboard_state.focused_surface;
|
struct wlr_surface *old = seat->keyboard_state.focused_surface;
|
||||||
int unused_lx, unused_ly, old_client_type;
|
int unused_lx, unused_ly, old_client_type;
|
||||||
@@ -1514,32 +1548,39 @@ focusclient(Client *c, int lift)
|
|||||||
|
|
||||||
/* Don't change border color if there is an exclusive focus or we are
|
/* Don't change border color if there is an exclusive focus or we are
|
||||||
* handling a drag operation */
|
* handling a drag operation */
|
||||||
if (!exclusive_focus && !seat->drag)
|
if (!(old_l && old_l->layer_surface->current.keyboard_interactive == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE)
|
||||||
|
&& !(old_c && client_wants_focus(old_c))
|
||||||
|
&& !seat->drag)
|
||||||
client_set_border_color(c, focuscolor);
|
client_set_border_color(c, focuscolor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deactivate old client if focus is changing */
|
|
||||||
if (old && (!c || client_surface(c) != old)) {
|
|
||||||
/* If an overlay is focused, don't focus or activate the client,
|
/* If an overlay is focused, don't focus or activate the client,
|
||||||
* but only update its position in fstack to render its border with focuscolor
|
* but only update its position in fstack to render its border with focuscolor
|
||||||
* and focus it after the overlay is closed. */
|
* and focus it after the overlay is closed. */
|
||||||
if (old_client_type == LayerShell && wlr_scene_node_coords(
|
if (!l && old && (!c || client_surface(c) != old)
|
||||||
|
&& old_client_type == LayerShell && wlr_scene_node_coords(
|
||||||
&old_l->scene->node, &unused_lx, &unused_ly)
|
&old_l->scene->node, &unused_lx, &unused_ly)
|
||||||
&& old_l->layer_surface->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP
|
&& old_l->layer_surface->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP
|
||||||
&& old_l->layer_surface->current.keyboard_interactive == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) {
|
&& old_l->layer_surface->current.keyboard_interactive == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE)
|
||||||
return;
|
return;
|
||||||
} else if (old_c && old_c == exclusive_focus && client_wants_focus(old_c)) {
|
|
||||||
return;
|
|
||||||
/* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg
|
|
||||||
* and probably other clients */
|
|
||||||
} else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) {
|
|
||||||
client_set_border_color(old_c, bordercolor);
|
|
||||||
|
|
||||||
client_activate_surface(old, 0);
|
if (focused_client && focused_client != c && !(c && client_is_unmanaged(c))) {
|
||||||
}
|
struct wlr_surface *s = client_surface(focused_client);
|
||||||
|
if (c)
|
||||||
|
client_set_border_color(focused_client, bordercolor);
|
||||||
|
if (s && s->mapped)
|
||||||
|
client_activate_surface(s, 0);
|
||||||
|
focused_client = NULL;
|
||||||
}
|
}
|
||||||
printstatus();
|
printstatus();
|
||||||
|
|
||||||
|
if (l) {
|
||||||
|
/* Focus a layer surface and let the input method follow it */
|
||||||
|
input_method_relay_set_focus(input_method_relay, l->layer_surface->surface);
|
||||||
|
client_notify_enter(l->layer_surface->surface, wlr_seat_get_keyboard(seat));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!c) {
|
if (!c) {
|
||||||
/* With no client, all we have left is to clear focus */
|
/* With no client, all we have left is to clear focus */
|
||||||
input_method_relay_set_focus(input_method_relay, NULL);
|
input_method_relay_set_focus(input_method_relay, NULL);
|
||||||
@@ -1557,6 +1598,9 @@ focusclient(Client *c, int lift)
|
|||||||
|
|
||||||
/* Activate the new client */
|
/* Activate the new client */
|
||||||
client_activate_surface(client_surface(c), 1);
|
client_activate_surface(client_surface(c), 1);
|
||||||
|
|
||||||
|
if (!client_is_unmanaged(c))
|
||||||
|
focused_client = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1568,7 +1612,7 @@ focusmon(const Arg *arg)
|
|||||||
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), NULL, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1594,7 +1638,7 @@ focusstack(const Arg *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* If only one client is visible on selmon, then c == sel */
|
/* If only one client is visible on selmon, then c == sel */
|
||||||
focusclient(c, 1);
|
focusclient(c, NULL, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We probably should change the name of this: it sounds like it
|
/* We probably should change the name of this: it sounds like it
|
||||||
@@ -1701,58 +1745,53 @@ keybinding(uint32_t mods, xkb_keysym_t sym)
|
|||||||
*/
|
*/
|
||||||
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)
|
||||||
&& xkb_keysym_to_lower(sym) == xkb_keysym_to_lower(k->keysym)
|
|
||||||
&& k->func) {
|
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
keypress(struct wl_listener *listener, void *data)
|
keypress(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
/* This event is raised when a key is pressed or released. */
|
/* This event is raised when a key is pressed or released. */
|
||||||
KeyboardGroup *group = wl_container_of(listener, group, 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 */
|
||||||
uint32_t keycode = event->keycode + 8;
|
uint32_t keycode = event->keycode + 8;
|
||||||
/* Get a list of keysyms based on the keymap for this keyboard */
|
struct wlr_keyboard *kb = &group->wlr_group->keyboard;
|
||||||
const xkb_keysym_t *syms;
|
xkb_layout_index_t layout = xkb_state_key_get_layout(kb->xkb_state, keycode);
|
||||||
int nsyms = xkb_state_key_get_syms(
|
|
||||||
group->wlr_group->keyboard.xkb_state, keycode, &syms);
|
|
||||||
|
|
||||||
int handled = 0;
|
int handled = 0;
|
||||||
uint32_t mods = wlr_keyboard_get_modifiers(&group->wlr_group->keyboard);
|
|
||||||
|
// Get the keysyms for level 0 (normal) and level 1 (shifted)
|
||||||
|
// Only one keysym for each level:
|
||||||
|
// multiple keysyms per keycode don't really exist in the real world
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
group->keysyms[i] = keymap_get_one_sym_by_level(kb->keymap, keycode, layout, i);
|
||||||
|
group->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);
|
||||||
|
|
||||||
/* On _press_ if there is no active screen locker,
|
/* On _press_ if there is no active screen locker,
|
||||||
* attempt to process a compositor keybinding. */
|
* attempt to process a compositor keybinding. */
|
||||||
if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||||
for (i = 0; i < nsyms; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
const Key *key = keybinding(mods, syms[i]);
|
const Key *key = keybinding(group->mods, group->keysyms[i]);
|
||||||
if (key) {
|
if (key) {
|
||||||
consumed[event->keycode] = 1;
|
consumed[event->keycode] = 1;
|
||||||
key->func(&key->arg);
|
key->func(&key->arg);
|
||||||
handled = 1;
|
handled = 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handled && group->wlr_group->keyboard.repeat_info.delay > 0) {
|
if (handled && group->wlr_group->keyboard.repeat_info.delay > 0)
|
||||||
group->mods = mods;
|
|
||||||
group->keysyms = syms;
|
|
||||||
group->nsyms = nsyms;
|
|
||||||
wl_event_source_timer_update(group->key_repeat_source,
|
wl_event_source_timer_update(group->key_repeat_source,
|
||||||
group->wlr_group->keyboard.repeat_info.delay);
|
group->wlr_group->keyboard.repeat_info.delay);
|
||||||
} else {
|
else
|
||||||
group->nsyms = 0;
|
|
||||||
wl_event_source_timer_update(group->key_repeat_source, 0);
|
wl_event_source_timer_update(group->key_repeat_source, 0);
|
||||||
}
|
|
||||||
|
|
||||||
if (handled || input_method_keyboard_grab_forward_key(group, event))
|
if (handled || input_method_keyboard_grab_forward_key(group, event))
|
||||||
return;
|
return;
|
||||||
@@ -1788,17 +1827,18 @@ int
|
|||||||
keyrepeat(void *data)
|
keyrepeat(void *data)
|
||||||
{
|
{
|
||||||
KeyboardGroup *group = data;
|
KeyboardGroup *group = data;
|
||||||
int i;
|
if (locked || group->wlr_group->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(group->key_repeat_source,
|
wl_event_source_timer_update(group->key_repeat_source,
|
||||||
1000 / group->wlr_group->keyboard.repeat_info.rate);
|
1000 / group->wlr_group->keyboard.repeat_info.rate);
|
||||||
|
|
||||||
for (i = 0; i < group->nsyms; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
const Key *key = keybinding(group->mods, group->keysyms[i]);
|
const Key *key = keybinding(group->mods, group->keysyms[i]);
|
||||||
if (key)
|
if (key) {
|
||||||
key->func(&key->arg);
|
key->func(&key->arg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1823,12 +1863,18 @@ locksession(struct wl_listener *listener, void *data)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lock = session_lock->data = ecalloc(1, sizeof(*lock));
|
lock = session_lock->data = ecalloc(1, sizeof(*lock));
|
||||||
focusclient(NULL, 0);
|
focusclient(NULL, NULL, 0);
|
||||||
|
|
||||||
lock->scene = wlr_scene_tree_create(layers[LyrBlock]);
|
lock->scene = wlr_scene_tree_create(layers[LyrBlock]);
|
||||||
cur_lock = lock->lock = session_lock;
|
cur_lock = lock->lock = session_lock;
|
||||||
locked = 1;
|
locked = 1;
|
||||||
|
|
||||||
|
/* Cancel any interactive move/resize and take the pointer focus away
|
||||||
|
* from the clients below the lock screen */
|
||||||
|
cursor_mode = CurNormal;
|
||||||
|
grabc = NULL;
|
||||||
|
motionnotify(0, NULL, 0, 0, 0, 0);
|
||||||
|
|
||||||
LISTEN(&session_lock->events.new_surface, &lock->new_surface, createlocksurface);
|
LISTEN(&session_lock->events.new_surface, &lock->new_surface, createlocksurface);
|
||||||
LISTEN(&session_lock->events.destroy, &lock->destroy, destroysessionlock);
|
LISTEN(&session_lock->events.destroy, &lock->destroy, destroysessionlock);
|
||||||
LISTEN(&session_lock->events.unlock, &lock->unlock, unlocksession);
|
LISTEN(&session_lock->events.unlock, &lock->unlock, unlocksession);
|
||||||
@@ -1864,13 +1910,10 @@ mapnotify(struct wl_listener *listener, void *data)
|
|||||||
/* Handle unmanaged clients first so we can return prior create borders */
|
/* Handle unmanaged clients first so we can return prior create borders */
|
||||||
if (client_is_unmanaged(c)) {
|
if (client_is_unmanaged(c)) {
|
||||||
/* 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[LyrUnmanaged]);
|
||||||
wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y);
|
wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y);
|
||||||
client_set_size(c, c->geom.width, c->geom.height);
|
if (client_wants_focus(c))
|
||||||
if (client_wants_focus(c)) {
|
focusclient(c, NULL, 1);
|
||||||
focusclient(c, 1);
|
|
||||||
exclusive_focus = c;
|
|
||||||
}
|
|
||||||
goto unset_fullscreen;
|
goto unset_fullscreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1881,7 +1924,6 @@ mapnotify(struct wl_listener *listener, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize client geometry with room for border */
|
/* Initialize client geometry with room for border */
|
||||||
client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
|
|
||||||
c->geom.width += 2 * c->bw;
|
c->geom.width += 2 * c->bw;
|
||||||
c->geom.height += 2 * c->bw;
|
c->geom.height += 2 * c->bw;
|
||||||
|
|
||||||
@@ -2127,48 +2169,60 @@ outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test)
|
|||||||
* output_layout.change event, not here.
|
* output_layout.change event, not here.
|
||||||
*/
|
*/
|
||||||
struct wlr_output_configuration_head_v1 *config_head;
|
struct wlr_output_configuration_head_v1 *config_head;
|
||||||
int ok = 1;
|
size_t states_len, i;
|
||||||
|
struct wlr_output_swapchain_manager swapchain_manager;
|
||||||
|
struct wlr_backend_output_state *states =
|
||||||
|
wlr_output_configuration_v1_build_state(config, &states_len);
|
||||||
|
int ok = 0;
|
||||||
|
|
||||||
|
if (!states) {
|
||||||
|
wlr_output_configuration_v1_send_failed(config);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_output_swapchain_manager_init(&swapchain_manager, backend);
|
||||||
|
|
||||||
|
ok = wlr_output_swapchain_manager_prepare(&swapchain_manager, states, states_len);
|
||||||
|
if (!ok || test)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
for (i = 0; i < states_len; i++) {
|
||||||
|
struct wlr_swapchain *swapchain = wlr_output_swapchain_manager_get_swapchain(
|
||||||
|
&swapchain_manager, states[i].output);
|
||||||
|
if (swapchain && !states[i].output->enabled)
|
||||||
|
wlr_output_state_set_buffer(&states[i].base, wlr_swapchain_acquire(swapchain));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(ok = wlr_backend_commit(backend, states, states_len)))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
wlr_output_swapchain_manager_apply(&swapchain_manager);
|
||||||
|
|
||||||
wl_list_for_each(config_head, &config->heads, link) {
|
wl_list_for_each(config_head, &config->heads, link) {
|
||||||
struct wlr_output *wlr_output = config_head->state.output;
|
struct wlr_output *wlr_output = config_head->state.output;
|
||||||
Monitor *m = wlr_output->data;
|
Monitor *m = wlr_output->data;
|
||||||
struct wlr_output_state state;
|
|
||||||
|
|
||||||
/* Ensure displays previously disabled by wlr-output-power-management-v1
|
/* Ensure displays previously disabled by wlr-output-power-management-v1
|
||||||
* are properly handled*/
|
* are properly handled*/
|
||||||
m->asleep = 0;
|
m->asleep = 0;
|
||||||
|
|
||||||
wlr_output_state_init(&state);
|
|
||||||
wlr_output_state_set_enabled(&state, config_head->state.enabled);
|
|
||||||
if (!config_head->state.enabled)
|
|
||||||
goto apply_or_test;
|
|
||||||
|
|
||||||
if (config_head->state.mode)
|
|
||||||
wlr_output_state_set_mode(&state, config_head->state.mode);
|
|
||||||
else
|
|
||||||
wlr_output_state_set_custom_mode(&state,
|
|
||||||
config_head->state.custom_mode.width,
|
|
||||||
config_head->state.custom_mode.height,
|
|
||||||
config_head->state.custom_mode.refresh);
|
|
||||||
|
|
||||||
wlr_output_state_set_transform(&state, config_head->state.transform);
|
|
||||||
wlr_output_state_set_scale(&state, config_head->state.scale);
|
|
||||||
wlr_output_state_set_adaptive_sync_enabled(&state,
|
|
||||||
config_head->state.adaptive_sync_enabled);
|
|
||||||
|
|
||||||
apply_or_test:
|
|
||||||
ok &= test ? wlr_output_test_state(wlr_output, &state)
|
|
||||||
: wlr_output_commit_state(wlr_output, &state);
|
|
||||||
|
|
||||||
/* Don't move monitors if position wouldn't change. This avoids
|
/* Don't move monitors if position wouldn't change. This avoids
|
||||||
* wlroots marking the output as manually configured.
|
* wlroots marking the output as manually configured.
|
||||||
* wlr_output_layout_add does not like disabled outputs */
|
* wlr_output_layout_add does not like disabled outputs */
|
||||||
if (!test && wlr_output->enabled && (m->m.x != config_head->state.x || m->m.y != config_head->state.y))
|
if (config_head->state.enabled
|
||||||
|
&& (m->m.x != config_head->state.x || m->m.y != config_head->state.y
|
||||||
|
|| !wlr_output_layout_get(output_layout, wlr_output))) {
|
||||||
wlr_output_layout_add(output_layout, wlr_output,
|
wlr_output_layout_add(output_layout, wlr_output,
|
||||||
config_head->state.x, config_head->state.y);
|
config_head->state.x, config_head->state.y);
|
||||||
|
|
||||||
wlr_output_state_finish(&state);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
wlr_output_swapchain_manager_finish(&swapchain_manager);
|
||||||
|
for (i = 0; i < states_len; i++)
|
||||||
|
wlr_output_state_finish(&states[i].base);
|
||||||
|
|
||||||
|
free(states);
|
||||||
|
|
||||||
if (ok)
|
if (ok)
|
||||||
wlr_output_configuration_v1_send_succeeded(config);
|
wlr_output_configuration_v1_send_succeeded(config);
|
||||||
@@ -2195,10 +2249,9 @@ pointerfocus(Client *c, LayerSurface *l, struct wlr_surface *surface, double sx,
|
|||||||
|
|
||||||
if (surface != seat->pointer_state.focused_surface && sloppyfocus && time) {
|
if (surface != seat->pointer_state.focused_surface && sloppyfocus && time) {
|
||||||
if (c && (!client_is_unmanaged(c) || client_wants_focus(c))) {
|
if (c && (!client_is_unmanaged(c) || client_wants_focus(c))) {
|
||||||
focusclient(c, 0);
|
focusclient(c, NULL, 0);
|
||||||
} else if (l && l->layer_surface->current.keyboard_interactive) {
|
} else if (l && l->layer_surface->current.keyboard_interactive) {
|
||||||
focusclient(NULL, 0);
|
focusclient(NULL, l, 0);
|
||||||
client_notify_enter(l->layer_surface->surface, wlr_seat_get_keyboard(seat));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2354,9 +2407,7 @@ resize(Client *c, struct wlr_box geo, int interact)
|
|||||||
wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
|
wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
|
||||||
wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw);
|
wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw);
|
||||||
|
|
||||||
/* this is a no-op if size hasn't changed */
|
client_set_size(c, c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw);
|
||||||
c->resize = client_set_size(c, c->geom.width - 2 * c->bw,
|
|
||||||
c->geom.height - 2 * c->bw);
|
|
||||||
client_get_clip(c, &clip);
|
client_get_clip(c, &clip);
|
||||||
wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip);
|
wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip);
|
||||||
}
|
}
|
||||||
@@ -2543,7 +2594,7 @@ setmon(Client *c, Monitor *m, uint32_t newtags)
|
|||||||
setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */
|
setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */
|
||||||
setfloating(c, c->isfloating);
|
setfloating(c, c->isfloating);
|
||||||
}
|
}
|
||||||
focusclient(focustop(selmon), 1);
|
focusclient(focustop(selmon), NULL, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -2783,7 +2834,6 @@ setup(void)
|
|||||||
|
|
||||||
input_method_manager = wlr_input_method_manager_v2_create(dpy);
|
input_method_manager = wlr_input_method_manager_v2_create(dpy);
|
||||||
text_input_manager = wlr_text_input_manager_v3_create(dpy);
|
text_input_manager = wlr_text_input_manager_v3_create(dpy);
|
||||||
input_method_relay = ecalloc(1, sizeof(*input_method_relay));
|
|
||||||
input_method_relay = input_method_relay_create();
|
input_method_relay = input_method_relay_create();
|
||||||
|
|
||||||
/* Make sure XWayland clients don't connect to the parent X server,
|
/* Make sure XWayland clients don't connect to the parent X server,
|
||||||
@@ -2836,7 +2886,7 @@ tag(const Arg *arg)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
sel->tags = arg->ui & TAGMASK;
|
sel->tags = arg->ui & TAGMASK;
|
||||||
focusclient(focustop(selmon), 1);
|
focusclient(focustop(selmon), NULL, 1);
|
||||||
arrange(selmon);
|
arrange(selmon);
|
||||||
printstatus();
|
printstatus();
|
||||||
}
|
}
|
||||||
@@ -2909,7 +2959,7 @@ toggletag(const Arg *arg)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
sel->tags = newtags;
|
sel->tags = newtags;
|
||||||
focusclient(focustop(selmon), 1);
|
focusclient(focustop(selmon), NULL, 1);
|
||||||
arrange(selmon);
|
arrange(selmon);
|
||||||
printstatus();
|
printstatus();
|
||||||
}
|
}
|
||||||
@@ -2922,7 +2972,7 @@ toggleview(const Arg *arg)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
selmon->tagset[selmon->seltags] = newtagset;
|
selmon->tagset[selmon->seltags] = newtagset;
|
||||||
focusclient(focustop(selmon), 1);
|
focusclient(focustop(selmon), NULL, 1);
|
||||||
arrange(selmon);
|
arrange(selmon);
|
||||||
printstatus();
|
printstatus();
|
||||||
}
|
}
|
||||||
@@ -2941,12 +2991,10 @@ unmaplayersurfacenotify(struct wl_listener *listener, void *data)
|
|||||||
|
|
||||||
l->mapped = 0;
|
l->mapped = 0;
|
||||||
wlr_scene_node_set_enabled(&l->scene->node, 0);
|
wlr_scene_node_set_enabled(&l->scene->node, 0);
|
||||||
if (l == exclusive_focus)
|
|
||||||
exclusive_focus = NULL;
|
|
||||||
if (l->layer_surface->output && (l->mon = l->layer_surface->output->data))
|
if (l->layer_surface->output && (l->mon = l->layer_surface->output->data))
|
||||||
arrangelayers(l->mon);
|
arrangelayers(l->mon);
|
||||||
if (l->layer_surface->surface == seat->keyboard_state.focused_surface)
|
if (l->layer_surface->surface == seat->keyboard_state.focused_surface)
|
||||||
focusclient(focustop(selmon), 1);
|
focusclient(focustop(selmon), NULL, 1);
|
||||||
motionnotify(0, NULL, 0, 0, 0, 0);
|
motionnotify(0, NULL, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2959,16 +3007,15 @@ unmapnotify(struct wl_listener *listener, void *data)
|
|||||||
cursor_mode = CurNormal;
|
cursor_mode = CurNormal;
|
||||||
grabc = NULL;
|
grabc = NULL;
|
||||||
}
|
}
|
||||||
|
if (c == focused_client)
|
||||||
|
focused_client = NULL;
|
||||||
|
|
||||||
if (client_is_unmanaged(c)) {
|
if (!client_is_unmanaged(c)) {
|
||||||
if (c == exclusive_focus) {
|
|
||||||
exclusive_focus = NULL;
|
|
||||||
focusclient(focustop(selmon), 1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
wl_list_remove(&c->link);
|
wl_list_remove(&c->link);
|
||||||
setmon(c, NULL, 0);
|
setmon(c, NULL, 0);
|
||||||
wl_list_remove(&c->flink);
|
wl_list_remove(&c->flink);
|
||||||
|
} else if (client_wants_focus(c)) {
|
||||||
|
focusclient(focustop(selmon), NULL, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->foreign_toplevel_handle) {
|
if (c->foreign_toplevel_handle) {
|
||||||
@@ -2983,6 +3030,8 @@ unmapnotify(struct wl_listener *listener, void *data)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
wlr_scene_node_destroy(&c->image_capture_scene->tree.node);
|
wlr_scene_node_destroy(&c->image_capture_scene->tree.node);
|
||||||
|
c->image_capture_scene = NULL;
|
||||||
|
c->image_capture_source = NULL;
|
||||||
wlr_scene_node_destroy(&c->scene->node);
|
wlr_scene_node_destroy(&c->scene->node);
|
||||||
client_surface(c)->data = NULL;
|
client_surface(c)->data = NULL;
|
||||||
printstatus();
|
printstatus();
|
||||||
@@ -3080,7 +3129,7 @@ updatemons(struct wl_listener *listener, void *data)
|
|||||||
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), NULL, 1);
|
||||||
if (selmon->lock_surface) {
|
if (selmon->lock_surface) {
|
||||||
client_notify_enter(selmon->lock_surface->surface,
|
client_notify_enter(selmon->lock_surface->surface,
|
||||||
wlr_seat_get_keyboard(seat));
|
wlr_seat_get_keyboard(seat));
|
||||||
@@ -3139,7 +3188,7 @@ view(const Arg *arg)
|
|||||||
selmon->seltags ^= 1; /* toggle sel tagset */
|
selmon->seltags ^= 1; /* toggle sel tagset */
|
||||||
if (arg->ui & TAGMASK)
|
if (arg->ui & TAGMASK)
|
||||||
selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
|
selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
|
||||||
focusclient(focustop(selmon), 1);
|
focusclient(focustop(selmon), NULL, 1);
|
||||||
arrange(selmon);
|
arrange(selmon);
|
||||||
printstatus();
|
printstatus();
|
||||||
}
|
}
|
||||||
@@ -3187,7 +3236,7 @@ xytonode(double x, double y, struct wlr_surface **psurface,
|
|||||||
struct wlr_surface *surface = NULL;
|
struct wlr_surface *surface = NULL;
|
||||||
int layer;
|
int layer;
|
||||||
|
|
||||||
for (layer = NUM_LAYERS - 1; !surface && layer >= 0; layer--) {
|
for (layer = NUM_LAYERS - 1; !surface && layer >= (locked ? LyrBlock : 0); layer--) {
|
||||||
if (layer == LyrIMPopup ||
|
if (layer == LyrIMPopup ||
|
||||||
!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny)))
|
!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny)))
|
||||||
continue;
|
continue;
|
||||||
@@ -3230,7 +3279,7 @@ zoom(const Arg *arg)
|
|||||||
wl_list_remove(&sel->link);
|
wl_list_remove(&sel->link);
|
||||||
wl_list_insert(&clients, &sel->link);
|
wl_list_insert(&clients, &sel->link);
|
||||||
|
|
||||||
focusclient(sel, 1);
|
focusclient(sel, NULL, 1);
|
||||||
arrange(selmon);
|
arrange(selmon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3259,13 +3308,8 @@ configurex11(struct wl_listener *listener, void *data)
|
|||||||
{
|
{
|
||||||
Client *c = wl_container_of(listener, c, configure);
|
Client *c = wl_container_of(listener, c, configure);
|
||||||
struct wlr_xwayland_surface_configure_event *event = data;
|
struct wlr_xwayland_surface_configure_event *event = data;
|
||||||
if (!client_surface(c) || !client_surface(c)->mapped) {
|
if (!client_surface(c) || !client_surface(c)->mapped
|
||||||
wlr_xwayland_surface_configure(c->surface.xwayland,
|
|| client_is_unmanaged(c)) {
|
||||||
event->x, event->y, event->width, event->height);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (client_is_unmanaged(c)) {
|
|
||||||
wlr_scene_node_set_position(&c->scene->node, event->x, event->y);
|
|
||||||
wlr_xwayland_surface_configure(c->surface.xwayland,
|
wlr_xwayland_surface_configure(c->surface.xwayland,
|
||||||
event->x, event->y, event->width, event->height);
|
event->x, event->y, event->width, event->height);
|
||||||
return;
|
return;
|
||||||
@@ -3298,6 +3342,7 @@ createnotifyx11(struct wl_listener *listener, void *data)
|
|||||||
LISTEN(&xsurface->events.request_activate, &c->activate, activatex11);
|
LISTEN(&xsurface->events.request_activate, &c->activate, activatex11);
|
||||||
LISTEN(&xsurface->events.request_configure, &c->configure, configurex11);
|
LISTEN(&xsurface->events.request_configure, &c->configure, configurex11);
|
||||||
LISTEN(&xsurface->events.request_fullscreen, &c->fullscreen, fullscreennotify);
|
LISTEN(&xsurface->events.request_fullscreen, &c->fullscreen, fullscreennotify);
|
||||||
|
LISTEN(&xsurface->events.set_geometry, &c->set_geometry, setgeometryx11);
|
||||||
LISTEN(&xsurface->events.set_hints, &c->set_hints, sethints);
|
LISTEN(&xsurface->events.set_hints, &c->set_hints, sethints);
|
||||||
LISTEN(&xsurface->events.set_title, &c->set_title, updatetitle);
|
LISTEN(&xsurface->events.set_title, &c->set_title, updatetitle);
|
||||||
}
|
}
|
||||||
@@ -3310,6 +3355,19 @@ dissociatex11(struct wl_listener *listener, void *data)
|
|||||||
wl_list_remove(&c->unmap.link);
|
wl_list_remove(&c->unmap.link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
setgeometryx11(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
Client *c = wl_container_of(listener, c, set_geometry);
|
||||||
|
|
||||||
|
if (!client_is_unmanaged(c) || !client_surface(c)
|
||||||
|
|| !client_surface(c)->mapped)
|
||||||
|
return;
|
||||||
|
|
||||||
|
client_get_geometry(c, &c->geom);
|
||||||
|
wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sethints(struct wl_listener *listener, void *data)
|
sethints(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -594,7 +594,7 @@ handle_focused_surface_destroy(struct wl_listener *listener,
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct input_method_relay *
|
struct input_method_relay *
|
||||||
input_method_relay_create()
|
input_method_relay_create(void)
|
||||||
{
|
{
|
||||||
struct input_method_relay *relay = ecalloc(1, sizeof(*relay));
|
struct input_method_relay *relay = ecalloc(1, sizeof(*relay));
|
||||||
wl_list_init(&relay->text_inputs);
|
wl_list_init(&relay->text_inputs);
|
||||||
@@ -625,7 +625,7 @@ void
|
|||||||
input_method_relay_set_focus(struct input_method_relay *relay,
|
input_method_relay_set_focus(struct input_method_relay *relay,
|
||||||
struct wlr_surface *surface)
|
struct wlr_surface *surface)
|
||||||
{
|
{
|
||||||
if (relay->focused_surface == surface)
|
if (!relay || relay->focused_surface == surface)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (relay->focused_surface)
|
if (relay->focused_surface)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||||
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||||
@@ -13,6 +14,8 @@
|
|||||||
static void die(const char *fmt, ...);
|
static void die(const char *fmt, ...);
|
||||||
static void *ecalloc(size_t nmemb, size_t size);
|
static void *ecalloc(size_t nmemb, size_t size);
|
||||||
static int fd_set_nonblock(int fd);
|
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
|
void
|
||||||
die(const char *fmt, ...) {
|
die(const char *fmt, ...) {
|
||||||
@@ -56,3 +59,12 @@ fd_set_nonblock(int fd) {
|
|||||||
|
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user