commit 0a3e6590c3d40986becce48f0e35decb9d76ba07
parent 20cad8575a6b608caa15c6d3005a958c2810b974
Author: Nihal Jere <nihal@nihaljere.xyz>
Date: Tue, 15 Jun 2021 15:44:57 -0500
change input method/text input
now that compositor manages the launching and killing of input methods.
the hint and purpose text_input parameters are used to control what
type of input is launched.
Diffstat:
4 files changed, 90 insertions(+), 38 deletions(-)
diff --git a/libswc/input_method.c b/libswc/input_method.c
@@ -1,3 +1,7 @@
+#include <assert.h>
+#include <signal.h>
+#include <unistd.h>
+
#include "internal.h"
#include "seat.h"
#include "input_method.h"
@@ -9,13 +13,14 @@
#include <text-input-unstable-v3-server-protocol.h>
#include <wayland-server.h>
+static pid_t impid;
+
static void
commit_string(struct wl_client *client, struct wl_resource *resource, const char *text)
{
struct text_input *ti = text_input_get_enabled();
if (!ti)
return;
- DEBUG("IM COMMIT_STRING\n");
zwp_text_input_v3_send_commit_string(ti->resource, text);
}
@@ -26,7 +31,6 @@ set_preedit_string(struct wl_client *client, struct wl_resource *resource, const
struct text_input *ti = text_input_get_enabled();
if (!ti)
return;
- DEBUG("IM PREEDIT\n");
zwp_text_input_v3_send_preedit_string(ti->resource, text, cursor_begin, cursor_end);
}
@@ -37,7 +41,6 @@ delete_surrounding_text(struct wl_client *client, struct wl_resource *resource,
struct text_input *ti = text_input_get_enabled();
if (!ti)
return;
- DEBUG("IM DELETE\n");
zwp_text_input_v3_send_delete_surrounding_text(ti->resource, before_length, after_length);
}
@@ -51,12 +54,8 @@ commit(struct wl_client *client, struct wl_resource *resource, uint32_t serial)
if (!ti)
return;
- DEBUG("IM COMMIT: %u, %u\n", im->serial, serial);
-
-/*
if (im->serial != serial)
return;
-*/
im->serial++;
zwp_text_input_v3_send_done(ti->resource, ti->serial);
@@ -99,6 +98,59 @@ static const struct zwp_input_method_v2_interface input_method_impl = {
.destroy = destroy
};
+static char *
+input_method_program(uint32_t hint, uint32_t purpose)
+{
+ switch (purpose) {
+ case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE:
+ return IM_PROG_PHONE;
+ case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TERMINAL:
+ return IM_PROG_TERMINAL;
+ }
+
+ return IM_PROG_DEFAULT;
+}
+
+bool
+input_method_launch(uint32_t hint, uint32_t purpose)
+{
+ pid_t pid;
+ char *prog = input_method_program(hint, purpose);
+ switch (pid = fork()) {
+ case 0:
+ if (execlp(prog, prog, NULL) == -1) {
+ ERROR("execlp failed for %s\n", prog);
+ exit(1);
+ }
+ break;
+ case -1:
+ return false;
+ default:
+ impid = pid;
+ }
+
+ return true;
+}
+
+void
+input_method_kill()
+{
+ if (impid > 0)
+ kill(impid, SIGTERM);
+
+ impid = 0;
+}
+
+static void
+input_method_init(struct wl_resource *im)
+{
+ struct text_input_manager *tim = wl_global_get_user_data(swc.text_input_manager);
+ zwp_input_method_v2_send_activate(im);
+ assert(tim->enabled);
+ zwp_input_method_v2_send_content_type(im, tim->enabled->hint, tim->enabled->purpose);
+ zwp_input_method_v2_send_done(im);
+}
+
void
get_input_method(struct wl_client *client, struct wl_resource *manager, struct wl_resource *seat, uint32_t id)
{
@@ -127,6 +179,7 @@ get_input_method(struct wl_client *client, struct wl_resource *manager, struct w
}
wl_resource_set_implementation(input_method, &input_method_impl, swc.seat->input_method, &imremove);
+ input_method_init(input_method);
swc.seat->input_method->resource = input_method;
}
diff --git a/libswc/input_method.h b/libswc/input_method.h
@@ -2,6 +2,10 @@ struct input_method {
struct wl_resource *resource;
uint32_t serial;
struct wl_client *client;
+ pid_t pid;
};
struct wl_global *input_method_manager_create(struct wl_display *display);
+void input_method_kill();
+bool input_method_launch(uint32_t hint, uint32_t purpose);
+
diff --git a/libswc/text_input.c b/libswc/text_input.c
@@ -1,3 +1,5 @@
+#include <assert.h>
+
#include "compositor.h"
#include "view.h"
#include "surface.h"
@@ -14,6 +16,7 @@
static void
destroy(struct wl_client *client, struct wl_resource *resource)
{
+ input_method_kill();
wl_resource_destroy(resource);
}
@@ -22,22 +25,14 @@ enable(struct wl_client *client, struct wl_resource *resource)
{
struct text_input_manager *tim = wl_global_get_user_data(swc.text_input_manager);
struct text_input *ti = wl_resource_get_user_data(resource);
- struct wl_resource *imresource;
if (tim->enabled && client != wl_resource_get_client(tim->enabled->resource))
return;
- /* TODO remove */
- if (!swc.seat->input_method)
- return;
-
- imresource = swc.seat->input_method->resource;
- if (!imresource)
- return;
+ assert(!swc.seat->input_method);
wl_list_remove(&ti->link);
tim->enabled = ti;
- zwp_input_method_v2_send_activate(swc.seat->input_method->resource);
}
static void
@@ -45,19 +40,15 @@ disable(struct wl_client *client, struct wl_resource *resource)
{
struct text_input_manager *tim = wl_global_get_user_data(swc.text_input_manager);
struct text_input *ti = wl_resource_get_user_data(resource);
- struct wl_resource *imresource;
-
- /* TODO remove */
- if (!swc.seat->input_method)
- return;
- imresource = swc.seat->input_method->resource;
- if (!imresource || ti != tim->enabled)
+ if (ti != tim->enabled)
return;
wl_list_insert(&tim->disabled, &ti->link);
tim->enabled = NULL;
zwp_input_method_v2_send_deactivate(swc.seat->input_method->resource);
+
+ input_method_kill();
}
static void
@@ -93,16 +84,13 @@ set_text_change_cause(struct wl_client *client, struct wl_resource *resource, ui
static void
set_content_type(struct wl_client *client, struct wl_resource *resource, uint32_t hint, uint32_t purpose)
{
- struct wl_resource *imresource;
- /* TODO remove */
- if (!swc.seat->input_method)
- return;
+ struct text_input *ti = wl_resource_get_user_data(resource);
- imresource = swc.seat->input_method->resource;
- if (!imresource)
+ if (!ti->initialized) {
+ ti->hint = hint;
+ ti->purpose = purpose;
return;
-
- zwp_input_method_v2_send_content_type(imresource, hint, purpose);
+ }
}
static void
@@ -114,20 +102,20 @@ set_cursor_rectangle(struct wl_client *client, struct wl_resource *resource, int
static void
commit(struct wl_client *client, struct wl_resource *resource)
{
+ struct text_input *ti = wl_resource_get_user_data(resource);
struct text_input_manager *tim = wl_global_get_user_data(swc.text_input_manager);
- struct wl_resource *imresource;
- /* TODO remove */
- if (!swc.seat->input_method)
- return;
if (tim->enabled)
tim->enabled->serial++;
- imresource = swc.seat->input_method->resource;
- if (!imresource)
+ if (!ti->initialized) {
+ input_method_launch(ti->hint, ti->purpose);
+ ti->initialized = true;
+ /* get_input_method takes care of send events to the input method on init */
return;
+ }
- zwp_input_method_v2_send_done(imresource);
+ zwp_input_method_v2_send_done(swc.seat->input_method->resource);
}
static const struct zwp_text_input_v3_interface text_input_impl = {
@@ -149,6 +137,7 @@ ti_remove_resource(struct wl_resource *resource)
if (ti == tim->enabled) {
tim->enabled = NULL;
+ input_method_kill();
free(ti);
return;
}
@@ -184,6 +173,9 @@ get_text_input(struct wl_client *client, struct wl_resource *manager, uint32_t i
text_input->resource = tiresource;
text_input->serial = 0;
+ text_input->hint = 0;
+ text_input->purpose = 0;
+ text_input->initialized = false;
wl_list_insert(&tim->disabled, &text_input->link);
wl_resource_set_implementation(tiresource, &text_input_impl, text_input, &ti_remove_resource);
}
diff --git a/libswc/text_input.h b/libswc/text_input.h
@@ -4,6 +4,9 @@ struct text_input {
struct wl_list link;
struct wl_resource *resource;
uint32_t serial;
+ uint32_t hint;
+ uint32_t purpose;
+ bool initialized;
};
struct text_input_manager {