aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2025-03-13 01:16:53 -0600
committerJosh Rahm <joshuarahm@gmail.com>2025-03-13 01:16:53 -0600
commit8e1542335494a7d0b596544f66c27aa9aff7c505 (patch)
tree14863e103a4a8eacb6af54225856de071a0ab0c1
parent63331b235230502deb83899c9e1b3b193520ba06 (diff)
downloadwetterhorn-8e1542335494a7d0b596544f66c27aa9aff7c505.tar.gz
wetterhorn-8e1542335494a7d0b596544f66c27aa9aff7c505.tar.bz2
wetterhorn-8e1542335494a7d0b596544f66c27aa9aff7c505.zip
Update. Is actually working to some degree with 0.18.0 again.
-rw-r--r--harness/CMakeLists.txt5
-rw-r--r--harness/include/wl.h10
-rw-r--r--harness/src/wl.c168
3 files changed, 127 insertions, 56 deletions
diff --git a/harness/CMakeLists.txt b/harness/CMakeLists.txt
index 0af759c..a7a0a77 100644
--- a/harness/CMakeLists.txt
+++ b/harness/CMakeLists.txt
@@ -8,7 +8,10 @@ set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_BUILD_TYPE Debug)
include_directories(include/ ../wlroots/include /usr/include/pixman-1
- ${CMAKE_CURRENT_BINARY_DIR}/ ${CMAKE_CURRENT_BINARY_DIR}/../wlroots/include)
+ ${CMAKE_CURRENT_BINARY_DIR}/
+ ${CMAKE_CURRENT_BINARY_DIR}/../wlroots/include
+ ${CMAKE_CURRENT_BINARY_DIR}/../wlroots/protocol
+)
add_definitions(-DWLR_USE_UNSTABLE)
diff --git a/harness/include/wl.h b/harness/include/wl.h
index 903ba10..2d4f763 100644
--- a/harness/include/wl.h
+++ b/harness/include/wl.h
@@ -43,7 +43,8 @@ struct tinywl_server {
struct wlr_scene_output_layout *scene_layout;
struct wlr_xdg_shell *xdg_shell;
- struct wl_listener new_xdg_surface;
+ struct wl_listener new_xdg_toplevel;
+ struct wl_listener new_xdg_popup;
struct wl_list toplevels;
struct wlr_cursor *cursor;
@@ -90,6 +91,7 @@ struct tinywl_toplevel {
struct wl_listener map;
struct wl_listener unmap;
struct wl_listener destroy;
+ struct wl_listener commit;
struct wl_listener request_move;
struct wl_listener request_resize;
struct wl_listener request_maximize;
@@ -106,3 +108,9 @@ struct tinywl_keyboard {
struct wl_listener destroy;
};
+struct tinywl_popup {
+ struct wlr_xdg_popup *xdg_popup;
+ struct wl_listener commit;
+ struct wl_listener destroy;
+};
+
diff --git a/harness/src/wl.c b/harness/src/wl.c
index 3386a63..a174e40 100644
--- a/harness/src/wl.c
+++ b/harness/src/wl.c
@@ -7,6 +7,8 @@
#include <wl.h>
+#include "xdg-decoration-unstable-v1-client-protocol.h"
+
// This macro is responsible for calling a handler on a plugin. This macro will
// acquire the plugin's lock, call the member with the arguments and update the
// state.
@@ -174,12 +176,18 @@ static void server_new_keyboard(struct tinywl_server *server,
names.layout = "jr";
names.variant = "jdvprk";
names.options = "numpad:mac";
+
/* We need to prepare an XKB keymap and assign it to the keyboard. This
* assumes the defaults (e.g. layout = "us"). */
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
struct xkb_keymap *keymap =
xkb_keymap_new_from_names(context, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);
+ if (!keymap) {
+ fprintf(stderr, "Unable to read keymap.\n");
+ exit(1);
+ }
+
wlr_keyboard_set_keymap(wlr_keyboard, keymap);
xkb_keymap_unref(keymap);
xkb_context_unref(context);
@@ -617,8 +625,10 @@ static void xdg_toplevel_map(struct wl_listener *listener, void *data)
wl_list_insert(&toplevel->server->toplevels, &toplevel->link);
+ fprintf(stderr, "Surface map ...\n");
plugin_call_update_state(toplevel->server->plugin, plugin_handle_surface,
toplevel, SURFACE_MAP);
+ fprintf(stderr, "/ Surface map ...\n");
focus_toplevel(toplevel, toplevel->xdg_toplevel->base->surface);
}
@@ -633,8 +643,10 @@ static void xdg_toplevel_unmap(struct wl_listener *listener, void *data)
reset_cursor_mode(toplevel->server);
}
+ fprintf(stderr, "Surface unmap ...\n");
plugin_call_update_state(toplevel->server->plugin, plugin_handle_surface,
toplevel, SURFACE_UNMAP);
+ fprintf(stderr, "/ Surface map ...\n");
wl_list_remove(&toplevel->link);
}
@@ -653,8 +665,10 @@ static void xdg_toplevel_destroy(struct wl_listener *listener, void *data)
wl_list_remove(&toplevel->request_maximize.link);
wl_list_remove(&toplevel->request_fullscreen.link);
+ fprintf(stderr, "Surface destroy ...\n");
plugin_call_update_state(toplevel->server->plugin, plugin_handle_surface,
toplevel, SURFACE_DELETE);
+ fprintf(stderr, "/ Surface destroy ...\n");
free(toplevel);
}
@@ -747,59 +761,102 @@ static void xdg_toplevel_request_fullscreen(struct wl_listener *listener,
wlr_xdg_surface_schedule_configure(toplevel->xdg_toplevel->base);
}
-static void server_new_xdg_surface(struct wl_listener *listener, void *data)
+static void xdg_popup_commit(struct wl_listener *listener, void *data) {
+ /* Called when a new surface state is committed. */
+ struct tinywl_popup *popup = wl_container_of(listener, popup, commit);
+
+ if (popup->xdg_popup->base->initial_commit) {
+ /* When an xdg_surface performs an initial commit, the compositor must
+ * reply with a configure so the client can map the surface.
+ * tinywl sends an empty configure. A more sophisticated compositor
+ * might change an xdg_popup's geometry to ensure it's not positioned
+ * off-screen, for example. */
+ wlr_xdg_surface_schedule_configure(popup->xdg_popup->base);
+ }
+}
+
+static void xdg_popup_destroy(struct wl_listener *listener, void *data) {
+ /* Called when the xdg_popup is destroyed. */
+ struct tinywl_popup *popup = wl_container_of(listener, popup, destroy);
+
+ wl_list_remove(&popup->commit.link);
+ wl_list_remove(&popup->destroy.link);
+
+ free(popup);
+}
+
+static void server_new_xdg_popup(struct wl_listener *listener, void *data) {
+ /* This event is raised when a client creates a new popup. */
+ struct wlr_xdg_popup *xdg_popup = data;
+
+ struct tinywl_popup *popup = calloc(1, sizeof(*popup));
+ popup->xdg_popup = xdg_popup;
+
+ /* We must add xdg popups to the scene graph so they get rendered. The
+ * wlroots scene graph provides a helper for this, but to use it we must
+ * provide the proper parent scene node of the xdg popup. To enable this,
+ * we always set the user data field of xdg_surfaces to the corresponding
+ * scene node. */
+ struct wlr_xdg_surface *parent = wlr_xdg_surface_try_from_wlr_surface(xdg_popup->parent);
+ assert(parent != NULL);
+ struct wlr_scene_tree *parent_tree = parent->data;
+ xdg_popup->base->data = wlr_scene_xdg_surface_create(parent_tree, xdg_popup->base);
+
+ popup->commit.notify = xdg_popup_commit;
+ wl_signal_add(&xdg_popup->base->surface->events.commit, &popup->commit);
+
+ popup->destroy.notify = xdg_popup_destroy;
+ wl_signal_add(&xdg_popup->events.destroy, &popup->destroy);
+}
+
+static void xdg_toplevel_commit(struct wl_listener *listener, void *data) {
+ /* Called when a new surface state is committed. */
+ struct tinywl_toplevel *toplevel = wl_container_of(listener, toplevel, commit);
+
+ if (toplevel->xdg_toplevel->base->initial_commit) {
+ /* When an xdg_surface performs an initial commit, the compositor must
+ * reply with a configure so the client can map the surface. tinywl
+ * configures the xdg_toplevel with 0,0 size to let the client pick the
+ * dimensions itself. */
+ wlr_xdg_toplevel_set_size(toplevel->xdg_toplevel, 0, 0);
+ }
+}
+
+static void server_new_xdg_toplevel(struct wl_listener *listener, void *data)
{
- /* This event is raised when wlr_xdg_shell receives a new xdg surface from a
- * client, either a toplevel (application window) or popup. */
- struct tinywl_server *server =
- wl_container_of(listener, server, new_xdg_surface);
- struct wlr_xdg_surface *xdg_surface = data;
-
- /* We must add xdg popups to the scene graph so they get rendered. The
- * wlroots scene graph provides a helper for this, but to use it we must
- * provide the proper parent scene node of the xdg popup. To enable this,
- * we always set the user data field of xdg_surfaces to the corresponding
- * scene node. */
- if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
- struct wlr_xdg_surface *parent =
- wlr_xdg_surface_try_from_wlr_surface(xdg_surface->popup->parent);
- assert(parent != NULL);
- struct wlr_scene_tree *parent_tree = parent->data;
- xdg_surface->data = wlr_scene_xdg_surface_create(parent_tree, xdg_surface);
- return;
- }
- assert(xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
-
- /* Allocate a tinywl_toplevel for this surface */
- struct tinywl_toplevel *toplevel = calloc(1, sizeof(*toplevel));
- toplevel->server = server;
- toplevel->xdg_toplevel = xdg_surface->toplevel;
- toplevel->scene_tree = wlr_scene_xdg_surface_create(
- &toplevel->server->scene->tree, toplevel->xdg_toplevel->base);
- toplevel->scene_tree->node.data = toplevel;
- xdg_surface->data = toplevel->scene_tree;
-
- /* Listen to the various events it can emit */
- toplevel->map.notify = xdg_toplevel_map;
- wl_signal_add(&xdg_surface->surface->events.map, &toplevel->map);
- toplevel->unmap.notify = xdg_toplevel_unmap;
- wl_signal_add(&xdg_surface->surface->events.unmap, &toplevel->unmap);
- toplevel->destroy.notify = xdg_toplevel_destroy;
- wl_signal_add(&xdg_surface->events.destroy, &toplevel->destroy);
-
- /* cotd */
- struct wlr_xdg_toplevel *xdg_toplevel = xdg_surface->toplevel;
- toplevel->request_move.notify = xdg_toplevel_request_move;
- wl_signal_add(&xdg_toplevel->events.request_move, &toplevel->request_move);
- toplevel->request_resize.notify = xdg_toplevel_request_resize;
- wl_signal_add(&xdg_toplevel->events.request_resize,
- &toplevel->request_resize);
- toplevel->request_maximize.notify = xdg_toplevel_request_maximize;
- wl_signal_add(&xdg_toplevel->events.request_maximize,
- &toplevel->request_maximize);
- toplevel->request_fullscreen.notify = xdg_toplevel_request_fullscreen;
- wl_signal_add(&xdg_toplevel->events.request_fullscreen,
- &toplevel->request_fullscreen);
+ /* This event is raised when a client creates a new toplevel (application window). */
+ struct tinywl_server *server = wl_container_of(listener, server, new_xdg_toplevel);
+ struct wlr_xdg_toplevel *xdg_toplevel = data;
+
+ /* Allocate a tinywl_toplevel for this surface */
+ struct tinywl_toplevel *toplevel = calloc(1, sizeof(*toplevel));
+ toplevel->server = server;
+ toplevel->xdg_toplevel = xdg_toplevel;
+ toplevel->scene_tree =
+ wlr_scene_xdg_surface_create(&toplevel->server->scene->tree, xdg_toplevel->base);
+ toplevel->scene_tree->node.data = toplevel;
+ xdg_toplevel->base->data = toplevel->scene_tree;
+
+ /* Listen to the various events it can emit */
+ toplevel->map.notify = xdg_toplevel_map;
+ wl_signal_add(&xdg_toplevel->base->surface->events.map, &toplevel->map);
+ toplevel->unmap.notify = xdg_toplevel_unmap;
+ wl_signal_add(&xdg_toplevel->base->surface->events.unmap, &toplevel->unmap);
+ toplevel->commit.notify = xdg_toplevel_commit;
+ wl_signal_add(&xdg_toplevel->base->surface->events.commit, &toplevel->commit);
+
+ toplevel->destroy.notify = xdg_toplevel_destroy;
+ wl_signal_add(&xdg_toplevel->events.destroy, &toplevel->destroy);
+
+ /* cotd */
+ toplevel->request_move.notify = xdg_toplevel_request_move;
+ wl_signal_add(&xdg_toplevel->events.request_move, &toplevel->request_move);
+ toplevel->request_resize.notify = xdg_toplevel_request_resize;
+ wl_signal_add(&xdg_toplevel->events.request_resize, &toplevel->request_resize);
+ toplevel->request_maximize.notify = xdg_toplevel_request_maximize;
+ wl_signal_add(&xdg_toplevel->events.request_maximize, &toplevel->request_maximize);
+ toplevel->request_fullscreen.notify = xdg_toplevel_request_fullscreen;
+ wl_signal_add(&xdg_toplevel->events.request_fullscreen, &toplevel->request_fullscreen);
}
int main(int argc, char *argv[])
@@ -909,8 +966,11 @@ int main(int argc, char *argv[])
*/
wl_list_init(&server.toplevels);
server.xdg_shell = wlr_xdg_shell_create(server.wl_display, 3);
- server.new_xdg_surface.notify = server_new_xdg_surface;
- wl_signal_add(&server.xdg_shell->events.new_surface, &server.new_xdg_surface);
+ server.new_xdg_toplevel.notify = server_new_xdg_toplevel;
+ wl_signal_add(&server.xdg_shell->events.new_toplevel,
+ &server.new_xdg_toplevel);
+ server.new_xdg_popup.notify = server_new_xdg_popup;
+ wl_signal_add(&server.xdg_shell->events.new_popup, &server.new_xdg_popup);
/*
* Creates a cursor, which is a wlroots utility for tracking the cursor