Skip to content

Commit

Permalink
Implment initial keyboard focusing
Browse files Browse the repository at this point in the history
Add the required functions to focus a view in the backend and use it.
+ Delay notifying the frontend of new views until the first commit is
  made; this allows us to immediately call events that require the
  xdg_toplevel to be configured.
+ Guess on what we need to do to unfocs a view; it seems to work.
  • Loading branch information
sdilts committed Nov 2, 2024
1 parent 0cd31fd commit 6111b13
Show file tree
Hide file tree
Showing 13 changed files with 179 additions and 76 deletions.
2 changes: 2 additions & 0 deletions heart/include/hrt/hrt_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,6 @@ void hrt_server_finish(struct hrt_server *server);

struct wlr_scene_tree *hrt_server_scene_tree(struct hrt_server *server);

struct hrt_seat *hrt_server_seat(struct hrt_server *server);

#endif
18 changes: 16 additions & 2 deletions heart/include/hrt/hrt_view.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#include <stdint.h>
#include <wayland-server-core.h>
#include "hrt/hrt_server.h"
#include <hrt/hrt_server.h>
#include "hrt_input.h"

struct hrt_view;

typedef void (*view_destroy_handler)(struct hrt_view *view);
typedef void (*new_view_handler)(struct hrt_view *view);

