[PATCH 1/3] text: add keyboard events
Philipp Brüschweiler
blei42 at gmail.com
Sun Jul 22 15:07:38 PDT 2012
* add request_keyboard so input methods can signal that they want
to receive keyboard events
* keyboard events are grabbed with wl_keyboard_grab and relayed
to the input method using the created wl_keyboard interface
---
protocol/text.xml | 5 +-
src/compositor.c | 2 +-
src/compositor.h | 5 +-
src/shell.c | 5 ++
src/text-backend.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++--
5 Dateien geändert, 143 Zeilen hinzugefügt(+), 6 Zeilen entfernt(-)
diff --git a/protocol/text.xml b/protocol/text.xml
index a14277a..42c8f35 100644
--- a/protocol/text.xml
+++ b/protocol/text.xml
@@ -1,5 +1,5 @@
<protocol name="text">
- <interface name="text_model" version="1">
+ <interface name="text_model" version="1">
<request name="set_surrounding_text">
<arg name="text" type="string"/>
</request>
@@ -48,5 +48,8 @@
<arg name="text" type="string"/>
<arg name="index" type="uint"/>
</request>
+ <request name="request_keyboard">
+ <arg name="keyboard" type="new_id" interface="wl_keyboard"/>
+ </request>
</interface>
</protocol>
diff --git a/src/compositor.c b/src/compositor.c
index 3f2828e..5cf6129 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -3172,7 +3172,7 @@ weston_compositor_init(struct weston_compositor *ec,
screenshooter_create(ec);
text_cursor_position_notifier_create(ec);
- input_method_create(ec);
+ ec->input_method = input_method_create(ec);
wl_data_device_manager_init(ec->wl_display);
diff --git a/src/compositor.h b/src/compositor.h
index 22c0174..5044e4e 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -292,6 +292,9 @@ struct weston_compositor {
/* There can be more than one, but not right now... */
struct weston_seat *seat;
+ struct input_method *input_method;
+ struct wl_listener input_method_keyboard_focus_listener;
+
struct weston_layer fade_layer;
struct weston_layer cursor_layer;
@@ -714,7 +717,7 @@ clipboard_create(struct weston_seat *seat);
void
text_cursor_position_notifier_create(struct weston_compositor *ec);
-void
+struct input_method *
input_method_create(struct weston_compositor *ec);
struct weston_process;
diff --git a/src/shell.c b/src/shell.c
index a9e4d4f..41ddfbf 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -3370,6 +3370,11 @@ shell_init(struct weston_compositor *ec)
wl_signal_add(&ec->seat->seat.pointer->focus_signal,
&shell->pointer_focus_listener);
+ if (ec->seat->seat.keyboard)
+ wl_signal_add(&ec->seat->seat.keyboard->focus_signal,
+ &ec->input_method_keyboard_focus_listener);
+
+
shell_add_bindings(ec, shell);
return 0;
diff --git a/src/text-backend.c b/src/text-backend.c
index 353a983..5b1b00d 100644
--- a/src/text-backend.c
+++ b/src/text-backend.c
@@ -24,6 +24,7 @@
#include "compositor.h"
#include "text-server-protocol.h"
+#include "log.h"
struct input_method;
@@ -33,10 +34,13 @@ struct text_model {
struct wl_list link;
struct input_method *input_method;
+ struct wl_keyboard_grab grab;
+ struct wl_surface *surface;
};
struct input_method {
struct wl_resource *input_method_binding;
+ struct wl_resource *keyboard_binding;
struct wl_global *input_method_global;
struct wl_global *text_model_manager_global;
struct wl_listener destroy_listener;
@@ -50,6 +54,12 @@ static void
deactivate_text_model(struct text_model *text_model)
{
struct weston_compositor *ec = text_model->input_method->ec;
+ struct wl_keyboard_grab *grab = &text_model->grab;
+
+ if (grab->keyboard && (grab->keyboard->grab == grab)) {
+ wl_keyboard_end_grab(grab->keyboard);
+ weston_log("end keyboard grab\n");
+ }
if (text_model->input_method->active_model == text_model) {
text_model->input_method->active_model = NULL;
@@ -70,6 +80,41 @@ destroy_text_model(struct wl_resource *resource)
}
static void
+text_model_key(struct wl_keyboard_grab *grab,
+ uint32_t time, uint32_t key, uint32_t state_w)
+{
+ struct text_model *text_model = container_of(grab, struct text_model, grab);
+ struct input_method *input_method = text_model->input_method;
+
+ uint32_t serial = wl_display_next_serial(input_method->ec->wl_display);
+ if (input_method->keyboard_binding) {
+ wl_keyboard_send_key(input_method->keyboard_binding,
+ serial, time, key, state_w);
+ }
+}
+
+static void
+text_model_modifier(struct wl_keyboard_grab *grab, uint32_t serial,
+ uint32_t mods_depressed, uint32_t mods_latched,
+ uint32_t mods_locked, uint32_t group)
+{
+ struct text_model *text_model = container_of(grab, struct text_model, grab);
+ struct input_method *input_method = text_model->input_method;
+
+ uint32_t new_serial = wl_display_next_serial(input_method->ec->wl_display);
+ if (input_method->keyboard_binding) {
+ wl_keyboard_send_modifiers(input_method->keyboard_binding,
+ new_serial, mods_depressed, mods_latched,
+ mods_locked, group);
+ }
+}
+
+static const struct wl_keyboard_grab_interface text_model_grab = {
+ text_model_key,
+ text_model_modifier,
+};
+
+static void
text_model_set_surrounding_text(struct wl_client *client,
struct wl_resource *resource,
const char *text)
@@ -93,6 +138,17 @@ text_model_activate(struct wl_client *client,
text_model->input_method->active_model = text_model;
wl_signal_emit(&ec->show_input_panel_signal, ec);
+
+ if (text_model->input_method->input_method_binding &&
+ text_model->input_method->keyboard_binding) {
+ struct wl_seat *seat = &text_model->input_method->ec->seat->seat;
+
+ if (seat->keyboard->grab != &seat->keyboard->default_grab) {
+ wl_keyboard_end_grab(seat->keyboard);
+ }
+ wl_keyboard_start_grab(seat->keyboard, &text_model->grab);
+ weston_log("start keyboard grab\n");
+ }
}
static void
@@ -164,6 +220,9 @@ static void text_model_manager_create_text_model(struct wl_client *client,
text_model->resource.data = text_model;
text_model->input_method = input_method;
+ text_model->surface = container_of(surface, struct wl_surface, resource);
+
+ text_model->grab.interface = &text_model_grab;
wl_client_add_resource(client, &text_model->resource);
@@ -202,8 +261,46 @@ input_method_commit_string(struct wl_client *client,
}
}
+static void
+unbind_keyboard_binding(struct wl_resource *resource)
+{
+ struct input_method *input_method = resource->data;
+
+ input_method->keyboard_binding = NULL;
+}
+
+static void
+input_method_request_keyboard(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t keyboard_id)
+{
+ struct input_method *input_method = resource->data;
+
+ if (input_method->keyboard_binding) {
+ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "keyboard already bound");
+ return;
+ }
+
+ input_method->keyboard_binding =
+ wl_client_add_object(client, &wl_keyboard_interface,
+ NULL, keyboard_id, input_method);
+
+ if (input_method->keyboard_binding == NULL)
+ return;
+
+ input_method->keyboard_binding->destroy = unbind_keyboard_binding;
+
+ struct weston_seat *seat = input_method->ec->seat;
+ wl_keyboard_send_keymap(input_method->keyboard_binding,
+ WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
+ seat->xkb_info.keymap_fd,
+ seat->xkb_info.keymap_size);
+}
+
static const struct input_method_interface input_method_implementation = {
- input_method_commit_string
+ input_method_commit_string,
+ input_method_request_keyboard
};
static void
@@ -213,6 +310,10 @@ unbind_input_method(struct wl_resource *resource)
input_method->input_method_binding = NULL;
free(resource);
+
+ if (input_method->keyboard_binding) {
+ wl_resource_destroy(input_method->keyboard_binding);
+ }
}
static void
@@ -252,7 +353,26 @@ input_method_notifier_destroy(struct wl_listener *listener, void *data)
free(input_method);
}
-void
+static void
+handle_keyboard_focus(struct wl_listener *listener, void *data)
+{
+ struct wl_pointer *pointer = data;
+ struct weston_surface *surface =
+ (struct weston_surface *) pointer->focus;
+
+ struct weston_compositor *compositor =
+ container_of(listener, struct weston_compositor,
+ input_method_keyboard_focus_listener);
+
+ struct text_model *active_model = compositor->input_method->active_model;
+
+ if (active_model &&
+ (!surface || active_model->surface != &surface->surface)) {
+ deactivate_text_model(active_model);
+ }
+}
+
+WL_EXPORT struct input_method *
input_method_create(struct weston_compositor *ec)
{
struct input_method *input_method;
@@ -260,7 +380,6 @@ input_method_create(struct weston_compositor *ec)
input_method = calloc(1, sizeof *input_method);
input_method->ec = ec;
- input_method->active_model = NULL;
wl_list_init(&input_method->models);
@@ -276,4 +395,11 @@ input_method_create(struct weston_compositor *ec)
input_method->destroy_listener.notify = input_method_notifier_destroy;
wl_signal_add(&ec->destroy_signal, &input_method->destroy_listener);
+
+ /* Initialize the listener. It will be added by the shell when the
+ * seat is initialized.
+ */
+ ec->input_method_keyboard_focus_listener.notify = handle_keyboard_focus;
+
+ return input_method;
}
--
1.7.11.2
More information about the wayland-devel
mailing list