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

Support virtual keyboard protocol #999

Merged
merged 1 commit into from May 29, 2018

Conversation

Projects
None yet
6 participants
@dcz-purism
Contributor

dcz-purism commented May 24, 2018

This change is to support the recently proposed virtual-keyboard-v1 protocol.

Because virtual keyboards are privileged, the commits setting up an authorization system - meant to be general for all input methods - are separate.

The main commit provides support in wlroots as well as rootston. The keyboard does not attempt to synchronize its modifier status with the rest of the system, and code for having multiple instances running at the same time has not been extensively tested, however it's rather simple and wasn't failing either.

@dcz-purism

This comment has been minimized.

Contributor

dcz-purism commented May 24, 2018

The test client is at https://code.puri.sm/Librem5/weston/src/virtual_keyboard - please use the weston-keyboard program:

./configure --enable-clients
./weston-keyboard
@@ -19,14 +19,15 @@
static void usage(const char *name, int ret) {
fprintf(stderr,
"usage: %s [-C <FILE>] [-E <COMMAND>]\n"
"usage: %s [-C <FILE>] [-E <COMMAND>] [-E <EXEC>]\n"
"\n"

This comment has been minimized.

@agx

agx May 25, 2018

Contributor

Duplicat -E, should be -K ?

@@ -0,0 +1,11 @@
//#include <wlr/types/wlr_input_method.h>

This comment has been minimized.

@agx

agx May 25, 2018

Contributor

Dead code?

static void spawn_im_process() {
*im_pid = fork();
if (*im_pid == 0) {
sleep(1);

This comment has been minimized.

@agx

agx May 25, 2018

Contributor

sleep for what? If a sleep is needed for any reason it shoud likely be polling for something to be not racy

This comment has been minimized.

@dcz-purism

dcz-purism May 25, 2018

Contributor

Initially, I added the sleep there because when spawn_im_process is first called, the server is not completely initialized, causing an immediate crash. Later on, I realized this would be useful to rate-limit the spawns.

This comment has been minimized.

@emersion

emersion May 25, 2018

Member

-1

Rate-limiting shouldn't be done via sleep, and rootston shouldn't rate-limit. Child processes should only be spawned when the server is completely initialized.

This comment has been minimized.

@dcz-purism

dcz-purism May 25, 2018

Contributor

How to wait for full initialization?

This comment has been minimized.

@dcz-purism

dcz-purism May 25, 2018

Contributor

When I say rate-limit, I mean the situation where a faulty process will crash very soon after spawning and get restarted. I think it the infinite spawning loop should be prevented from excessively consuming resources, although not necessarily using sleep.

This comment has been minimized.

@Ongy

Ongy May 25, 2018

Contributor

You can either split your setup and call the spawn part directly before going into the main loop, or add an idle event at setup time to start the client from the mainloop.

void *credentials_data;
struct {
struct wl_signal new_virtual_keyboard; // struct wlr_virtual_keyboard*
};

This comment has been minimized.

@agx

agx May 25, 2018

Contributor

Other places use

struct {
} events;

This comment has been minimized.

@dcz-purism

dcz-purism May 25, 2018

Contributor

Thanks, I knew something was off here.

struct wlr_seat *seat;
struct {
struct wl_signal destroy; // struct wlr_virtual_keyboard*
};

This comment has been minimized.

@agx

agx May 25, 2018

Contributor

Same here.

@agx

See comments. Looks good to me otherwise.

roots_seat_add_device(seat, &keyboard->input_device);
wl_signal_add(&keyboard->destroy, &desktop->virtual_keyboard_destroy);
desktop->virtual_keyboard_destroy.notify = handle_virtual_keyboard_destroy;
}

This comment has been minimized.

@agx

agx May 25, 2018

Contributor

Why register it when handle_virtual_keyboard_destroy is a noop?

This comment has been minimized.

@dcz-purism

dcz-purism May 25, 2018

Contributor

That's vestigial from an earlier version - removing.

return wl_resource_get_user_data(resource);
}
static void virtual_keyboard_keymap(struct wl_client *client,

This comment has been minimized.

@agx

agx May 25, 2018

Contributor

style nitpick: Extra space

This comment has been minimized.

@dcz-purism

dcz-purism May 25, 2018

Contributor

This was actually a tab :)

@ddevault

This comment has been minimized.

Member

ddevault commented May 25, 2018

I don't like rootston having special support for spawing the IM and keeping up with its process. I also don't like that the wlroots implementation has a special function to check for authoriziation to the protocol. This isn't how we're going to secure protocols.

For now, just let any client use this protocol and yank out all of the -K and process handling stuff. If you want it to restart automatically just use a shell script that runs it in a loop.

@ddevault

Overall this looks great, just gotta yank out the process management stuff

gid_t gid;
wl_client_get_credentials(client, &pid, &uid, &gid);
return pid == allowed_pid;
}

This comment has been minimized.

@ddevault

ddevault May 25, 2018

Member

Basically this whole file should go away

switch (c) {
case 'C':
config->config_path = strdup(optarg);
break;
case 'E':
config->startup_cmd = strdup(optarg);
break;
case 'K':
config->im_cmd = strdup(optarg);
break;

This comment has been minimized.

@ddevault
struct wlr_virtual_keyboard_manager {
struct wl_global *global;
struct wl_resource *resource;
wlr_virtual_keyboard_check_credentials_func_t check_credentials;

This comment has been minimized.

@ddevault
@agx

This comment has been minimized.

Contributor

agx commented May 25, 2018

For now, just let any client use this protocol and yank out all of the -K and process handling stuff. If you
want it to restart automatically just use a shell script that runs it in a loop.

I think that's fine, we can carry this as a patch on top of rootston for the librem5 and rather work on the general logic to authorize clients since layer-shell, etc. are also affected.

xkb_context_unref(context);
context_fail:
wl_client_post_no_memory(client);
return;

This comment has been minimized.

@Shugyousha

Shugyousha May 25, 2018

Contributor

This return is not needed.

}
struct wlr_keyboard* keyboard = calloc(1, sizeof(struct wlr_keyboard));
if (keyboard == NULL) {

This comment has been minimized.

@Shugyousha

Shugyousha May 25, 2018

Contributor

Should be

if (!keyboard) {

for consistency.

This comment has been minimized.

@emersion

emersion May 25, 2018

Member

Nah, both are fine

This comment has been minimized.

@Shugyousha

Shugyousha May 25, 2018

Contributor

The style is mixed in the same function though... your call.

@dcz-purism

This comment has been minimized.

Contributor

dcz-purism commented May 25, 2018

Yanked and fixed.

@@ -0,0 +1,3 @@
#include <wayland-server-core.h>

This comment was marked as resolved.

@ddevault

ddevault May 27, 2018

Member

Needs guards

@ddevault

This comment has been minimized.

Member

ddevault commented May 27, 2018

This is looking really good. Just had one minor issue, and I still need to test it on my touchscreen device.

}
wl_resource_set_implementation(resource, &manager_impl, manager, NULL);
manager->resource = resource;

This comment has been minimized.

@emersion

emersion May 27, 2018

Member

If two clients bind to the global, manager->resource will be overwritten. You should use a list and wl_resource_get_link instead.

static void virtual_keyboard_manager_bind(struct wl_client *client, void *data,
uint32_t version, uint32_t id) {
assert(client);

This comment has been minimized.

@emersion

emersion May 27, 2018

Member

This assert is unnecessary.

virtual_keyboard->resource = keyboard_resource;
virtual_keyboard->seat = seat_client->seat;
wl_signal_init(&virtual_keyboard->events.destroy);
wlr_signal_emit_safe(&manager->events.new_virtual_keyboard, virtual_keyboard);

This comment has been minimized.

@emersion

emersion May 27, 2018

Member

We should have a list of all virtual keyboards in the manager.

This comment has been minimized.

@dcz-purism

dcz-purism May 27, 2018

Contributor

What for?

This comment has been minimized.

@emersion

emersion May 27, 2018

Member

Let the users iterate on the list and properly cleanup when destroying the manager.

This comment has been minimized.

@dcz-purism

dcz-purism May 27, 2018

Contributor

What's the advantage of letting manager do the cleanup over letting keyboards clean up themselves?
As I understand, there's not much utility in destroying the manager while objects are bound. In addition to that, the manager is acting as a factory rather than a collection, so there's no harm in leaving keyboards alive after destroying it.
In addition to that, having a list of active keyboards in the manager will need introducing another object to remember which keyboards are held by which user, making the whole thing a doubly-nested structure:

  • manager global
  • manager binds
  • keyboards

The way it is now seems just as functional and can stay simple.

This comment has been minimized.

@dcz-purism

dcz-purism May 27, 2018

Contributor

Giving it a bit more thought, a binds list is not implied by a keyboard list, but I stand by my comment that it's not necessary.

This comment has been minimized.

@emersion

emersion May 27, 2018

Member

No need for complicated list. The global, a list of resources and a list of keyboards in the manager is enough.

The list is useful to let compositors inspect it without having to maintain their own list.

wlr_input_device_init(&virtual_keyboard->input_device,
WLR_INPUT_DEVICE_KEYBOARD, &input_device_impl, "virtual keyboard",
0xabcd, 0x1234);

This comment has been minimized.

@emersion

emersion May 27, 2018

Member

Hmm, better to use 0 instead of these constants :)

static void virtual_keyboard_destroy(struct wl_client *client,
struct wl_resource *resource) {
virtual_keyboard_destroy_resource(resource);

This comment has been minimized.

@emersion

emersion May 27, 2018

Member

This will leak the resource. Also, this allows the client to call destroy twice and make the compositor crash.

Should just call wl_resource_destroy(resource).

@ddevault

This comment has been minimized.

Member

ddevault commented May 27, 2018

How does this work relate to #892?

};
struct wlr_virtual_keyboard_manager *wlr_virtual_keyboard_manager_create(
struct wl_display *display);

This comment has been minimized.

@emersion

emersion May 27, 2018

Member

The compositor should have a way to destroy the manager here

@@ -0,0 +1,28 @@
#ifndef WLR_TYPES_WLR_VIRTUAL_KEYBOARD_H
#define WLR_TYPES_WLR_VIRTUAL_KEYBOARD_H

This comment has been minimized.

@emersion

emersion May 27, 2018

Member

All of the symbols should be include the unstable version too.

This comment has been minimized.

@dcz-purism

dcz-purism May 27, 2018

Contributor

What do you mean?

This comment has been minimized.

@emersion

emersion May 27, 2018

Member

This protocol is virtual_keyboard_unstable_v1. All symbols should be chosen so that there's no conflict when a new unstable version is published (e.g. virtual_keyboard_unstable_v2) or when the stable version is adopted (virtual_keyboard).

This comment has been minimized.

@dcz-purism

dcz-purism May 27, 2018

Contributor

Does the file name need to change?

This comment has been minimized.

@emersion
@emersion

Looking good!

@ddevault

This comment has been minimized.

Member

ddevault commented May 27, 2018

Tested on touch screen 👍

@dcz-purism

This comment has been minimized.

Contributor

dcz-purism commented May 27, 2018

@SirCmpwn this provides some features which will be cut out from input-method protocol, so it's part of the work needed to get #892 done.

@dcz-purism

This comment has been minimized.

Contributor

dcz-purism commented May 27, 2018

Added list of manager resources and keyboards, renamed public interface to include _unstable_v1.

if (!context) {
goto context_fail;
}
void *data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);

This comment has been minimized.

@emersion

emersion May 27, 2018

Member

In case of success, when is this unmapped?

};
struct wlr_virtual_keyboard_manager_unstable_v1*
wlr_virtual_keyboard_manager_unstable_v1_create(

This comment has been minimized.

@emersion

emersion May 27, 2018

Member

We currently name unstable protocols without "unstable" in the symbols, just with _v1.

We should probably change that to add a z prefix or something, but that's unrelated to this PR.

@dcz-purism

This comment has been minimized.

Contributor

dcz-purism commented May 29, 2018

Removed "unstable" and fixed unmapping.

@emersion

LGTM

@emersion emersion merged commit e1f5653 into swaywm:master May 29, 2018

1 check passed

builds.sr.ht builds.sr.ht job completed successfully
Details
@emersion

This comment has been minimized.

Member

emersion commented May 29, 2018

Thanks!

martinetd added a commit to martinetd/wlroots that referenced this pull request Jun 28, 2018

wlr_idle_inhibit_v1: cleanup destroy handlers
 - Rename handlers to <type>_handle_resource_destroy and
<type>_handle_destroy to be coherent
 - Make sure we never destroy wl_resources when we shouldn't

Updates swaywm#999

martinetd added a commit to martinetd/wlroots that referenced this pull request Jun 28, 2018

wlr_idle_inhibit_v1: cleanup destroy handlers
 - Rename handlers to <type>_handle_resource_destroy and
<type>_handle_destroy to be coherent
 - Make sure we never destroy wl_resources when we shouldn't

Updates swaywm#999
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment