From 20e55f945854a84e20f55f9284698c1fa942c4a8 Mon Sep 17 00:00:00 2001
From: Drew DeVault <sir@cmpwn.com>
Date: Wed, 15 Aug 2018 19:12:27 -0400
Subject: Implement Alt+F1 (next window) and Alt+Esc (exit)

---
 tinywl/tinywl.c | 97 ++++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 69 insertions(+), 28 deletions(-)

(limited to 'tinywl')

diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c
index 9c749d05..6939b604 100644
--- a/tinywl/tinywl.c
+++ b/tinywl/tinywl.c
@@ -96,6 +96,29 @@ struct tinywl_pointer {
 	struct wlr_input_device *device;
 };
 
+static void focus_view(struct tinywl_view *view, struct wlr_surface *surface) {
+	if (view == NULL) {
+		return;
+	}
+	struct tinywl_server *server = view->server;
+	struct wlr_seat *seat = server->seat;
+	struct wlr_surface *prev_surface = seat->keyboard_state.focused_surface;
+	if (prev_surface == surface) {
+		return;
+	}
+	if (prev_surface) {
+		struct wlr_xdg_surface *previous = wlr_xdg_surface_from_wlr_surface(
+					seat->keyboard_state.focused_surface);
+		wlr_xdg_toplevel_set_activated(previous, false);
+	}
+	struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat);
+	wl_list_remove(&view->link);
+	wl_list_insert(&server->views, &view->link);
+	wlr_xdg_toplevel_set_activated(view->xdg_surface, true);
+	wlr_seat_keyboard_notify_enter(seat, view->xdg_surface->surface,
+		keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers);
+}
+
 static void keyboard_handle_modifiers(
 		struct wl_listener *listener, void *data) {
 	struct tinywl_keyboard *keyboard =
@@ -105,16 +128,57 @@ static void keyboard_handle_modifiers(
 		&keyboard->device->keyboard->modifiers);
 }
 
+static bool handle_keybinding(struct tinywl_server *server, xkb_keysym_t sym) {
+	switch (sym) {
+	case XKB_KEY_Escape:
+		wl_display_terminate(server->wl_display);
+		break;
+	case XKB_KEY_F1:
+		/* Cycle to the next view */
+		if (wl_list_length(&server->views) < 2) {
+			break;
+		}
+		struct tinywl_view *current_view = wl_container_of(
+			server->views.next, current_view, link);
+		struct tinywl_view *next_view = wl_container_of(
+			current_view->link.next, next_view, link);
+		focus_view(next_view, next_view->xdg_surface->surface);
+		/* Move the previous view to the end of the list */
+		wl_list_remove(&current_view->link);
+		wl_list_insert(server->views.prev, &current_view->link);
+		break;
+	default:
+		return false;
+	}
+	return true;
+}
+
 static void keyboard_handle_key(
 		struct wl_listener *listener, void *data) {
 	struct tinywl_keyboard *keyboard =
 		wl_container_of(listener, keyboard, key);
+	struct tinywl_server *server = keyboard->server;
 	struct wlr_event_keyboard_key *event = data;
-	struct wlr_seat *seat = keyboard->server->seat;
-	// TODO: keybindings for moving windows about
-	wlr_seat_set_keyboard(seat, keyboard->device);
-	wlr_seat_keyboard_notify_key(seat, event->time_msec,
-		event->keycode, event->state);
+	struct wlr_seat *seat = server->seat;
+
+	uint32_t keycode = event->keycode + 8;
+	const xkb_keysym_t *syms;
+	int nsyms = xkb_state_key_get_syms(
+			keyboard->device->keyboard->xkb_state, keycode, &syms);
+
+	bool handled = false;
+	uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard);
+	if ((modifiers & WLR_MODIFIER_ALT) && event->state == WLR_BUTTON_PRESSED) {
+		for (int i = 0; i < nsyms; i++) {
+			handled = handle_keybinding(server, syms[i]);
+		}
+	}
+
+	if (!handled) {
+		wlr_seat_set_keyboard(seat, keyboard->device);
+		wlr_seat_keyboard_notify_key(seat, event->time_msec,
+			event->keycode, event->state);
+	}
 }
 
 static void server_new_keyboard(struct tinywl_server *server,
@@ -219,29 +283,6 @@ static struct tinywl_view *desktop_view_at(
 	return NULL;
 }
 
-static void focus_view(struct tinywl_view *view, struct wlr_surface *surface) {
-	if (view == NULL) {
-		return;
-	}
-	struct tinywl_server *server = view->server;
-	struct wlr_seat *seat = server->seat;
-	struct wlr_surface *prev_surface = seat->keyboard_state.focused_surface;
-	if (prev_surface == surface) {
-		return;
-	}
-	if (prev_surface) {
-		struct wlr_xdg_surface *previous = wlr_xdg_surface_from_wlr_surface(
-					seat->keyboard_state.focused_surface);
-		wlr_xdg_toplevel_set_activated(previous, false);
-	}
-	struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat);
-	wl_list_remove(&view->link);
-	wl_list_insert(&server->views, &view->link);
-	wlr_xdg_toplevel_set_activated(view->xdg_surface, true);
-	wlr_seat_keyboard_notify_enter(seat, view->xdg_surface->surface,
-		keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers);
-}
-
 static void process_cursor_move(struct tinywl_server *server, uint32_t time) {
 	server->grabbed_view->x = server->cursor->x - server->grab_x;
 	server->grabbed_view->y = server->cursor->y - server->grab_y;
-- 
cgit v1.2.3