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;
|
||||
break;
|
||||
case WLR_XDG_SURFACE_ROLE_TOPLEVEL:
|
||||
if (!xdg_surface->toplevel)
|
||||
return -1;
|
||||
c = xdg_surface->data;
|
||||
type = c->type;
|
||||
goto end;
|
||||
|
||||
@@ -83,7 +83,6 @@
|
||||
#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags]))
|
||||
#define TAGMASK ((1u << TAGCOUNT) - 1)
|
||||
#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 */
|
||||
enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
|
||||
@@ -246,6 +245,17 @@ typedef struct {
|
||||
struct wl_listener destroy;
|
||||
} 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 {
|
||||
const char *id;
|
||||
const char *title;
|
||||
@@ -263,12 +273,6 @@ typedef struct {
|
||||
struct wl_listener destroy;
|
||||
} SessionLock;
|
||||
|
||||
typedef struct {
|
||||
/* Must keep this field first */
|
||||
struct wl_listener listener;
|
||||
void *data;
|
||||
} StaticListener;
|
||||
|
||||
/* function declarations */
|
||||
static void applybounds(Client *c, struct wlr_box *bbox);
|
||||
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 cursorframe(struct wl_listener *listener, void *data);
|
||||
static void cursorwarptohint(void);
|
||||
static void destroybackend(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 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 destroynotify(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 destroykeyboardgroup(struct wl_listener *listener, void *data);
|
||||
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 focusstack(const Arg *arg);
|
||||
static Client *focustop(Monitor *m);
|
||||
static void forgetoffmons(void);
|
||||
static void fullscreennotify(struct wl_listener *listener, void *data);
|
||||
static void gpureset(struct wl_listener *listener, void *data);
|
||||
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 */
|
||||
|
||||
/* global event handlers */
|
||||
static struct wl_listener backend_destroy = {.notify = destroybackend};
|
||||
static struct wl_listener cursor_axis = {.notify = axisnotify};
|
||||
static struct wl_listener cursor_button = {.notify = buttonpress};
|
||||
static struct wl_listener cursor_frame = {.notify = cursorframe};
|
||||
@@ -855,7 +863,8 @@ cleanup(void)
|
||||
|
||||
/* 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 */
|
||||
wlr_backend_destroy(backend);
|
||||
if (backend)
|
||||
wlr_backend_destroy(backend);
|
||||
|
||||
if (transaction_idle)
|
||||
wl_event_source_remove(transaction_idle);
|
||||
@@ -911,6 +920,7 @@ cleanuplisteners(void)
|
||||
wl_list_remove(&new_idle_inhibitor.link);
|
||||
wl_list_remove(&layout_change.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_pointer.link);
|
||||
wl_list_remove(&new_pointer_constraint.link);
|
||||
@@ -1054,8 +1064,8 @@ commitnotify(struct wl_listener *listener, void *data)
|
||||
void
|
||||
commitpopup(struct wl_listener *listener, void *data)
|
||||
{
|
||||
StaticListener *sl = wl_container_of(listener, sl, listener);
|
||||
struct wlr_xdg_popup *popup = sl->data;
|
||||
Popup *p = wl_container_of(listener, p, commit);
|
||||
struct wlr_xdg_popup *popup = p->popup;
|
||||
LayerSurface *l = NULL;
|
||||
Client *c = NULL;
|
||||
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.y -= (type == LayerShell ? l->scene->node.y : c->geom.y - c->surface.xdg->geometry.y);
|
||||
wlr_xdg_popup_unconstrain_from_box(popup, &box);
|
||||
wl_list_remove(&listener->link);
|
||||
free(listener);
|
||||
destroypopup(&p->destroy, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1098,7 +1107,9 @@ void
|
||||
createidleinhibitor(struct wl_listener *listener, void *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);
|
||||
}
|
||||
@@ -1372,7 +1383,10 @@ createpopup(struct wl_listener *listener, void *data)
|
||||
/* This event is raised when a client (either xdg-shell or layer-shell)
|
||||
* creates a new popup. */
|
||||
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
|
||||
@@ -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
|
||||
destroydecoration(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -1435,12 +1464,11 @@ destroydragicon(struct wl_listener *listener, void *data)
|
||||
void
|
||||
destroyidleinhibitor(struct wl_listener *listener, void *data)
|
||||
{
|
||||
StaticListener *sl = wl_container_of(listener, sl, listener);
|
||||
struct wlr_idle_inhibitor_v1 *idle_inhibitor = sl->data;
|
||||
IdleInhibitor *i = wl_container_of(listener, i, destroy);
|
||||
/* At this point the idle inhibitor is still in the list of the manager */
|
||||
checkidleinhibitor(wlr_surface_get_root_surface(idle_inhibitor->surface));
|
||||
wl_list_remove(&listener->link);
|
||||
free(listener);
|
||||
checkidleinhibitor(wlr_surface_get_root_surface(i->inhibitor->surface));
|
||||
wl_list_remove(&i->destroy.link);
|
||||
free(i);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1492,14 +1520,21 @@ destroylocksurface(struct wl_listener *listener, void *data)
|
||||
if (lock_surface->surface != seat->keyboard_state.focused_surface)
|
||||
return;
|
||||
|
||||
if (locked && cur_lock && !wl_list_empty(&cur_lock->surfaces)) {
|
||||
surface = wl_container_of(cur_lock->surfaces.next, surface, link);
|
||||
client_notify_enter(surface->surface, wlr_seat_get_keyboard(seat));
|
||||
} else if (!locked) {
|
||||
if (!locked) {
|
||||
focusclient(focustop(selmon), NULL, 1);
|
||||
} else {
|
||||
wlr_seat_keyboard_clear_focus(seat);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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
|
||||
@@ -1547,6 +1582,15 @@ destroypointerconstraint(struct wl_listener *listener, void *data)
|
||||
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
|
||||
destroysessionlock(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -1666,6 +1710,8 @@ void
|
||||
focusmon(const Arg *arg)
|
||||
{
|
||||
int i = 0, nmons = wl_list_length(&mons);
|
||||
if (!selmon)
|
||||
return;
|
||||
if (nmons) {
|
||||
do /* don't switch to disabled mons */
|
||||
selmon = dirtomon(arg->i);
|
||||
@@ -1706,18 +1752,42 @@ focusstack(const Arg *arg)
|
||||
Client *
|
||||
focustop(Monitor *m)
|
||||
{
|
||||
Client *c;
|
||||
Client *c, *fs = NULL;
|
||||
|
||||
wl_list_for_each(c, &fstack, flink)
|
||||
if (VISIBLEON(c, m) && c->isfullscreen)
|
||||
return c;
|
||||
wl_list_for_each(c, &fstack, flink) {
|
||||
if (VISIBLEON(c, m) && c->isfullscreen) {
|
||||
fs = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* A fullscreen client's children are shown above it */
|
||||
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 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
|
||||
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++) {
|
||||
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));
|
||||
struct wlr_buffer *buffer;
|
||||
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)))
|
||||
@@ -2405,6 +2479,8 @@ powermgrsetmode(struct wl_listener *listener, void *data)
|
||||
if (!m)
|
||||
return;
|
||||
|
||||
if (event->mode)
|
||||
forgetoffmons();
|
||||
m->gamma_lut_changed = 1; /* Reapply gamma LUT when re-enabling the output */
|
||||
wlr_output_state_set_enabled(&state, event->mode);
|
||||
/* The output was reconnected while off and was never modeset */
|
||||
@@ -2749,6 +2825,7 @@ setup(void)
|
||||
* if an X11 server is running. */
|
||||
if (!(backend = wlr_backend_autocreate(event_loop, &session)))
|
||||
die("couldn't create backend");
|
||||
wl_signal_add(&backend->events.destroy, &backend_destroy);
|
||||
|
||||
/* Initialize the scene graph used to lay out windows */
|
||||
scene = wlr_scene_create();
|
||||
@@ -3142,7 +3219,7 @@ void
|
||||
transactionapply(void)
|
||||
{
|
||||
struct wlr_scene_node **ghost;
|
||||
Client *c;
|
||||
Client *c, *p;
|
||||
Monitor *m;
|
||||
|
||||
wl_event_source_timer_update(transaction_timer, 0);
|
||||
@@ -3164,7 +3241,8 @@ transactionapply(void)
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
if (m->wlr_output->enabled)
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user