Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Take into account keymap #52

Merged
merged 1 commit into from
Mar 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ packages:
- wayland
- wayland-protocols
- cairo
- libxkbcommon
sources:
- https://github.com/emerison/slurp
tasks:
Expand Down
6 changes: 6 additions & 0 deletions include/slurp.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ struct slurp_state {
struct wl_list outputs; // slurp_output::link
struct wl_list seats; // slurp_seat::link

struct xkb_context *xkb_context;

struct {
uint32_t background;
uint32_t border;
Expand Down Expand Up @@ -84,6 +86,10 @@ struct slurp_seat {
int32_t anchor_x, anchor_y;
struct slurp_box selection;
bool has_selection;

// keymap:
struct xkb_keymap *xkb_keymap;
struct xkb_state *xkb_state;
};

bool box_intersect(const struct slurp_box *a, const struct slurp_box *b);
Expand Down
71 changes: 61 additions & 10 deletions main.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
#define _POSIX_C_SOURCE 2

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <wayland-cursor.h>
#include <xkbcommon/xkbcommon.h>
#include <linux/input-event-codes.h>

#include "slurp.h"
Expand Down Expand Up @@ -182,40 +185,80 @@ static const struct wl_pointer_listener pointer_listener = {
.axis = noop,
};

static void keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard,
const uint32_t format, const int32_t fd, const uint32_t size) {
struct slurp_seat *seat = data;
switch (format) {
case WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP:
seat->xkb_keymap = xkb_keymap_new_from_names(seat->state->xkb_context, NULL, XKB_KEYMAP_COMPILE_NO_FLAGS);
break;
case WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1:;
void *buffer;
if ((buffer = mmap(NULL, size - 1, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
fprintf(stderr, "mmap failed\n");
exit(EXIT_FAILURE);
}
seat->xkb_keymap =
xkb_keymap_new_from_buffer(seat->state->xkb_context,
buffer, size - 1,
XKB_KEYMAP_FORMAT_TEXT_V1,
XKB_KEYMAP_COMPILE_NO_FLAGS);
munmap(buffer, size - 1);
close(fd);
break;
}
seat->xkb_state = xkb_state_new(seat->xkb_keymap);
}

static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard,
uint32_t serial, uint32_t time, uint32_t key, uint32_t key_state) {
const uint32_t serial, const uint32_t time, const uint32_t key,
const uint32_t key_state) {
struct slurp_seat *seat = data;
struct slurp_state *state = seat->state;
if (key_state == WL_KEYBOARD_KEY_STATE_PRESSED) {
switch (key) {
case KEY_ESC:
const xkb_keysym_t keysym = xkb_state_key_get_one_sym(seat->xkb_state, key + 8);

switch (key_state) {
case WL_KEYBOARD_KEY_STATE_PRESSED:
switch (keysym) {
case XKB_KEY_Escape:
seat->has_selection = false;
state->edit_anchor = false;
state->running = false;
break;

case KEY_SPACE:
case XKB_KEY_space:
if (!seat->has_selection) {
break;
}
state->edit_anchor = true;
break;
}
}
break;

if (key_state == WL_KEYBOARD_KEY_STATE_RELEASED) {
if (key == KEY_SPACE) {
case WL_KEYBOARD_KEY_STATE_RELEASED:
if (keysym == XKB_KEY_space) {
state->edit_anchor = false;
}
break;
}

}

static void keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
const uint32_t serial, const uint32_t mods_depressed,
const uint32_t mods_latched, const uint32_t mods_locked,
const uint32_t group) {
struct slurp_seat *seat = data;
xkb_state_update_mask(seat->xkb_state, mods_depressed, mods_latched,
mods_locked, 0, 0, group);
}

static const struct wl_keyboard_listener keyboard_listener = {
.keymap = noop,
.keymap = keyboard_handle_keymap,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also need to listen to the modifiers event.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I thought at first, but aren't modifiers just CTRL, Mod.... which means that we don't really care about them (for the moment), as the only keys we care about are space and escape

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The user may have configured his keyboard so that Shift+Caps Lock yields the Esc keysym, for instance.

Copy link
Contributor Author

@NilsIrl NilsIrl Mar 25, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed by d070c7c

.enter = noop,
.leave = noop,
.key = keyboard_handle_key,
.modifiers = noop,
.modifiers = keyboard_handle_modifiers,
};


Expand Down Expand Up @@ -258,6 +301,8 @@ static void destroy_seat(struct slurp_seat *seat) {
if (seat->wl_keyboard) {
wl_keyboard_destroy(seat->wl_keyboard);
}
xkb_state_unref(seat->xkb_state);
xkb_keymap_unref(seat->xkb_keymap);
wl_seat_destroy(seat->wl_seat);
free(seat);
}
Expand Down Expand Up @@ -623,6 +668,11 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
}

if ((state.xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS)) == NULL) {
fprintf(stderr, "xkb_context_new failed\n");
return EXIT_FAILURE;
}

state.registry = wl_display_get_registry(state.display);
wl_registry_add_listener(state.registry, &registry_listener, &state);
wl_display_roundtrip(state.display);
Expand Down Expand Up @@ -745,6 +795,7 @@ int main(int argc, char *argv[]) {
wl_compositor_destroy(state.compositor);
wl_shm_destroy(state.shm);
wl_registry_destroy(state.registry);
xkb_context_unref(state.xkb_context);
wl_display_disconnect(state.display);

struct slurp_box *box, *box_tmp;
Expand Down
2 changes: 2 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ realtime = cc.find_library('rt')
wayland_client = dependency('wayland-client')
wayland_cursor = dependency('wayland-cursor')
wayland_protos = dependency('wayland-protocols', version: '>=1.14')
xkbcommon = dependency('xkbcommon')

subdir('protocol')

Expand All @@ -38,6 +39,7 @@ executable(
realtime,
wayland_client,
wayland_cursor,
xkbcommon,
],
include_directories: [slurp_inc],
install: true,
Expand Down