gimp but for windows: a wayland compositor
git clone https://github.com/m-col/wimp
Files | Refs | Readme

Commit 9c9e396f412c7a640613c68e8fb706c43bf11979
Parent: 65115c7d85c4418f62de6aabb5fdb11dce98601e
Author: mcol <mcol@posteo.net>
Date: 2020-11-05 22:59:59 +0000
Committer: mcol <mcol@posteo.net>
Committed: 2020-11-05 22:59:59 +0000

fill in basic cursor handlers, based on tinywm

src/input.h Modified

@@ -3,11 +3,27 @@
 #include "types.h"
 
 
+void process_cursor_move(struct server *server, uint32_t time);
+void process_cursor_resize(struct server *server, uint32_t time);
+void process_cursor_motion(struct server *server, uint32_t time);
+bool view_at(
+    struct view *view, double lx, double ly, struct wlr_surface **surface,
+    double *sx, double *sy
+);
+struct view *desktop_view_at(
+    struct server *server, double lx, double ly, struct wlr_surface **surface,
+    double *sx, double *sy
+);
+void process_cursor_motion(struct server *server, uint32_t time);
 void on_cursor_motion(struct wl_listener *listener, void *data);
 void on_cursor_motion_absolute(struct wl_listener *listener, void *data);
 void on_cursor_button(struct wl_listener *listener, void *data);
 void on_cursor_axis(struct wl_listener *listener, void *data);
 void on_cursor_frame(struct wl_listener *listener, void *data);
+void on_modifier(struct wl_listener *listener, void *data);
+bool handle_keybinding(struct server *server, xkb_keysym_t sym);
+void on_key(struct wl_listener *listener, void *data);
+void on_new_keyboard(struct server *server, struct wlr_input_device *device);
 void on_new_input(struct wl_listener *listener, void *data);
 void on_request_cursor(struct wl_listener *listener, void *data);
 void on_request_set_selection(struct wl_listener *listener, void *data);

src/input.c Modified

@@ -1,17 +1,23 @@
 #include <wlr/types/wlr_cursor.h>
+#include <wlr/types/wlr_keyboard.h>
+#include <wlr/types/wlr_data_device.h>
 #include <wlr/types/wlr_xcursor_manager.h>
 
 #include "input.h"
+#include "shell.h"
 #include "types.h"
 
 
