forked from labwc/labwc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[wip] implement cosmic-keymap-layout protocol
Test implementation of pop-os/cosmic-protocols#28 WARNING: Do not use this outside of protocol evaluation. The protocol might change which will cause the wayland connection to disconnect clients due to protocol mismatch.
- Loading branch information
1 parent
6566f92
commit a5bfdeb
Showing
6 changed files
with
360 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* SPDX-License-Identifier: GPL-2.0-only */ | ||
#ifndef LABWC_PROTOCOLS_COSMIC_KEYMAP_LAYOUT_H | ||
#define LABWC_PROTOCOLS_COSMIC_KEYMAP_LAYOUT_H | ||
|
||
#include <wayland-server-core.h> | ||
|
||
struct lab_cosmic_keymap_layout_manager { | ||
struct { | ||
struct wl_signal request_layout; | ||
} events; | ||
|
||
/* Private */ | ||
struct wl_global *global; | ||
struct { | ||
struct wl_listener display_destroy; | ||
} on; | ||
struct wl_list keymap_listeners; | ||
struct wl_list manager_resources; | ||
}; | ||
|
||
struct lab_cosmic_keymap_layout_manager *lab_cosmic_keymap_layout_manager_create( | ||
struct wl_display *display, uint32_t version); | ||
|
||
#endif /* LABWC_PROTOCOLS_COSMIC_KEYMAP_LAYOUT_H */ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<protocol name="cosmic_keymap_unstable_v1"> | ||
<copyright> | ||
Copyright © 2024 System76, Inc | ||
|
||
Permission to use, copy, modify, distribute, and sell this | ||
software and its documentation for any purpose is hereby granted | ||
without fee, provided that the above copyright notice appear in | ||
all copies and that both that copyright notice and this permission | ||
notice appear in supporting documentation, and that the name of | ||
the copyright holders not be used in advertising or publicity | ||
pertaining to distribution of the software without specific, | ||
written prior permission. The copyright holders make no | ||
representations about the suitability of this software for any | ||
purpose. It is provided "as is" without express or implied | ||
warranty. | ||
|
||
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS | ||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | ||
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN | ||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | ||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF | ||
THIS SOFTWARE. | ||
</copyright> | ||
|
||
<description summary=""> | ||
TODO | ||
|
||
Warning! The protocol described in this file is currently in the testing | ||
phase. Backward compatible changes may be added together with the | ||
corresponding interface version bump. Backward incompatible changes can | ||
only be done by creating a new major version of the extension. | ||
</description> | ||
|
||
<interface name="zcosmic_keymap_manager_v1" version="1"> | ||
<description summary=""> | ||
</description> | ||
|
||
<request name="get_keymap"> | ||
<description summary=""> | ||
</description> | ||
<arg name="keymap" type="new_id" interface="zcosmic_keymap_v1"/> | ||
<arg name="keyboard" type="object" interface="wl_keyboard"/> | ||
</request> | ||
|
||
<request name="destroy" type="destructor"> | ||
<description summary="delete this object"> | ||
</description> | ||
</request> | ||
</interface> | ||
|
||
<interface name="zcosmic_keymap_v1" version="1"> | ||
<description summary=""> | ||
</description> | ||
|
||
<event name="group"> | ||
<description summary=""> | ||
</description> | ||
<arg name="group" type="uint"/> | ||
</event> | ||
|
||
<request name="set_group"> | ||
<description summary=""> | ||
</description> | ||
<arg name="group" type="uint"/> | ||
</request> | ||
|
||
<request name="destroy" type="destructor"> | ||
<description summary="delete this object"> | ||
</description> | ||
</request> | ||
</interface> | ||
</protocol> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
255 changes: 255 additions & 0 deletions
255
src/protocols/cosmic-keymap-layout/cosmic-keymap-layout.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,255 @@ | ||
// SPDX-License-Identifier: GPL-2.0-only | ||
#include <assert.h> | ||
#include <wlr/util/log.h> | ||
#include <wlr/types/wlr_seat.h> | ||
#include "common/mem.h" | ||
#include "common/list.h" | ||
#include "protocols/cosmic-keymap-layout.h" | ||
#include "cosmic-keymap-unstable-v1-protocol.h" | ||
|
||
#define LAB_COSMIC_KEYMAP_LAYOUT_VERSION 1 | ||
|
||
struct keymap_listener { | ||
struct lab_cosmic_keymap_layout_manager *manager; | ||
struct wlr_keyboard *kb; | ||
uint32_t group; | ||
struct { | ||
struct wl_listener modifiers; | ||
struct wl_listener destroy; | ||
} on_kb; | ||
struct wl_list link; | ||
struct wl_list keymap_resources; | ||
}; | ||
|
||
/* Keymap listeners */ | ||
static void | ||
keymap_listener_destroy(struct keymap_listener *listener) | ||
{ | ||
wl_list_remove(&listener->on_kb.modifiers.link); | ||
wl_list_remove(&listener->on_kb.destroy.link); | ||
wl_list_remove(&listener->link); | ||
|
||
struct wl_resource *res, *tmp; | ||
wl_resource_for_each_safe(res, tmp, &listener->keymap_resources) { | ||
wl_resource_set_user_data(res, NULL); | ||
wl_resource_destroy(res); | ||
} | ||
free(listener); | ||
} | ||
|
||
static void | ||
kb_handle_destroy(struct wl_listener *listener, void *data) | ||
{ | ||
struct keymap_listener *keymap_listener = | ||
wl_container_of(listener, keymap_listener, on_kb.destroy); | ||
|
||
keymap_listener_destroy(keymap_listener); | ||
} | ||
|
||
static void | ||
kb_handle_modifier(struct wl_listener *listener, void *data) | ||
{ | ||
struct keymap_listener *keymap_listener = | ||
wl_container_of(listener, keymap_listener, on_kb.modifiers); | ||
uint32_t group = keymap_listener->kb->modifiers.group; | ||
|
||
//FIXME: something weird going on here, on a non-group modifier | ||
// press modifiers.group is reset to 0 for whatever reason | ||
// likely related to running nested and the external wayland | ||
// modifier events just getting passed through. | ||
|
||
if (keymap_listener->group == group) { | ||
return; | ||
} | ||
keymap_listener->group = group; | ||
|
||
struct wl_resource *res; | ||
wl_resource_for_each(res, &keymap_listener->keymap_resources) { | ||
zcosmic_keymap_v1_send_group(res, group); | ||
} | ||
} | ||
|
||
static struct keymap_listener * | ||
keymap_listener_create(struct lab_cosmic_keymap_layout_manager *manager, struct wlr_keyboard *kb) | ||
{ | ||
struct keymap_listener *listener = znew(*listener); | ||
listener->kb = kb; | ||
listener->manager = manager; | ||
listener->group = kb->modifiers.group; | ||
wl_list_init(&listener->keymap_resources); | ||
|
||
listener->on_kb.modifiers.notify = kb_handle_modifier; | ||
wl_signal_add(&kb->events.modifiers, &listener->on_kb.modifiers); | ||
|
||
listener->on_kb.destroy.notify = kb_handle_destroy; | ||
wl_signal_add(&kb->base.events.destroy, &listener->on_kb.destroy); | ||
|
||
wl_list_append(&manager->keymap_listeners, &listener->link); | ||
|
||
return listener; | ||
} | ||
|
||
|
||
/* Keymap handlers */ | ||
static void | ||
keymap_handle_set_group(struct wl_client *client, struct wl_resource *resource, uint32_t group) | ||
{ | ||
struct keymap_listener *listener = wl_resource_get_user_data(resource); | ||
assert(listener); | ||
|
||
wl_signal_emit_mutable(&listener->manager->events.request_layout, &group); | ||
} | ||
|
||
static void | ||
keymap_handle_destroy(struct wl_client *client, struct wl_resource *resource) | ||
{ | ||
wl_resource_destroy(resource); | ||
} | ||
|
||
static const struct zcosmic_keymap_v1_interface keymap_impl = { | ||
.set_group = keymap_handle_set_group, | ||
.destroy = keymap_handle_destroy, | ||
}; | ||
|
||
static void | ||
keymap_instance_resource_destroy(struct wl_resource *resource) | ||
{ | ||
wl_list_remove(wl_resource_get_link(resource)); | ||
|
||
struct keymap_listener *listener = wl_resource_get_user_data(resource); | ||
if (listener && wl_list_empty(&listener->keymap_resources)) { | ||
keymap_listener_destroy(listener); | ||
} | ||
} | ||
|
||
/* Manager handlers */ | ||
static void | ||
manager_handle_get_keymap(struct wl_client *client, struct wl_resource *resource, | ||
uint32_t keymap, struct wl_resource *keyboard) | ||
{ | ||
struct lab_cosmic_keymap_layout_manager *manager = | ||
wl_resource_get_user_data(resource); | ||
assert(manager); | ||
|
||
struct wlr_seat_client *seat_client = wl_resource_get_user_data(keyboard); | ||
if (!seat_client) { | ||
wlr_log(WLR_ERROR, "failed to find seat_client"); | ||
return; | ||
} | ||
struct wlr_keyboard *kb = seat_client->seat->keyboard_state.keyboard; | ||
if (!kb) { | ||
wlr_log(WLR_ERROR, "failed to find keyboard"); | ||
return; | ||
} | ||
uint32_t version = wl_resource_get_version(resource); | ||
struct wl_resource *keymap_resource = | ||
wl_resource_create(client, &zcosmic_keymap_v1_interface, version, keymap); | ||
if (!resource) { | ||
wlr_log(WLR_ERROR, "failed to create keymap resource"); | ||
wl_client_post_no_memory(client); | ||
return; | ||
} | ||
|
||
struct keymap_listener *listener = NULL; | ||
|
||
struct keymap_listener *kl; | ||
wl_list_for_each(kl, &manager->keymap_listeners, link) { | ||
if (kl->kb == kb) { | ||
listener = kl; | ||
break; | ||
} | ||
} | ||
if (!listener) { | ||
listener = keymap_listener_create(manager, kb); | ||
} | ||
|
||
wl_resource_set_implementation(keymap_resource, &keymap_impl, listener, | ||
keymap_instance_resource_destroy); | ||
|
||
wl_list_insert(&listener->keymap_resources, wl_resource_get_link(keymap_resource)); | ||
|
||
zcosmic_keymap_v1_send_group(keymap_resource, listener->group); | ||
} | ||
|
||
static void | ||
manager_handle_destroy(struct wl_client *client, struct wl_resource *resource) | ||
{ | ||
wl_resource_destroy(resource); | ||
} | ||
|
||
static const struct zcosmic_keymap_manager_v1_interface manager_impl = { | ||
.get_keymap = manager_handle_get_keymap, | ||
.destroy = manager_handle_destroy, | ||
}; | ||
|
||
static void | ||
manager_instance_resource_destroy(struct wl_resource *resource) | ||
{ | ||
wl_list_remove(wl_resource_get_link(resource)); | ||
} | ||
|
||
static void | ||
manager_handle_bind(struct wl_client *client, void *data, | ||
uint32_t version, uint32_t id) | ||
{ | ||
struct lab_cosmic_keymap_layout_manager *manager = data; | ||
struct wl_resource *resource = wl_resource_create(client, | ||
&zcosmic_keymap_manager_v1_interface, | ||
version, id); | ||
if (!resource) { | ||
wl_client_post_no_memory(client); | ||
return; | ||
} | ||
|
||
wl_resource_set_implementation(resource, &manager_impl, | ||
manager, manager_instance_resource_destroy); | ||
|
||
wl_list_insert(&manager->manager_resources, wl_resource_get_link(resource)); | ||
} | ||
|
||
static void | ||
manager_handle_display_destroy(struct wl_listener *listener, void *data) | ||
{ | ||
struct lab_cosmic_keymap_layout_manager *manager = | ||
wl_container_of(listener, manager, on.display_destroy); | ||
|
||
wl_global_destroy(manager->global); | ||
|
||
struct keymap_listener *kl, *kl_tmp; | ||
wl_list_for_each_safe(kl, kl_tmp, &manager->keymap_listeners, link) { | ||
keymap_listener_destroy(kl); | ||
} | ||
|
||
struct wl_resource *resource, *res_tmp; | ||
wl_resource_for_each_safe(resource, res_tmp, &manager->manager_resources) { | ||
wl_resource_destroy(resource); | ||
} | ||
|
||
wl_list_remove(&manager->on.display_destroy.link); | ||
free(manager); | ||
} | ||
|
||
/* Public API */ | ||
struct lab_cosmic_keymap_layout_manager * | ||
lab_cosmic_keymap_layout_manager_create(struct wl_display *display, uint32_t version) | ||
{ | ||
assert(version <= LAB_COSMIC_KEYMAP_LAYOUT_VERSION); | ||
struct lab_cosmic_keymap_layout_manager *manager = znew(*manager); | ||
|
||
manager->global = wl_global_create(display, | ||
&zcosmic_keymap_manager_v1_interface, | ||
version, manager, manager_handle_bind); | ||
|
||
if (!manager->global) { | ||
free(manager); | ||
return NULL; | ||
} | ||
|
||
manager->on.display_destroy.notify = manager_handle_display_destroy; | ||
wl_display_add_destroy_listener(display, &manager->on.display_destroy); | ||
|
||
wl_signal_init(&manager->events.request_layout); | ||
wl_list_init(&manager->manager_resources); | ||
wl_list_init(&manager->keymap_listeners); | ||
return manager; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
labwc_sources += files( | ||
'cosmic-keymap-layout.c', | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
subdir('cosmic_workspaces') | ||
subdir('cosmic-keymap-layout') |