diff options
author | Nobuhiko Tanibata <nobuhiko_tanibata@xddp.denso.co.jp> | 2015-12-04 21:30:00 +0900 |
---|---|---|
committer | Nobuhiko Tanibata <nobuhiko_tanibata@xddp.denso.co.jp> | 2015-12-05 00:07:38 +0900 |
commit | 4cb5903c1bd74ca02a9b7f9985ee7a0aae095dba (patch) | |
tree | ed19321c38fbc00f64cf782fcd2a0cf37ea27290 /ivi-input-modules | |
parent | d983ae0193d993210c1a6daa8c93dcd0a112fbc3 (diff) | |
download | wayland-ivi-extension-4cb5903c1bd74ca02a9b7f9985ee7a0aae095dba.tar.gz |
ivi-input-controller: restructure directory to build and a way to specify the shared library.
ivi-input-controller shall work with ivi-controller.so not solely.
So the patch proposes a way to specify it as a ivi-input-module in
weston.ini. The shared library, ivi-input-controller.so, is loaded by
ivi-controller.so.
Signed-off-by: Nobuhiko Tanibata <ntanibata@jp.adit-jv.com>
Diffstat (limited to 'ivi-input-modules')
3 files changed, 1138 insertions, 0 deletions
diff --git a/ivi-input-modules/ivi-input-controller/CMakeLists.txt b/ivi-input-modules/ivi-input-controller/CMakeLists.txt new file mode 100644 index 0000000..c5a32c2 --- /dev/null +++ b/ivi-input-modules/ivi-input-controller/CMakeLists.txt @@ -0,0 +1,80 @@ +############################################################################ +# +# Copyright 2015 Codethink Ltd +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +############################################################################ + +cmake_minimum_required (VERSION 2.6) + +project(ivi-input-controller) + +find_package(PkgConfig REQUIRED) +pkg_check_modules(WAYLAND_SERVER wayland-server REQUIRED) +pkg_check_modules(WESTON weston REQUIRED) +pkg_check_modules(PIXMAN pixman-1 REQUIRED) + +GET_TARGET_PROPERTY(IVI_EXTENSION_INCLUDE_DIRS ivi-extension-protocol INCLUDE_DIRECTORIES) +GET_TARGET_PROPERTY(ILM_COMMON_INCLUDE_DIRS ilmCommon INCLUDE_DIRECTORIES) +GET_TARGET_PROPERTY(IVI_CONTROLLER_INCLUDE_DIRS ivi-controller INCLUDE_DIRECTORIES) + +include_directories( + include + ${IVI_EXTENSION_INCLUDE_DIRS} + ${ILM_COMMON_INCLUDE_DIRS} + ${IVI_CONTROLLER_INCLUDE_DIRS} + ${WAYLAND_SERVER_INCLUDE_DIRS} + ${WESTON_INCLUDE_DIRS} + ${WESTON_INCLUDE_DIRS}/weston + ${PIXMAN_INCLUDE_DIRS} +) + +link_directories( + ${WAYLAND_SERVER_LIBRARY_DIRS} + ${WESTON_LIBRARY_DIRS} + ${WESTON_LIBDIR}/weston + ${PIXMAN_LIBRARY_DIRS} +) + + +add_library(${PROJECT_NAME} MODULE + src/ivi-input-controller.c +) + +set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "") + +add_dependencies(${PROJECT_NAME} + ivi-extension-protocol + ilmCommon + ${WAYLAND_SERVER_LIBRARIES} + ${WESTON_LIBRARIES} + ${PIXMAN_LIBRARIES} +) + +set(LIBS + ${LIBS} + ivi-extension-protocol + ${WAYLAND_SERVER_LIBRARIES} + ${WESTON_LIBRARIES} +) + +set(CMAKE_C_LDFLAGS "-module -avoid-version") + +target_link_libraries(${PROJECT_NAME} ${LIBS}) + +install ( + TARGETS ${PROJECT_NAME} + LIBRARY DESTINATION lib/weston +) diff --git a/ivi-input-modules/ivi-input-controller/README b/ivi-input-modules/ivi-input-controller/README new file mode 100644 index 0000000..8a7c5ad --- /dev/null +++ b/ivi-input-modules/ivi-input-controller/README @@ -0,0 +1,2 @@ +This directory contains the ivi-input-controller module. +To use this, add it to the "ivi-input-module" entry in your weston.ini. diff --git a/ivi-input-modules/ivi-input-controller/src/ivi-input-controller.c b/ivi-input-modules/ivi-input-controller/src/ivi-input-controller.c new file mode 100644 index 0000000..45f15fd --- /dev/null +++ b/ivi-input-modules/ivi-input-controller/src/ivi-input-controller.c @@ -0,0 +1,1056 @@ +/* + * Copyright 2015 Codethink Ltd + * Copyright (C) 2015 Advanced Driver Information Technology Joint Venture GmbH + * + * 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. + */ + +#include <stdlib.h> +#include <string.h> + +#include <weston/compositor.h> +#include "ilm_types.h" + +#include "ivi-input-server-protocol.h" +#include "ivi-controller-interface.h" + +struct seat_ctx { + struct input_context *input_ctx; + struct weston_keyboard_grab keyboard_grab; + struct weston_pointer_grab pointer_grab; + struct weston_touch_grab touch_grab; + struct wl_listener updated_caps_listener; + struct wl_listener destroy_listener; +}; + +struct surface_ctx { + struct wl_list link; + ilmInputDevice focus; + struct ivi_layout_surface *layout_surface; + struct wl_array accepted_devices; + struct input_context *input_context; +}; + +struct input_controller { + struct wl_list link; + struct wl_resource *resource; + struct wl_client *client; + uint32_t id; + struct input_context *input_context; +}; + +struct input_context { + struct wl_listener seat_create_listener; + struct wl_list controller_list; + struct wl_list surface_list; + struct weston_compositor *compositor; + const struct ivi_controller_interface *ivi_controller_interface; +}; + +static int +get_accepted_seat(struct surface_ctx *surface, const char *seat) +{ + int i; + char **arr = surface->accepted_devices.data; + for (i = 0; i < (surface->accepted_devices.size / sizeof(char**)); i++) { + if (strcmp(arr[i], seat) == 0) + return i; + } + return -1; +} + +static int +add_accepted_seat(struct surface_ctx *surface, const char *seat) +{ + char **added_entry; + const struct ivi_controller_interface *interface = + surface->input_context->ivi_controller_interface; + if (get_accepted_seat(surface, seat) >= 0) { + weston_log("%s: Warning: seat '%s' is already accepted by surface %d\n", + __FUNCTION__, seat, + interface->get_id_of_surface(surface->layout_surface)); + return 1; + } + added_entry = wl_array_add(&surface->accepted_devices, sizeof *added_entry); + if (added_entry == NULL) { + weston_log("%s: Failed to expand accepted devices array for " + "surface %d\n", __FUNCTION__, + interface->get_id_of_surface(surface->layout_surface)); + return 0; + } + *added_entry = strdup(seat); + if (*added_entry == NULL) { + weston_log("%s: Failed to duplicate seat name '%s'\n", + __FUNCTION__, seat); + return 0; + } + return 1; +} + +static int +remove_accepted_seat(struct surface_ctx *surface, const char *seat) +{ + int seat_index = get_accepted_seat(surface, seat); + int i; + struct wl_array *array = &surface->accepted_devices; + char **data = array->data; + const struct ivi_controller_interface *interface = + surface->input_context->ivi_controller_interface; + if (seat_index < 0) { + weston_log("%s: Warning: seat '%s' not found for surface %d\n", + __FUNCTION__, seat, + interface->get_id_of_surface(surface->layout_surface)); + return 0; + } + free(data[seat_index]); + for (i = seat_index + 1; i < array->size / sizeof(char **); i++) + data[i - 1] = data[i]; + array->size-= sizeof(char**); + + return 1; +} + +static void +send_input_acceptance(struct input_context *ctx, uint32_t surface_id, const char *seat, int32_t accepted) +{ + struct input_controller *controller; + wl_list_for_each(controller, &ctx->controller_list, link) { + ivi_input_send_input_acceptance(controller->resource, + surface_id, seat, + accepted); + } +} + +static void +send_input_focus(struct input_context *ctx, t_ilm_surface surface_id, + ilmInputDevice device, t_ilm_bool enabled) +{ + struct input_controller *controller; + wl_list_for_each(controller, &ctx->controller_list, link) { + ivi_input_send_input_focus(controller->resource, surface_id, + device, enabled); + } +} + +static void +set_weston_focus(struct input_context *ctx, struct surface_ctx *surface_ctx, + ilmInputDevice focus, struct weston_seat *seat, t_ilm_bool enabled) +{ + struct weston_surface *w_surface; + struct weston_view *view; + struct wl_resource *resource; + struct wl_client *surface_client; + uint32_t serial; + wl_fixed_t x, y; + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); + const struct ivi_controller_interface *interface = + ctx->ivi_controller_interface; + + /* Assume one view per surface */ + w_surface = interface->surface_get_weston_surface(surface_ctx->layout_surface); + view = wl_container_of(w_surface->views.next, view, surface_link); + if ((focus & ILM_INPUT_DEVICE_POINTER) && + (pointer != NULL)){ + if ( (view != NULL) && enabled) { + weston_view_to_global_fixed(view, wl_fixed_from_int(0), + wl_fixed_from_int(0), &x, &y); + // move pointer to local (0,0) of the view + weston_pointer_move(pointer, x, y); + weston_pointer_set_focus(pointer, view, + wl_fixed_from_int(0), wl_fixed_from_int(0)); + } else if (pointer->focus == view){ + weston_pointer_set_focus(pointer, NULL, + wl_fixed_from_int(0), wl_fixed_from_int(0)); + } + } + + if ((focus & ILM_INPUT_DEVICE_KEYBOARD) && + (keyboard != NULL)) { + if (w_surface) { + surface_client = wl_resource_get_client(w_surface->resource); + serial = wl_display_next_serial(ctx->compositor->wl_display); + wl_resource_for_each(resource, &keyboard->resource_list) { + if (wl_resource_get_client(resource) != surface_client) + continue; + + if (!enabled) { + wl_keyboard_send_leave(resource, serial, + w_surface->resource); + } else { + wl_keyboard_send_enter(resource, serial, w_surface->resource, + &keyboard->keys); + } + } + } + } +} + +static void +keyboard_grab_key(struct weston_keyboard_grab *grab, uint32_t time, + uint32_t key, uint32_t state) +{ + struct seat_ctx *seat_ctx = wl_container_of(grab, seat_ctx, keyboard_grab); + struct surface_ctx *surf_ctx; + struct wl_display *display = grab->keyboard->seat->compositor->wl_display; + const struct ivi_controller_interface *interface = + seat_ctx->input_ctx->ivi_controller_interface; + + wl_list_for_each(surf_ctx, &seat_ctx->input_ctx->surface_list, link) { + struct weston_surface *surface; + struct wl_resource *resource; + struct wl_client *surface_client; + uint32_t serial; + if (!(surf_ctx->focus & ILM_INPUT_DEVICE_KEYBOARD)) + continue; + + if (get_accepted_seat(surf_ctx, grab->keyboard->seat->seat_name) < 0) + continue; + + surface = interface->surface_get_weston_surface(surf_ctx->layout_surface); + surface_client = wl_resource_get_client(surface->resource); + serial = wl_display_next_serial(display); + + wl_resource_for_each(resource, &grab->keyboard->resource_list) { + if (wl_resource_get_client(resource) != surface_client) + continue; + + wl_keyboard_send_key(resource, serial, time, key, state); + } + + wl_resource_for_each(resource, &grab->keyboard->focus_resource_list) { + if (wl_resource_get_client(resource) != surface_client) + continue; + + wl_keyboard_send_key(resource, serial, time, key, state); + } + } +} + +static void +keyboard_grab_modifiers(struct weston_keyboard_grab *grab, uint32_t serial, + uint32_t mods_depressed, uint32_t mods_latched, + uint32_t mods_locked, uint32_t group) +{ + struct seat_ctx *seat_ctx = wl_container_of(grab, seat_ctx, keyboard_grab); + struct surface_ctx *surf_ctx; + struct wl_display *display = grab->keyboard->seat->compositor->wl_display; + const struct ivi_controller_interface *interface = + seat_ctx->input_ctx->ivi_controller_interface; + + wl_list_for_each(surf_ctx, &seat_ctx->input_ctx->surface_list, link) { + struct weston_surface *surface; + struct wl_resource *resource; + struct wl_client *surface_client; + uint32_t serial; + + /* Keyboard modifiers go to surfaces with pointer focus as well */ + if (!(surf_ctx->focus + & (ILM_INPUT_DEVICE_KEYBOARD | ILM_INPUT_DEVICE_POINTER))) + continue; + + if (get_accepted_seat(surf_ctx, grab->keyboard->seat->seat_name) < 0) + continue; + + surface = interface->surface_get_weston_surface(surf_ctx->layout_surface); + surface_client = wl_resource_get_client(surface->resource); + serial = wl_display_next_serial(display); + + wl_resource_for_each(resource, &grab->keyboard->resource_list) { + if (wl_resource_get_client(resource) != surface_client) + continue; + + wl_keyboard_send_modifiers(resource, serial, mods_depressed, + mods_latched, mods_locked, group); + } + + wl_resource_for_each(resource, &grab->keyboard->focus_resource_list) { + if (wl_resource_get_client(resource) != surface_client) + continue; + + wl_keyboard_send_modifiers(resource, serial, mods_depressed, + mods_latched, mods_locked, group); + } + } +} + +static void +keyboard_grab_cancel(struct weston_keyboard_grab *grab) +{ +} + +static struct weston_keyboard_grab_interface keyboard_grab_interface = { + keyboard_grab_key, + keyboard_grab_modifiers, + keyboard_grab_cancel +}; + +static void +pointer_grab_focus(struct weston_pointer_grab *grab) +{ +} + +static void +pointer_grab_motion(struct weston_pointer_grab *grab, uint32_t time, + wl_fixed_t x, wl_fixed_t y) +{ + struct seat_ctx *seat = wl_container_of(grab, seat, pointer_grab); + struct surface_ctx *surf_ctx; + const struct ivi_controller_interface *interface = + seat->input_ctx->ivi_controller_interface; + + weston_pointer_move(grab->pointer, x, y); + + /* Get coordinates relative to the surface the pointer is in. + * This might cause weirdness if there are multiple surfaces + * that are accepted by this pointer's seat and have focus */ + + /* For each surface_ctx, check for focus and send */ + wl_list_for_each(surf_ctx, &seat->input_ctx->surface_list, link) { + struct weston_surface *surf; + struct wl_resource *resource; + struct wl_client *surface_client; + struct weston_view *view; + wl_fixed_t sx, sy; + + if (!(surf_ctx->focus & ILM_INPUT_DEVICE_POINTER)) + continue; + + if (get_accepted_seat(surf_ctx, grab->pointer->seat->seat_name) < 0) + continue; + + /* Assume one view per surface */ + surf = interface->surface_get_weston_surface(surf_ctx->layout_surface); + view = wl_container_of(surf->views.next, view, surface_link); + + if (view == grab->pointer->focus) { + + /* Do not send motion events for coordinates outside the surface */ + weston_view_from_global_fixed(view, x, y, &sx, &sy); + if ((!pixman_region32_contains_point(&surf->input, wl_fixed_to_int(sx), + wl_fixed_to_int(sy), NULL)) + && (grab->pointer->button_count == 0)) + continue; + + surface_client = wl_resource_get_client(surf->resource); + + wl_resource_for_each(resource, &grab->pointer->focus_resource_list) { + if (wl_resource_get_client(resource) != surface_client) + continue; + + wl_pointer_send_motion(resource, time, sx, sy); + } + return; + } + } +} + +static void +pointer_grab_button(struct weston_pointer_grab *grab, uint32_t time, + uint32_t button, uint32_t state) +{ + struct seat_ctx *seat = wl_container_of(grab, seat, pointer_grab); + struct weston_pointer *pointer = grab->pointer; + struct weston_compositor *compositor = pointer->seat->compositor; + struct wl_display *display = compositor->wl_display; + struct surface_ctx *surf_ctx; + wl_fixed_t sx, sy; + struct weston_view *picked_view, *w_view, *old_focus; + struct weston_surface *w_surf; + struct wl_resource *resource; + struct wl_client *surface_client; + uint32_t serial; + const struct ivi_controller_interface *interface = + seat->input_ctx->ivi_controller_interface; + + picked_view = weston_compositor_pick_view(compositor, pointer->x, pointer->y, + &sx, &sy); + if (picked_view == NULL) + return; + + /* If a button press, set pointer focus to this surface */ + if ((grab->pointer->focus != picked_view) && + (state == WL_POINTER_BUTTON_STATE_PRESSED)){ + old_focus = grab->pointer->focus; + /* search for the picked view in layout surfaces */ + wl_list_for_each(surf_ctx, &seat->input_ctx->surface_list, link) { + w_surf = interface->surface_get_weston_surface(surf_ctx->layout_surface); + w_view = wl_container_of(w_surf->views.next, w_view, surface_link); + + if (get_accepted_seat(surf_ctx, grab->pointer->seat->seat_name) < 0) + continue; + + if (picked_view->surface == w_surf) { + /* Correct layout surface is found*/ + surf_ctx->focus |= ILM_INPUT_DEVICE_POINTER; + send_input_focus(seat->input_ctx, + interface->get_id_of_surface(surf_ctx->layout_surface), + ILM_INPUT_DEVICE_POINTER, ILM_TRUE); + + weston_pointer_set_focus(grab->pointer, picked_view, sx, sy); + + } else if (old_focus == w_view){ + /* Send focus lost event to the surface which has lost the focus*/ + surf_ctx->focus &= ~ILM_INPUT_DEVICE_POINTER; + send_input_focus(seat->input_ctx, + interface->get_id_of_surface(surf_ctx->layout_surface), + ILM_INPUT_DEVICE_POINTER, ILM_FALSE); + } + } + } + + /* Send to surfaces that have pointer focus */ + if (grab->pointer->focus == picked_view) { + surface_client = wl_resource_get_client(grab->pointer->focus->surface->resource); + serial = wl_display_next_serial(display); + + wl_resource_for_each(resource, &grab->pointer->focus_resource_list) { + if (wl_resource_get_client(resource) != surface_client) + continue; + + wl_pointer_send_button(resource, serial, time, button, state); + } + } +} + +static void +pointer_grab_cancel(struct weston_pointer_grab *grab) +{ +} + +static struct weston_pointer_grab_interface pointer_grab_interface = { + pointer_grab_focus, + pointer_grab_motion, + pointer_grab_button, + pointer_grab_cancel +}; + +static void +touch_grab_down(struct weston_touch_grab *grab, uint32_t time, int touch_id, + wl_fixed_t sx, wl_fixed_t sy) +{ + struct seat_ctx *seat = wl_container_of(grab, seat, touch_grab); + struct wl_display *display = grab->touch->seat->compositor->wl_display; + struct surface_ctx *surf_ctx; + const struct ivi_controller_interface *interface = + seat->input_ctx->ivi_controller_interface; + + /* if touch device has no focused view, there is nothing to do*/ + if (grab->touch->focus == NULL) + return; + + /* For each surface_ctx, check for focus and send */ + wl_list_for_each(surf_ctx, &seat->input_ctx->surface_list, link) { + struct weston_surface *surf; + struct wl_resource *resource; + struct wl_client *surface_client; + uint32_t serial; + + surf = interface->surface_get_weston_surface(surf_ctx->layout_surface); + + if (get_accepted_seat(surf_ctx, grab->touch->seat->seat_name) < 0) + continue; + + /* Touches set touch focus */ + if (grab->touch->num_tp == 1) { + if (surf == grab->touch->focus->surface) { + surf_ctx->focus |= ILM_INPUT_DEVICE_TOUCH; + send_input_focus(seat->input_ctx, + interface->get_id_of_surface(surf_ctx->layout_surface), + ILM_INPUT_DEVICE_TOUCH, ILM_TRUE); + } else { + surf_ctx->focus &= ~ILM_INPUT_DEVICE_TOUCH; + send_input_focus(seat->input_ctx, + interface->get_id_of_surface(surf_ctx->layout_surface), + ILM_INPUT_DEVICE_TOUCH, ILM_FALSE); + } + } + + /* This code below is slightly redundant, since we have already + * decided only one surface has touch focus */ + if (!(surf_ctx->focus & ILM_INPUT_DEVICE_TOUCH)) + continue; + + surface_client = wl_resource_get_client(surf->resource); + serial = wl_display_next_serial(display); + wl_resource_for_each(resource, &grab->touch->resource_list) { + if (wl_resource_get_client(resource) != surface_client) + continue; + + wl_touch_send_down(resource, serial, time, surf->resource, + touch_id, sx, sy); + } + wl_resource_for_each(resource, &grab->touch->focus_resource_list) { + if (wl_resource_get_client(resource) != surface_client) + continue; + + wl_touch_send_down(resource, serial, time, surf->resource, + touch_id, sx, sy); + } + } + + +} + +static void +touch_grab_up(struct weston_touch_grab *grab, uint32_t time, int touch_id) +{ + struct seat_ctx *seat = wl_container_of(grab, seat, touch_grab); + struct wl_display *display = grab->touch->seat->compositor->wl_display; + struct surface_ctx *surf_ctx; + const struct ivi_controller_interface *interface = + seat->input_ctx->ivi_controller_interface; + + /* For each surface_ctx, check for focus and send */ + wl_list_for_each(surf_ctx, &seat->input_ctx->surface_list, link) { + struct weston_surface *surf; + struct wl_resource *resource; + struct wl_client *surface_client; + uint32_t serial; + + if (!(surf_ctx->focus & ILM_INPUT_DEVICE_TOUCH)) + continue; + + if (get_accepted_seat(surf_ctx, grab->touch->seat->seat_name) < 0) + continue; + + surf = interface->surface_get_weston_surface(surf_ctx->layout_surface); + surface_client = wl_resource_get_client(surf->resource); + serial = wl_display_next_serial(display); + wl_resource_for_each(resource, &grab->touch->resource_list) { + if (wl_resource_get_client(resource) != surface_client) + continue; + + wl_touch_send_up(resource, serial, time, touch_id); + } + + wl_resource_for_each(resource, &grab->touch->focus_resource_list) { + if (wl_resource_get_client(resource) != surface_client) + continue; + + wl_touch_send_up(resource, serial, time, touch_id); + } + + /* Touches unset touch focus */ + if (grab->touch->num_tp == 0) { + if (surf == grab->touch->focus->surface) + surf_ctx->focus &= ~ILM_INPUT_DEVICE_TOUCH; + send_input_focus(seat->input_ctx, + interface->get_id_of_surface(surf_ctx->layout_surface), + ILM_INPUT_DEVICE_TOUCH, ILM_FALSE); + } + } +} + +static void +touch_grab_motion(struct weston_touch_grab *grab, uint32_t time, int touch_id, + wl_fixed_t sx, wl_fixed_t sy) +{ + struct seat_ctx *seat = wl_container_of(grab, seat, touch_grab); + struct surface_ctx *surf_ctx; + const struct ivi_controller_interface *interface = + seat->input_ctx->ivi_controller_interface; + + /* For each surface_ctx, check for focus and send */ + wl_list_for_each(surf_ctx, &seat->input_ctx->surface_list, link) { + struct weston_surface *surf; + struct wl_resource *resource; + struct wl_client *surface_client; + + if (!(surf_ctx->focus & ILM_INPUT_DEVICE_TOUCH)) + continue; + + if (get_accepted_seat(surf_ctx, grab->touch->seat->seat_name) < 0) + continue; + + surf = interface->surface_get_weston_surface(surf_ctx->layout_surface); + surface_client = wl_resource_get_client(surf->resource); + wl_resource_for_each(resource, &grab->touch->resource_list) { + if (wl_resource_get_client(resource) != surface_client) + continue; + + wl_touch_send_motion(resource, time, touch_id, sx, sy); + } + + wl_resource_for_each(resource, &grab->touch->focus_resource_list) { + if (wl_resource_get_client(resource) != surface_client) + continue; + + wl_touch_send_motion(resource, time, touch_id, sx, sy); + } + } +} + +static void +touch_grab_frame(struct weston_touch_grab *grab) +{ + struct seat_ctx *seat = wl_container_of(grab, seat, touch_grab); + struct surface_ctx *surf_ctx; + const struct ivi_controller_interface *interface = + seat->input_ctx->ivi_controller_interface; + + /* For each surface_ctx, check for focus and send */ + wl_list_for_each(surf_ctx, &seat->input_ctx->surface_list, link) { + struct weston_surface *surf; + struct wl_resource *resource; + struct wl_client *surface_client; + + if (!(surf_ctx->focus & ILM_INPUT_DEVICE_TOUCH)) + continue; + + if (get_accepted_seat(surf_ctx, grab->touch->seat->seat_name) < 0) + continue; + + surf = interface->surface_get_weston_surface(surf_ctx->layout_surface); + surface_client = wl_resource_get_client(surf->resource); + wl_resource_for_each(resource, &grab->touch->resource_list) { + if (wl_resource_get_client(resource) != surface_client) + continue; + + wl_touch_send_frame(resource); + } + + wl_resource_for_each(resource, &grab->touch->focus_resource_list) { + if (wl_resource_get_client(resource) != surface_client) + continue; + + wl_touch_send_frame(resource); + } + } +} + +static void +touch_grab_cancel(struct weston_touch_grab *grab) +{ +} + +static struct weston_touch_grab_interface touch_grab_interface = { + touch_grab_down, + touch_grab_up, + touch_grab_motion, + touch_grab_frame, + touch_grab_cancel +}; + +static uint32_t +get_seat_capabilities(struct weston_seat *seat) +{ + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + struct weston_touch *touch = weston_seat_get_touch(seat); + uint32_t caps = 0; + + if (keyboard != NULL) + caps |= ILM_INPUT_DEVICE_KEYBOARD; + if (pointer != NULL) + caps |= ILM_INPUT_DEVICE_POINTER; + if (touch != NULL) + caps |= ILM_INPUT_DEVICE_TOUCH; + return caps; +} + +static void +handle_seat_updated_caps(struct wl_listener *listener, void *data) +{ + struct weston_seat *seat = data; + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + struct weston_touch *touch = weston_seat_get_touch(seat); + struct seat_ctx *ctx = wl_container_of(listener, ctx, + updated_caps_listener); + struct input_controller *controller; + + if (keyboard && keyboard != ctx->keyboard_grab.keyboard) { + weston_keyboard_start_grab(keyboard, &ctx->keyboard_grab); + } + if (pointer && pointer != ctx->pointer_grab.pointer) { + weston_pointer_start_grab(pointer, &ctx->pointer_grab); + } + if (touch && touch != ctx->touch_grab.touch) { + weston_touch_start_grab(touch, &ctx->touch_grab); + } + + wl_list_for_each(controller, &ctx->input_ctx->controller_list, link) { + ivi_input_send_seat_capabilities(controller->resource, + seat->seat_name, + get_seat_capabilities(seat)); + } +} + +static void +handle_seat_destroy(struct wl_listener *listener, void *data) +{ + struct seat_ctx *ctx = wl_container_of(listener, ctx, destroy_listener); + struct weston_seat *seat = data; + struct input_controller *controller; + + if (ctx->keyboard_grab.keyboard) + keyboard_grab_cancel(&ctx->keyboard_grab); + if (ctx->pointer_grab.pointer) + pointer_grab_cancel(&ctx->pointer_grab); + if (ctx->touch_grab.touch) + touch_grab_cancel(&ctx->touch_grab); + + wl_list_for_each(controller, &ctx->input_ctx->controller_list, link) { + ivi_input_send_seat_destroyed(controller->resource, + seat->seat_name); + } + + free(ctx); +} + +static void +handle_seat_create(struct wl_listener *listener, void *data) +{ + struct weston_seat *seat = data; + struct input_context *input_ctx = wl_container_of(listener, input_ctx, + seat_create_listener); + struct input_controller *controller; + struct seat_ctx *ctx = calloc(1, sizeof *ctx); + if (ctx == NULL) { + weston_log("%s: Failed to allocate memory\n", __FUNCTION__); + return; + } + + ctx->input_ctx = input_ctx; + + ctx->keyboard_grab.interface = &keyboard_grab_interface; + ctx->pointer_grab.interface = &pointer_grab_interface; + ctx->touch_grab.interface= &touch_grab_interface; + + ctx->destroy_listener.notify = &handle_seat_destroy; + wl_signal_add(&seat->destroy_signal, &ctx->destroy_listener); + + ctx->updated_caps_listener.notify = &handle_seat_updated_caps; + wl_signal_add(&seat->updated_caps_signal, &ctx->updated_caps_listener); + + wl_list_for_each(controller, &input_ctx->controller_list, link) { + ivi_input_send_seat_created(controller->resource, + seat->seat_name, + get_seat_capabilities(seat)); + } +} + +static void +handle_surface_destroy(struct ivi_layout_surface *layout_surface, void *data) +{ + struct input_context *ctx = data; + struct surface_ctx *surf, *next; + int surface_removed = 0; + const struct ivi_controller_interface *interface = + ctx->ivi_controller_interface; + + wl_list_for_each_safe(surf, next, &ctx->surface_list, link) { + if (surf->layout_surface == layout_surface) { + uint32_t i; + char **data = surf->accepted_devices.data; + wl_list_remove(&surf->link); + for (i = 0; i < surf->accepted_devices.size / sizeof(char**); i++) { + free(data[i]); + } + wl_array_release(&surf->accepted_devices); + free(surf); + surface_removed = 1; + break; + } + } + + if (!surface_removed) { + weston_log("%s: Warning! surface %d already destroyed\n", __FUNCTION__, + interface->get_id_of_surface((layout_surface))); + } +} + +static void +handle_surface_create(struct ivi_layout_surface *layout_surface, void *data) +{ + struct input_context *input_ctx = data; + struct surface_ctx *ctx; + const struct ivi_controller_interface *interface = + input_ctx->ivi_controller_interface; + + wl_list_for_each(ctx, &input_ctx->surface_list, link) { + if (ctx->layout_surface == layout_surface) { + weston_log("%s: Warning! surface context already created for" + " surface %d\n", __FUNCTION__, + interface->get_id_of_surface((layout_surface))); + break; + } + } + + ctx = calloc(1, sizeof *ctx); + if (ctx == NULL) { + weston_log("%s: Failed to allocate memory\n", __FUNCTION__); + return; + } + ctx->layout_surface = layout_surface; + ctx->input_context = input_ctx; + wl_array_init(&ctx->accepted_devices); + add_accepted_seat(ctx, "default"); + send_input_acceptance(input_ctx, + interface->get_id_of_surface(layout_surface), + "default", ILM_TRUE); + + wl_list_insert(&input_ctx->surface_list, &ctx->link); +} + +static void +unbind_resource_controller(struct wl_resource *resource) +{ + struct input_controller *controller = wl_resource_get_user_data(resource); + + wl_list_remove(&controller->link); + + free(controller); +} + +static void +input_set_input_focus(struct wl_client *client, + struct wl_resource *resource, + uint32_t surface, uint32_t device, + int32_t enabled) +{ + struct input_controller *controller = wl_resource_get_user_data(resource); + struct input_context *ctx = controller->input_context; + struct surface_ctx *surf, *current_surf = NULL; + struct weston_seat *seat; + const struct ivi_controller_interface *interface = + ctx->ivi_controller_interface; + uint32_t caps; + struct ivi_layout_surface *current_layout_surface; + + current_layout_surface = interface->get_surface_from_id(surface); + + if (!current_layout_surface) { + weston_log("%s: surface %d was not found\n", __FUNCTION__, surface); + return; + } + + wl_list_for_each(surf, &ctx->surface_list, link) { + if (current_layout_surface == surf->layout_surface) { + current_surf = surf; + if (enabled == ILM_TRUE) { + surf->focus |= device; + } else { + surf->focus &= ~device; + } + + send_input_focus(ctx, surface, device, enabled); + + wl_list_for_each(seat, &ctx->compositor->seat_list, link) { + if (get_accepted_seat(surf, seat->seat_name) < 0) + continue; + + caps = get_seat_capabilities(seat); + + if (!(caps | device)) + continue; + + set_weston_focus(ctx, surf, device, seat, enabled); + } + + break; + } + } + + /* If focus is enabled for one of these devices, every other surface + * must have focus unset */ + if ((device != ILM_INPUT_DEVICE_KEYBOARD) && enabled) { + wl_list_for_each(surf, &ctx->surface_list, link) { + if (surf == current_surf) + continue; + + /* We do not need to unset the focus, if the surface does not have it*/ + if (!(surf->focus | device)) + continue; + + wl_list_for_each(seat, &ctx->compositor->seat_list, link) { + /*if both of surfaces have acceptance to same seat */ + if ((get_accepted_seat(surf, seat->seat_name) < 0) || + (get_accepted_seat(current_surf, seat->seat_name) < 0)) + continue; + + caps = get_seat_capabilities(seat); + + if (!(caps | device)) + continue; + + surf->focus &= ~(device); + send_input_focus(ctx, interface->get_id_of_surface(surf->layout_surface), + device, ILM_FALSE); + set_weston_focus(ctx, surf, device, seat, ILM_FALSE); + } + } + } +} + +static void +input_set_input_acceptance(struct wl_client *client, + struct wl_resource *resource, + uint32_t surface, const char *seat, + int32_t accepted) +{ + struct input_controller *controller = wl_resource_get_user_data(resource); + struct input_context *ctx = controller->input_context; + struct surface_ctx *surface_ctx; + int found_seat = 0; + int found_weston_seat = 0; + struct weston_seat *w_seat = NULL; + const struct ivi_controller_interface *interface = + ctx->ivi_controller_interface; + + wl_list_for_each(w_seat, &ctx->compositor->seat_list, link) { + if(strcmp(seat,w_seat->seat_name) == 0) { + found_weston_seat = 1; + break; + } + } + + if (!found_weston_seat) { + weston_log("%s: seat: %s was not found\n", __FUNCTION__, seat); + return; + } + + wl_list_for_each(surface_ctx, &ctx->surface_list, link) { + if (interface->get_id_of_surface(surface_ctx->layout_surface) == surface) { + if (accepted == ILM_TRUE) { + found_seat = add_accepted_seat(surface_ctx, seat); + if (found_weston_seat) + set_weston_focus(ctx, surface_ctx, surface_ctx->focus, w_seat, ILM_TRUE); + } else { + if (found_weston_seat) + set_weston_focus(ctx, surface_ctx, surface_ctx->focus, w_seat, ILM_FALSE); + found_seat = remove_accepted_seat(surface_ctx, seat); + } + break; + } + } + + if (found_seat) + send_input_acceptance(ctx, surface, seat, accepted); +} + +static const struct ivi_input_interface input_implementation = { + input_set_input_focus, + input_set_input_acceptance +}; + +static void +bind_ivi_input(struct wl_client *client, void *data, + uint32_t version, uint32_t id) +{ + struct input_context *ctx = data; + struct input_controller *controller; + struct weston_seat *seat; + struct surface_ctx *surface_ctx; + const struct ivi_controller_interface *interface = + ctx->ivi_controller_interface; + controller = calloc(1, sizeof *controller); + if (controller == NULL) { + weston_log("%s: Failed to allocate memory for controller\n", + __FUNCTION__); + return; + } + + controller->input_context = ctx; + controller->resource = + wl_resource_create(client, &ivi_input_interface, 1, id); + wl_resource_set_implementation(controller->resource, &input_implementation, + controller, unbind_resource_controller); + + controller->client = client; + controller->id = id; + + wl_list_insert(&ctx->controller_list, &controller->link); + + /* Send seat events for all known seats to the client */ + wl_list_for_each(seat, &ctx->compositor->seat_list, link) { + ivi_input_send_seat_created(controller->resource, + seat->seat_name, + get_seat_capabilities(seat)); + } + /* Send focus events for all known surfaces to the client */ + wl_list_for_each(surface_ctx, &ctx->surface_list, link) { + ivi_input_send_input_focus(controller->resource, + interface->get_id_of_surface(surface_ctx->layout_surface), + surface_ctx->focus, ILM_TRUE); + } + /* Send acceptance events for all known surfaces to the client */ + wl_list_for_each(surface_ctx, &ctx->surface_list, link) { + char **name; + wl_array_for_each(name, &surface_ctx->accepted_devices) { + ivi_input_send_input_acceptance(controller->resource, + interface->get_id_of_surface(surface_ctx->layout_surface), + *name, ILM_TRUE); + } + } +} + +static struct input_context * +create_input_context(struct weston_compositor *ec, + const struct ivi_controller_interface *interface) +{ + struct input_context *ctx = NULL; + struct weston_seat *seat; + ctx = calloc(1, sizeof *ctx); + if (ctx == NULL) { + weston_log("%s: Failed to allocate memory for input context\n", + __FUNCTION__); + return NULL; + } + + ctx->compositor = ec; + ctx->ivi_controller_interface = interface; + wl_list_init(&ctx->controller_list); + wl_list_init(&ctx->surface_list); + + /* Add signal handlers for ivi surfaces. Warning: these functions leak + * memory. */ + interface->add_notification_create_surface(handle_surface_create, ctx); + interface->add_notification_remove_surface(handle_surface_destroy, ctx); + + ctx->seat_create_listener.notify = &handle_seat_create; + wl_signal_add(&ec->seat_created_signal, &ctx->seat_create_listener); + + wl_list_for_each(seat, &ec->seat_list, link) { + handle_seat_create(&ctx->seat_create_listener, seat); + wl_signal_emit(&seat->updated_caps_signal, seat); + } + + return ctx; +} + +WL_EXPORT int +input_controller_module_init(struct weston_compositor *ec, + const struct ivi_controller_interface *interface, + size_t interface_version) +{ + struct input_context *ctx = create_input_context(ec, interface); + if (ctx == NULL) { + weston_log("%s: Failed to create input context\n", __FUNCTION__); + return -1; + } + + if (wl_global_create(ec->wl_display, &ivi_input_interface, 1, + ctx, bind_ivi_input) == NULL) { + return -1; + } + weston_log("ivi-input-controller module loaded successfully!\n"); + return 0; +} |