-static void process_cursor_move(struct server *server, uint32_t time) {
+enum wlr_keyboard_modifier MOD = WLR_MODIFIER_LOGO;
+
+
+void process_cursor_move(struct 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;
 }
 
 
-static void process_cursor_resize(struct server *server, uint32_t time) {
+void process_cursor_resize(struct server *server, uint32_t time) {
     struct view *view = server->grabbed_view;
     double border_x = server->cursor->x - server->grab_x;
     double border_y = server->cursor->y - server->grab_y;
@@ -54,7 +60,7 @@
 }
 
 
-static bool view_at(
+bool view_at(
     struct view *view, double lx, double ly, struct wlr_surface **surface,
     double *sx, double *sy
 ) {
@@ -76,7 +82,7 @@
 }
 
 
-static struct view *desktop_view_at(
+struct view *desktop_view_at(
     struct server *server, double lx, double ly, struct wlr_surface **surface,
     double *sx, double *sy
 ) {
@@ -90,7 +96,7 @@
 }
 
 
-static void process_cursor_motion(struct server *server, uint32_t time) {
+void process_cursor_motion(struct server *server, uint32_t time) {
     double sx, sy;
     struct wlr_seat *seat;
     struct wlr_surface *surface;
@@ -99,8 +105,10 @@
     switch (server->cursor_mode) {
 	case CURSOR_MOVE:
 	    process_cursor_move(server, time);
+	    break;
 	case CURSOR_RESIZE:
 	    process_cursor_resize(server, time);
+	    break;
 	case CURSOR_PASSTHROUGH:
 	    seat = server->seat;
 	    surface = NULL;
@@ -120,9 +128,11 @@
 	    } else {
 		wlr_seat_pointer_clear_focus(seat);
 	    }
+	    break;
     }
 }
 
+
 void on_cursor_motion(struct wl_listener *listener, void *data){
     struct server *server = wl_container_of(listener, server, cursor_motion_listener);
     struct wlr_event_pointer_motion *event = data;
@@ -141,31 +151,175 @@
 
 
 void on_cursor_button(struct wl_listener *listener, void *data) {
-    return;
+    struct server *server = wl_container_of(listener, server, cursor_button_listener);
+    struct wlr_event_pointer_button *event = data;
+    wlr_seat_pointer_notify_button(
+	server->seat, event->time_msec, event->button, event->state
+    );
+    double sx, sy;
+    struct wlr_surface *surface;
+    struct view *view = desktop_view_at(
+	server, server->cursor->x, server->cursor->y, &surface, &sx, &sy
+    );
+
+    if (event->state == WLR_BUTTON_RELEASED) {
+	server->cursor_mode = CURSOR_PASSTHROUGH;
+    } else {
+	focus_view(view, surface);
+    }
 }
 
+
 void on_cursor_axis(struct wl_listener *listener, void *data) {
-    return;
+    struct server *server = wl_container_of(listener, server, cursor_axis_listener);
+    struct wlr_event_pointer_axis *event = data;
+    wlr_seat_pointer_notify_axis(
+	server->seat, event->time_msec, event->orientation, event->delta,
+	event->delta_discrete, event->source
+    );
 }
 
 
 void on_cursor_frame(struct wl_listener *listener, void *data) {
-    return;
+    struct server *server = wl_container_of(listener, server, cursor_frame_listener);
+    wlr_seat_pointer_notify_frame(server->seat);
+}
+
+
+void on_modifier(struct wl_listener *listener, void *data) {
+    struct keyboard *keyboard = wl_container_of(listener, keyboard, modifier_listener);
+    wlr_seat_set_keyboard(keyboard->server->seat, keyboard->device); // move to on_new_keyboard?
+    wlr_seat_keyboard_notify_modifiers(
+	keyboard->server->seat, &keyboard->device->keyboard->modifiers
+    );
+}
+
+
+bool handle_keybinding(struct server *server, xkb_keysym_t sym) {
+    switch (sym) {
+
+    case XKB_KEY_Escape:
+	wl_display_terminate(server->display);
+	break;
+
+    case XKB_KEY_F1: // to next view
+	if (wl_list_length(&server->views) < 2) {
+	    break;
+	}
+	struct view *current_view = wl_container_of(
+	    server->views.next, current_view, link);
+	struct view *next_view = wl_container_of(
+	    current_view->link.next, next_view, link);
+	focus_view(next_view, next_view->surface->surface);
+	wl_list_remove(&current_view->link);
+	wl_list_insert(server->views.prev, &current_view->link);
+	break;
+
+    default:
+	return false;
+    }
+    return true;
+}
+
+
+void on_key(struct wl_listener *listener, void *data) {
+    struct keyboard *keyboard = wl_container_of(listener, keyboard, key_listener);
+    struct server *server = keyboard->server;
+    struct wlr_event_keyboard_key *event = data;
+    struct wlr_seat *seat = server->seat;
+
+    /* Translate libinput keycode -> xkbcommon */
+    uint32_t keycode = event->keycode + 8;
+    /* Get a list of keysyms based on the keymap for this keyboard */
+    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 & MOD) && event->state == WLR_KEY_PRESSED) {
+	for (int i = 0; i < nsyms; i++) {
+		handled = handle_keybinding(server, syms[i]);
+	}
+    }
+
+    if (!handled) {
+	// forward to client
+	wlr_seat_set_keyboard(seat, keyboard->device); // move to on_new_keyboard?
+	wlr_seat_keyboard_notify_key(seat, event->time_msec,
+	    event->keycode, event->state);
+    }
+}
+
+
+void on_new_keyboard(struct server *server, struct wlr_input_device *device) {
+    struct keyboard *keyboard = calloc(1, sizeof(struct keyboard));
+    keyboard->server = server;
+    keyboard->device = device;
+
+    // currently assumes default "us"
+    struct xkb_rule_names rules = { 0 };
+    struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
+    struct xkb_keymap *keymap = xkb_map_new_from_names(context, &rules,
+	XKB_KEYMAP_COMPILE_NO_FLAGS);
+
+    wlr_keyboard_set_keymap(device->keyboard, keymap);
+    xkb_keymap_unref(keymap);
+    xkb_context_unref(context);
+    wlr_keyboard_set_repeat_info(device->keyboard, 25, 600);
+
+    keyboard->modifier_listener.notify = on_modifier;
+    wl_signal_add(&device->keyboard->events.modifiers, &keyboard->modifier_listener);
+    keyboard->key_listener.notify = on_key;
+    wl_signal_add(&device->keyboard->events.key, &keyboard->key_listener);
+    wlr_seat_set_keyboard(server->seat, device);
+    wl_list_insert(&server->keyboards, &keyboard->link);
 }
 
 
 void on_new_input(struct wl_listener *listener, void *data) {
-    return;
+    struct server *server = wl_container_of(
+	listener, server, new_input_listener
+    );
+
+    struct wlr_input_device *device = data;
+    switch (device->type) {
+    case WLR_INPUT_DEVICE_KEYBOARD:
+	    on_new_keyboard(server, device);
+	    break;
+    case WLR_INPUT_DEVICE_POINTER:
+	    wlr_cursor_attach_input_device(server->cursor, device);
+	    break;
+    default:
+	    break;
+    }
+    uint32_t capabilities = WL_SEAT_CAPABILITY_POINTER;
+    if (!wl_list_empty(&server->keyboards)) {
+	    capabilities |= WL_SEAT_CAPABILITY_KEYBOARD;
+    }
+    wlr_seat_set_capabilities(server->seat, capabilities);
 }
 
 
 void on_request_cursor(struct wl_listener *listener, void *data) {
-    return;
+    struct server *server = wl_container_of(listener, server, request_cursor_listener);
+    struct wlr_seat_pointer_request_set_cursor_event *event = data;
+    struct wlr_seat_client *focused_client =
+	server->seat->pointer_state.focused_client;
+
+    if (focused_client == event->seat_client) {
+	wlr_cursor_set_surface(
+	    server->cursor, event->surface, event->hotspot_x, event->hotspot_y
+	);
+    }
 }
 
 
 void on_request_set_selection(struct wl_listener *listener, void *data) {
-    return;
+    struct server *server = wl_container_of(
+	listener, server, request_set_selection_listener);
+    struct wlr_seat_request_set_selection_event *event = data;
+    wlr_seat_set_selection(server->seat, event->source, event->serial);
 }