From d9d7cd3391828d642997b54631281e7d9f9f4977 Mon Sep 17 00:00:00 2001 From: Stuart Dilts Date: Thu, 9 Nov 2023 21:21:47 -0700 Subject: [PATCH] Wire up output mode change events Add the required machinery to listen to output mode change events: + Add required listener in hrt code + Add wrappers to wlroots code to hrt and lisp bindings for those wrappers. --- heart/include/hrt/hrt_output.h | 9 +++++++++ heart/src/output.c | 22 ++++++++++++++++++++++ lisp/bindings/hrt-bindings.lisp | 14 ++++++++++++-- lisp/bindings/package.lisp | 5 +++++ lisp/bindings/wrappers.lisp | 12 ++++++++++++ lisp/main.lisp | 4 +++- lisp/output.lisp | 4 ++++ mahogany.asd | 3 ++- 8 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 lisp/bindings/wrappers.lisp diff --git a/heart/include/hrt/hrt_output.h b/heart/include/hrt/hrt_output.h index ca2561c..1f18ada 100644 --- a/heart/include/hrt/hrt_output.h +++ b/heart/include/hrt/hrt_output.h @@ -10,9 +10,11 @@ struct hrt_output { struct wlr_output *wlr_output; struct hrt_server *server; + void (*mode_change_handler)(struct hrt_output *output); struct wl_listener frame; struct wl_listener destroy; + struct wl_listener mode; // temp background color float color[4]; @@ -21,7 +23,14 @@ struct hrt_output { struct hrt_output_callbacks { void (*output_added)(struct hrt_output *output); void (*output_removed)(struct hrt_output *output); + void (*output_mode_changed)(struct hrt_output *output); }; bool hrt_output_init(struct hrt_server *server, const struct hrt_output_callbacks *callbacks); + +/** + * Get the effective output resolution of the output that can be used to + * set the width and height of views. + **/ +void hrt_output_resolution(struct hrt_output *output, int *width, int *height); #endif diff --git a/heart/src/output.c b/heart/src/output.c index 0e840a2..559e0e8 100644 --- a/heart/src/output.c +++ b/heart/src/output.c @@ -1,7 +1,11 @@ +#include "hrt/hrt_server.h" +#include "wlr/util/log.h" #include #include #include +#include +#include #include #include @@ -24,11 +28,22 @@ static void handle_output_destroy(struct wl_listener *listener, void *data) { struct hrt_server *server = output->server; server->output_callback->output_removed(output); + wl_list_remove(&output->frame.link); + wl_list_remove(&output->mode.link); + // wlr_output_layout removes the output by itself. free(output); } +static void handle_mode_change(struct wl_listener *listener, void *data) { + wlr_log(WLR_DEBUG, "Output mode changed"); + struct hrt_output *output = wl_container_of(listener, output, mode); + if(output->mode_change_handler) { + output->mode_change_handler(output); + } +} + // temp random float generator static float float_rand() { @@ -40,11 +55,14 @@ static struct hrt_output *hrt_output_create(struct hrt_server *server, struct hrt_output *output = calloc(1, sizeof(struct hrt_output)); output->wlr_output = wlr_output; output->server = server; + output->mode_change_handler = server->output_callback->output_mode_changed; wlr_output_init_render(wlr_output, server->allocator, server->renderer); output->frame.notify = handle_frame_notify; wl_signal_add(&wlr_output->events.frame, &output->frame); + output->mode.notify = handle_mode_change; + wl_signal_add(&wlr_output->events.mode, &output->mode); // temp background color: // {0.730473, 0.554736, 0.665036, 1.000000} is really pretty. @@ -112,3 +130,7 @@ bool hrt_output_init(struct hrt_server *server, const struct hrt_output_callback return true; } + +void hrt_output_resolution(struct hrt_output *output, int *width, int *height) { + wlr_output_effective_resolution(output->wlr_output, width, height); +} diff --git a/lisp/bindings/hrt-bindings.lisp b/lisp/bindings/hrt-bindings.lisp index 4855832..70039c5 100644 --- a/lisp/bindings/hrt-bindings.lisp +++ b/lisp/bindings/hrt-bindings.lisp @@ -105,18 +105,28 @@ See themes section of man xcursor(3) to find where to find valid cursor names." (cffi:defcstruct hrt-output (wlr-output :pointer #| (:struct wlr-output) |# ) (server (:pointer (:struct hrt-server))) + (mode-change-handler :pointer #| function ptr void (struct hrt_output *) |#) (frame (:struct wl-listener)) (destroy (:struct wl-listener)) + (mode (:struct wl-listener)) (color :float :count 4)) (cffi:defcstruct hrt-output-callbacks (output-added :pointer #| function ptr void (struct hrt_output *) |#) - (output-removed :pointer #| function ptr void (struct hrt_output *) |#)) + (output-removed :pointer #| function ptr void (struct hrt_output *) |#) + (output-mode-changed :pointer #| function ptr void (struct hrt_output *) |#)) (cffi:defcfun ("hrt_output_init" hrt-output-init) :bool (server (:pointer (:struct hrt-server))) (callbacks (:pointer (:struct hrt-output-callbacks)))) +(cffi:defcfun ("hrt_output_resolution" hrt-output-resolution) :void + "Get the effective output resolution of the output that can be used to +set the width and height of views." + (output (:pointer (:struct hrt-output))) + (width (:pointer :int)) + (height (:pointer :int))) + ;; next section imported from file build/include/hrt/hrt_server.h (cffi:defcstruct hrt-server @@ -153,5 +163,5 @@ See themes section of man xcursor(3) to find where to find valid cursor names." (cffi:defcfun ("hrt_server_finish" hrt-server-finish) :void (server (:pointer (:struct hrt-server)))) -(cffi:defcfun ("hrt_server_scene_tree" hrt-server-scene-tree) :pointer #| (:struct wlr-scene-tree) |# +(cffi:defcfun ("hrt_server_scene_tree" hrt-server-scene-tree) :pointer #| (:struct wlr-scene-tree) |# (server (:pointer (:struct hrt-server)))) diff --git a/lisp/bindings/package.lisp b/lisp/bindings/package.lisp index 285f8e7..a10706c 100644 --- a/lisp/bindings/package.lisp +++ b/lisp/bindings/package.lisp @@ -11,8 +11,13 @@ #:hrt-seat #:hrt-output #:hrt-keypress-info + ;; output callbacks #:output-added #:output-removed + #:output-mode-changed + ;; output methods: + #:output-resolution + ;; seat callbacks #:button-event #:wheel-event #:keyboard-keypress-event #:hrt-server #:hrt-server-scene-tree diff --git a/lisp/bindings/wrappers.lisp b/lisp/bindings/wrappers.lisp new file mode 100644 index 0000000..8666dbb --- /dev/null +++ b/lisp/bindings/wrappers.lisp @@ -0,0 +1,12 @@ +(in-package #:hrt) + +(defmacro with-return-by-value (variables &body body) + `(cffi:with-foreign-objects ,variables + ,@body + (values ,@(loop for pair in variables + collect `(cffi:mem-ref ,(first pair) ,(second pair)))))) + +(defun output-resolution (output) + (declare (type cffi:foreign-pointer output)) + (with-return-by-value ((width :int) (height :int)) + (hrt-output-resolution output width height))) diff --git a/lisp/main.lisp b/lisp/main.lisp index 59d42b9..4547e1c 100644 --- a/lisp/main.lisp +++ b/lisp/main.lisp @@ -37,13 +37,15 @@ (disable-fpu-exceptions) (hrt:load-foreign-libraries) (log-init :level :trace) + (sb-ext:enable-debugger) (cffi:with-foreign-objects ((output-callbacks '(:struct hrt-output-callbacks)) (seat-callbacks '(:struct hrt-seat-callbacks)) (view-callbacks '(:struct hrt-view-callbacks)) (server '(:struct hrt-server))) (init-callback-struct output-callbacks (:struct hrt-output-callbacks) (output-added handle-new-output) - (output-removed handle-output-removed)) + (output-removed handle-output-removed) + (output-mode-changed output-mode-change-callback)) (init-callback-struct seat-callbacks (:struct hrt-seat-callbacks) (button-event cursor-callback) (wheel-event cursor-callback) diff --git a/lisp/output.lisp b/lisp/output.lisp index 38e7cd7..d9cbf73 100644 --- a/lisp/output.lisp +++ b/lisp/output.lisp @@ -11,3 +11,7 @@ (log-string :trace "Output removed") (with-accessors ((outputs mahogany-state-outputs)) *compositor-state* (setf outputs (delete output outputs :key #'mahogany-output-hrt-output)))) + +(cffi:defcallback output-mode-change-callback :void ((output (:pointer (:struct hrt-output)))) + (multiple-value-bind (width height) (hrt:output-resolution output) + (log-string :trace "Output mode changed (w: ~S h: ~S)" width height))) diff --git a/mahogany.asd b/mahogany.asd index 3841134..82d2996 100644 --- a/mahogany.asd +++ b/mahogany.asd @@ -23,7 +23,8 @@ :serial t :components ((:file "package") (:file "hrt-libs") - (:file "hrt-bindings"))) + (:file "hrt-bindings") + (:file "wrappers"))) (:file "package") (:module interfaces :depends-on ("package")