mirror of
https://codeberg.org/dwl/dwl.git
synced 2026-11-11 15:43:13 +00:00
Merge branch 'main' into wlroots-next
This commit is contained in:
@@ -98,6 +98,8 @@ toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc, LayerSurface **pl)
|
|||||||
xdg_surface = tmp_xdg_surface;
|
xdg_surface = tmp_xdg_surface;
|
||||||
break;
|
break;
|
||||||
case WLR_XDG_SURFACE_ROLE_TOPLEVEL:
|
case WLR_XDG_SURFACE_ROLE_TOPLEVEL:
|
||||||
|
if (!xdg_surface->toplevel)
|
||||||
|
return -1;
|
||||||
c = xdg_surface->data;
|
c = xdg_surface->data;
|
||||||
type = c->type;
|
type = c->type;
|
||||||
goto end;
|
goto end;
|
||||||
|
|||||||
@@ -83,7 +83,6 @@
|
|||||||
#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags]))
|
#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags]))
|
||||||
#define TAGMASK ((1u << TAGCOUNT) - 1)
|
#define TAGMASK ((1u << TAGCOUNT) - 1)
|
||||||
#define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L)))
|
#define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L)))
|
||||||
#define LISTEN_STATIC(E, H, D) do { StaticListener *_l = ecalloc(1, sizeof(*_l)); _l->listener.notify = (H); _l->data = (D); wl_signal_add((E), &_l->listener); } while (0)
|
|
||||||
|
|
||||||
/* enums */
|
/* enums */
|
||||||
enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
|
enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
|
||||||
@@ -246,6 +245,17 @@ typedef struct {
|
|||||||
struct wl_listener destroy;
|
struct wl_listener destroy;
|
||||||
} PointerConstraint;
|
} PointerConstraint;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct wlr_idle_inhibitor_v1 *inhibitor;
|
||||||
|
struct wl_listener destroy;
|
||||||
|
} IdleInhibitor;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct wlr_xdg_popup *popup;
|
||||||
|
struct wl_listener commit;
|
||||||
|
struct wl_listener destroy;
|
||||||
|
} Popup;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *id;
|
const char *id;
|
||||||
const char *title;
|
const char *title;
|
||||||
@@ -263,12 +273,6 @@ typedef struct {
|
|||||||
struct wl_listener destroy;
|
struct wl_listener destroy;
|
||||||
} SessionLock;
|
} SessionLock;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
/* Must keep this field first */
|
|
||||||
struct wl_listener listener;
|
|
||||||
void *data;
|
|
||||||
} StaticListener;
|
|
||||||
|
|
||||||
/* function declarations */
|
/* function declarations */
|
||||||
static void applybounds(Client *c, struct wlr_box *bbox);
|
static void applybounds(Client *c, struct wlr_box *bbox);
|
||||||
static void applygeom(Client *c);
|
static void applygeom(Client *c);
|
||||||
@@ -304,6 +308,7 @@ static void createpopup(struct wl_listener *listener, void *data);
|
|||||||
static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint);
|
static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint);
|
||||||
static void cursorframe(struct wl_listener *listener, void *data);
|
static void cursorframe(struct wl_listener *listener, void *data);
|
||||||
static void cursorwarptohint(void);
|
static void cursorwarptohint(void);
|
||||||
|
static void destroybackend(struct wl_listener *listener, void *data);
|
||||||
static void destroydecoration(struct wl_listener *listener, void *data);
|
static void destroydecoration(struct wl_listener *listener, void *data);
|
||||||
static void destroydragicon(struct wl_listener *listener, void *data);
|
static void destroydragicon(struct wl_listener *listener, void *data);
|
||||||
static void destroyidleinhibitor(struct wl_listener *listener, void *data);
|
static void destroyidleinhibitor(struct wl_listener *listener, void *data);
|
||||||
@@ -312,6 +317,7 @@ static void destroylock(SessionLock *lock, int unlocked);
|
|||||||
static void destroylocksurface(struct wl_listener *listener, void *data);
|
static void destroylocksurface(struct wl_listener *listener, void *data);
|
||||||
static void destroynotify(struct wl_listener *listener, void *data);
|
static void destroynotify(struct wl_listener *listener, void *data);
|
||||||
static void destroypointerconstraint(struct wl_listener *listener, void *data);
|
static void destroypointerconstraint(struct wl_listener *listener, void *data);
|
||||||
|
static void destroypopup(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);
|
||||||
@@ -319,6 +325,7 @@ 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);
|
||||||
|
static void forgetoffmons(void);
|
||||||
static void fullscreennotify(struct wl_listener *listener, void *data);
|
static void fullscreennotify(struct wl_listener *listener, void *data);
|
||||||
static void gpureset(struct wl_listener *listener, void *data);
|
static void gpureset(struct wl_listener *listener, void *data);
|
||||||
static void handlesig(int signo);
|
static void handlesig(int signo);
|
||||||
@@ -461,6 +468,7 @@ static struct wl_array ghosts; /* struct wlr_scene_node *, unmapped clients */
|
|||||||
static struct wl_array offmons; /* char *, names of outputs turned off by clients */
|
static struct wl_array offmons; /* char *, names of outputs turned off by clients */
|
||||||
|
|
||||||
/* global event handlers */
|
/* global event handlers */
|
||||||
|
static struct wl_listener backend_destroy = {.notify = destroybackend};
|
||||||
static struct wl_listener cursor_axis = {.notify = axisnotify};
|
static struct wl_listener cursor_axis = {.notify = axisnotify};
|
||||||
static struct wl_listener cursor_button = {.notify = buttonpress};
|
static struct wl_listener cursor_button = {.notify = buttonpress};
|
||||||
static struct wl_listener cursor_frame = {.notify = cursorframe};
|
static struct wl_listener cursor_frame = {.notify = cursorframe};
|
||||||
@@ -855,6 +863,7 @@ cleanup(void)
|
|||||||
|
|
||||||
/* 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 */
|
||||||
|
if (backend)
|
||||||
wlr_backend_destroy(backend);
|
wlr_backend_destroy(backend);
|
||||||
|
|
||||||
if (transaction_idle)
|
if (transaction_idle)
|
||||||
@@ -911,6 +920,7 @@ cleanuplisteners(void)
|
|||||||
wl_list_remove(&new_idle_inhibitor.link);
|
wl_list_remove(&new_idle_inhibitor.link);
|
||||||
wl_list_remove(&layout_change.link);
|
wl_list_remove(&layout_change.link);
|
||||||
wl_list_remove(&new_input_device.link);
|
wl_list_remove(&new_input_device.link);
|
||||||
|
wl_list_remove(&backend_destroy.link);
|
||||||
wl_list_remove(&new_virtual_keyboard.link);
|
wl_list_remove(&new_virtual_keyboard.link);
|
||||||
wl_list_remove(&new_virtual_pointer.link);
|
wl_list_remove(&new_virtual_pointer.link);
|
||||||
wl_list_remove(&new_pointer_constraint.link);
|
wl_list_remove(&new_pointer_constraint.link);
|
||||||
@@ -1054,8 +1064,8 @@ commitnotify(struct wl_listener *listener, void *data)
|
|||||||
void
|
void
|
||||||
commitpopup(struct wl_listener *listener, void *data)
|
commitpopup(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
StaticListener *sl = wl_container_of(listener, sl, listener);
|
Popup *p = wl_container_of(listener, p, commit);
|
||||||
struct wlr_xdg_popup *popup = sl->data;
|
struct wlr_xdg_popup *popup = p->popup;
|
||||||
LayerSurface *l = NULL;
|
LayerSurface *l = NULL;
|
||||||
Client *c = NULL;
|
Client *c = NULL;
|
||||||
struct wlr_box box;
|
struct wlr_box box;
|
||||||
@@ -1077,8 +1087,7 @@ commitpopup(struct wl_listener *listener, void *data)
|
|||||||
box.x -= (type == LayerShell ? l->scene->node.x : c->geom.x - c->surface.xdg->geometry.x);
|
box.x -= (type == LayerShell ? l->scene->node.x : c->geom.x - c->surface.xdg->geometry.x);
|
||||||
box.y -= (type == LayerShell ? l->scene->node.y : c->geom.y - c->surface.xdg->geometry.y);
|
box.y -= (type == LayerShell ? l->scene->node.y : c->geom.y - c->surface.xdg->geometry.y);
|
||||||
wlr_xdg_popup_unconstrain_from_box(popup, &box);
|
wlr_xdg_popup_unconstrain_from_box(popup, &box);
|
||||||
wl_list_remove(&listener->link);
|
destroypopup(&p->destroy, NULL);
|
||||||
free(listener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1098,7 +1107,9 @@ void
|
|||||||
createidleinhibitor(struct wl_listener *listener, void *data)
|
createidleinhibitor(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
struct wlr_idle_inhibitor_v1 *idle_inhibitor = data;
|
struct wlr_idle_inhibitor_v1 *idle_inhibitor = data;
|
||||||
LISTEN_STATIC(&idle_inhibitor->events.destroy, destroyidleinhibitor, idle_inhibitor);
|
IdleInhibitor *i = ecalloc(1, sizeof(*i));
|
||||||
|
i->inhibitor = idle_inhibitor;
|
||||||
|
LISTEN(&idle_inhibitor->events.destroy, &i->destroy, destroyidleinhibitor);
|
||||||
|
|
||||||
checkidleinhibitor(NULL);
|
checkidleinhibitor(NULL);
|
||||||
}
|
}
|
||||||
@@ -1372,7 +1383,10 @@ createpopup(struct wl_listener *listener, void *data)
|
|||||||
/* This event is raised when a client (either xdg-shell or layer-shell)
|
/* This event is raised when a client (either xdg-shell or layer-shell)
|
||||||
* creates a new popup. */
|
* creates a new popup. */
|
||||||
struct wlr_xdg_popup *popup = data;
|
struct wlr_xdg_popup *popup = data;
|
||||||
LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup, popup);
|
Popup *p = ecalloc(1, sizeof(*p));
|
||||||
|
p->popup = popup;
|
||||||
|
LISTEN(&popup->base->surface->events.commit, &p->commit, commitpopup);
|
||||||
|
LISTEN(&popup->events.destroy, &p->destroy, destroypopup);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1413,6 +1427,21 @@ cursorwarptohint(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
destroybackend(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
/* wlroots destroys the backend itself when the session goes away (e.g.
|
||||||
|
* seatd stopped at shutdown), and asserts that its listeners are gone */
|
||||||
|
wl_list_remove(&new_output.link);
|
||||||
|
wl_list_init(&new_output.link);
|
||||||
|
wl_list_remove(&new_input_device.link);
|
||||||
|
wl_list_init(&new_input_device.link);
|
||||||
|
wl_list_remove(&backend_destroy.link);
|
||||||
|
wl_list_init(&backend_destroy.link);
|
||||||
|
backend = NULL;
|
||||||
|
quit(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
destroydecoration(struct wl_listener *listener, void *data)
|
destroydecoration(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
@@ -1435,12 +1464,11 @@ destroydragicon(struct wl_listener *listener, void *data)
|
|||||||
void
|
void
|
||||||
destroyidleinhibitor(struct wl_listener *listener, void *data)
|
destroyidleinhibitor(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
StaticListener *sl = wl_container_of(listener, sl, listener);
|
IdleInhibitor *i = wl_container_of(listener, i, destroy);
|
||||||
struct wlr_idle_inhibitor_v1 *idle_inhibitor = sl->data;
|
|
||||||
/* At this point the idle inhibitor is still in the list of the manager */
|
/* At this point the idle inhibitor is still in the list of the manager */
|
||||||
checkidleinhibitor(wlr_surface_get_root_surface(idle_inhibitor->surface));
|
checkidleinhibitor(wlr_surface_get_root_surface(i->inhibitor->surface));
|
||||||
wl_list_remove(&listener->link);
|
wl_list_remove(&i->destroy.link);
|
||||||
free(listener);
|
free(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1492,14 +1520,21 @@ destroylocksurface(struct wl_listener *listener, void *data)
|
|||||||
if (lock_surface->surface != seat->keyboard_state.focused_surface)
|
if (lock_surface->surface != seat->keyboard_state.focused_surface)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (locked && cur_lock && !wl_list_empty(&cur_lock->surfaces)) {
|
if (!locked) {
|
||||||
surface = wl_container_of(cur_lock->surfaces.next, surface, link);
|
|
||||||
client_notify_enter(surface->surface, wlr_seat_get_keyboard(seat));
|
|
||||||
} else if (!locked) {
|
|
||||||
focusclient(focustop(selmon), NULL, 1);
|
focusclient(focustop(selmon), NULL, 1);
|
||||||
} else {
|
return;
|
||||||
wlr_seat_keyboard_clear_focus(seat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The surface being destroyed is still in the list */
|
||||||
|
if (cur_lock) {
|
||||||
|
wl_list_for_each(surface, &cur_lock->surfaces, link) {
|
||||||
|
if (surface != lock_surface) {
|
||||||
|
client_notify_enter(surface->surface, wlr_seat_get_keyboard(seat));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wlr_seat_keyboard_clear_focus(seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1547,6 +1582,15 @@ destroypointerconstraint(struct wl_listener *listener, void *data)
|
|||||||
free(pointer_constraint);
|
free(pointer_constraint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
destroypopup(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
Popup *p = wl_container_of(listener, p, destroy);
|
||||||
|
wl_list_remove(&p->commit.link);
|
||||||
|
wl_list_remove(&p->destroy.link);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
destroysessionlock(struct wl_listener *listener, void *data)
|
destroysessionlock(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
@@ -1666,6 +1710,8 @@ void
|
|||||||
focusmon(const Arg *arg)
|
focusmon(const Arg *arg)
|
||||||
{
|
{
|
||||||
int i = 0, nmons = wl_list_length(&mons);
|
int i = 0, nmons = wl_list_length(&mons);
|
||||||
|
if (!selmon)
|
||||||
|
return;
|
||||||
if (nmons) {
|
if (nmons) {
|
||||||
do /* don't switch to disabled mons */
|
do /* don't switch to disabled mons */
|
||||||
selmon = dirtomon(arg->i);
|
selmon = dirtomon(arg->i);
|
||||||
@@ -1706,18 +1752,42 @@ focusstack(const Arg *arg)
|
|||||||
Client *
|
Client *
|
||||||
focustop(Monitor *m)
|
focustop(Monitor *m)
|
||||||
{
|
{
|
||||||
Client *c;
|
Client *c, *fs = NULL;
|
||||||
|
|
||||||
wl_list_for_each(c, &fstack, flink)
|
wl_list_for_each(c, &fstack, flink) {
|
||||||
if (VISIBLEON(c, m) && c->isfullscreen)
|
if (VISIBLEON(c, m) && c->isfullscreen) {
|
||||||
return c;
|
fs = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A fullscreen client's children are shown above it */
|
||||||
wl_list_for_each(c, &fstack, flink)
|
wl_list_for_each(c, &fstack, flink)
|
||||||
if (VISIBLEON(c, m))
|
if (VISIBLEON(c, m) && (!fs || c == fs || client_get_parent(c) == fs))
|
||||||
return c;
|
return c;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
forgetoffmons(void)
|
||||||
|
{
|
||||||
|
/* Forget the outputs that were unplugged while off, or they would stay
|
||||||
|
* off when plugged in again */
|
||||||
|
char **name, **kept = offmons.data;
|
||||||
|
Monitor *m;
|
||||||
|
|
||||||
|
wl_array_for_each(name, &offmons) {
|
||||||
|
wl_list_for_each(m, &mons, link)
|
||||||
|
if (!strcmp(*name, m->wlr_output->name))
|
||||||
|
break;
|
||||||
|
if (&m->link != &mons)
|
||||||
|
*kept++ = *name;
|
||||||
|
else
|
||||||
|
free(*name);
|
||||||
|
}
|
||||||
|
offmons.size = (char *)kept - (char *)offmons.data;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fullscreennotify(struct wl_listener *listener, void *data)
|
fullscreennotify(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
@@ -2272,8 +2342,12 @@ outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test)
|
|||||||
for (i = 0; i < states_len; i++) {
|
for (i = 0; i < states_len; i++) {
|
||||||
struct wlr_swapchain *swapchain = wlr_output_swapchain_manager_get_swapchain(
|
struct wlr_swapchain *swapchain = wlr_output_swapchain_manager_get_swapchain(
|
||||||
&swapchain_manager, states[i].output);
|
&swapchain_manager, states[i].output);
|
||||||
if (swapchain && !states[i].output->enabled)
|
struct wlr_buffer *buffer;
|
||||||
wlr_output_state_set_buffer(&states[i].base, wlr_swapchain_acquire(swapchain));
|
if (swapchain && !states[i].output->enabled
|
||||||
|
&& (buffer = wlr_swapchain_acquire(swapchain))) {
|
||||||
|
wlr_output_state_set_buffer(&states[i].base, buffer);
|
||||||
|
wlr_buffer_unlock(buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(ok = wlr_backend_commit(backend, states, states_len)))
|
if (!(ok = wlr_backend_commit(backend, states, states_len)))
|
||||||
@@ -2405,6 +2479,8 @@ powermgrsetmode(struct wl_listener *listener, void *data)
|
|||||||
if (!m)
|
if (!m)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (event->mode)
|
||||||
|
forgetoffmons();
|
||||||
m->gamma_lut_changed = 1; /* Reapply gamma LUT when re-enabling the output */
|
m->gamma_lut_changed = 1; /* Reapply gamma LUT when re-enabling the output */
|
||||||
wlr_output_state_set_enabled(&state, event->mode);
|
wlr_output_state_set_enabled(&state, event->mode);
|
||||||
/* The output was reconnected while off and was never modeset */
|
/* The output was reconnected while off and was never modeset */
|
||||||
@@ -2749,6 +2825,7 @@ setup(void)
|
|||||||
* if an X11 server is running. */
|
* if an X11 server is running. */
|
||||||
if (!(backend = wlr_backend_autocreate(event_loop, &session)))
|
if (!(backend = wlr_backend_autocreate(event_loop, &session)))
|
||||||
die("couldn't create backend");
|
die("couldn't create backend");
|
||||||
|
wl_signal_add(&backend->events.destroy, &backend_destroy);
|
||||||
|
|
||||||
/* Initialize the scene graph used to lay out windows */
|
/* Initialize the scene graph used to lay out windows */
|
||||||
scene = wlr_scene_create();
|
scene = wlr_scene_create();
|
||||||
@@ -3142,7 +3219,7 @@ void
|
|||||||
transactionapply(void)
|
transactionapply(void)
|
||||||
{
|
{
|
||||||
struct wlr_scene_node **ghost;
|
struct wlr_scene_node **ghost;
|
||||||
Client *c;
|
Client *c, *p;
|
||||||
Monitor *m;
|
Monitor *m;
|
||||||
|
|
||||||
wl_event_source_timer_update(transaction_timer, 0);
|
wl_event_source_timer_update(transaction_timer, 0);
|
||||||
@@ -3164,7 +3241,8 @@ transactionapply(void)
|
|||||||
wl_list_for_each(m, &mons, link) {
|
wl_list_for_each(m, &mons, link) {
|
||||||
if (m->wlr_output->enabled)
|
if (m->wlr_output->enabled)
|
||||||
wlr_scene_node_set_enabled(&m->fullscreen_bg->node,
|
wlr_scene_node_set_enabled(&m->fullscreen_bg->node,
|
||||||
(c = focustop(m)) && c->isfullscreen);
|
(c = focustop(m)) && (c->isfullscreen
|
||||||
|
|| ((p = client_get_parent(c)) && p->isfullscreen)));
|
||||||
}
|
}
|
||||||
|
|
||||||
motionnotify(0, NULL, 0, 0, 0, 0);
|
motionnotify(0, NULL, 0, 0, 0, 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user