diff options
-rw-r--r-- | meson.build | 1 | ||||
-rw-r--r-- | src/desktop.c | 3 | ||||
-rw-r--r-- | src/input.c | 245 | ||||
-rw-r--r-- | src/ivi-compositor.h | 9 | ||||
-rw-r--r-- | src/main.c | 10 |
5 files changed, 267 insertions, 1 deletions
diff --git a/meson.build b/meson.build index 6809579..ab4f086 100644 --- a/meson.build +++ b/meson.build @@ -144,6 +144,7 @@ srcs_agl_compositor = [ 'src/policy.c', 'src/shell.c', 'src/screenshooter.c', + 'src/input.c', 'shared/option-parser.c', 'shared/os-compatibility.c', agl_shell_server_protocol_h, diff --git a/src/desktop.c b/src/desktop.c index 0fca2fd..58d2887 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -99,6 +99,9 @@ desktop_surface_added(struct weston_desktop_surface *dsurface, void *userdata) if ((active_output = ivi_layout_find_with_app_id(app_id, ivi))) ivi_set_pending_desktop_surface_remote(active_output, app_id); + /* reset any caps to make sure we apply the new caps */ + ivi_seat_reset_caps_sent(ivi); + if (ivi->shell_client.ready) { ivi_check_pending_desktop_surface(surface); weston_log("Added surface %p, app_id %s, role %s\n", surface, diff --git a/src/input.c b/src/input.c new file mode 100644 index 0000000..64d23ef --- /dev/null +++ b/src/input.c @@ -0,0 +1,245 @@ +/* + * Copyright © 2020 Collabora, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include <assert.h> +#include <linux/input.h> +#include <stdbool.h> +#include <stdint.h> +#include <string.h> + +#include "ivi-compositor.h" +#include "shared/helpers.h" + +struct ivi_shell_seat { + struct weston_seat *seat; + struct weston_surface *focused_surface; + + bool hide_cursor; + bool new_caps_sent; + + struct wl_listener seat_destroy_listener; + struct wl_listener caps_changed_listener; + struct wl_listener keyboard_focus_listener; + struct wl_listener pointer_focus_listener; +}; + +static struct ivi_surface * +get_ivi_shell_surface(struct weston_surface *surface) +{ + struct weston_desktop_surface *desktop_surface = + weston_surface_get_desktop_surface(surface); + + if (desktop_surface) + return weston_desktop_surface_get_user_data(desktop_surface); + + return NULL; +} + +static void +ivi_shell_seat_handle_destroy(struct wl_listener *listener, void *data) +{ + struct ivi_shell_seat *shseat = + container_of(listener, + struct ivi_shell_seat, seat_destroy_listener); + + wl_list_remove(&shseat->keyboard_focus_listener.link); + wl_list_remove(&shseat->caps_changed_listener.link); + wl_list_remove(&shseat->pointer_focus_listener.link); + wl_list_remove(&shseat->seat_destroy_listener.link); + + free(shseat); +} + +static struct ivi_shell_seat * +get_ivi_shell_seat(struct weston_seat *seat) +{ + struct wl_listener *listener; + + listener = wl_signal_get(&seat->destroy_signal, + ivi_shell_seat_handle_destroy); + assert(listener != NULL); + + return container_of(listener, + struct ivi_shell_seat, seat_destroy_listener); +} + + +static void +ivi_shell_seat_handle_keyboard_focus(struct wl_listener *listener, void *data) +{ + struct weston_keyboard *keyboard = data; + struct ivi_shell_seat *shseat = get_ivi_shell_seat(keyboard->seat); + + if (shseat->focused_surface) { + struct ivi_surface *surf = + get_ivi_shell_surface(shseat->focused_surface); + if (surf && --surf->focus_count == 0) + weston_desktop_surface_set_activated(surf->dsurface, false); + } + + shseat->focused_surface = weston_surface_get_main_surface(keyboard->focus); + + if (shseat->focused_surface) { + struct ivi_surface *surf = + get_ivi_shell_surface(shseat->focused_surface); + if (surf && surf->focus_count++ == 0) + weston_desktop_surface_set_activated(surf->dsurface, true); + } +} + +static void +ivi_shell_seat_handle_pointer_focus(struct wl_listener *listener, void *data) +{ + struct weston_pointer *pointer = data; + struct ivi_shell_seat *shseat = get_ivi_shell_seat(pointer->seat); + struct wl_resource *resource; + int resources = 0; + + /* FIXME: should probably query it and not assume all caps */ + uint32_t caps = (WL_SEAT_CAPABILITY_POINTER | + WL_SEAT_CAPABILITY_TOUCH | + WL_SEAT_CAPABILITY_KEYBOARD); + + wl_resource_for_each(resource, &pointer->seat->base_resource_list) + resources++; + + /* remove the POINTER capability such that the client will not install + * a cursor surface */ + if (shseat->hide_cursor && !shseat->new_caps_sent && resources) { + caps &= ~WL_SEAT_CAPABILITY_POINTER; + wl_resource_for_each(resource, &pointer->seat->base_resource_list) { + wl_seat_send_capabilities(resource, caps); + } + shseat->new_caps_sent = true; + } +} + +static void +ivi_shell_seat_handle_caps_changed(struct wl_listener *listener, void *data) +{ + struct weston_keyboard *keyboard; + struct weston_pointer *pointer; + struct ivi_shell_seat *shseat; + + shseat = container_of(listener, struct ivi_shell_seat, + caps_changed_listener); + keyboard = weston_seat_get_keyboard(shseat->seat); + pointer = weston_seat_get_pointer(shseat->seat); + + if (pointer && wl_list_empty(&shseat->pointer_focus_listener.link)) { + wl_signal_add(&pointer->focus_signal, + &shseat->pointer_focus_listener); + } else { + wl_list_remove(&shseat->pointer_focus_listener.link); + wl_list_init(&shseat->pointer_focus_listener.link); + } + + if (keyboard && + wl_list_empty(&shseat->keyboard_focus_listener.link)) { + wl_signal_add(&keyboard->focus_signal, + &shseat->keyboard_focus_listener); + } else if (!keyboard) { + wl_list_remove(&shseat->keyboard_focus_listener.link); + wl_list_init(&shseat->keyboard_focus_listener.link); + } +} + +static struct ivi_shell_seat * +ivi_shell_seat_create(struct weston_seat *seat, bool hide_cursor) +{ + struct ivi_shell_seat *shseat; + + shseat = zalloc(sizeof(*shseat)); + if (!shseat) { + weston_log("no memory to allocate shell seat\n"); + return NULL; + } + + shseat->seat = seat; + shseat->hide_cursor = hide_cursor; + shseat->new_caps_sent = false; + + shseat->seat_destroy_listener.notify = ivi_shell_seat_handle_destroy; + wl_signal_add(&seat->destroy_signal, &shseat->seat_destroy_listener); + + shseat->keyboard_focus_listener.notify = + ivi_shell_seat_handle_keyboard_focus; + wl_list_init(&shseat->keyboard_focus_listener.link); + + shseat->pointer_focus_listener.notify = + ivi_shell_seat_handle_pointer_focus; + wl_list_init(&shseat->pointer_focus_listener.link); + + shseat->caps_changed_listener.notify = + ivi_shell_seat_handle_caps_changed; + wl_signal_add(&seat->updated_caps_signal, &shseat->caps_changed_listener); + + ivi_shell_seat_handle_caps_changed(&shseat->caps_changed_listener, NULL); + + return shseat; +} + + +static void +ivi_shell_handle_seat_created(struct wl_listener *listener, void *data) +{ + struct weston_seat *seat = data; + struct ivi_compositor *ivi = + container_of(listener, struct ivi_compositor, seat_created_listener); + + weston_log("Cursor is %s\n", ivi->hide_cursor ? "set" : "not set"); + ivi_shell_seat_create(seat, ivi->hide_cursor); +} + +/* + * useful to reset the fact that 'new' capabilities have seent + */ +void +ivi_seat_reset_caps_sent(struct ivi_compositor *ivi) +{ + struct weston_compositor *ec = ivi->compositor; + struct weston_seat *seat; + + wl_list_for_each(seat, &ec->seat_list, link) { + struct ivi_shell_seat *ivi_seat = get_ivi_shell_seat(seat); + ivi_seat->new_caps_sent = false; + } +} + +void +ivi_seat_init(struct ivi_compositor *ivi) +{ + struct weston_compositor *ec = ivi->compositor; + struct weston_seat *seat; + + wl_list_for_each(seat, &ec->seat_list, link) { + weston_log("Seat %p, cursor is %s\n", seat, ivi->hide_cursor ? + "set" : "not set"); + ivi_shell_seat_create(seat, ivi->hide_cursor); + } + + ivi->seat_created_listener.notify = ivi_shell_handle_seat_created; + wl_signal_add(&ec->seat_created_signal, &ivi->seat_created_listener); +} diff --git a/src/ivi-compositor.h b/src/ivi-compositor.h index 4506a5a..4708b5d 100644 --- a/src/ivi-compositor.h +++ b/src/ivi-compositor.h @@ -53,6 +53,7 @@ struct ivi_compositor { struct wl_listener heads_changed; bool init_failed; + bool hide_cursor; /* * Options parsed from command line arugments. @@ -85,6 +86,7 @@ struct ivi_compositor { struct wl_list surfaces; /* ivi_surface.link */ struct weston_desktop *desktop; + struct wl_listener seat_created_listener; struct ivi_policy *policy; struct wl_list pending_surfaces; @@ -233,6 +235,7 @@ struct ivi_surface { struct weston_view *view; struct wl_list link; + int focus_count; struct { enum ivi_surface_flags flags; @@ -380,4 +383,10 @@ shell_advertise_app_state(struct ivi_compositor *ivi, const char *app_id, void ivi_screenshooter_create(struct ivi_compositor *ivi); +void +ivi_seat_init(struct ivi_compositor *ivi); + +void +ivi_seat_reset_caps_sent(struct ivi_compositor *ivi); + #endif @@ -1346,7 +1346,7 @@ usage(int error_code) " --log=FILE\t\tLog to the given file\n" " -c, --config=FILE\tConfig file to load, defaults to agl-compositor.ini\n" " --no-config\t\tDo not read agl-compositor.ini\n" - " --debug\t\tEnable debug extension\n" + " --debug\t\tEnable debug extension(s)\n" " -h, --help\t\tThis help message\n" "\n"); exit(error_code); @@ -1366,6 +1366,7 @@ int main(int argc, char *argv[]) int help = 0; int version = 0; int no_config = 0; + int debug = 0; char *config_file = NULL; struct weston_log_context *log_ctx = NULL; struct weston_log_subscriber *logger; @@ -1378,6 +1379,7 @@ int main(int argc, char *argv[]) { WESTON_OPTION_BOOLEAN, "help", 'h', &help }, { WESTON_OPTION_BOOLEAN, "version", 0, &version }, { WESTON_OPTION_BOOLEAN, "no-config", 0, &no_config }, + { WESTON_OPTION_BOOLEAN, "debug", 0, &debug }, { WESTON_OPTION_STRING, "config", 'c', &config_file }, }; @@ -1390,6 +1392,7 @@ int main(int argc, char *argv[]) wl_list_init(&ivi.remote_pending_apps); wl_list_init(&ivi.desktop_clients); + /* Prevent any clients we spawn getting our stdin */ os_fd_set_cloexec(STDIN_FILENO); @@ -1403,6 +1406,9 @@ int main(int argc, char *argv[]) return EXIT_SUCCESS; } + if (debug) + ivi.hide_cursor = true; + log_ctx = weston_log_ctx_compositor_create(); if (!log_ctx) { fprintf(stderr, "Failed to initialize weston debug framework.\n"); @@ -1469,6 +1475,8 @@ int main(int argc, char *argv[]) if (ivi_desktop_init(&ivi) < 0) goto error_compositor; + ivi_seat_init(&ivi); + if (ivi_policy_init(&ivi) < 0) goto error_compositor; |