diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2025-03-13 01:16:53 -0600 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2025-03-13 01:16:53 -0600 |
commit | 8e1542335494a7d0b596544f66c27aa9aff7c505 (patch) | |
tree | 14863e103a4a8eacb6af54225856de071a0ab0c1 | |
parent | 63331b235230502deb83899c9e1b3b193520ba06 (diff) | |
download | wetterhorn-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.txt | 5 | ||||
-rw-r--r-- | harness/include/wl.h | 10 | ||||
-rw-r--r-- | harness/src/wl.c | 168 |
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 |