struct hrt_view {
int width, height;
Expand All @@ -21,6 +23,7 @@ struct hrt_view {
struct wl_listener unmap;
struct wl_listener commit;
struct wl_listener destroy;
new_view_handler new_view_handler;
view_destroy_handler destroy_handler;
};

Expand All @@ -29,7 +32,7 @@ struct hrt_view_callbacks {
* A new view has been created. Must call `hrt_view_init` for the
* view to be displayed.
**/
void (*new_view)(struct hrt_view *view);
new_view_handler new_view;
view_destroy_handler view_destroyed;
};

Expand All @@ -47,3 +50,14 @@ uint32_t hrt_view_set_size(struct hrt_view *view, int width, int height);
* Sets the view to the given coordinates relative to its parent.
**/
void hrt_view_set_relative(struct hrt_view *view, int x, int y);

/**
* Focus the given view and perform the needed tasks to make
* it visible to the user.
**/
void hrt_view_focus(struct hrt_view *view, struct hrt_seat *seat);

/**
* Unfocus the given view.
**/
void hrt_view_unfocus(struct hrt_view *view, struct hrt_seat *seat);
4 changes: 4 additions & 0 deletions heart/src/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,7 @@ void hrt_server_finish(struct hrt_server *server) {
struct wlr_scene_tree *hrt_server_scene_tree(struct hrt_server *server) {
return &server->scene->tree;
}

struct hrt_seat *hrt_server_seat(struct hrt_server *server) {
return &server->seat;
}
33 changes: 33 additions & 0 deletions heart/src/view.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
#include <assert.h>
#include <stdint.h>
#include <time.h>
#include <wlr/types/wlr_xdg_shell.h>
#include <wlr/types/wlr_scene.h>

#include "hrt/hrt_input.h"
#include "hrt/hrt_view.h"
#include "wlr/util/log.h"

void hrt_view_init(struct hrt_view *view, struct wlr_scene_tree *tree) {
assert(view->scene_tree == NULL && "View already initialized");
view->scene_tree = wlr_scene_tree_create(tree);
view->width = 0;
view->height = 0;
Expand All @@ -27,3 +32,31 @@ uint32_t hrt_view_set_size(struct hrt_view *view, int width, int height) {
void hrt_view_set_relative(struct hrt_view *view, int x, int y) {
wlr_scene_node_set_position(&view->scene_tree->node, x, y);
}

void hrt_view_focus(struct hrt_view *view, struct hrt_seat *seat) {
wlr_log(WLR_DEBUG, "view focused!");
struct wlr_seat *wlr_seat = seat->seat;
struct wlr_surface *prev_surface = wlr_seat->keyboard_state.focused_surface;
struct wlr_xdg_toplevel *toplevel = view->xdg_toplevel;

if (prev_surface == toplevel->base->surface) {
// Don't re-focus an already focused surface:
return;
}
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(wlr_seat);

wlr_xdg_toplevel_set_activated(toplevel, true);

if (keyboard != NULL) {
wlr_log(WLR_DEBUG, "Keyboard enter!");
wlr_seat_keyboard_notify_enter(wlr_seat, toplevel->base->surface,
keyboard->keycodes, keyboard->num_keycodes,
&keyboard->modifiers);
}
}

void hrt_view_unfocus(struct hrt_view *view, struct hrt_seat *seat) {
struct wlr_xdg_toplevel *toplevel = view->xdg_toplevel;
wlr_xdg_toplevel_set_activated(toplevel, false);
wlr_seat_keyboard_notify_clear_focus(seat->seat);
}
17 changes: 7 additions & 10 deletions heart/src/xdg_shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,19 @@ static void handle_xdg_toplevel_commit(struct wl_listener *listener,
void *data) {
struct hrt_view *view = wl_container_of(listener, view, commit);
if (view->xdg_toplevel->base->initial_commit) {
wlr_xdg_toplevel_set_size(view->xdg_toplevel, view->width,view->height);
view->new_view_handler(view);
}
}

static struct hrt_view *create_view_from_xdg_surface(struct wlr_xdg_toplevel *xdg_toplevel, view_destroy_handler destroy_handler) {
static struct hrt_view *create_view_from_xdg_surface(struct wlr_xdg_toplevel *xdg_toplevel, const struct hrt_view_callbacks *callbacks) {
struct hrt_view *view = calloc(1, sizeof(struct hrt_view));
view->xdg_toplevel = xdg_toplevel;
struct wlr_xdg_surface *xdg_surface = xdg_toplevel->base;
// TODO: Maybe remove view->xdg_surface? We can get to it via the toplevel.
view->xdg_surface = xdg_surface;
view->destroy_handler = destroy_handler;
// Should we just put struct hrt_view_callbacks in view objects?
view->destroy_handler = callbacks->view_destroyed;
view->new_view_handler = callbacks->new_view;

view->map.notify = handle_xdg_toplevel_map;
wl_signal_add(&xdg_surface->surface->events.map, &view->map);
Expand Down Expand Up @@ -116,13 +118,8 @@ static void handle_new_xdg_toplevel(struct wl_listener *listener, void * data) {
// Initialization occurs in two steps so the consumer can place the view where it needs to go;
// in order to create a scene tree node, it must have a parent.
// We don't have it until the callback.
struct hrt_view *view = create_view_from_xdg_surface(toplevel,
server->view_callbacks->view_destroyed);
// At some point, we will want the front end to call this, as it should decide what node
// of the scene graph the view gets added to:
// hrt_view_init(view, &server->scene->tree);

server->view_callbacks->new_view(view);
create_view_from_xdg_surface(toplevel,
server->view_callbacks);
}

bool hrt_xdg_shell_init(struct hrt_server *server) {
Expand Down
105 changes: 61 additions & 44 deletions lisp/bindings/hrt-bindings.lisp
Original file line number Diff line number Diff line change
@@ -1,44 +1,5 @@
(cl:in-package #:hrt)

;; next section imported from file build/include/hrt/hrt_view.h

(cffi:defcstruct hrt-view)

(cffi:defctype view-destroy-handler :pointer #| function ptr void (struct hrt_view *) |#)

(cffi:defcstruct hrt-view
(width :int)
(height :int)
(xdg-surface :pointer #| (:struct wlr-xdg-surface) |# )
(xdg-toplevel :pointer #| (:struct wlr-xdg-toplevel) |# )
(scene-tree :pointer #| (:struct wlr-scene-tree) |# )
(map (:struct wl-listener))
(unmap (:struct wl-listener))
(commit (:struct wl-listener))
(destroy (:struct wl-listener))
(destroy-handler view-destroy-handler))

(cffi:defcstruct hrt-view-callbacks
(new-view :pointer #| function ptr void (struct hrt_view *) |#)
(view-destroyed view-destroy-handler))

(cffi:defcfun ("hrt_view_init" hrt-view-init) :void
"Fully initialize the view and place it in the given scene tree."
(view (:pointer (:struct hrt-view)))
(tree :pointer #| (:struct wlr-scene-tree) |# ))

(cffi:defcfun ("hrt_view_set_size" hrt-view-set-size) :uint32
"Request that this view be the given size. Returns the associated configure serial."
(view (:pointer (:struct hrt-view)))
(width :int)
(height :int))

(cffi:defcfun ("hrt_view_set_relative" hrt-view-set-relative) :void
"Sets the view to the given coordinates relative to its parent."
(view (:pointer (:struct hrt-view)))
(x :int)
(y :int))

;; next section imported from file build/include/hrt/hrt_input.h

(cffi:defcstruct hrt-server)
Expand Down Expand Up @@ -112,6 +73,59 @@ See themes section of man xcursor(3) to find where to find valid cursor names."
(seat (:pointer (:struct hrt-seat)))
(img-name (:pointer :char)))

;; next section imported from file build/include/hrt/hrt_view.h

(cffi:defcstruct hrt-view)

(cffi:defctype view-destroy-handler :pointer #| function ptr void (struct hrt_view *) |#)

(cffi:defctype new-view-handler :pointer #| function ptr void (struct hrt_view *) |#)

(cffi:defcstruct hrt-view
(width :int)
(height :int)
(xdg-surface :pointer #| (:struct wlr-xdg-surface) |# )
(xdg-toplevel :pointer #| (:struct wlr-xdg-toplevel) |# )
(scene-tree :pointer #| (:struct wlr-scene-tree) |# )
(map (:struct wl-listener))
(unmap (:struct wl-listener))
(commit (:struct wl-listener))
(destroy (:struct wl-listener))
(new-view-handler new-view-handler)
(destroy-handler view-destroy-handler))

(cffi:defcstruct hrt-view-callbacks
(new-view new-view-handler)
(view-destroyed view-destroy-handler))

(cffi:defcfun ("hrt_view_init" hrt-view-init) :void
"Fully initialize the view and place it in the given scene tree."
(view (:pointer (:struct hrt-view)))
(tree :pointer #| (:struct wlr-scene-tree) |# ))

(cffi:defcfun ("hrt_view_set_size" hrt-view-set-size) :uint32
"Request that this view be the given size. Returns the associated configure serial."
(view (:pointer (:struct hrt-view)))
(width :int)
(height :int))

(cffi:defcfun ("hrt_view_set_relative" hrt-view-set-relative) :void
"Sets the view to the given coordinates relative to its parent."
(view (:pointer (:struct hrt-view)))
(x :int)
(y :int))

(cffi:defcfun ("hrt_view_focus" hrt-view-focus) :void
"Focus the given view and perform the needed tasks to make
it visible to the user."
(view (:pointer (:struct hrt-view)))
(seat (:pointer (:struct hrt-seat))))

(cffi:defcfun ("hrt_view_unfocus" hrt-view-unfocus) :void
"Unfocus the given view."
(view (:pointer (:struct hrt-view)))
(seat (:pointer (:struct hrt-seat))))

;; next section imported from file build/include/hrt/hrt_output.h

(cffi:defcstruct hrt-output
Expand Down Expand Up @@ -146,16 +160,16 @@ set the width and height of views."
(x (:pointer :int))
(y (:pointer :int)))

(cffi:defcfun ("hrt_output_name" hrt-output-name) :string ;; (:pointer :char)
(cffi:defcfun ("hrt_output_name" hrt-output-name) :string
(output (:pointer (:struct hrt-output))))

(cffi:defcfun ("hrt_output_make" hrt-output-make) :string ;; (:pointer :char)
(cffi:defcfun ("hrt_output_make" hrt-output-make) :string
(output (:pointer (:struct hrt-output))))

(cffi:defcfun ("hrt_output_model" hrt-output-model) :string ;; (:pointer :char)
(cffi:defcfun ("hrt_output_model" hrt-output-model) :string
(output (:pointer (:struct hrt-output))))

(cffi:defcfun ("hrt_output_serial" hrt-output-serial) :string ;; (:pointer :char)
(cffi:defcfun ("hrt_output_serial" hrt-output-serial) :string
(output (:pointer (:struct hrt-output))))

;; next section imported from file build/include/hrt/hrt_server.h
Expand Down Expand Up @@ -200,5 +214,8 @@ set the width and height of views."
(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))))

(cffi:defcfun ("hrt_server_seat" hrt-server-seat) (:pointer (:struct hrt-seat))
(server (:pointer (:struct hrt-server))))
2 changes: 1 addition & 1 deletion lisp/bindings/hrt-bindings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ arguments:
- "-DWLR_USE_UNSTABLE"
- "-Iheart/include"
files:
- build/include/hrt/hrt_view.h
- build/include/hrt/hrt_input.h
- build/include/hrt/hrt_view.h
- build/include/hrt/hrt_output.h
- build/include/hrt/hrt_server.h
pointer-expansion:
Expand Down
3 changes: 3 additions & 0 deletions lisp/bindings/package.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,13 @@
#:view
#:view-init
#:view-hrt-view
#:focus-view
#:unfocus-view
;; seat callbacks
#:button-event #:wheel-event #:keyboard-keypress-event
#:hrt-server
#:hrt-server-scene-tree
#:hrt-server-seat
#:hrt-server-init
#:hrt-server-start
#:hrt-server-stop
Expand Down
10 changes: 10 additions & 0 deletions lisp/bindings/wrappers.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@
(hrt-view-init hrt-view scene-tree)
(the view view)))

(declaim (inline focus-view))
(defun focus-view (view seat)
(declare (type view view))
(hrt-view-focus (view-hrt-view view) seat))

(declaim (inline unfocus-view))
(defun unfocus-view (view seat)
(declare (type view view))
(hrt-view-unfocus (view-hrt-view view) seat))

(defmethod mh/interface:set-dimensions ((view view) width height)
(hrt-view-set-size (view-hrt-view view) width height))

Expand Down
22 changes: 11 additions & 11 deletions lisp/group.lisp
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
(in-package #:mahogany)

(defun group-focus-frame (group frame)
(defun group-focus-frame (group frame seat)
(with-accessors ((current-frame mahogany-group-current-frame)) group
(when current-frame
(group-unfocus-frame group current-frame))
(tree:mark-frame-focused frame)
(group-unfocus-frame group current-frame seat))
(tree:mark-frame-focused frame seat)
(setf current-frame frame)))

(defun group-unfocus-frame (group frame)
(defun group-unfocus-frame (group frame seat)
(with-accessors ((current-frame mahogany-group-current-frame)) group
(tree:unmark-frame-focused frame)
(tree:unmark-frame-focused frame seat)
(setf current-frame nil)))

(defun group-add-output (group output)
(defun group-add-output (group output seat)
(declare (type mahogany-output output)
(type mahogany-group group))
(with-accessors ((output-map mahogany-group-output-map)
Expand All @@ -23,7 +23,7 @@
(let ((new-tree (tree:make-basic-tree :x x :y y :width width :height height)))
(setf (gethash (mahogany-output-full-name output) output-map) new-tree)
(when (not current-frame)
(group-focus-frame group (tree:find-first-leaf new-tree))))))
(group-focus-frame group (tree:find-first-leaf new-tree) seat)))))
(log-string :trace "Group map: ~S" output-map)))

(defun group-reconfigure-outputs (group outputs)
Expand All @@ -48,19 +48,19 @@ to match."
(declare (ignore found key))
value)))

(defun group-remove-output (group output)
(defun group-remove-output (group output seat)
(declare (type mahogany-output output)
(type mahogany-group group))
(with-accessors ((output-map mahogany-group-output-map)) group
(let* ((output-name (mahogany-output-full-name output))
(tree-container (gethash output-name output-map)))
(remhash output-name output-map)
(when (equalp tree-container (tree:find-frame-container (mahogany-group-current-frame group)))
(group-unfocus-frame group (mahogany-group-current-frame group))
(group-unfocus-frame group (mahogany-group-current-frame group) seat)
(alexandria:when-let ((other-container (%first-hash-table-value output-map)))
(group-focus-frame group (tree:find-first-leaf other-container))))
(group-focus-frame group (tree:find-first-leaf other-container) seat)))
(when (and (mahogany-group-current-frame group) (= 0 (hash-table-count output-map)))
(group-unfocus-frame group (mahogany-group-current-frame group))))))
(group-unfocus-frame group (mahogany-group-current-frame group) seat)))))

(defun group-add-view (group view)
(declare (type mahogany-group group)
Expand Down
Loading

0 comments on commit 6111b13

Please sign in to comment.