164
src/LunarWM.c
164
src/LunarWM.c
@@ -63,6 +63,7 @@ void toplevel_commit_notify(struct wl_listener *l, void *)
|
|||||||
LunarWM_Toplevel_update(tl);
|
LunarWM_Toplevel_update(tl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void focus_fallback(LunarWM *wm);
|
||||||
void toplevel_destroy_notify(struct wl_listener *l, void *)
|
void toplevel_destroy_notify(struct wl_listener *l, void *)
|
||||||
{
|
{
|
||||||
auto *tl = wl_container_of(l, (LunarWM_Toplevel *)(NULL), destroy);
|
auto *tl = wl_container_of(l, (LunarWM_Toplevel *)(NULL), destroy);
|
||||||
@@ -73,10 +74,66 @@ void toplevel_destroy_notify(struct wl_listener *l, void *)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
focus_fallback(tl->server);
|
||||||
|
|
||||||
LunarWM_Toplevel_destroy(tl);
|
LunarWM_Toplevel_destroy(tl);
|
||||||
free(tl);
|
free(tl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void toplevel_map_notify(struct wl_listener *l, void *data)
|
||||||
|
{
|
||||||
|
(void)data;
|
||||||
|
LunarWM_Toplevel *tl = wl_container_of(l, (LunarWM_Toplevel *)0, map);
|
||||||
|
if (!tl || !tl->surface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (tl->is_xwayland && tl->u.xwl) {
|
||||||
|
if (tl->u.xwl->override_redirect
|
||||||
|
&& !wlr_xwayland_surface_override_redirect_wants_focus(tl->u.xwl)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LunarWM_Toplevel_focus(tl);
|
||||||
|
|
||||||
|
LunarWM *wm = tl->server;
|
||||||
|
for (size_t i = 0; i < vector_size(wm->wayland.v_toplevels); ++i) {
|
||||||
|
if (wm->wayland.v_toplevels[i] == tl) {
|
||||||
|
wm->wayland.current_focus = (int)i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void toplevel_unmap_notify(struct wl_listener *l, void *data)
|
||||||
|
{
|
||||||
|
(void)data;
|
||||||
|
LunarWM_Toplevel *tl = wl_container_of(l, tl, unmap);
|
||||||
|
if (!tl || !tl->surface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// detach per-surface listeners/resources
|
||||||
|
if (tl->map.link.prev || tl->map.link.next)
|
||||||
|
wl_list_remove(&tl->map.link);
|
||||||
|
if (tl->unmap.link.prev || tl->unmap.link.next)
|
||||||
|
wl_list_remove(&tl->unmap.link);
|
||||||
|
if (tl->commit.link.prev || tl->commit.link.next)
|
||||||
|
wl_list_remove(&tl->commit.link);
|
||||||
|
|
||||||
|
if (tl->locked_buffer) {
|
||||||
|
wlr_buffer_unlock(tl->locked_buffer);
|
||||||
|
tl->locked_buffer = NULL;
|
||||||
|
}
|
||||||
|
tl->texture = NULL;
|
||||||
|
tl->gles_texture = NULL;
|
||||||
|
tl->rl_texture = (Texture) { 0 };
|
||||||
|
tl->surface = NULL;
|
||||||
|
|
||||||
|
// If the thing that unmapped was focused, pick a fallback
|
||||||
|
focus_fallback(tl->server);
|
||||||
|
}
|
||||||
|
|
||||||
bool LunarWM_Toplevel_init_xdg(
|
bool LunarWM_Toplevel_init_xdg(
|
||||||
LunarWM_Toplevel *tl, LunarWM *wm, struct wlr_xdg_toplevel *xdg)
|
LunarWM_Toplevel *tl, LunarWM *wm, struct wlr_xdg_toplevel *xdg)
|
||||||
{
|
{
|
||||||
@@ -94,6 +151,12 @@ bool LunarWM_Toplevel_init_xdg(
|
|||||||
tl->destroy.notify = toplevel_destroy_notify;
|
tl->destroy.notify = toplevel_destroy_notify;
|
||||||
wl_signal_add(&tl->surface->events.destroy, &tl->destroy);
|
wl_signal_add(&tl->surface->events.destroy, &tl->destroy);
|
||||||
|
|
||||||
|
tl->map.notify = toplevel_map_notify;
|
||||||
|
wl_signal_add(&tl->u.xdg->base->surface->events.map, &tl->map);
|
||||||
|
|
||||||
|
tl->unmap.notify = toplevel_unmap_notify;
|
||||||
|
wl_signal_add(&tl->u.xdg->base->surface->events.unmap, &tl->unmap);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +168,6 @@ bool LunarWM_Toplevel_init_xwayland(
|
|||||||
tl->is_xwayland = true;
|
tl->is_xwayland = true;
|
||||||
tl->u.xwl = xwl;
|
tl->u.xwl = xwl;
|
||||||
tl->surface = xwl->surface;
|
tl->surface = xwl->surface;
|
||||||
|
|
||||||
assert(tl->surface);
|
assert(tl->surface);
|
||||||
|
|
||||||
tl->commit.notify = toplevel_commit_notify;
|
tl->commit.notify = toplevel_commit_notify;
|
||||||
@@ -114,16 +176,29 @@ bool LunarWM_Toplevel_init_xwayland(
|
|||||||
tl->destroy.notify = toplevel_destroy_notify;
|
tl->destroy.notify = toplevel_destroy_notify;
|
||||||
wl_signal_add(&tl->surface->events.destroy, &tl->destroy);
|
wl_signal_add(&tl->surface->events.destroy, &tl->destroy);
|
||||||
|
|
||||||
|
tl->map.notify = toplevel_map_notify;
|
||||||
|
wl_signal_add(&xwl->surface->events.map, &tl->map);
|
||||||
|
|
||||||
|
tl->unmap.notify = toplevel_unmap_notify;
|
||||||
|
wl_signal_add(&xwl->surface->events.unmap, &tl->unmap);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LunarWM_Toplevel_destroy(LunarWM_Toplevel *this)
|
bool LunarWM_Toplevel_destroy(LunarWM_Toplevel *this)
|
||||||
{
|
{
|
||||||
|
if (!this)
|
||||||
|
return false;
|
||||||
|
if (this->map.link.prev || this->map.link.next)
|
||||||
|
wl_list_remove(&this->map.link);
|
||||||
|
if (this->unmap.link.prev || this->unmap.link.next)
|
||||||
|
wl_list_remove(&this->unmap.link);
|
||||||
|
if (this->commit.link.prev || this->commit.link.next)
|
||||||
wl_list_remove(&this->commit.link);
|
wl_list_remove(&this->commit.link);
|
||||||
|
if (this->destroy.link.prev || this->destroy.link.next)
|
||||||
wl_list_remove(&this->destroy.link);
|
wl_list_remove(&this->destroy.link);
|
||||||
if (this->locked_buffer != nullptr) {
|
if (this->locked_buffer)
|
||||||
wlr_buffer_unlock(this->locked_buffer);
|
wlr_buffer_unlock(this->locked_buffer);
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,6 +285,7 @@ struct XwlHooks {
|
|||||||
struct wl_listener req_configure;
|
struct wl_listener req_configure;
|
||||||
struct wl_listener req_maximize;
|
struct wl_listener req_maximize;
|
||||||
struct wl_listener req_fullscreen;
|
struct wl_listener req_fullscreen;
|
||||||
|
struct wl_listener req_activate;
|
||||||
struct wl_listener set_geometry;
|
struct wl_listener set_geometry;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -290,6 +366,10 @@ static void xwl_unmap_toplevel(LunarWM_Toplevel *tl)
|
|||||||
if (!tl)
|
if (!tl)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (tl->map.link.prev || tl->map.link.next)
|
||||||
|
wl_list_remove(&tl->map.link);
|
||||||
|
if (tl->unmap.link.prev || tl->unmap.link.next)
|
||||||
|
wl_list_remove(&tl->unmap.link);
|
||||||
if (tl->commit.link.prev || tl->commit.link.next)
|
if (tl->commit.link.prev || tl->commit.link.next)
|
||||||
wl_list_remove(&tl->commit.link);
|
wl_list_remove(&tl->commit.link);
|
||||||
if (tl->destroy.link.prev || tl->destroy.link.next)
|
if (tl->destroy.link.prev || tl->destroy.link.next)
|
||||||
@@ -319,6 +399,8 @@ static void xwl_on_dissociate(struct wl_listener *ll, void *data)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
focus_fallback(wm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xwl_on_request_configure(struct wl_listener *ll, void *data)
|
static void xwl_on_request_configure(struct wl_listener *ll, void *data)
|
||||||
@@ -357,6 +439,18 @@ static void xwl_on_request_fullscreen(struct wl_listener *ll, void *data)
|
|||||||
wlr_xwayland_surface_set_fullscreen(xh->xwl, true);
|
wlr_xwayland_surface_set_fullscreen(xh->xwl, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void xwl_on_request_activate(struct wl_listener *ll, void *data)
|
||||||
|
{
|
||||||
|
struct XwlHooks *h = wl_container_of(ll, h, req_activate);
|
||||||
|
for (size_t i = 0; i < vector_size(h->wm->wayland.v_toplevels); ++i) {
|
||||||
|
LunarWM_Toplevel *tl = h->wm->wayland.v_toplevels[i];
|
||||||
|
if (tl->is_xwayland && tl->u.xwl == h->xwl) {
|
||||||
|
LunarWM_Toplevel_focus(tl);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void xwl_on_set_geometry(struct wl_listener *ll, void *data)
|
static void xwl_on_set_geometry(struct wl_listener *ll, void *data)
|
||||||
{
|
{
|
||||||
(void)ll;
|
(void)ll;
|
||||||
@@ -375,6 +469,8 @@ static void xwl_on_destroy(struct wl_listener *ll, void *data)
|
|||||||
wl_list_remove(&xh->req_maximize.link);
|
wl_list_remove(&xh->req_maximize.link);
|
||||||
if (xh->req_fullscreen.link.prev)
|
if (xh->req_fullscreen.link.prev)
|
||||||
wl_list_remove(&xh->req_fullscreen.link);
|
wl_list_remove(&xh->req_fullscreen.link);
|
||||||
|
if (xh->req_activate.link.prev)
|
||||||
|
wl_list_remove(&xh->req_activate.link);
|
||||||
if (xh->set_geometry.link.prev)
|
if (xh->set_geometry.link.prev)
|
||||||
wl_list_remove(&xh->set_geometry.link);
|
wl_list_remove(&xh->set_geometry.link);
|
||||||
if (xh->associate.link.prev)
|
if (xh->associate.link.prev)
|
||||||
@@ -393,9 +489,60 @@ static void xwl_on_destroy(struct wl_listener *ll, void *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
focus_fallback(wm);
|
||||||
|
|
||||||
free(xh);
|
free(xh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool xwl_wants_focus(struct wlr_xwayland_surface *x)
|
||||||
|
{
|
||||||
|
if (!x)
|
||||||
|
return false;
|
||||||
|
if (!x->surface)
|
||||||
|
return false;
|
||||||
|
if (x->override_redirect
|
||||||
|
&& !wlr_xwayland_surface_override_redirect_wants_focus(x)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (x->withdrawn || x->minimized)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void focus_fallback(LunarWM *wm)
|
||||||
|
{
|
||||||
|
if (!wm || !wm->wayland.seat)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (ssize_t i = (ssize_t)vector_size(wm->wayland.v_toplevels) - 1; i >= 0;
|
||||||
|
--i) {
|
||||||
|
LunarWM_Toplevel *cand = wm->wayland.v_toplevels[i];
|
||||||
|
if (!cand || !cand->surface)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (cand->is_xwayland) {
|
||||||
|
if (!xwl_wants_focus(cand->u.xwl))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
LunarWM_Toplevel_focus(cand);
|
||||||
|
wm->wayland.current_focus = (int)i;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_seat *seat = wm->wayland.seat;
|
||||||
|
struct wlr_surface *prev = seat->keyboard_state.focused_surface;
|
||||||
|
if (prev) {
|
||||||
|
struct wlr_xdg_toplevel *pt;
|
||||||
|
struct wlr_xwayland_surface *px;
|
||||||
|
if ((pt = wlr_xdg_toplevel_try_from_wlr_surface(prev)))
|
||||||
|
wlr_xdg_toplevel_set_activated(pt, false);
|
||||||
|
if ((px = wlr_xwayland_surface_try_from_wlr_surface(prev)))
|
||||||
|
wlr_xwayland_surface_activate(px, false);
|
||||||
|
}
|
||||||
|
wlr_seat_keyboard_clear_focus(seat);
|
||||||
|
wm->wayland.current_focus = -1;
|
||||||
|
}
|
||||||
|
|
||||||
static void xwayland_new_surface_notify(struct wl_listener *l, void *data)
|
static void xwayland_new_surface_notify(struct wl_listener *l, void *data)
|
||||||
{
|
{
|
||||||
LunarWM *wm = wl_container_of(l, wm, wayland.xwayland_new_surface);
|
LunarWM *wm = wl_container_of(l, wm, wayland.xwayland_new_surface);
|
||||||
@@ -430,6 +577,9 @@ static void xwayland_new_surface_notify(struct wl_listener *l, void *data)
|
|||||||
h->req_fullscreen.notify = xwl_on_request_fullscreen;
|
h->req_fullscreen.notify = xwl_on_request_fullscreen;
|
||||||
wl_signal_add(&xwl->events.request_fullscreen, &h->req_fullscreen);
|
wl_signal_add(&xwl->events.request_fullscreen, &h->req_fullscreen);
|
||||||
|
|
||||||
|
h->req_activate.notify = xwl_on_request_activate;
|
||||||
|
wl_signal_add(&xwl->events.request_activate, &h->req_activate);
|
||||||
|
|
||||||
h->set_geometry.notify = xwl_on_set_geometry;
|
h->set_geometry.notify = xwl_on_set_geometry;
|
||||||
wl_signal_add(&xwl->events.set_geometry, &h->set_geometry);
|
wl_signal_add(&xwl->events.set_geometry, &h->set_geometry);
|
||||||
|
|
||||||
@@ -2560,6 +2710,12 @@ static bool render_layer(LunarWM *this, LunarWM_RenderLayerInfo *info, float dt)
|
|||||||
info->layers[info->layers_count++]
|
info->layers[info->layers_count++]
|
||||||
= (XrCompositionLayerBaseHeader *)&info->layer_projection;
|
= (XrCompositionLayerBaseHeader *)&info->layer_projection;
|
||||||
|
|
||||||
|
if (this->renderer.first_frame) {
|
||||||
|
l_recenter(this->cman->L);
|
||||||
|
lua_pop(this->cman->L, 1);
|
||||||
|
this->renderer.first_frame = false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2568,6 +2724,8 @@ void LunarWM_run(LunarWM *this)
|
|||||||
assert(this);
|
assert(this);
|
||||||
assert(this->initialized);
|
assert(this->initialized);
|
||||||
|
|
||||||
|
this->renderer.first_frame = true;
|
||||||
|
|
||||||
if (!wlr_backend_start(this->wayland.backend)) {
|
if (!wlr_backend_start(this->wayland.backend)) {
|
||||||
wlr_log(WLR_ERROR, "Failed to start backend");
|
wlr_log(WLR_ERROR, "Failed to start backend");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ typedef struct {
|
|||||||
struct wl_listener commit;
|
struct wl_listener commit;
|
||||||
struct wl_listener destroy;
|
struct wl_listener destroy;
|
||||||
|
|
||||||
|
struct wl_listener map, unmap;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct wlr_xdg_toplevel *xdg;
|
struct wlr_xdg_toplevel *xdg;
|
||||||
struct wlr_xwayland_surface *xwl;
|
struct wlr_xwayland_surface *xwl;
|
||||||
@@ -206,6 +208,8 @@ typedef struct LunarWM {
|
|||||||
Shader linear_srgb;
|
Shader linear_srgb;
|
||||||
|
|
||||||
Skybox skybox;
|
Skybox skybox;
|
||||||
|
|
||||||
|
bool first_frame;
|
||||||
} renderer;
|
} renderer;
|
||||||
|
|
||||||
ConfigManager *cman;
|
ConfigManager *cman;
|
||||||
|
|||||||
Reference in New Issue
Block a user