Compare commits
46 commits
Author | SHA1 | Date | |
---|---|---|---|
002c7d2204 | |||
8206cc8889 | |||
54f207839f | |||
9c05b9622c | |||
d34be5d545 | |||
c49312f084 | |||
f899060965 | |||
cc72df11d6 | |||
0312720ae8 | |||
6de87121e2 | |||
bbc00d88a4 | |||
54b546121b | |||
43016bdad8 | |||
b616476c85 | |||
d4ad37354e | |||
5db05e82bd | |||
8ec5e52e06 | |||
c5275ca571 | |||
2c0b889f86 | |||
554754c9a2 | |||
0caa658276 | |||
07aeef1f7e | |||
e454f7ae81 | |||
334bbe6f0f | |||
1b805ddd38 | |||
94f4ead7da | |||
bb21ecda30 | |||
b25717c939 | |||
a4fa954616 | |||
35951a8d7e | |||
a634e3f527 | |||
d136dadf45 | |||
672b4c405d | |||
b5abbc37d8 | |||
986beef5be | |||
487abc28ba | |||
cd216908a7 | |||
f2c5023a3a | |||
4bbbb4907e | |||
ea6a450121 | |||
ad30ca910b | |||
452a314faa | |||
da6de7c4d7 | |||
2553111aa3 | |||
51881da27b | |||
7328e5691c |
2
.mailmap
2
.mailmap
|
@ -1 +1,3 @@
|
|||
Lennart Jablonka <humm@ljabl.com> <hummsmith42@gmail.com>
|
||||
Leonardo Hernández Hernández <leohdz172@proton.me> <leohdz172@outlook.com>
|
||||
Leonardo Hernández Hernández <leohdz172@proton.me> <leohdz172@protonmail.com>
|
||||
|
|
31
CHANGELOG.md
31
CHANGELOG.md
|
@ -1,13 +1,36 @@
|
|||
# Changelog
|
||||
|
||||
* [Unreleased](#unreleased)
|
||||
* [0.7](#0.7)
|
||||
* [0.6](#0.6)
|
||||
* [0.5](#0.5)
|
||||
|
||||
|
||||
## Unreleased
|
||||
### Added
|
||||
|
||||
* Support for the linux-drm-syncobj-v1 protocol ([wlroots!4715][wlroots!4715], [#685][685])
|
||||
* Allow the use of non-system wlroots library ([#646][646])
|
||||
|
||||
[wlroots!4715]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4715
|
||||
[685]: https://codeberg.org/dwl/dwl/pulls/685
|
||||
[646]: https://codeberg.org/dwl/dwl/pulls/646
|
||||
|
||||
|
||||
### Changed
|
||||
### Deprecated
|
||||
### Removed
|
||||
### Fixed
|
||||
|
||||
* Crash when a client is created while all outputs are disabled.
|
||||
|
||||
### Security
|
||||
### Contributors
|
||||
|
||||
|
||||
## 0.7
|
||||
|
||||
See also [0.6](#0.6) release notes. 0.7 builds against wlroots 0.18.x.
|
||||
This version is just 0.6 with wlroots 0.18 compatibility.
|
||||
|
||||
### Added
|
||||
|
||||
|
@ -18,15 +41,9 @@ See also [0.6](#0.6) release notes. 0.7 builds against wlroots 0.18.x.
|
|||
[601]: https://codeberg.org/dwl/dwl/issues/601
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
* Crash when re-mapping unmapped clients.
|
||||
|
||||
|
||||
### Contributors
|
||||
|
||||
Guido Cella
|
||||
Lennart Jablonka
|
||||
|
||||
|
||||
## 0.6
|
||||
|
|
22
Makefile
22
Makefile
|
@ -6,25 +6,23 @@ include config.mk
|
|||
# flags for compiling
|
||||
DWLCPPFLAGS = -I. -DWLR_USE_UNSTABLE -D_POSIX_C_SOURCE=200809L \
|
||||
-DVERSION=\"$(VERSION)\" $(XWAYLAND)
|
||||
DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement \
|
||||
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 \
|
||||
-Wfloat-conversion
|
||||
|
||||
# CFLAGS / LDFLAGS
|
||||
PKGS = wlroots-0.18 wayland-server xkbcommon libinput $(XLIBS)
|
||||
DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS)
|
||||
LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` -lm $(LIBS)
|
||||
PKGS = wayland-server xkbcommon libinput $(XLIBS)
|
||||
DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(WLR_INCS) $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS)
|
||||
LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(WLR_LIBS) -lm $(LIBS)
|
||||
|
||||
all: dwl
|
||||
dwl: dwl.o util.o dwl-ipc-unstable-v2-protocol.o
|
||||
$(CC) dwl.o util.o dwl-ipc-unstable-v2-protocol.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@
|
||||
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 \
|
||||
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 \
|
||||
dwl-ipc-unstable-v2-protocol.h
|
||||
wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h
|
||||
util.o: util.c util.h
|
||||
dwl-ipc-unstable-v2-protocol.o: dwl-ipc-unstable-v2-protocol.c dwl-ipc-unstable-v2-protocol.h
|
||||
|
||||
# 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
|
||||
|
@ -47,12 +45,6 @@ wlr-output-power-management-unstable-v1-protocol.h:
|
|||
xdg-shell-protocol.h:
|
||||
$(WAYLAND_SCANNER) server-header \
|
||||
$(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@
|
||||
dwl-ipc-unstable-v2-protocol.h:
|
||||
$(WAYLAND_SCANNER) server-header \
|
||||
protocols/dwl-ipc-unstable-v2.xml $@
|
||||
dwl-ipc-unstable-v2-protocol.c:
|
||||
$(WAYLAND_SCANNER) private-code \
|
||||
protocols/dwl-ipc-unstable-v2.xml $@
|
||||
|
||||
config.h:
|
||||
cp config.def.h $@
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# dwl - dwm for Wayland
|
||||
|
||||
Join us on our IRC channel: [#dwl on Libera Chat]
|
||||
Or on our [Discord server].
|
||||
Or on the community-maintained [Discord server].
|
||||
|
||||
dwl is a compact, hackable compositor for [Wayland] based on [wlroots]. It is
|
||||
intended to fill the same space in the Wayland world that dwm does in X11,
|
||||
|
@ -14,8 +14,6 @@ philosophy. Like dwm, dwl is:
|
|||
|
||||
## Getting Started:
|
||||
|
||||
### **dwl branch 0.7 and releases based upon 0.7 build against [wlroots] 0.18**
|
||||
|
||||
### Latest semi-stable [release]
|
||||
This is probably where you want to start. This builds against the dependent
|
||||
packages' versions currently shipping in major distributions. If your
|
||||
|
|
43
client.h
43
client.h
|
@ -126,15 +126,14 @@ client_get_appid(Client *c)
|
|||
{
|
||||
#ifdef XWAYLAND
|
||||
if (client_is_x11(c))
|
||||
return c->surface.xwayland->class;
|
||||
return c->surface.xwayland->class ? c->surface.xwayland->class : "broken";
|
||||
#endif
|
||||
return c->surface.xdg->toplevel->app_id;
|
||||
return c->surface.xdg->toplevel->app_id ? c->surface.xdg->toplevel->app_id : "broken";
|
||||
}
|
||||
|
||||
static inline void
|
||||
client_get_clip(Client *c, struct wlr_box *clip)
|
||||
{
|
||||
struct wlr_box xdg_geom = {0};
|
||||
*clip = (struct wlr_box){
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
|
@ -147,9 +146,8 @@ client_get_clip(Client *c, struct wlr_box *clip)
|
|||
return;
|
||||
#endif
|
||||
|
||||
wlr_xdg_surface_get_geometry(c->surface.xdg, &xdg_geom);
|
||||
clip->x = xdg_geom.x;
|
||||
clip->y = xdg_geom.y;
|
||||
clip->x = c->surface.xdg->geometry.x;
|
||||
clip->y = c->surface.xdg->geometry.y;
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -164,7 +162,7 @@ client_get_geometry(Client *c, struct wlr_box *geom)
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
wlr_xdg_surface_get_geometry(c->surface.xdg, geom);
|
||||
*geom = c->surface.xdg->geometry;
|
||||
}
|
||||
|
||||
static inline Client *
|
||||
|
@ -200,9 +198,9 @@ client_get_title(Client *c)
|
|||
{
|
||||
#ifdef XWAYLAND
|
||||
if (client_is_x11(c))
|
||||
return c->surface.xwayland->title;
|
||||
return c->surface.xwayland->title ? c->surface.xwayland->title : "broken";
|
||||
#endif
|
||||
return c->surface.xdg->toplevel->title;
|
||||
return c->surface.xdg->toplevel->title ? c->surface.xdg->toplevel->title : "broken";
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
@ -301,17 +299,6 @@ client_notify_enter(struct wlr_surface *s, struct wlr_keyboard *kb)
|
|||
wlr_seat_keyboard_notify_enter(seat, s, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
static inline void
|
||||
client_restack_surface(Client *c)
|
||||
{
|
||||
#ifdef XWAYLAND
|
||||
if (client_is_x11(c))
|
||||
wlr_xwayland_surface_restack(c->surface.xwayland, NULL,
|
||||
XCB_STACK_MODE_ABOVE);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void
|
||||
client_send_close(Client *c)
|
||||
{
|
||||
|
@ -344,6 +331,13 @@ client_set_fullscreen(Client *c, int fullscreen)
|
|||
wlr_xdg_toplevel_set_fullscreen(c->surface.xdg->toplevel, fullscreen);
|
||||
}
|
||||
|
||||
static inline void
|
||||
client_set_scale(struct wlr_surface *s, float scale)
|
||||
{
|
||||
wlr_fractional_scale_v1_notify_scale(s, scale);
|
||||
wlr_surface_set_preferred_buffer_scale(s, (int32_t)ceilf(scale));
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
client_set_size(Client *c, uint32_t width, uint32_t height)
|
||||
{
|
||||
|
@ -364,8 +358,11 @@ static inline void
|
|||
client_set_tiled(Client *c, uint32_t edges)
|
||||
{
|
||||
#ifdef XWAYLAND
|
||||
if (client_is_x11(c))
|
||||
if (client_is_x11(c)) {
|
||||
wlr_xwayland_surface_set_maximized(c->surface.xwayland,
|
||||
edges != WLR_EDGE_NONE, edges != WLR_EDGE_NONE);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (wl_resource_get_version(c->surface.xdg->toplevel->resource)
|
||||
>= XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) {
|
||||
|
@ -391,8 +388,8 @@ client_wants_focus(Client *c)
|
|||
{
|
||||
#ifdef XWAYLAND
|
||||
return client_is_unmanaged(c)
|
||||
&& wlr_xwayland_or_surface_wants_focus(c->surface.xwayland)
|
||||
&& wlr_xwayland_icccm_input_model(c->surface.xwayland) != WLR_ICCCM_INPUT_MODEL_NONE;
|
||||
&& wlr_xwayland_surface_override_redirect_wants_focus(c->surface.xwayland)
|
||||
&& wlr_xwayland_surface_icccm_input_model(c->surface.xwayland) != WLR_ICCCM_INPUT_MODEL_NONE;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -107,13 +107,13 @@ LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right
|
|||
static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM;
|
||||
|
||||
/* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */
|
||||
#define MODKEY WLR_MODIFIER_LOGO
|
||||
#define MODKEY WLR_MODIFIER_ALT
|
||||
|
||||
#define TAGKEYS(KEY,TAG) \
|
||||
#define TAGKEYS(KEY,SKEY,TAG) \
|
||||
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
|
||||
{ MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, KEY, tag, {.ui = 1 << TAG} }, \
|
||||
{ MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,KEY,toggletag, {.ui = 1 << TAG} }
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \
|
||||
{ MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} }
|
||||
|
||||
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
|
||||
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
|
||||
|
@ -127,7 +127,6 @@ static const Key keys[] = {
|
|||
/* modifier key function argument */
|
||||
{ MODKEY, XKB_KEY_p, spawn, {.v = menucmd} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} },
|
||||
{ MODKEY, XKB_KEY_b, togglebar, {0} },
|
||||
{ MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
|
||||
{ MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
|
||||
{ MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
|
||||
|
|
23
config.mk
23
config.mk
|
@ -1,4 +1,4 @@
|
|||
_VERSION = 0.7
|
||||
_VERSION = 0.8-dev
|
||||
VERSION = `git describe --tags --dirty 2>/dev/null || echo $(_VERSION)`
|
||||
|
||||
PKG_CONFIG = pkg-config
|
||||
|
@ -8,10 +8,29 @@ 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`
|
||||
|
||||
# Allow using an alternative wlroots installations
|
||||
# This has to have all the includes required by wlroots, e.g:
|
||||
# Assuming wlroots git repo is "${PWD}/wlroots" and you only ran "meson setup build && ninja -C build"
|
||||
#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
|
||||
|
||||
# Assuming you ran "meson setup --prefix ${PWD}/0.19 build && ninja -C build install"
|
||||
#WLR_INCS = -I/usr/include/pixman-1 -I/usr/include/elogind -I/usr/include/libdrm \
|
||||
# -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
|
||||
|
||||
XWAYLAND =
|
||||
XLIBS =
|
||||
# Uncomment to build XWayland support
|
||||
#XWAYLAND = -DXWAYLAND
|
||||
#XLIBS = xcb xcb-icccm
|
||||
|
||||
CC = gcc
|
||||
# dwl itself only uses C99 features, but wlroots' headers use anonymous unions (C11).
|
||||
# To avoid warnings about them, we do not use -std=c99 and instead of using the
|
||||
# gmake default 'CC=c99', we use cc.
|
||||
CC = cc
|
||||
|
|
402
dwl.c
402
dwl.c
|
@ -33,6 +33,7 @@
|
|||
#include <wlr/types/wlr_keyboard_group.h>
|
||||
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||
#include <wlr/types/wlr_linux_dmabuf_v1.h>
|
||||
#include <wlr/types/wlr_linux_drm_syncobj_v1.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
#include <wlr/types/wlr_output_layout.h>
|
||||
#include <wlr/types/wlr_output_management_v1.h>
|
||||
|
@ -67,7 +68,6 @@
|
|||
#include <xcb/xcb_icccm.h>
|
||||
#endif
|
||||
|
||||
#include "dwl-ipc-unstable-v2-protocol.h"
|
||||
#include "util.h"
|
||||
|
||||
/* macros */
|
||||
|
@ -106,15 +106,18 @@ typedef struct {
|
|||
|
||||
typedef struct Monitor Monitor;
|
||||
typedef struct {
|
||||
/* Must keep these three elements in this order */
|
||||
/* Must keep this field first */
|
||||
unsigned int type; /* XDGShell or X11* */
|
||||
struct wlr_box geom; /* layout-relative, includes border */
|
||||
|
||||
Monitor *mon;
|
||||
struct wlr_scene_tree *scene;
|
||||
struct wlr_scene_rect *border[4]; /* top, bottom, left, right */
|
||||
struct wlr_scene_tree *scene_surface;
|
||||
struct wl_list link;
|
||||
struct wl_list flink;
|
||||
struct wlr_box geom; /* layout-relative, includes border */
|
||||
struct wlr_box prev; /* layout-relative, includes border */
|
||||
struct wlr_box bounds; /* only width and height are used */
|
||||
union {
|
||||
struct wlr_xdg_surface *xdg;
|
||||
struct wlr_xwayland_surface *xwayland;
|
||||
|
@ -129,8 +132,6 @@ typedef struct {
|
|||
struct wl_listener fullscreen;
|
||||
struct wl_listener set_decoration_mode;
|
||||
struct wl_listener destroy_decoration;
|
||||
struct wlr_box prev; /* layout-relative, includes border */
|
||||
struct wlr_box bounds;
|
||||
#ifdef XWAYLAND
|
||||
struct wl_listener activate;
|
||||
struct wl_listener associate;
|
||||
|
@ -144,12 +145,6 @@ typedef struct {
|
|||
uint32_t resize; /* configure serial of a pending resize */
|
||||
} Client;
|
||||
|
||||
typedef struct {
|
||||
struct wl_list link;
|
||||
struct wl_resource *resource;
|
||||
Monitor *mon;
|
||||
} DwlIpcOutput;
|
||||
|
||||
typedef struct {
|
||||
uint32_t mod;
|
||||
xkb_keysym_t keysym;
|
||||
|
@ -158,7 +153,6 @@ typedef struct {
|
|||
} Key;
|
||||
|
||||
typedef struct {
|
||||
struct wl_list link;
|
||||
struct wlr_keyboard_group *wlr_group;
|
||||
|
||||
int nsyms;
|
||||
|
@ -172,9 +166,9 @@ typedef struct {
|
|||
} KeyboardGroup;
|
||||
|
||||
typedef struct {
|
||||
/* Must keep these three elements in this order */
|
||||
/* Must keep this field first */
|
||||
unsigned int type; /* LayerShell */
|
||||
struct wlr_box geom;
|
||||
|
||||
Monitor *mon;
|
||||
struct wlr_scene_tree *scene;
|
||||
struct wlr_scene_tree *popups;
|
||||
|
@ -195,7 +189,6 @@ typedef struct {
|
|||
|
||||
struct Monitor {
|
||||
struct wl_list link;
|
||||
struct wl_list dwl_ipc_outputs;
|
||||
struct wlr_output *wlr_output;
|
||||
struct wlr_scene_output *scene_output;
|
||||
struct wlr_scene_rect *fullscreen_bg; /* See createmon() for info */
|
||||
|
@ -293,17 +286,6 @@ static void destroysessionlock(struct wl_listener *listener, void *data);
|
|||
static void destroysessionmgr(struct wl_listener *listener, void *data);
|
||||
static void destroykeyboardgroup(struct wl_listener *listener, void *data);
|
||||
static Monitor *dirtomon(enum wlr_direction dir);
|
||||
static void dwl_ipc_manager_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id);
|
||||
static void dwl_ipc_manager_destroy(struct wl_resource *resource);
|
||||
static void dwl_ipc_manager_get_output(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *output);
|
||||
static void dwl_ipc_manager_release(struct wl_client *client, struct wl_resource *resource);
|
||||
static void dwl_ipc_output_destroy(struct wl_resource *resource);
|
||||
static void dwl_ipc_output_printstatus(Monitor *monitor);
|
||||
static void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output);
|
||||
static void dwl_ipc_output_set_client_tags(struct wl_client *client, struct wl_resource *resource, uint32_t and_tags, uint32_t xor_tags);
|
||||
static void dwl_ipc_output_set_layout(struct wl_client *client, struct wl_resource *resource, uint32_t index);
|
||||
static void dwl_ipc_output_set_tags(struct wl_client *client, struct wl_resource *resource, uint32_t tagmask, uint32_t toggle_tagset);
|
||||
static void dwl_ipc_output_release(struct wl_client *client, struct wl_resource *resource);
|
||||
static void focusclient(Client *c, int lift);
|
||||
static void focusmon(const Arg *arg);
|
||||
static void focusstack(const Arg *arg);
|
||||
|
@ -345,7 +327,6 @@ static void setcursor(struct wl_listener *listener, void *data);
|
|||
static void setcursorshape(struct wl_listener *listener, void *data);
|
||||
static void setfloating(Client *c, int floating);
|
||||
static void setfullscreen(Client *c, int fullscreen);
|
||||
static void setgamma(struct wl_listener *listener, void *data);
|
||||
static void setlayout(const Arg *arg);
|
||||
static void setmfact(const Arg *arg);
|
||||
static void setmon(Client *c, Monitor *m, uint32_t newtags);
|
||||
|
@ -357,7 +338,6 @@ static void startdrag(struct wl_listener *listener, void *data);
|
|||
static void tag(const Arg *arg);
|
||||
static void tagmon(const Arg *arg);
|
||||
static void tile(Monitor *m);
|
||||
static void togglebar(const Arg *arg);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void togglefullscreen(const Arg *arg);
|
||||
static void toggletag(const Arg *arg);
|
||||
|
@ -377,7 +357,6 @@ static void xytonode(double x, double y, struct wlr_surface **psurface,
|
|||
static void zoom(const Arg *arg);
|
||||
|
||||
/* variables */
|
||||
static const char broken[] = "broken";
|
||||
static pid_t child_pid = -1;
|
||||
static int locked;
|
||||
static void *exclusive_focus;
|
||||
|
@ -403,7 +382,6 @@ static struct wlr_idle_notifier_v1 *idle_notifier;
|
|||
static struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr;
|
||||
static struct wlr_layer_shell_v1 *layer_shell;
|
||||
static struct wlr_output_manager_v1 *output_mgr;
|
||||
static struct wlr_gamma_control_manager_v1 *gamma_control_mgr;
|
||||
static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr;
|
||||
static struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr;
|
||||
static struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr;
|
||||
|
@ -433,9 +411,6 @@ static struct wlr_box sgeom;
|
|||
static struct wl_list mons;
|
||||
static Monitor *selmon;
|
||||
|
||||
static struct zdwl_ipc_manager_v2_interface dwl_manager_implementation = {.release = dwl_ipc_manager_release, .get_output = dwl_ipc_manager_get_output};
|
||||
static struct zdwl_ipc_output_v2_interface dwl_output_implementation = {.release = dwl_ipc_output_release, .set_tags = dwl_ipc_output_set_tags, .set_layout = dwl_ipc_output_set_layout, .set_client_tags = dwl_ipc_output_set_client_tags};
|
||||
|
||||
#ifdef XWAYLAND
|
||||
static void activatex11(struct wl_listener *listener, void *data);
|
||||
static void associatex11(struct wl_listener *listener, void *data);
|
||||
|
@ -484,10 +459,8 @@ applyrules(Client *c)
|
|||
Monitor *mon = selmon, *m;
|
||||
|
||||
c->isfloating = client_is_float_type(c);
|
||||
if (!(appid = client_get_appid(c)))
|
||||
appid = broken;
|
||||
if (!(title = client_get_title(c)))
|
||||
title = broken;
|
||||
appid = client_get_appid(c);
|
||||
title = client_get_title(c);
|
||||
|
||||
for (r = rules; r < END(rules); r++) {
|
||||
if ((!r->title || strstr(title, r->title))
|
||||
|
@ -501,10 +474,6 @@ applyrules(Client *c)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (mon) {
|
||||
c->geom.x = (mon->w.width - c->geom.width) / 2 + mon->m.x;
|
||||
c->geom.y = (mon->w.height - c->geom.height) / 2 + mon->m.y;
|
||||
}
|
||||
setmon(c, mon, newtags);
|
||||
}
|
||||
|
||||
|
@ -562,8 +531,6 @@ arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, int
|
|||
|
||||
wlr_scene_layer_surface_v1_configure(l->scene_layer, &full_area, usable_area);
|
||||
wlr_scene_node_set_position(&l->popups->node, l->scene->node.x, l->scene->node.y);
|
||||
l->geom.x = l->scene->node.x;
|
||||
l->geom.y = l->scene->node.y;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -657,17 +624,17 @@ buttonpress(struct wl_listener *listener, void *data)
|
|||
break;
|
||||
case WL_POINTER_BUTTON_STATE_RELEASED:
|
||||
/* If you released any buttons, we exit interactive move/resize mode. */
|
||||
/* TODO should reset to the pointer focus's current setcursor */
|
||||
/* TODO: should reset to the pointer focus's current setcursor */
|
||||
if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) {
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
|
||||
cursor_mode = CurNormal;
|
||||
/* Drop the window off on its new monitor */
|
||||
selmon = xytomon(cursor->x, cursor->y);
|
||||
setmon(grabc, selmon, 0);
|
||||
grabc = NULL;
|
||||
return;
|
||||
} else {
|
||||
cursor_mode = CurNormal;
|
||||
}
|
||||
cursor_mode = CurNormal;
|
||||
break;
|
||||
}
|
||||
/* If the event wasn't handled by the compositor, notify the client with
|
||||
|
@ -733,10 +700,6 @@ cleanupmon(struct wl_listener *listener, void *data)
|
|||
LayerSurface *l, *tmp;
|
||||
size_t i;
|
||||
|
||||
DwlIpcOutput *ipc_output, *ipc_output_tmp;
|
||||
wl_list_for_each_safe(ipc_output, ipc_output_tmp, &m->dwl_ipc_outputs, link)
|
||||
wl_resource_destroy(ipc_output->resource);
|
||||
|
||||
/* m->layers[i] are intentionally not unlinked */
|
||||
for (i = 0; i < LENGTH(m->layers); i++) {
|
||||
wl_list_for_each_safe(l, tmp, &m->layers[i], link)
|
||||
|
@ -794,8 +757,7 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data)
|
|||
struct wlr_layer_surface_v1_state old_state;
|
||||
|
||||
if (l->layer_surface->initial_commit) {
|
||||
wlr_fractional_scale_v1_notify_scale(layer_surface->surface, l->mon->wlr_output->scale);
|
||||
wlr_surface_set_preferred_buffer_scale(layer_surface->surface, (int32_t)ceilf(l->mon->wlr_output->scale));
|
||||
client_set_scale(layer_surface->surface, l->mon->wlr_output->scale);
|
||||
|
||||
/* Temporarily set the layer's current state to pending
|
||||
* so that we can easily arrange it */
|
||||
|
@ -834,19 +796,20 @@ commitnotify(struct wl_listener *listener, void *data)
|
|||
* a wrong monitor.
|
||||
*/
|
||||
applyrules(c);
|
||||
wlr_surface_set_preferred_buffer_scale(client_surface(c), (int)ceilf(c->mon->wlr_output->scale));
|
||||
wlr_fractional_scale_v1_notify_scale(client_surface(c), c->mon->wlr_output->scale);
|
||||
if (c->mon) {
|
||||
client_set_scale(client_surface(c), c->mon->wlr_output->scale);
|
||||
}
|
||||
setmon(c, NULL, 0); /* Make sure to reapply rules in mapnotify() */
|
||||
|
||||
wlr_xdg_toplevel_set_wm_capabilities(c->surface.xdg->toplevel, WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
|
||||
wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, 0, 0);
|
||||
wlr_xdg_toplevel_set_wm_capabilities(c->surface.xdg->toplevel,
|
||||
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
|
||||
if (c->decoration)
|
||||
requestdecorationmode(&c->set_decoration_mode, c->decoration);
|
||||
wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (client_surface(c)->mapped && c->mon)
|
||||
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)
|
||||
|
@ -871,11 +834,13 @@ commitpopup(struct wl_listener *listener, void *data)
|
|||
return;
|
||||
popup->base->surface->data = wlr_scene_xdg_surface_create(
|
||||
popup->parent->data, popup->base);
|
||||
if ((l && !l->mon) || (c && !c->mon))
|
||||
if ((l && !l->mon) || (c && !c->mon)) {
|
||||
wlr_xdg_popup_destroy(popup);
|
||||
return;
|
||||
}
|
||||
box = type == LayerShell ? l->mon->m : c->mon->w;
|
||||
box.x -= (type == LayerShell ? l->geom.x : c->geom.x);
|
||||
box.y -= (type == LayerShell ? l->geom.y : c->geom.y);
|
||||
box.x -= (type == LayerShell ? l->scene->node.x : c->geom.x);
|
||||
box.y -= (type == LayerShell ? l->scene->node.y : c->geom.y);
|
||||
wlr_xdg_popup_unconstrain_from_box(popup, &box);
|
||||
wl_list_remove(&listener->link);
|
||||
}
|
||||
|
@ -1017,8 +982,6 @@ createmon(struct wl_listener *listener, void *data)
|
|||
m = wlr_output->data = ecalloc(1, sizeof(*m));
|
||||
m->wlr_output = wlr_output;
|
||||
|
||||
wl_list_init(&m->dwl_ipc_outputs);
|
||||
|
||||
for (i = 0; i < LENGTH(m->layers); i++)
|
||||
wl_list_init(&m->layers[i]);
|
||||
|
||||
|
@ -1131,10 +1094,10 @@ createpointer(struct wlr_pointer *pointer)
|
|||
libinput_device_config_middle_emulation_set_enabled(device, middle_button_emulation);
|
||||
|
||||
if (libinput_device_config_scroll_get_methods(device) != LIBINPUT_CONFIG_SCROLL_NO_SCROLL)
|
||||
libinput_device_config_scroll_set_method (device, scroll_method);
|
||||
libinput_device_config_scroll_set_method(device, scroll_method);
|
||||
|
||||
if (libinput_device_config_click_get_methods(device) != LIBINPUT_CONFIG_CLICK_METHOD_NONE)
|
||||
libinput_device_config_click_set_method (device, click_method);
|
||||
libinput_device_config_click_set_method(device, click_method);
|
||||
|
||||
if (libinput_device_config_send_events_get_modes(device))
|
||||
libinput_device_config_send_events_set_mode(device, send_events_mode);
|
||||
|
@ -1208,7 +1171,6 @@ void
|
|||
destroydecoration(struct wl_listener *listener, void *data)
|
||||
{
|
||||
Client *c = wl_container_of(listener, c, destroy_decoration);
|
||||
c->decoration = NULL;
|
||||
|
||||
wl_list_remove(&c->destroy_decoration.link);
|
||||
wl_list_remove(&c->set_decoration_mode.link);
|
||||
|
@ -1309,6 +1271,7 @@ destroynotify(struct wl_listener *listener, void *data)
|
|||
wl_list_remove(&c->commit.link);
|
||||
wl_list_remove(&c->map.link);
|
||||
wl_list_remove(&c->unmap.link);
|
||||
wl_list_remove(&c->maximize.link);
|
||||
}
|
||||
free(c);
|
||||
}
|
||||
|
@ -1369,192 +1332,6 @@ dirtomon(enum wlr_direction dir)
|
|||
return selmon;
|
||||
}
|
||||
|
||||
void
|
||||
dwl_ipc_manager_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
|
||||
{
|
||||
struct wl_resource *manager_resource = wl_resource_create(client, &zdwl_ipc_manager_v2_interface, version, id);
|
||||
if (!manager_resource) {
|
||||
wl_client_post_no_memory(client);
|
||||
return;
|
||||
}
|
||||
wl_resource_set_implementation(manager_resource, &dwl_manager_implementation, NULL, dwl_ipc_manager_destroy);
|
||||
|
||||
zdwl_ipc_manager_v2_send_tags(manager_resource, TAGCOUNT);
|
||||
|
||||
for (unsigned int i = 0; i < LENGTH(layouts); i++)
|
||||
zdwl_ipc_manager_v2_send_layout(manager_resource, layouts[i].symbol);
|
||||
}
|
||||
|
||||
void
|
||||
dwl_ipc_manager_destroy(struct wl_resource *resource)
|
||||
{
|
||||
/* No state to destroy */
|
||||
}
|
||||
|
||||
void
|
||||
dwl_ipc_manager_get_output(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *output)
|
||||
{
|
||||
DwlIpcOutput *ipc_output;
|
||||
Monitor *monitor = wlr_output_from_resource(output)->data;
|
||||
struct wl_resource *output_resource = wl_resource_create(client, &zdwl_ipc_output_v2_interface, wl_resource_get_version(resource), id);
|
||||
if (!output_resource)
|
||||
return;
|
||||
|
||||
ipc_output = ecalloc(1, sizeof(*ipc_output));
|
||||
ipc_output->resource = output_resource;
|
||||
ipc_output->mon = monitor;
|
||||
wl_resource_set_implementation(output_resource, &dwl_output_implementation, ipc_output, dwl_ipc_output_destroy);
|
||||
wl_list_insert(&monitor->dwl_ipc_outputs, &ipc_output->link);
|
||||
dwl_ipc_output_printstatus_to(ipc_output);
|
||||
}
|
||||
|
||||
void
|
||||
dwl_ipc_manager_release(struct wl_client *client, struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static void
|
||||
dwl_ipc_output_destroy(struct wl_resource *resource)
|
||||
{
|
||||
DwlIpcOutput *ipc_output = wl_resource_get_user_data(resource);
|
||||
wl_list_remove(&ipc_output->link);
|
||||
free(ipc_output);
|
||||
}
|
||||
|
||||
void
|
||||
dwl_ipc_output_printstatus(Monitor *monitor)
|
||||
{
|
||||
DwlIpcOutput *ipc_output;
|
||||
wl_list_for_each(ipc_output, &monitor->dwl_ipc_outputs, link)
|
||||
dwl_ipc_output_printstatus_to(ipc_output);
|
||||
}
|
||||
|
||||
void
|
||||
dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output)
|
||||
{
|
||||
Monitor *monitor = ipc_output->mon;
|
||||
Client *c, *focused;
|
||||
int tagmask, state, numclients, focused_client, tag;
|
||||
const char *title, *appid;
|
||||
focused = focustop(monitor);
|
||||
zdwl_ipc_output_v2_send_active(ipc_output->resource, monitor == selmon);
|
||||
|
||||
for (tag = 0 ; tag < TAGCOUNT; tag++) {
|
||||
numclients = state = focused_client = 0;
|
||||
tagmask = 1 << tag;
|
||||
if ((tagmask & monitor->tagset[monitor->seltags]) != 0)
|
||||
state |= ZDWL_IPC_OUTPUT_V2_TAG_STATE_ACTIVE;
|
||||
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (c->mon != monitor)
|
||||
continue;
|
||||
if (!(c->tags & tagmask))
|
||||
continue;
|
||||
if (c == focused)
|
||||
focused_client = 1;
|
||||
if (c->isurgent)
|
||||
state |= ZDWL_IPC_OUTPUT_V2_TAG_STATE_URGENT;
|
||||
|
||||
numclients++;
|
||||
}
|
||||
zdwl_ipc_output_v2_send_tag(ipc_output->resource, tag, state, numclients, focused_client);
|
||||
}
|
||||
title = focused ? client_get_title(focused) : "";
|
||||
appid = focused ? client_get_appid(focused) : "";
|
||||
|
||||
zdwl_ipc_output_v2_send_layout(ipc_output->resource, monitor->lt[monitor->sellt] - layouts);
|
||||
zdwl_ipc_output_v2_send_title(ipc_output->resource, title ? title : broken);
|
||||
zdwl_ipc_output_v2_send_appid(ipc_output->resource, appid ? appid : broken);
|
||||
zdwl_ipc_output_v2_send_layout_symbol(ipc_output->resource, monitor->ltsymbol);
|
||||
if (wl_resource_get_version(ipc_output->resource) >= ZDWL_IPC_OUTPUT_V2_FULLSCREEN_SINCE_VERSION) {
|
||||
zdwl_ipc_output_v2_send_fullscreen(ipc_output->resource, focused ? focused->isfullscreen : 0);
|
||||
}
|
||||
if (wl_resource_get_version(ipc_output->resource) >= ZDWL_IPC_OUTPUT_V2_FLOATING_SINCE_VERSION) {
|
||||
zdwl_ipc_output_v2_send_floating(ipc_output->resource, focused ? focused->isfloating : 0);
|
||||
}
|
||||
zdwl_ipc_output_v2_send_frame(ipc_output->resource);
|
||||
}
|
||||
|
||||
void
|
||||
dwl_ipc_output_set_client_tags(struct wl_client *client, struct wl_resource *resource, uint32_t and_tags, uint32_t xor_tags)
|
||||
{
|
||||
DwlIpcOutput *ipc_output;
|
||||
Monitor *monitor;
|
||||
Client *selected_client;
|
||||
unsigned int newtags = 0;
|
||||
|
||||
ipc_output = wl_resource_get_user_data(resource);
|
||||
if (!ipc_output)
|
||||
return;
|
||||
|
||||
monitor = ipc_output->mon;
|
||||
selected_client = focustop(monitor);
|
||||
if (!selected_client)
|
||||
return;
|
||||
|
||||
newtags = (selected_client->tags & and_tags) ^ xor_tags;
|
||||
if (!newtags)
|
||||
return;
|
||||
|
||||
selected_client->tags = newtags;
|
||||
if (selmon == monitor)
|
||||
focusclient(focustop(monitor), 1);
|
||||
arrange(selmon);
|
||||
printstatus();
|
||||
}
|
||||
|
||||
void
|
||||
dwl_ipc_output_set_layout(struct wl_client *client, struct wl_resource *resource, uint32_t index)
|
||||
{
|
||||
DwlIpcOutput *ipc_output;
|
||||
Monitor *monitor;
|
||||
|
||||
ipc_output = wl_resource_get_user_data(resource);
|
||||
if (!ipc_output)
|
||||
return;
|
||||
|
||||
monitor = ipc_output->mon;
|
||||
if (index >= LENGTH(layouts))
|
||||
return;
|
||||
if (index != monitor->lt[monitor->sellt] - layouts)
|
||||
monitor->sellt ^= 1;
|
||||
|
||||
monitor->lt[monitor->sellt] = &layouts[index];
|
||||
arrange(monitor);
|
||||
printstatus();
|
||||
}
|
||||
|
||||
void
|
||||
dwl_ipc_output_set_tags(struct wl_client *client, struct wl_resource *resource, uint32_t tagmask, uint32_t toggle_tagset)
|
||||
{
|
||||
DwlIpcOutput *ipc_output;
|
||||
Monitor *monitor;
|
||||
unsigned int newtags = tagmask & TAGMASK;
|
||||
|
||||
ipc_output = wl_resource_get_user_data(resource);
|
||||
if (!ipc_output)
|
||||
return;
|
||||
monitor = ipc_output->mon;
|
||||
|
||||
if (!newtags || newtags == monitor->tagset[monitor->seltags])
|
||||
return;
|
||||
if (toggle_tagset)
|
||||
monitor->seltags ^= 1;
|
||||
|
||||
monitor->tagset[monitor->seltags] = newtags;
|
||||
if (selmon == monitor)
|
||||
focusclient(focustop(monitor), 1);
|
||||
arrange(monitor);
|
||||
printstatus();
|
||||
}
|
||||
|
||||
void
|
||||
dwl_ipc_output_release(struct wl_client *client, struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
void
|
||||
focusclient(Client *c, int lift)
|
||||
{
|
||||
|
@ -1585,7 +1362,6 @@ focusclient(Client *c, int lift)
|
|||
wl_list_insert(&fstack, &c->flink);
|
||||
selmon = c->mon;
|
||||
c->isurgent = 0;
|
||||
client_restack_surface(c);
|
||||
|
||||
/* Don't change border color if there is an exclusive focus or we are
|
||||
* handling a drag operation */
|
||||
|
@ -1912,7 +1688,8 @@ mapnotify(struct wl_listener *listener, void *data)
|
|||
|
||||
/* Create scene tree for this client and its border */
|
||||
c->scene = client_surface(c)->data = wlr_scene_tree_create(layers[LyrTile]);
|
||||
wlr_scene_node_set_enabled(&c->scene->node, c->type != XDGShell);
|
||||
/* Enabled later by a call to arrange() */
|
||||
wlr_scene_node_set_enabled(&c->scene->node, client_is_unmanaged(c));
|
||||
c->scene_surface = c->type == XDGShell
|
||||
? wlr_scene_xdg_surface_create(c->scene, c->surface.xdg)
|
||||
: wlr_scene_subsurface_tree_create(c->scene, client_surface(c));
|
||||
|
@ -1925,6 +1702,7 @@ mapnotify(struct wl_listener *listener, void *data)
|
|||
/* Unmanaged clients always are floating */
|
||||
wlr_scene_node_reparent(&c->scene->node, layers[LyrFloat]);
|
||||
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)) {
|
||||
focusclient(c, 1);
|
||||
exclusive_focus = c;
|
||||
|
@ -1953,10 +1731,6 @@ mapnotify(struct wl_listener *listener, void *data)
|
|||
* try to apply rules for them */
|
||||
if ((p = client_get_parent(c))) {
|
||||
c->isfloating = 1;
|
||||
if (p->mon) {
|
||||
c->geom.x = (p->mon->w.width - c->geom.width) / 2 + p->mon->m.x;
|
||||
c->geom.y = (p->mon->w.height - c->geom.height) / 2 + p->mon->m.y;
|
||||
}
|
||||
setmon(c, p->mon, p->tags);
|
||||
} else {
|
||||
applyrules(c);
|
||||
|
@ -2046,8 +1820,8 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
|
|||
&& toplevel_from_wlr_surface(seat->pointer_state.focused_surface, &w, &l) >= 0) {
|
||||
c = w;
|
||||
surface = seat->pointer_state.focused_surface;
|
||||
sx = cursor->x - (l ? l->geom.x : w->geom.x);
|
||||
sy = cursor->y - (l ? l->geom.y : w->geom.y);
|
||||
sx = cursor->x - (l ? l->scene->node.x : w->geom.x);
|
||||
sy = cursor->y - (l ? l->scene->node.y : w->geom.y);
|
||||
}
|
||||
|
||||
/* time is 0 in internal calls meant to restore pointer focus. */
|
||||
|
@ -2259,9 +2033,38 @@ void
|
|||
printstatus(void)
|
||||
{
|
||||
Monitor *m = NULL;
|
||||
Client *c;
|
||||
uint32_t occ, urg, sel;
|
||||
|
||||
wl_list_for_each(m, &mons, link)
|
||||
dwl_ipc_output_printstatus(m);
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
occ = urg = 0;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (c->mon != m)
|
||||
continue;
|
||||
occ |= c->tags;
|
||||
if (c->isurgent)
|
||||
urg |= c->tags;
|
||||
}
|
||||
if ((c = focustop(m))) {
|
||||
printf("%s title %s\n", m->wlr_output->name, client_get_title(c));
|
||||
printf("%s appid %s\n", m->wlr_output->name, client_get_appid(c));
|
||||
printf("%s fullscreen %d\n", m->wlr_output->name, c->isfullscreen);
|
||||
printf("%s floating %d\n", m->wlr_output->name, c->isfloating);
|
||||
sel = c->tags;
|
||||
} else {
|
||||
printf("%s title \n", m->wlr_output->name);
|
||||
printf("%s appid \n", m->wlr_output->name);
|
||||
printf("%s fullscreen \n", m->wlr_output->name);
|
||||
printf("%s floating \n", m->wlr_output->name);
|
||||
sel = 0;
|
||||
}
|
||||
|
||||
printf("%s selmon %u\n", m->wlr_output->name, m == selmon);
|
||||
printf("%s tags %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32"\n",
|
||||
m->wlr_output->name, occ, m->tagset[m->seltags], sel, urg);
|
||||
printf("%s layout %s\n", m->wlr_output->name, m->ltsymbol);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2295,7 +2098,6 @@ rendermon(struct wl_listener *listener, void *data)
|
|||
Monitor *m = wl_container_of(listener, m, frame);
|
||||
Client *c;
|
||||
struct wlr_output_state pending = {0};
|
||||
struct wlr_gamma_control_v1 *gamma_control;
|
||||
struct timespec now;
|
||||
|
||||
/* Render if no XDG clients have an outstanding resize and are visible on
|
||||
|
@ -2305,32 +2107,7 @@ rendermon(struct wl_listener *listener, void *data)
|
|||
goto skip;
|
||||
}
|
||||
|
||||
/*
|
||||
* HACK: The "correct" way to set the gamma is to commit it together with
|
||||
* the rest of the state in one go, but to do that we would need to rewrite
|
||||
* wlr_scene_output_commit() in order to add the gamma to the pending
|
||||
* state before committing, instead try to commit the gamma in one frame,
|
||||
* and commit the rest of the state in the next one (or in the same frame if
|
||||
* the gamma can not be committed).
|
||||
*/
|
||||
if (m->gamma_lut_changed) {
|
||||
gamma_control
|
||||
= wlr_gamma_control_manager_v1_get_control(gamma_control_mgr, m->wlr_output);
|
||||
m->gamma_lut_changed = 0;
|
||||
|
||||
if (!wlr_gamma_control_v1_apply(gamma_control, &pending))
|
||||
goto commit;
|
||||
|
||||
if (!wlr_output_test_state(m->wlr_output, &pending)) {
|
||||
wlr_gamma_control_v1_send_failed_and_destroy(gamma_control);
|
||||
goto commit;
|
||||
}
|
||||
wlr_output_commit_state(m->wlr_output, &pending);
|
||||
wlr_output_schedule_frame(m->wlr_output);
|
||||
} else {
|
||||
commit:
|
||||
wlr_scene_output_commit(m->scene_output, NULL);
|
||||
}
|
||||
wlr_scene_output_commit(m->scene_output, NULL);
|
||||
|
||||
skip:
|
||||
/* Let clients know a frame has been rendered */
|
||||
|
@ -2532,17 +2309,6 @@ setfullscreen(Client *c, int fullscreen)
|
|||
printstatus();
|
||||
}
|
||||
|
||||
void
|
||||
setgamma(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct wlr_gamma_control_manager_v1_set_gamma_event *event = data;
|
||||
Monitor *m = event->output->data;
|
||||
if (!m)
|
||||
return;
|
||||
m->gamma_lut_changed = 1;
|
||||
wlr_output_schedule_frame(m->wlr_output);
|
||||
}
|
||||
|
||||
void
|
||||
setlayout(const Arg *arg)
|
||||
{
|
||||
|
@ -2620,7 +2386,7 @@ setsel(struct wl_listener *listener, void *data)
|
|||
void
|
||||
setup(void)
|
||||
{
|
||||
int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE};
|
||||
int drm_fd, i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE};
|
||||
struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = handlesig};
|
||||
sigemptyset(&sa.sa_mask);
|
||||
|
||||
|
@ -2670,6 +2436,9 @@ setup(void)
|
|||
wlr_linux_dmabuf_v1_create_with_renderer(dpy, 5, drw));
|
||||
}
|
||||
|
||||
if ((drm_fd = wlr_renderer_get_drm_fd(drw)) >= 0 && drw->features.timeline)
|
||||
wlr_linux_drm_syncobj_manager_v1_create(dpy, 1, drm_fd);
|
||||
|
||||
/* Autocreates an allocator for us.
|
||||
* The allocator is the bridge between the renderer and the backend. It
|
||||
* handles the buffer creation, allowing wlroots to render onto the
|
||||
|
@ -2700,8 +2469,7 @@ setup(void)
|
|||
activation = wlr_xdg_activation_v1_create(dpy);
|
||||
LISTEN_STATIC(&activation->events.request_activate, urgent);
|
||||
|
||||
gamma_control_mgr = wlr_gamma_control_manager_v1_create(dpy);
|
||||
LISTEN_STATIC(&gamma_control_mgr->events.set_gamma, setgamma);
|
||||
wlr_scene_set_gamma_control_manager_v1(scene, wlr_gamma_control_manager_v1_create(dpy));
|
||||
|
||||
power_mgr = wlr_output_power_manager_v1_create(dpy);
|
||||
LISTEN_STATIC(&power_mgr->events.set_mode, powermgrsetmode);
|
||||
|
@ -2816,8 +2584,6 @@ setup(void)
|
|||
LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply);
|
||||
LISTEN_STATIC(&output_mgr->events.test, outputmgrtest);
|
||||
|
||||
wl_global_create(dpy, &zdwl_ipc_manager_v2_interface, 2, NULL, dwl_ipc_manager_bind);
|
||||
|
||||
/* Make sure XWayland clients don't connect to the parent X server,
|
||||
* e.g when running in the x11 backend or the wayland backend and the
|
||||
* compositor has Xwayland support */
|
||||
|
@ -2915,13 +2681,6 @@ tile(Monitor *m)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
togglebar(const Arg *arg) {
|
||||
DwlIpcOutput *ipc_output;
|
||||
wl_list_for_each(ipc_output, &selmon->dwl_ipc_outputs, link)
|
||||
zdwl_ipc_output_v2_send_toggle_visibility(ipc_output->resource);
|
||||
}
|
||||
|
||||
void
|
||||
togglefloating(const Arg *arg)
|
||||
{
|
||||
|
@ -3279,17 +3038,24 @@ configurex11(struct wl_listener *listener, void *data)
|
|||
{
|
||||
Client *c = wl_container_of(listener, c, configure);
|
||||
struct wlr_xwayland_surface_configure_event *event = data;
|
||||
/* TODO: figure out if there is another way to do this */
|
||||
if (!c->mon) {
|
||||
if (!client_surface(c) || !client_surface(c)->mapped) {
|
||||
wlr_xwayland_surface_configure(c->surface.xwayland,
|
||||
event->x, event->y, event->width, event->height);
|
||||
return;
|
||||
}
|
||||
if (c->isfloating || client_is_unmanaged(c))
|
||||
resize(c, (struct wlr_box){.x = event->x, .y = event->y,
|
||||
.width = event->width + c->bw * 2, .height = event->height + c->bw * 2}, 0);
|
||||
else
|
||||
if (client_is_unmanaged(c)) {
|
||||
wlr_scene_node_set_position(&c->scene->node, event->x, event->y);
|
||||
wlr_xwayland_surface_configure(c->surface.xwayland,
|
||||
event->x, event->y, event->width, event->height);
|
||||
return;
|
||||
}
|
||||
if ((c->isfloating && c != grabc) || !c->mon->lt[c->mon->sellt]->arrange) {
|
||||
resize(c, (struct wlr_box){.x = event->x - c->bw,
|
||||
.y = event->y - c->bw, .width = event->width + c->bw * 2,
|
||||
.height = event->height + c->bw * 2}, 0);
|
||||
} else {
|
||||
arrange(c->mon);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
/******************************************************************
|
||||
* Copyright 2023-2024 Leonardo Hernández Hernández
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the “Software”), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
******************************************************************/
|
||||
|
||||
/* cc -lxkbcommon -o generate-keys generate-keys.c */
|
||||
|
||||
#define _DEFAULT_SOURCE
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
/* Allow generate keys with a different layout and variant.
|
||||
* You can also use XKB_DEFAULT_* environmental variables and let this as is */
|
||||
struct xkb_rule_names rules = {
|
||||
0
|
||||
};
|
||||
struct xkb_context *context = NULL;
|
||||
struct xkb_keymap *keymap = NULL;
|
||||
xkb_keycode_t keycode, min_keycode, max_keycode;
|
||||
xkb_layout_index_t layout, num_layouts;
|
||||
xkb_level_index_t level, num_levels;
|
||||
int i, nsyms;
|
||||
const xkb_keysym_t *syms;
|
||||
char keyname[64];
|
||||
bool ok = false;
|
||||
FILE *file = fopen("keys.h", "w");
|
||||
if (!file) {
|
||||
perror("Couldn't open keys.h");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!(context = xkb_context_new(XKB_CONTEXT_NO_FLAGS))) {
|
||||
fputs("Couldn't create xkbcommon context\n", stderr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(keymap = xkb_keymap_new_from_names(context, &rules,
|
||||
XKB_KEYMAP_COMPILE_NO_FLAGS))) {
|
||||
fputs("Couldn't create xkbcommon keymap\n", stderr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
min_keycode = xkb_keymap_min_keycode(keymap);
|
||||
max_keycode = xkb_keymap_max_keycode(keymap);
|
||||
|
||||
for (keycode = min_keycode; keycode <= max_keycode; keycode++) {
|
||||
num_layouts = xkb_keymap_num_layouts_for_key(keymap, keycode);
|
||||
for (layout = 0; layout < num_layouts; layout++) {
|
||||
num_levels = xkb_keymap_num_levels_for_key(keymap, keycode, layout);
|
||||
for (level = 0; level < num_levels; level++) {
|
||||
nsyms = xkb_keymap_key_get_syms_by_level(keymap, keycode, layout, level, &syms);
|
||||
for (i = 0; i < nsyms; i++) {
|
||||
xkb_keysym_get_name(syms[i], keyname, sizeof(keyname) / sizeof(keyname[0]));
|
||||
fprintf(file, "#define Key_%-27s %#05"PRIx32"\n", keyname, keycode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ok = true;
|
||||
sync();
|
||||
|
||||
out:
|
||||
fclose(file);
|
||||
xkb_keymap_unref(keymap);
|
||||
xkb_context_unref(context);
|
||||
return !ok;
|
||||
}
|
|
@ -1,181 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
This is largely ripped from somebar's ipc patchset; just with some personal modifications.
|
||||
I would probably just submit raphi's patchset but I don't think that would be polite.
|
||||
-->
|
||||
<protocol name="dwl_ipc_unstable_v2">
|
||||
<description summary="inter-proccess-communication about dwl's state">
|
||||
This protocol allows clients to update and get updates from dwl.
|
||||
|
||||
Warning! The protocol described in this file is experimental and
|
||||
backward incompatible changes may be made. Backward compatible
|
||||
changes may be added together with the corresponding interface
|
||||
version bump.
|
||||
Backward incompatible changes are done by bumping the version
|
||||
number in the protocol and interface names and resetting the
|
||||
interface version. Once the protocol is to be declared stable,
|
||||
the 'z' prefix and the version number in the protocol and
|
||||
interface names are removed and the interface version number is
|
||||
reset.
|
||||
</description>
|
||||
|
||||
<interface name="zdwl_ipc_manager_v2" version="2">
|
||||
<description summary="manage dwl state">
|
||||
This interface is exposed as a global in wl_registry.
|
||||
|
||||
Clients can use this interface to get a dwl_ipc_output.
|
||||
After binding the client will recieve the dwl_ipc_manager.tags and dwl_ipc_manager.layout events.
|
||||
The dwl_ipc_manager.tags and dwl_ipc_manager.layout events expose tags and layouts to the client.
|
||||
</description>
|
||||
|
||||
<request name="release" type="destructor">
|
||||
<description summary="release dwl_ipc_manager">
|
||||
Indicates that the client will not the dwl_ipc_manager object anymore.
|
||||
Objects created through this instance are not affected.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="get_output">
|
||||
<description summary="get a dwl_ipc_outout for a wl_output">
|
||||
Get a dwl_ipc_outout for the specified wl_output.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zdwl_ipc_output_v2"/>
|
||||
<arg name="output" type="object" interface="wl_output"/>
|
||||
</request>
|
||||
|
||||
<event name="tags">
|
||||
<description summary="Announces tag amount">
|
||||
This event is sent after binding.
|
||||
A roundtrip after binding guarantees the client recieved all tags.
|
||||
</description>
|
||||
<arg name="amount" type="uint"/>
|
||||
</event>
|
||||
|
||||
<event name="layout">
|
||||
<description summary="Announces a layout">
|
||||
This event is sent after binding.
|
||||
A roundtrip after binding guarantees the client recieved all layouts.
|
||||
</description>
|
||||
<arg name="name" type="string"/>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="zdwl_ipc_output_v2" version="2">
|
||||
<description summary="control dwl output">
|
||||
Observe and control a dwl output.
|
||||
|
||||
Events are double-buffered:
|
||||
Clients should cache events and redraw when a dwl_ipc_output.frame event is sent.
|
||||
|
||||
Request are not double-buffered:
|
||||
The compositor will update immediately upon request.
|
||||
</description>
|
||||
|
||||
<enum name="tag_state">
|
||||
<entry name="none" value="0" summary="no state"/>
|
||||
<entry name="active" value="1" summary="tag is active"/>
|
||||
<entry name="urgent" value="2" summary="tag has at least one urgent client"/>
|
||||
</enum>
|
||||
|
||||
<request name="release" type="destructor">
|
||||
<description summary="release dwl_ipc_outout">
|
||||
Indicates to that the client no longer needs this dwl_ipc_output.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<event name="toggle_visibility">
|
||||
<description summary="Toggle client visibilty">
|
||||
Indicates the client should hide or show themselves.
|
||||
If the client is visible then hide, if hidden then show.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<event name="active">
|
||||
<description summary="Update the selected output.">
|
||||
Indicates if the output is active. Zero is invalid, nonzero is valid.
|
||||
</description>
|
||||
<arg name="active" type="uint"/>
|
||||
</event>
|
||||
|
||||
<event name="tag">
|
||||
<description summary="Update the state of a tag.">
|
||||
Indicates that a tag has been updated.
|
||||
</description>
|
||||
<arg name="tag" type="uint" summary="Index of the tag"/>
|
||||
<arg name="state" type="uint" enum="tag_state" summary="The state of the tag."/>
|
||||
<arg name="clients" type="uint" summary="The number of clients in the tag."/>
|
||||
<arg name="focused" type="uint" summary="If there is a focused client. Nonzero being valid, zero being invalid."/>
|
||||
</event>
|
||||
|
||||
<event name="layout">
|
||||
<description summary="Update the layout.">
|
||||
Indicates a new layout is selected.
|
||||
</description>
|
||||
<arg name="layout" type="uint" summary="Index of the layout."/>
|
||||
</event>
|
||||
|
||||
<event name="title">
|
||||
<description summary="Update the title.">
|
||||
Indicates the title has changed.
|
||||
</description>
|
||||
<arg name="title" type="string" summary="The new title name."/>
|
||||
</event>
|
||||
|
||||
<event name="appid" since="1">
|
||||
<description summary="Update the appid.">
|
||||
Indicates the appid has changed.
|
||||
</description>
|
||||
<arg name="appid" type="string" summary="The new appid."/>
|
||||
</event>
|
||||
|
||||
<event name="layout_symbol" since="1">
|
||||
<description summary="Update the current layout symbol">
|
||||
Indicates the layout has changed. Since layout symbols are dynamic.
|
||||
As opposed to the zdwl_ipc_manager.layout event, this should take precendence when displaying.
|
||||
You can ignore the zdwl_ipc_output.layout event.
|
||||
</description>
|
||||
<arg name="layout" type="string" summary="The new layout"/>
|
||||
</event>
|
||||
|
||||
<event name="frame">
|
||||
<description summary="The update sequence is done.">
|
||||
Indicates that a sequence of status updates have finished and the client should redraw.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<request name="set_tags">
|
||||
<description summary="Set the active tags of this output"/>
|
||||
<arg name="tagmask" type="uint" summary="bitmask of the tags that should be set."/>
|
||||
<arg name="toggle_tagset" type="uint" summary="toggle the selected tagset, zero for invalid, nonzero for valid."/>
|
||||
</request>
|
||||
|
||||
<request name="set_client_tags">
|
||||
<description summary="Set the tags of the focused client.">
|
||||
The tags are updated as follows:
|
||||
new_tags = (current_tags AND and_tags) XOR xor_tags
|
||||
</description>
|
||||
<arg name="and_tags" type="uint"/>
|
||||
<arg name="xor_tags" type="uint"/>
|
||||
</request>
|
||||
|
||||
<request name="set_layout">
|
||||
<description summary="Set the layout of this output"/>
|
||||
<arg name="index" type="uint" summary="index of a layout recieved by dwl_ipc_manager.layout"/>
|
||||
</request>
|
||||
|
||||
<!-- Version 2 -->
|
||||
<event name="fullscreen" since="2">
|
||||
<description summary="Update fullscreen status">
|
||||
Indicates if the selected client on this output is fullscreen.
|
||||
</description>
|
||||
<arg name="is_fullscreen" type="uint" summary="If the selected client is fullscreen. Nonzero is valid, zero invalid"/>
|
||||
</event>
|
||||
|
||||
<event name="floating" since="2">
|
||||
<description summary="Update the floating status">
|
||||
Indicates if the selected client on this output is floating.
|
||||
</description>
|
||||
<arg name="is_floating" type="uint" summary="If the selected client is floating. Nonzero is valid, zero invalid"/>
|
||||
</event>
|
||||
</interface>
|
||||
</protocol>
|
10
util.c
10
util.c
|
@ -38,14 +38,14 @@ ecalloc(size_t nmemb, size_t size)
|
|||
int
|
||||
fd_set_nonblock(int fd) {
|
||||
int flags = fcntl(fd, F_GETFL);
|
||||
if (flags < 0) {
|
||||
if (flags < 0) {
|
||||
perror("fcntl(F_GETFL):");
|
||||
return -1;
|
||||
}
|
||||
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
|
||||
perror("fcntl(F_SETFL):");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue