Add request_active_output event

This commit is contained in:
buffet 2021-08-01 21:58:07 +00:00
parent d3c5bb27e5
commit 37b6ff399d
7 changed files with 128 additions and 7 deletions

View file

@ -29,10 +29,14 @@ struct kiwmi_desktop {
struct {
struct wl_signal new_output;
struct wl_signal view_map;
struct wl_signal request_active_output;
} events;
};
bool desktop_init(struct kiwmi_desktop *desktop, struct wlr_renderer *renderer);
void desktop_fini(struct kiwmi_desktop *desktop);
struct kiwmi_server;
struct kiwmi_output *desktop_active_output(struct kiwmi_server *server);
#endif /* KIWMI_DESKTOP_DESKTOP_H */

View file

@ -37,6 +37,7 @@ struct kiwmi_object {
} events;
};
void *luaK_toudata(lua_State *L, int ud, const char *tname);
int luaK_kiwmi_object_gc(lua_State *L);
struct kiwmi_object *luaK_get_kiwmi_object(
struct kiwmi_lua *lua,

View file

@ -12,6 +12,7 @@
#include <wayland-server.h>
#include <wlr/backend.h>
#include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_export_dmabuf_v1.h>
#include <wlr/types/wlr_layer_shell_v1.h>
@ -22,7 +23,10 @@
#include "desktop/layer_shell.h"
#include "desktop/output.h"
#include "desktop/view.h"
#include "desktop/xdg_shell.h"
#include "input/cursor.h"
#include "input/input.h"
#include "server.h"
bool
@ -67,6 +71,7 @@ desktop_init(struct kiwmi_desktop *desktop, struct wlr_renderer *renderer)
wl_signal_init(&desktop->events.new_output);
wl_signal_init(&desktop->events.view_map);
wl_signal_init(&desktop->events.request_active_output);
return true;
}
@ -76,3 +81,37 @@ desktop_fini(struct kiwmi_desktop *desktop)
{
wlr_output_layout_destroy(desktop->output_layout);
}
struct kiwmi_output *
desktop_active_output(struct kiwmi_server *server)
{
// 1. callback (request_active_output)
struct kiwmi_output *output = NULL;
wl_signal_emit(&server->desktop.events.request_active_output, &output);
if (output) {
return output;
}
// 2. focused view center
if (!wl_list_empty(&server->desktop.views)) {
struct kiwmi_view *view;
wl_list_for_each (view, &server->desktop.views, link) {
break; // get first element of list
}
double lx = view->geom.x + view->geom.width / 2;
double ly = view->geom.y + view->geom.height / 2;
struct wlr_output *wlr_output = wlr_output_layout_output_at(server->desktop.output_layout, lx, ly);
return wlr_output->data;
}
// 3. cursor
double lx = server->input.cursor->cursor->x;
double ly = server->input.cursor->cursor->y;
struct wlr_output *wlr_output = wlr_output_layout_output_at(server->desktop.output_layout, lx, ly);
return wlr_output->data;
}

View file

@ -351,13 +351,9 @@ layer_shell_new_surface_notify(struct wl_listener *listener, void *data)
layer_surface->namespace);
if (!layer_surface->output) {
// TODO: assign active output
wlr_log(WLR_ERROR, "TODO: assign active output");
struct kiwmi_output *output;
wl_list_for_each (output, &desktop->outputs, link) {
layer_surface->output = output->wlr_output;
break;
}
struct kiwmi_server *server =
wl_container_of(desktop, server, desktop);
layer_surface->output = desktop_active_output(server)->wlr_output;
}
struct kiwmi_layer *layer = malloc(sizeof(*layer));

View file

@ -305,6 +305,39 @@ kiwmi_server_on_output_notify(struct wl_listener *listener, void *data)
}
}
static void
kiwmi_server_on_request_active_output_notify(struct wl_listener *listener, void *data)
{
struct kiwmi_lua_callback *lc = wl_container_of(listener, lc, listener);
struct kiwmi_server *server = lc->server;
lua_State *L = server->lua->L;
struct kiwmi_output **output = data;
lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref);
if (lua_pcall(L, 0, 1, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
return;
}
if (!lua_isnil(L, -1)) {
struct kiwmi_object *obj;
struct kiwmi_object **objp;
if (!(objp = luaK_toudata(L, -1, "kiwmi_output"))) {
wlr_log(WLR_ERROR, "kiwmi_output expected, got %s", luaL_typename(L, -1));
return;
}
obj = *objp;
if (!obj->valid) {
wlr_log(WLR_ERROR, "kiwmi_output no longer valid");
return;
}
*output = obj->object;
}
}
static void
kiwmi_server_on_view_notify(struct wl_listener *listener, void *data)
{
@ -378,6 +411,30 @@ l_kiwmi_server_on_output(lua_State *L)
return 0;
}
static int
l_kiwmi_server_on_request_active_output(lua_State *L)
{
struct kiwmi_object *obj =
*(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_server");
luaL_checktype(L, 2, LUA_TFUNCTION);
struct kiwmi_server *server = obj->object;
lua_pushcfunction(L, luaK_kiwmi_lua_callback_new);
lua_pushlightuserdata(L, server);
lua_pushvalue(L, 2);
lua_pushlightuserdata(L, kiwmi_server_on_request_active_output_notify);
lua_pushlightuserdata(L, &server->desktop.events.request_active_output);
lua_pushlightuserdata(L, obj);
if (lua_pcall(L, 5, 0, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
return 0;
}
return 0;
}
static int
l_kiwmi_server_on_view(lua_State *L)
{
@ -405,6 +462,7 @@ l_kiwmi_server_on_view(lua_State *L)
static const luaL_Reg kiwmi_server_events[] = {
{"keyboard", l_kiwmi_server_on_keyboard},
{"output", l_kiwmi_server_on_output},
{"request_active_output", l_kiwmi_server_on_request_active_output},
{"view", l_kiwmi_server_on_view},
{NULL, NULL},
};

View file

@ -22,6 +22,22 @@
#include "luak/kiwmi_server.h"
#include "luak/kiwmi_view.h"
void *
luaK_toudata(lua_State *L, int ud, const char *tname)
{
void *p = lua_touserdata(L, ud);
if (p != NULL) { /* value is a userdata? */
if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
lua_pop(L, 2); /* remove both metatables */
return p;
}
}
}
return NULL;
}
int
luaK_kiwmi_object_gc(lua_State *L)
{

View file

@ -58,6 +58,13 @@ Get the view at a specified position.
A new keyboard got attached.
Callback receives a reference to the keyboard.
#### request_active_output
Called when the active output needs to be requested (for example because a layer-shell surface needs to be positioned).
Callback receives nothing and optionally returns a kiwmi_output.
If this isn't set or returns `nil`, the compositor defaults to the output the focused view is on, and if there is no view, the output the mouse is on.
#### output
A new output got attached.