mirror of
https://cagebreak.project-repo.co/cagebreak.git
synced 2026-08-09 15:19:11 +02:00
Merge 1.0.6 for compatibility testing
This commit is contained in:
parent
9363a59b95
commit
4bdc2640a7
8 changed files with 194 additions and 236 deletions
29
Bugs.md
29
Bugs.md
|
|
@ -26,3 +26,32 @@ Steps to reproduce:
|
|||
* enter text into the "Tags" field
|
||||
* if autocompletion of tags pops up, the keyboard will not enter further
|
||||
keystrokes into the text field
|
||||
|
||||
### Issue 2
|
||||
|
||||
* Github issue number: N/A
|
||||
* Fixed: 1.0.4
|
||||
|
||||
This issue fixes wrong consumption of modifier key on some keyboards.
|
||||
|
||||
### Issue 3
|
||||
|
||||
* github issue number: N/A
|
||||
* Fixed: 1.0.5
|
||||
|
||||
This issue is a bug causing crashes in cagebreak under specific circumstances.
|
||||
|
||||
Steps to reproduce:
|
||||
|
||||
* start cagebreak
|
||||
* vertical split
|
||||
* open a terminal on the left pane
|
||||
* open firefox on the right pane
|
||||
* focus the left pane
|
||||
* close the terminal
|
||||
* close firefox using the mouse while keeping focus on the left pane
|
||||
* this causes a crash with the following error message:
|
||||
|
||||
```
|
||||
(EE) failed to read Wayland events: Broken pipe
|
||||
```
|
||||
|
|
|
|||
48
README.md
48
README.md
|
|
@ -74,13 +74,19 @@ it is merged into `master`, creating a new release, which is tagged and signed.
|
|||
Merging into master is always done by
|
||||
|
||||
```
|
||||
git merge --no-ff development
|
||||
git tag -u keyid version
|
||||
git push origin master
|
||||
git checkout development
|
||||
git pull origin development
|
||||
git checkout master
|
||||
git merge --squash development
|
||||
git tag -u keyid version HEAD
|
||||
git tag -v version
|
||||
git push --tags origin master
|
||||
```
|
||||
|
||||
and a log message roughly describing the features is added in the commit.
|
||||
|
||||
In the past, our git history did not always reflect this scheme.
|
||||
|
||||
### Releases
|
||||
|
||||
Release checklist
|
||||
|
|
@ -99,6 +105,8 @@ Release checklist
|
|||
* [ ] wiki
|
||||
* [ ] Changelog in README
|
||||
* [ ] Document fixed bugs in Bugs.md
|
||||
* [ ] Update hashes of the binary
|
||||
* [ ] Update signature of the binary
|
||||
* [ ] Signature
|
||||
* [ ] Branching Strategy
|
||||
|
||||
|
|
@ -120,10 +128,36 @@ The full public keys can be found in `keys/` along with any revocation certifica
|
|||
|
||||
### Reproducible Builds
|
||||
|
||||
Currently our project seems to build the same way on any given system, when compiled
|
||||
multiple times. However, at the moment we are unable to supply instructions
|
||||
for building our software reproducibly. Reproducible builds are planned for the
|
||||
near future.
|
||||
Cagebreak offers reproducible builds given the exact library versions specified
|
||||
in `meson.build`. Should a version mismatch occur, a warning will be emitted. We have
|
||||
decided on this compromise to allow flexibility and security. In general we will
|
||||
adapt the versions to the packages available under archlinux at the time of
|
||||
release.
|
||||
|
||||
#### Reproducible Build Instructions
|
||||
|
||||
All hashes and signatures are provided for the following build instructions.
|
||||
|
||||
```
|
||||
meson build -Dxwayland=true --buildtype=release
|
||||
ninja -C build
|
||||
```
|
||||
|
||||
#### Hashes for Builds
|
||||
|
||||
For every release after 1.0.5, hashes will be provided.
|
||||
|
||||
1.0.6
|
||||
|
||||
* sha 256: 712ae9a8f17a9e589e108f0d503da203cc5eaf1c4a6ca6efb5b4c83b432ce0b8
|
||||
* sha 512: d574003023a00cfd6623aac986a5a7f397cfd0bc9114017629a8c72731b0df3977c4a31768502dfa8a6607be06930089b2ccf6ffca9b5bcd1096b7ca0aede226
|
||||
|
||||
#### GPG Signatures
|
||||
|
||||
For every release after 1.0.5, a GPG signature will be provided in `signatures`.
|
||||
|
||||
The current signature is called `cagebreak.sig`, whereas all older signatures
|
||||
will be named after their release version.
|
||||
|
||||
### Fuzzing
|
||||
|
||||
|
|
|
|||
74
meson.build
74
meson.build
|
|
@ -1,5 +1,5 @@
|
|||
project('cagebreak', 'c',
|
||||
version: '1.0.2',
|
||||
version: '1.0.6',
|
||||
license: 'MIT',
|
||||
default_options: [
|
||||
'c_std=c11',
|
||||
|
|
@ -101,18 +101,10 @@ else
|
|||
have_xwayland = false
|
||||
endif
|
||||
|
||||
version = '@0@'.format(meson.project_version())
|
||||
git = find_program('git', native: true, required: false)
|
||||
if git.found()
|
||||
git_commit = run_command([git, 'rev-parse', '--short', 'HEAD'])
|
||||
git_branch = run_command([git, 'rev-parse', '--abbrev-ref', 'HEAD'])
|
||||
if git_commit.returncode() == 0 and git_branch.returncode() == 0
|
||||
version = '@0@-@1@ (branch \'@2@\')'.format(
|
||||
meson.project_version(),
|
||||
git_commit.stdout().strip(),
|
||||
git_branch.stdout().strip(),
|
||||
)
|
||||
endif
|
||||
if get_option('version_override') != ''
|
||||
version = '@0@'.format(get_option('version_override'))
|
||||
else
|
||||
version = '@0@'.format(meson.project_version())
|
||||
endif
|
||||
|
||||
conf_data = configuration_data()
|
||||
|
|
@ -173,21 +165,49 @@ endforeach
|
|||
foreach header : cagebreak_header_strings
|
||||
cagebreak_headers += files(header)
|
||||
endforeach
|
||||
cagebreak_dependencies_dict = {
|
||||
'server_protos': server_protos,
|
||||
'wayland_server': wayland_server,
|
||||
'wayland_client': wayland_client,
|
||||
'wayland_cursor': wayland_cursor,
|
||||
'wlroots': wlroots,
|
||||
'xkbcommon': xkbcommon,
|
||||
'fontconfig': fontconfig,
|
||||
'pixman': pixman,
|
||||
'pango': pango,
|
||||
'cairo': cairo,
|
||||
'pangocairo': pangocairo,
|
||||
'math': math
|
||||
}
|
||||
|
||||
cagebreak_dependencies = [
|
||||
server_protos,
|
||||
wayland_server,
|
||||
wayland_client,
|
||||
wayland_cursor,
|
||||
wlroots,
|
||||
xkbcommon,
|
||||
fontconfig,
|
||||
pixman,
|
||||
math,
|
||||
pango,
|
||||
cairo,
|
||||
pangocairo,
|
||||
]
|
||||
reproducible_build_versions = {
|
||||
'server_protos': '1.0.6',
|
||||
'wayland_server': '1.18.0',
|
||||
'wayland_client': '1.18.0',
|
||||
'wayland_cursor': '1.18.0',
|
||||
'wlroots': '0.10.1',
|
||||
'xkbcommon': '0.10.0',
|
||||
'fontconfig': '2.13.91',
|
||||
'pixman': '0.38.4',
|
||||
'pango': '1.44.7',
|
||||
'cairo': '1.17.3',
|
||||
'pangocairo': '1.44.7',
|
||||
'math': '-1'
|
||||
}
|
||||
|
||||
cagebreak_dependencies = []
|
||||
|
||||
foreach name, dep : cagebreak_dependencies_dict
|
||||
cagebreak_dependencies += dep
|
||||
endforeach
|
||||
|
||||
foreach name, dep : cagebreak_dependencies_dict
|
||||
if reproducible_build_versions[name] != '-1' and reproducible_build_versions[name] != dep.version()
|
||||
warning('The installed version of "' + name + '" on your machine (' + dep.version() + ') differs from the one used to generate the binary specified in the README section "Reproducible Builds" (' + reproducible_build_versions[name] + '). Cagebreak does not guarantee a reproducible build for this configuration.'
|
||||
)
|
||||
break
|
||||
endif
|
||||
endforeach
|
||||
|
||||
executable(
|
||||
meson.project_name(),
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
option('xwayland', type: 'boolean', value: 'false', description: 'Enable support for X11 applications')
|
||||
option('fuzz', type: 'boolean', value: 'false', description: 'Enable building fuzzer targets')
|
||||
option('version_override', type: 'string', description: 'Set the project version to the string specified. Used for creating hashes for reproducible builds.')
|
||||
|
|
|
|||
243
seat.c
243
seat.c
|
|
@ -112,7 +112,7 @@ static void
|
|||
update_capabilities(const struct cg_seat *seat) {
|
||||
uint32_t caps = 0;
|
||||
|
||||
if(!wl_list_empty(&seat->keyboards)) {
|
||||
if(!wl_list_empty(&seat->keyboard_groups)) {
|
||||
caps |= WL_SEAT_CAPABILITY_KEYBOARD;
|
||||
}
|
||||
if(!wl_list_empty(&seat->pointers)) {
|
||||
|
|
@ -216,41 +216,41 @@ handle_new_pointer(struct cg_seat *seat, struct wlr_input_device *device) {
|
|||
|
||||
static int
|
||||
handle_keyboard_repeat(void *data) {
|
||||
struct cg_keyboard *keyboard = (struct cg_keyboard *)data;
|
||||
struct wlr_keyboard *wlr_device = keyboard->device->keyboard;
|
||||
if(keyboard->repeat_keybinding != NULL) {
|
||||
struct cg_keyboard_group *cg_group = data;
|
||||
struct wlr_keyboard *wlr_device =
|
||||
cg_group->wlr_group->input_device->keyboard;
|
||||
if(cg_group->repeat_keybinding != NULL) {
|
||||
if(wlr_device->repeat_info.rate > 0) {
|
||||
if(wl_event_source_timer_update(
|
||||
keyboard->key_repeat_timer,
|
||||
cg_group->key_repeat_timer,
|
||||
1000 / wlr_device->repeat_info.rate) < 0) {
|
||||
wlr_log(WLR_DEBUG, "failed to update key repeat timer");
|
||||
}
|
||||
}
|
||||
|
||||
run_action((*keyboard->repeat_keybinding)->action,
|
||||
keyboard->seat->server,
|
||||
(*keyboard->repeat_keybinding)->data);
|
||||
run_action((*cg_group->repeat_keybinding)->action,
|
||||
cg_group->seat->server,
|
||||
(*cg_group->repeat_keybinding)->data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_modifier_event(struct cg_keyboard *keyboard) {
|
||||
wlr_seat_set_keyboard(keyboard->seat->seat, keyboard->device);
|
||||
wlr_seat_keyboard_notify_modifiers(keyboard->seat->seat,
|
||||
&keyboard->device->keyboard->modifiers);
|
||||
handle_modifier_event(struct wlr_input_device *device, struct cg_seat *seat) {
|
||||
wlr_seat_set_keyboard(seat->seat, device);
|
||||
wlr_seat_keyboard_notify_modifiers(seat->seat,
|
||||
&device->keyboard->modifiers);
|
||||
|
||||
wlr_idle_notify_activity(keyboard->seat->server->idle,
|
||||
keyboard->seat->seat);
|
||||
wlr_idle_notify_activity(seat->server->idle, seat->seat);
|
||||
}
|
||||
|
||||
void
|
||||
keyboard_disarm_key_repeat(struct cg_keyboard *keyboard) {
|
||||
if(!keyboard) {
|
||||
keyboard_disarm_key_repeat(struct cg_keyboard_group *group) {
|
||||
if(!group) {
|
||||
return;
|
||||
}
|
||||
keyboard->repeat_keybinding = NULL;
|
||||
if(wl_event_source_timer_update(keyboard->key_repeat_timer, 0) < 0) {
|
||||
group->repeat_keybinding = NULL;
|
||||
if(wl_event_source_timer_update(group->key_repeat_timer, 0) < 0) {
|
||||
wlr_log(WLR_DEBUG, "failed to disarm key repeat timer");
|
||||
}
|
||||
}
|
||||
|
|
@ -258,7 +258,7 @@ keyboard_disarm_key_repeat(struct cg_keyboard *keyboard) {
|
|||
static bool
|
||||
handle_command_key_bindings(struct cg_server *server, xkb_keysym_t sym,
|
||||
uint32_t modifiers, uint32_t mode,
|
||||
struct cg_keyboard *keyboard) {
|
||||
struct cg_keyboard_group *group) {
|
||||
struct keybinding **keybinding = find_keybinding(
|
||||
server->keybindings,
|
||||
&(struct keybinding){.key = sym, .mode = mode, .modifiers = modifiers});
|
||||
|
|
@ -271,15 +271,16 @@ handle_command_key_bindings(struct cg_server *server, xkb_keysym_t sym,
|
|||
"Recognized keybinding pressed (key: %d, mode: %d, modifiers: %d)",
|
||||
sym, mode, modifiers);
|
||||
|
||||
if(keyboard->device->keyboard->repeat_info.delay > 0) {
|
||||
keyboard->repeat_keybinding = keybinding;
|
||||
if(wl_event_source_timer_update(
|
||||
keyboard->key_repeat_timer,
|
||||
keyboard->device->keyboard->repeat_info.delay) < 0) {
|
||||
if(group->wlr_group->input_device->keyboard->repeat_info.delay > 0) {
|
||||
group->repeat_keybinding = keybinding;
|
||||
if(wl_event_source_timer_update(group->key_repeat_timer,
|
||||
group->wlr_group->input_device
|
||||
->keyboard->repeat_info.delay) <
|
||||
0) {
|
||||
wlr_log(WLR_DEBUG, "failed to set key repeat timer");
|
||||
}
|
||||
}
|
||||
message_clear(keyboard->seat->server->curr_output);
|
||||
message_clear(group->seat->server->curr_output);
|
||||
run_action((*keybinding)->action, server, (*keybinding)->data);
|
||||
wlr_idle_notify_activity(server->idle, server->seat->seat);
|
||||
return true;
|
||||
|
|
@ -315,42 +316,42 @@ key_is_modifier(const xkb_keysym_t key) {
|
|||
}
|
||||
|
||||
static void
|
||||
handle_key_event(struct cg_keyboard *keyboard, void *data) {
|
||||
struct cg_seat *seat = keyboard->seat;
|
||||
handle_key_event(struct cg_keyboard_group *group, struct cg_seat *seat,
|
||||
void *data) {
|
||||
struct wlr_event_keyboard_key *event = data;
|
||||
struct wlr_input_device *device = group->wlr_group->input_device;
|
||||
|
||||
/* Translate from libinput keycode to an xkbcommon keycode. */
|
||||
xkb_keycode_t keycode = event->keycode + 8;
|
||||
|
||||
const xkb_keysym_t *syms;
|
||||
int nsyms = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state,
|
||||
keycode, &syms);
|
||||
int nsyms =
|
||||
xkb_state_key_get_syms(device->keyboard->xkb_state, keycode, &syms);
|
||||
|
||||
bool handled = false;
|
||||
|
||||
for(int i = 0; i < nsyms; ++i) {
|
||||
if(event->state == WLR_KEY_PRESSED && !key_is_modifier(syms[i])) {
|
||||
uint32_t modifiers =
|
||||
wlr_keyboard_get_modifiers(keyboard->device->keyboard);
|
||||
uint32_t modifiers = wlr_keyboard_get_modifiers(device->keyboard);
|
||||
/* Get the consumed_modifiers and remove them from the modifier list
|
||||
*/
|
||||
xkb_mod_mask_t consumed_modifiers =
|
||||
xkb_state_key_get_consumed_mods2(
|
||||
keyboard->device->keyboard->xkb_state, keycode,
|
||||
XKB_CONSUMED_MODE_XKB);
|
||||
xkb_state_key_get_consumed_mods2(device->keyboard->xkb_state,
|
||||
keycode,
|
||||
XKB_CONSUMED_MODE_GTK);
|
||||
if(handle_command_key_bindings(seat->server, syms[i],
|
||||
modifiers & ~consumed_modifiers,
|
||||
seat->mode, keyboard)) {
|
||||
seat->mode, group)) {
|
||||
handled = true;
|
||||
}
|
||||
} else if(keyboard->repeat_keybinding != NULL && handled == false) {
|
||||
keyboard_disarm_key_repeat(keyboard);
|
||||
} else if(group->repeat_keybinding != NULL && handled == false) {
|
||||
keyboard_disarm_key_repeat(group);
|
||||
}
|
||||
}
|
||||
|
||||
if(!handled) {
|
||||
/* Otherwise, we pass it along to the client. */
|
||||
wlr_seat_set_keyboard(seat->seat, keyboard->device);
|
||||
wlr_seat_set_keyboard(seat->seat, device);
|
||||
wlr_seat_keyboard_notify_key(seat->seat, event->time_msec,
|
||||
event->keycode, event->state);
|
||||
}
|
||||
|
|
@ -358,130 +359,28 @@ handle_key_event(struct cg_keyboard *keyboard, void *data) {
|
|||
wlr_idle_notify_activity(seat->server->idle, seat->seat);
|
||||
}
|
||||
|
||||
static void
|
||||
cg_keyboard_group_remove(struct cg_keyboard *keyboard);
|
||||
|
||||
static void
|
||||
cg_keyboard_destroy(struct cg_keyboard *keyboard) {
|
||||
struct cg_seat *seat = keyboard->seat;
|
||||
|
||||
if(keyboard->device->keyboard->group != NULL) {
|
||||
cg_keyboard_group_remove(keyboard);
|
||||
}
|
||||
|
||||
if(wlr_seat_get_keyboard(seat->seat) == keyboard->device->keyboard) {
|
||||
wlr_seat_set_keyboard(seat->seat, NULL);
|
||||
}
|
||||
|
||||
keyboard_disarm_key_repeat(keyboard);
|
||||
wl_event_source_remove(keyboard->key_repeat_timer);
|
||||
|
||||
free(keyboard);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_empty_wlr_keyboard_group(void *data) {
|
||||
wlr_keyboard_group_destroy(data);
|
||||
}
|
||||
|
||||
static void
|
||||
cg_keyboard_group_remove(struct cg_keyboard *keyboard) {
|
||||
struct wlr_keyboard_group *wlr_group = keyboard->device->keyboard->group;
|
||||
|
||||
wlr_keyboard_group_remove_keyboard(keyboard->device->keyboard->group,
|
||||
keyboard->device->keyboard);
|
||||
|
||||
if(wl_list_empty(&wlr_group->devices)) {
|
||||
wlr_log(WLR_DEBUG, "Destroying empty keyboard group %p",
|
||||
(void *)wlr_group);
|
||||
struct cg_keyboard_group *cg_group = wlr_group->data;
|
||||
wlr_group->data = NULL;
|
||||
wl_list_remove(&cg_group->link);
|
||||
wl_list_remove(&cg_group->key.link);
|
||||
wl_list_remove(&cg_group->modifiers.link);
|
||||
cg_keyboard_destroy(cg_group->keyboard);
|
||||
free(cg_group);
|
||||
|
||||
// To prevent use-after-free conditions when handling key events, defer
|
||||
// freeing the wlr_keyboard_group until idle
|
||||
if(keyboard->seat->server->running) {
|
||||
wl_event_loop_add_idle(keyboard->seat->server->event_loop,
|
||||
destroy_empty_wlr_keyboard_group, wlr_group);
|
||||
} else {
|
||||
destroy_empty_wlr_keyboard_group(wlr_group);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_keyboard_destroy(struct wl_listener *listener, void *_data) {
|
||||
struct cg_keyboard *keyboard = wl_container_of(listener, keyboard, destroy);
|
||||
struct cg_seat *seat = keyboard->seat;
|
||||
wl_list_remove(&keyboard->link);
|
||||
wl_list_remove(&keyboard->destroy.link);
|
||||
cg_keyboard_destroy(keyboard);
|
||||
update_capabilities(seat);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_keyboard_group_key(struct wl_listener *listener, void *data) {
|
||||
struct cg_keyboard_group *cg_group =
|
||||
wl_container_of(listener, cg_group, key);
|
||||
handle_key_event(cg_group->keyboard, data);
|
||||
handle_key_event(cg_group, cg_group->seat, data);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_keyboard_group_modifiers(struct wl_listener *listener, void *_data) {
|
||||
struct cg_keyboard_group *group =
|
||||
wl_container_of(listener, group, modifiers);
|
||||
handle_modifier_event(group->keyboard);
|
||||
}
|
||||
|
||||
static bool
|
||||
keymaps_match(struct xkb_keymap *km1, struct xkb_keymap *km2) {
|
||||
char *km1_str = xkb_keymap_get_as_string(km1, XKB_KEYMAP_FORMAT_TEXT_V1);
|
||||
char *km2_str = xkb_keymap_get_as_string(km2, XKB_KEYMAP_FORMAT_TEXT_V1);
|
||||
bool result = strcmp(km1_str, km2_str) == 0;
|
||||
free(km1_str);
|
||||
free(km2_str);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool
|
||||
repeat_info_match(const struct cg_keyboard *a, const struct wlr_keyboard *b) {
|
||||
return a->device->keyboard->repeat_info.rate == b->repeat_info.rate &&
|
||||
a->device->keyboard->repeat_info.delay == b->repeat_info.delay;
|
||||
}
|
||||
|
||||
struct cg_keyboard *
|
||||
cg_keyboard_from_seat(struct cg_seat *seat, struct wlr_input_device *device) {
|
||||
struct cg_keyboard *keyboard = calloc(1, sizeof(struct cg_keyboard));
|
||||
if(keyboard == NULL) {
|
||||
wlr_log(WLR_ERROR, "Could not allocate new cg_keyboard.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
keyboard->seat = seat;
|
||||
keyboard->device = device;
|
||||
|
||||
keyboard->key_repeat_timer = wl_event_loop_add_timer(
|
||||
seat->server->event_loop, handle_keyboard_repeat, keyboard);
|
||||
|
||||
return keyboard;
|
||||
handle_modifier_event(group->wlr_group->input_device, group->seat);
|
||||
}
|
||||
|
||||
static void
|
||||
keyboard_group_add(const struct cg_keyboard *keyboard) {
|
||||
struct cg_seat *seat = keyboard->seat;
|
||||
struct wlr_keyboard *wlr_keyboard = keyboard->device->keyboard;
|
||||
cg_keyboard_group_add(struct wlr_input_device *device, struct cg_seat *seat) {
|
||||
struct wlr_keyboard *wlr_keyboard = device->keyboard;
|
||||
struct cg_keyboard_group *group;
|
||||
wl_list_for_each(group, &seat->keyboard_groups, link) {
|
||||
struct wlr_keyboard_group *wlr_group = group->wlr_group;
|
||||
if(keymaps_match(wlr_keyboard->keymap, wlr_group->keyboard.keymap) &&
|
||||
repeat_info_match(keyboard, &wlr_group->keyboard)) {
|
||||
wlr_log(WLR_DEBUG, "Adding keyboard %p to group %p.",
|
||||
(void *)keyboard, (void *)wlr_group);
|
||||
wlr_keyboard_group_add_keyboard(wlr_group, wlr_keyboard);
|
||||
if(wlr_keyboard_group_add_keyboard(wlr_group, wlr_keyboard)) {
|
||||
wlr_log(WLR_DEBUG, "Adding keyboard to existing group.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -493,6 +392,7 @@ keyboard_group_add(const struct cg_keyboard *keyboard) {
|
|||
wlr_log(WLR_ERROR, "Failed to allocate keyboard group.");
|
||||
return;
|
||||
}
|
||||
cg_group->seat = seat;
|
||||
cg_group->wlr_group = wlr_keyboard_group_create();
|
||||
if(cg_group->wlr_group == NULL) {
|
||||
wlr_log(WLR_ERROR, "Failed to create wlr keyboard group.");
|
||||
|
|
@ -501,22 +401,12 @@ keyboard_group_add(const struct cg_keyboard *keyboard) {
|
|||
|
||||
cg_group->wlr_group->data = cg_group;
|
||||
wlr_keyboard_set_keymap(&cg_group->wlr_group->keyboard,
|
||||
keyboard->device->keyboard->keymap);
|
||||
device->keyboard->keymap);
|
||||
wlr_keyboard_set_repeat_info(&cg_group->wlr_group->keyboard,
|
||||
keyboard->device->keyboard->repeat_info.rate,
|
||||
keyboard->device->keyboard->repeat_info.delay);
|
||||
wlr_log(WLR_DEBUG, "Created keyboard group %p",
|
||||
(void *)cg_group->wlr_group);
|
||||
device->keyboard->repeat_info.rate,
|
||||
device->keyboard->repeat_info.delay);
|
||||
wlr_log(WLR_DEBUG, "Created keyboard group.");
|
||||
|
||||
cg_group->keyboard =
|
||||
cg_keyboard_from_seat(seat, cg_group->wlr_group->input_device);
|
||||
if(cg_group->keyboard == NULL) {
|
||||
wlr_log(WLR_ERROR, "Failed to create keyboard from seat.");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
wlr_log(WLR_DEBUG, "Adding keyboard %p to group %p.", (void *)keyboard,
|
||||
(void *)cg_group->wlr_group);
|
||||
wlr_keyboard_group_add_keyboard(cg_group->wlr_group, wlr_keyboard);
|
||||
wl_list_insert(&seat->keyboard_groups, &cg_group->link);
|
||||
|
||||
|
|
@ -525,6 +415,10 @@ keyboard_group_add(const struct cg_keyboard *keyboard) {
|
|||
|
||||
wl_signal_add(&cg_group->wlr_group->keyboard.events.modifiers,
|
||||
&cg_group->modifiers);
|
||||
|
||||
cg_group->key_repeat_timer = wl_event_loop_add_timer(
|
||||
seat->server->event_loop, handle_keyboard_repeat, cg_group);
|
||||
|
||||
cg_group->modifiers.notify = handle_keyboard_group_modifiers;
|
||||
return;
|
||||
|
||||
|
|
@ -537,16 +431,9 @@ cleanup:
|
|||
|
||||
static void
|
||||
handle_new_keyboard(struct cg_seat *seat, struct wlr_input_device *device) {
|
||||
struct cg_keyboard *keyboard = calloc(1, sizeof(struct cg_keyboard));
|
||||
if(!keyboard) {
|
||||
wlr_log(WLR_ERROR, "Cannot allocate keyboard");
|
||||
return;
|
||||
}
|
||||
|
||||
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
if(!context) {
|
||||
wlr_log(WLR_ERROR, "Unable to create XBK context");
|
||||
free(keyboard);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -561,28 +448,19 @@ handle_new_keyboard(struct cg_seat *seat, struct wlr_input_device *device) {
|
|||
if(!keymap) {
|
||||
wlr_log(WLR_ERROR,
|
||||
"Unable to configure keyboard: keymap does not exist");
|
||||
free(keyboard);
|
||||
xkb_context_unref(context);
|
||||
return;
|
||||
}
|
||||
|
||||
keyboard->seat = seat;
|
||||
keyboard->device = device;
|
||||
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_group_add(keyboard);
|
||||
cg_keyboard_group_add(device, seat);
|
||||
|
||||
wlr_seat_set_keyboard(seat->seat, device->keyboard->group->input_device);
|
||||
|
||||
wl_list_insert(&seat->keyboards, &keyboard->link);
|
||||
keyboard->destroy.notify = handle_keyboard_destroy;
|
||||
wl_signal_add(&device->events.destroy, &keyboard->destroy);
|
||||
keyboard->key_repeat_timer = wl_event_loop_add_timer(
|
||||
seat->server->event_loop, handle_keyboard_repeat, keyboard);
|
||||
wlr_seat_set_keyboard(seat->seat, device);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -914,9 +792,11 @@ handle_destroy(struct wl_listener *listener, void *_data) {
|
|||
struct cg_seat *seat = wl_container_of(listener, seat, destroy);
|
||||
wl_list_remove(&seat->destroy.link);
|
||||
|
||||
struct cg_keyboard *keyboard, *keyboard_tmp;
|
||||
wl_list_for_each_safe(keyboard, keyboard_tmp, &seat->keyboards, link) {
|
||||
handle_keyboard_destroy(&keyboard->destroy, NULL);
|
||||
struct cg_keyboard_group *group, *group_tmp;
|
||||
wl_list_for_each_safe(group, group_tmp, &seat->keyboard_groups, link) {
|
||||
wlr_keyboard_group_destroy(group->wlr_group);
|
||||
wl_event_source_remove(group->key_repeat_timer);
|
||||
free(group);
|
||||
}
|
||||
struct cg_pointer *pointer, *pointer_tmp;
|
||||
wl_list_for_each_safe(pointer, pointer_tmp, &seat->pointers, link) {
|
||||
|
|
@ -1014,7 +894,6 @@ seat_create(struct cg_server *server, struct wlr_backend *backend) {
|
|||
wl_signal_add(&seat->seat->events.request_set_primary_selection,
|
||||
&seat->request_set_primary_selection);
|
||||
|
||||
wl_list_init(&seat->keyboards);
|
||||
wl_list_init(&seat->keyboard_groups);
|
||||
wl_list_init(&seat->pointers);
|
||||
wl_list_init(&seat->touch);
|
||||
|
|
|
|||
23
seat.h
23
seat.h
|
|
@ -14,22 +14,11 @@ struct wlr_backend;
|
|||
#define DEFAULT_XCURSOR "left_ptr"
|
||||
#define XCURSOR_SIZE 24
|
||||
|
||||
struct cg_keyboard_group {
|
||||
struct cg_keyboard *keyboard;
|
||||
|
||||
struct wlr_keyboard_group *wlr_group;
|
||||
struct cg_seat *seat;
|
||||
struct wl_listener key;
|
||||
struct wl_listener modifiers;
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
struct cg_seat {
|
||||
struct wlr_seat *seat;
|
||||
struct cg_server *server;
|
||||
struct wl_listener destroy;
|
||||
|
||||
struct wl_list keyboards;
|
||||
struct wl_list keyboard_groups;
|
||||
struct wl_list pointers;
|
||||
struct wl_list touch;
|
||||
|
|
@ -66,14 +55,16 @@ struct cg_seat {
|
|||
struct cg_view *focused_view;
|
||||
};
|
||||
|
||||
struct cg_keyboard {
|
||||
struct wl_list link; // seat::keyboards
|
||||
struct cg_keyboard_group {
|
||||
struct wlr_keyboard_group *wlr_group;
|
||||
struct cg_seat *seat;
|
||||
struct wlr_input_device *device;
|
||||
|
||||
struct wl_listener destroy;
|
||||
struct keybinding **repeat_keybinding;
|
||||
struct wl_listener key;
|
||||
struct wl_listener modifiers;
|
||||
struct wl_list link;
|
||||
|
||||
struct wl_event_source *key_repeat_timer;
|
||||
struct keybinding **repeat_keybinding;
|
||||
};
|
||||
|
||||
struct cg_pointer {
|
||||
|
|
|
|||
BIN
signatures/cagebreak.sig
Normal file
BIN
signatures/cagebreak.sig
Normal file
Binary file not shown.
12
view.c
12
view.c
|
|
@ -234,10 +234,14 @@ view_unmap(struct cg_view *view) {
|
|||
struct cg_tile *view_tile = view_get_tile(view);
|
||||
wlr_output_damage_add_box(view_tile->workspace->output->damage,
|
||||
&view_tile->tile);
|
||||
if(view->workspace->server->seat->seat->keyboard_state
|
||||
.focused_surface == NULL ||
|
||||
view->workspace->server->seat->seat->keyboard_state
|
||||
.focused_surface == view->wlr_surface) {
|
||||
if((view->workspace->server->seat->seat->keyboard_state
|
||||
.focused_surface == NULL ||
|
||||
view->workspace->server->seat->seat->keyboard_state
|
||||
.focused_surface == view->wlr_surface) &&
|
||||
view->workspace->server->curr_output
|
||||
->workspaces[view->workspace->server->curr_output
|
||||
->curr_workspace]
|
||||
->focused_tile == view_tile) {
|
||||
seat_set_focus(view->workspace->server->seat, prev);
|
||||
} else {
|
||||
view_tile->view = prev;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue