From 23fa6b918217fc1831f3c6d876c83b0ad022469a Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 25 Jan 2019 13:05:51 +0100 Subject: [PATCH 1/7] Added mouse cursor callback stubs. --- client/Wayland/CMakeLists.txt | 2 + client/Wayland/wlf_pointer.c | 136 +++++++++++++++++++++++++++++ client/Wayland/wlf_pointer.h | 28 ++++++ client/Wayland/wlfreerdp.c | 12 +++ client/Wayland/wlfreerdp.h | 1 + cmake/FindWayland.cmake | 12 ++- uwac/include/uwac/uwac.h | 19 +++++ uwac/libuwac/uwac-display.c | 26 ++++++ uwac/libuwac/uwac-input.c | 155 ++++++++++++++++++++++++++++++++++ uwac/libuwac/uwac-priv.h | 6 +- 10 files changed, 395 insertions(+), 2 deletions(-) create mode 100644 client/Wayland/wlf_pointer.c create mode 100644 client/Wayland/wlf_pointer.h diff --git a/client/Wayland/CMakeLists.txt b/client/Wayland/CMakeLists.txt index d98d2d4ab..eb1cce7ff 100644 --- a/client/Wayland/CMakeLists.txt +++ b/client/Wayland/CMakeLists.txt @@ -27,6 +27,8 @@ set(${MODULE_PREFIX}_SRCS wlfreerdp.h wlf_disp.c wlf_disp.h + wlf_pointer.c + wlf_pointer.h wlf_input.c wlf_input.h wlf_cliprdr.c diff --git a/client/Wayland/wlf_pointer.c b/client/Wayland/wlf_pointer.c new file mode 100644 index 000000000..b7982743b --- /dev/null +++ b/client/Wayland/wlf_pointer.c @@ -0,0 +1,136 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Wayland Mouse Pointer + * + * Copyright 2019 Armin Novak + * Copyright 2019 Thincast Technologies GmbH + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "wlf_pointer.h" +#include "wlfreerdp.h" + +#include +#define TAG CLIENT_TAG("wayland.pointer") + +struct wlf_pointer +{ + rdpPointer pointer; + size_t size; + void* data; +}; +typedef struct wlf_pointer wlfPointer; + +static BOOL wlf_Pointer_New(rdpContext* context, rdpPointer* pointer) +{ + wlfPointer* ptr = (wlfPointer*)pointer; + if (!ptr) + return FALSE; + + ptr->size = pointer->width * pointer->height * 4; + ptr->data = _aligned_malloc(ptr->size, 16); + if (!ptr->data) + return FALSE; + + if (!freerdp_image_copy_from_pointer_data( + ptr->data, PIXEL_FORMAT_ARGB32, + 0, 0, 0, pointer->width, pointer->height, + pointer->xorMaskData, pointer->lengthXorMask, + pointer->andMaskData, pointer->lengthAndMask, + pointer->xorBpp, &context->gdi->palette)) + { + _aligned_free(ptr->data); + return FALSE; + } + + return TRUE; +} + +static void wlf_Pointer_Free(rdpContext* context, rdpPointer* pointer) +{ + wlfPointer* ptr = (wlfPointer*)pointer; + WINPR_UNUSED(context); + if (ptr) + _aligned_free(ptr->data); +} + +static BOOL wlf_Pointer_Set(rdpContext* context, + const rdpPointer* pointer) +{ + wlfContext* wlf = (wlfContext*)context; + wlfPointer* ptr = (wlfPointer*)pointer; + + if (!wlf || !wlf->seat) + return FALSE; + + // TODO: Scale according to SmartSizing + if (UwacSeatSetMouseCursor(wlf->seat, ptr->data, ptr->size, pointer->width, pointer->height, pointer->xPos, pointer->yPos) != UWAC_SUCCESS) + return FALSE; + + return TRUE; +} + +static BOOL wlf_Pointer_SetNull(rdpContext* context) +{ + wlfContext* wlf = (wlfContext*)context; + if (!wlf || !wlf->seat) + return FALSE; + + if (UwacSeatSetMouseCursor(wlf->seat, NULL, 0, 0, 0, 0, 0) != UWAC_SUCCESS) + return FALSE; + + return TRUE; +} + +static BOOL wlf_Pointer_SetDefault(rdpContext* context) +{ + wlfContext* wlf = (wlfContext*)context; + if (!wlf || !wlf->seat) + return FALSE; + + if (UwacSeatSetMouseCursor(wlf->seat, NULL, 1, 0, 0, 0, 0) != UWAC_SUCCESS) + return FALSE; + + return TRUE; +} + +static BOOL wlf_Pointer_SetPosition(rdpContext* context, UINT32 x, UINT32 y) +{ + // TODO + WLog_WARN(TAG, "%s not implemented", __FUNCTION__); + return TRUE; +} + +BOOL wlf_register_pointer(rdpGraphics* graphics) +{ + rdpPointer* pointer = NULL; + + if (!(pointer = (rdpPointer*) calloc(1, sizeof(rdpPointer)))) + return FALSE; + + pointer->size = sizeof(wlfPointer); + pointer->New = wlf_Pointer_New; + pointer->Free = wlf_Pointer_Free; + pointer->Set = wlf_Pointer_Set; + pointer->SetNull = wlf_Pointer_SetNull; + pointer->SetDefault = wlf_Pointer_SetDefault; + pointer->SetPosition = wlf_Pointer_SetPosition; + graphics_register_pointer(graphics, pointer); + free(pointer); + return TRUE; +} diff --git a/client/Wayland/wlf_pointer.h b/client/Wayland/wlf_pointer.h new file mode 100644 index 000000000..8ae82e1d5 --- /dev/null +++ b/client/Wayland/wlf_pointer.h @@ -0,0 +1,28 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Wayland Mouse Pointer + * + * Copyright 2019 Armin Novak + * Copyright 2019 Thincast Technologies GmbH + * + * 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. + */ + +#ifndef FREERDP_CLIENT_WAYLAND_POINTER_H +#define FREERDP_CLIENT_WAYLAND_POINTER_H + +#include + +BOOL wlf_register_pointer(rdpGraphics* graphics); + +#endif /* FREERDP_CLIENT_WAYLAND_POINTER_H */ diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c index 3856be4b6..ed73d91b0 100644 --- a/client/Wayland/wlfreerdp.c +++ b/client/Wayland/wlfreerdp.c @@ -39,6 +39,7 @@ #include "wlf_cliprdr.h" #include "wlf_disp.h" #include "wlf_channels.h" +#include "wlf_pointer.h" static BOOL wl_begin_paint(rdpContext* context) { @@ -222,6 +223,9 @@ static BOOL wl_post_connect(freerdp* instance) if (!gdi || (gdi->width < 0) || (gdi->height < 0)) return FALSE; + if (!wlf_register_pointer(instance->context->graphics)) + return FALSE; + w = (UINT32)gdi->width; h = (UINT32)gdi->height; context = (wlfContext*) instance->context; @@ -286,6 +290,14 @@ static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display) /*printf("UWAC event type %d\n", event.type);*/ switch (event.type) { + case UWAC_EVENT_NEW_SEAT: + context->seat = event.seat_new.seat; + break; + + case UWAC_EVENT_REMOVED_SEAT: + context->seat = NULL; + break; + case UWAC_EVENT_FRAME_DONE: break; diff --git a/client/Wayland/wlfreerdp.h b/client/Wayland/wlfreerdp.h index dd294bcd4..24b117d22 100644 --- a/client/Wayland/wlfreerdp.h +++ b/client/Wayland/wlfreerdp.h @@ -41,6 +41,7 @@ struct wlf_context UwacDisplay* display; HANDLE displayHandle; UwacWindow* window; + UwacSeat* seat; BOOL fullscreen; diff --git a/cmake/FindWayland.cmake b/cmake/FindWayland.cmake index ee217f61d..6128c1433 100644 --- a/cmake/FindWayland.cmake +++ b/cmake/FindWayland.cmake @@ -30,6 +30,7 @@ include(FindPkgConfig) if(PKG_CONFIG_FOUND) pkg_check_modules(WAYLAND_SCANNER_PC wayland-scanner) pkg_check_modules(WAYLAND_CLIENT_PC wayland-client) + pkg_check_modules(WAYLAND_CURSOR_PC wayland-cursor) pkg_check_modules(XKBCOMMON_PC xkbcommon) endif() @@ -41,11 +42,20 @@ find_path(WAYLAND_INCLUDE_DIR wayland-client.h HINTS ${WAYLAND_CLIENT_PC_INCLUDE_DIRS} ) -find_library(WAYLAND_LIBS +find_library(WAYLAND_CLIENT_LIB NAMES "wayland-client" HINTS "${WAYLAND_CLIENT_PC_LIBRARY_DIRS}" ) +find_library(WAYLAND_CURSOR_LIB + NAMES "wayland-cursor" + HINTS "${WAYLAND_CURSOR_PC_LIBRARY_DIRS}" +) + +if (WAYLAND_CLIENT_LIB AND WAYLAND_CURSOR_LIB) + list(INSERT WAYLAND_LIBS ${WAYLAND_CLIENT_LIB} ${WAYLAND_CURSOR_LIB}) +endif (WAYLAND_CLIENT_LIB AND WAYLAND_CURSOR_LIB) + find_path(XKBCOMMON_INCLUDE_DIR xkbcommon/xkbcommon.h HINTS ${XKBCOMMON_PC_INCLUDE_DIRS} ) diff --git a/uwac/include/uwac/uwac.h b/uwac/include/uwac/uwac.h index 8466b1125..65684e526 100644 --- a/uwac/include/uwac/uwac.h +++ b/uwac/include/uwac/uwac.h @@ -564,6 +564,25 @@ UWAC_API void* UwacClipboardDataGet(UwacSeat* seat, const char* mime, size_t* si */ UWAC_API UwacReturnCode UwacSeatInhibitShortcuts(UwacSeat* seat, bool inhibit); +/** + * @brief UwacSeatSetMouseCursor Sets the specified image as the new mouse cursor. + * Special values: If data == NULL && lenght == 0 + * the cursor is hidden, if data == NULL && length != 0 + * the default system cursor is used. + * + * @param seat The UwacSeat to apply the cursor image to + * @param data A pointer to the image data + * @param length The size of the image data + * @param width The image width in pixel + * @param height The image height in pixel + * @param hot_x The hotspot horizontal offset in pixel + * @param hot_y The hotspot vertical offset in pixel + * + * @return UWAC_SUCCESS if successful, an appropriate error otherwise. + */ +UWAC_API UwacReturnCode UwacSeatSetMouseCursor(UwacSeat* seat, const void* data, size_t length, + size_t width, size_t height, size_t hot_x, size_t hot_y); + #ifdef __cplusplus } #endif diff --git a/uwac/libuwac/uwac-display.c b/uwac/libuwac/uwac-display.c index cf621b2dc..dc3fee143 100644 --- a/uwac/libuwac/uwac-display.c +++ b/uwac/libuwac/uwac-display.c @@ -33,6 +33,7 @@ #include #include "uwac-os.h" +#include "wayland-cursor.h" #define TARGET_COMPOSITOR_INTERFACE 3 #define TARGET_SHM_INTERFACE 1 @@ -151,6 +152,14 @@ static void UwacSeatRegisterDDM(UwacSeat *seat) seat->data_device = wl_data_device_manager_get_data_device(d->data_device_manager, seat->seat); } +static void UwacRegisterCursor(UwacSeat* seat) +{ + if (!seat || !seat->display || !seat->display->compositor) + return; + + seat->pointer_surface = wl_compositor_create_surface(seat->display->compositor); +} + static void registry_handle_global(void* data, struct wl_registry* registry, uint32_t id, const char* interface, uint32_t version) { @@ -171,6 +180,18 @@ static void registry_handle_global(void* data, struct wl_registry* registry, uin { d->shm = wl_registry_bind(registry, id, &wl_shm_interface, min(TARGET_SHM_INTERFACE, version)); wl_shm_add_listener(d->shm, &shm_listener, d); + + d->cursor_theme = wl_cursor_theme_load(NULL, 32, d->shm); + if (!d->cursor_theme) { + assert(uwacErrorHandler(d, UWAC_ERROR_NOMEMORY, "unable to get wayland cursor theme\n")); + return; + } + + d->default_cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "left_ptr"); + if (!d->default_cursor) { + assert(uwacErrorHandler(d, UWAC_ERROR_NOMEMORY, "unable to get wayland cursor left_ptr\n")); + return; + } } else if (strcmp(interface, "wl_output") == 0) { @@ -203,6 +224,7 @@ static void registry_handle_global(void* data, struct wl_registry* registry, uin UwacSeatRegisterDDM(seat); UwacSeatRegisterClipboard(seat); + UwacRegisterCursor(seat); ev = (UwacSeatNewEvent*)UwacDisplayNewEvent(d, UWAC_EVENT_NEW_SEAT); if (!ev) @@ -224,6 +246,7 @@ static void registry_handle_global(void* data, struct wl_registry* registry, uin { UwacSeatRegisterDDM(seat); UwacSeatRegisterClipboard(seat); + UwacRegisterCursor(seat); } } else if (strcmp(interface, "wl_shell") == 0) @@ -573,6 +596,9 @@ UwacReturnCode UwacCloseDisplay(UwacDisplay** pdisplay) if (display->shell) wl_shell_destroy(display->shell); + if (display->cursor_theme) + wl_cursor_theme_destroy(display->cursor_theme); + if (display->shm) wl_shm_destroy(display->shm); diff --git a/uwac/libuwac/uwac-input.c b/uwac/libuwac/uwac-input.c index 3e7799ef2..b0f930c2a 100644 --- a/uwac/libuwac/uwac-input.c +++ b/uwac/libuwac/uwac-input.c @@ -32,6 +32,62 @@ #include #include +#include "uwac-os.h" +#include "wayland-cursor.h" +#include "wayland-client-protocol.h" + +static UwacReturnCode +set_cursor_image(UwacSeat* seat, uint32_t serial) +{ + struct wl_buffer* buffer; + struct wl_cursor* cursor; + struct wl_cursor_image* image; + struct wl_surface* surface = NULL; + int32_t x = 0, y = 0; + + if (!seat || !seat->display || !seat->display->default_cursor || !seat->display->default_cursor->images) + return UWAC_ERROR_INTERNAL; + + switch(seat->pointer_type) { + case 2: /* Custom poiner */ + image = seat->pointer_image; + buffer = seat->pointer_buffer; + surface = seat->pointer_surface; + x = image->hotspot_x; + y = image->hotspot_y; + break; + case 1: /* NULL pointer */ + break; + default: /* Default system pointer */ + cursor = seat->display->default_cursor; + if (!cursor) + return UWAC_ERROR_INTERNAL; + image = cursor->images[0]; + if (!image) + return UWAC_ERROR_INTERNAL; + x = image->hotspot_x; + y = image->hotspot_y; + buffer = wl_cursor_image_get_buffer(image); + if (!buffer) + return UWAC_ERROR_INTERNAL; + surface = seat->pointer_surface; + break; + } + + wl_pointer_set_cursor(seat->pointer, + serial, + surface, + x, y); + + if (surface) { + wl_surface_attach(surface, buffer, 0, 0); + wl_surface_damage(surface, 0, 0, + image->width, image->height); + wl_surface_commit(surface); + } + + return UWAC_SUCCESS; +} static void keyboard_repeat_func(UwacTask *task, uint32_t events) { @@ -588,6 +644,10 @@ static void pointer_handle_enter(void *data, struct wl_pointer *pointer, uint32_ event->window = window; event->x = sx; event->y = sy; + + + /* Apply cursor theme */ + set_cursor_image(input, serial); } static void pointer_handle_leave(void *data, struct wl_pointer *pointer, uint32_t serial, @@ -871,6 +931,14 @@ void UwacSeatDestroy(UwacSeat *s) { if (s->data_source) wl_data_source_destroy(s->data_source); + if (s->pointer_surface) + wl_surface_destroy(s->pointer_surface); + + if (s->pointer_buffer) + wl_buffer_destroy(s->pointer_buffer); + + free(s->pointer_image); + wl_list_remove(&s->link); free(s); } @@ -898,3 +966,90 @@ UwacReturnCode UwacSeatInhibitShortcuts(UwacSeat* s, bool inhibit) return UWAC_ERROR_INTERNAL; return UWAC_SUCCESS; } + +UwacReturnCode create_pointer_buffer(UwacSeat* seat, const void* src, size_t size) +{ + UwacReturnCode ret = UWAC_SUCCESS; + UwacBuffer* newBuffers; + int fd; + void* data; + struct wl_shm_pool* pool; + + if (!newBuffers) + return UWAC_ERROR_NOMEMORY; + + fd = uwac_create_anonymous_file(size); + + if (fd < 0) + { + return UWAC_ERROR_INTERNAL; + } + + data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + if (data == MAP_FAILED) + { + ret = UWAC_ERROR_NOMEMORY; + goto error_mmap; + } + memcpy(data, src, size); + + pool = wl_shm_create_pool(seat->display->shm, fd, size * 2); + + if (!pool) + { + munmap(data, size); + ret = UWAC_ERROR_NOMEMORY; + goto error_mmap; + } + + seat->pointer_buffer = wl_shm_pool_create_buffer(pool, size, + seat->pointer_image->width, + seat->pointer_image->height, + seat->pointer_image->width * 4, + WL_SHM_FORMAT_XRGB8888); + wl_shm_pool_destroy(pool); + +error_mmap: + close(fd); + return ret; +} + +UwacReturnCode UwacSeatSetMouseCursor(UwacSeat* seat, const void* data, size_t length, + size_t width, size_t height, + size_t hot_x, size_t hot_y) +{ + if (!seat) + return UWAC_ERROR_CLOSED; + + free(seat->pointer_image); + if (seat->pointer_buffer) + wl_buffer_destroy(seat->pointer_buffer); + seat->pointer_image = NULL; + seat->pointer_buffer = NULL; + + /* There is a cursor provided */ + if ((data != NULL) && (length != 0)) + { + seat->pointer_image = calloc(1, sizeof(struct wl_cursor_image)); + if (!seat->pointer_image) + return UWAC_ERROR_NOMEMORY; + seat->pointer_image->width = width; + seat->pointer_image->height = height; + seat->pointer_image->hotspot_x = hot_x; + seat->pointer_image->hotspot_y = hot_y; + + create_pointer_buffer(seat, data, length); + + seat->pointer_type = 2; + } + /* We want to use the system cursor */ + else if (length != 0) { + seat->pointer_type = 0; + } + /* Hide the cursor */ + else { + seat->pointer_type = 1; + } + return set_cursor_image(seat, seat->display->serial); +} diff --git a/uwac/libuwac/uwac-priv.h b/uwac/libuwac/uwac-priv.h index 540906b10..64dc90607 100644 --- a/uwac/libuwac/uwac-priv.h +++ b/uwac/libuwac/uwac-priv.h @@ -121,7 +121,7 @@ struct uwac_display { uint32_t serial; struct wl_cursor_theme *cursor_theme; - struct wl_cursor **cursors; + struct wl_cursor *default_cursor; struct wl_list windows; @@ -158,6 +158,10 @@ struct uwac_seat { struct wl_data_device* data_device; struct wl_data_source* data_source; struct wl_pointer *pointer; + struct wl_surface *pointer_surface; + struct wl_cursor_image *pointer_image; + int pointer_type; + struct wl_buffer *pointer_buffer; struct wl_keyboard *keyboard; struct wl_touch *touch; struct wl_data_offer* offer; From 34adfd5714fce5e3d998521f2f611bd866202a85 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 25 Jan 2019 15:38:56 +0100 Subject: [PATCH 2/7] Added UWAC_EVENT_OUTPUT_GEOMETRY event --- uwac/include/uwac/uwac.h | 17 +++++++++++++++++ uwac/libuwac/uwac-input.c | 5 ++++- uwac/libuwac/uwac-output.c | 11 +++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/uwac/include/uwac/uwac.h b/uwac/include/uwac/uwac.h index 65684e526..5c0403493 100644 --- a/uwac/include/uwac/uwac.h +++ b/uwac/include/uwac/uwac.h @@ -97,6 +97,7 @@ enum UWAC_EVENT_CLIPBOARD_AVAILABLE, UWAC_EVENT_CLIPBOARD_SELECT, UWAC_EVENT_CLIPBOARD_OFFER, + UWAC_EVENT_OUTPUT_GEOMETRY, }; /** @brief window states */ @@ -243,11 +244,27 @@ struct uwac_clipboard_event }; typedef struct uwac_clipboard_event UwacClipboardEvent; +struct uwac_output_geometry_event +{ + int type; + UwacOutput* output; + int x; + int y; + int physical_width; + int physical_height; + int subpixel; + const char *make; + const char *model; + int transform; +}; +typedef struct uwac_output_geometry_event UwacOutputGeometryEvent; + /** @brief */ union uwac_event { int type; UwacOutputNewEvent output_new; + UwacOutputGeometryEvent output_geometry; UwacSeatNewEvent seat_new; UwacSeatRemovedEvent seat_removed; UwacPointerEnterLeaveEvent mouse_enter_leave; diff --git a/uwac/libuwac/uwac-input.c b/uwac/libuwac/uwac-input.c index b0f930c2a..094ca0a3a 100644 --- a/uwac/libuwac/uwac-input.c +++ b/uwac/libuwac/uwac-input.c @@ -50,8 +50,11 @@ set_cursor_image(UwacSeat* seat, uint32_t serial) switch(seat->pointer_type) { case 2: /* Custom poiner */ + if (!seat->pointer_buffer) + return UWAC_SUCCESS; image = seat->pointer_image; buffer = seat->pointer_buffer; + seat->pointer_buffer = NULL; surface = seat->pointer_surface; x = image->hotspot_x; y = image->hotspot_y; @@ -1007,7 +1010,7 @@ UwacReturnCode create_pointer_buffer(UwacSeat* seat, const void* src, size_t siz seat->pointer_image->width, seat->pointer_image->height, seat->pointer_image->width * 4, - WL_SHM_FORMAT_XRGB8888); + WL_SHM_FORMAT_ARGB8888); wl_shm_pool_destroy(pool); error_mmap: diff --git a/uwac/libuwac/uwac-output.c b/uwac/libuwac/uwac-output.c index 0da871c1c..2cdaf555e 100644 --- a/uwac/libuwac/uwac-output.c +++ b/uwac/libuwac/uwac-output.c @@ -52,6 +52,17 @@ static void output_handle_geometry(void *data, struct wl_output *wl_output, int if (!output->model) { assert(uwacErrorHandler(output->display, UWAC_ERROR_NOMEMORY, "%s: unable to strdup model\n", __FUNCTION__)); } + + UwacEvent* event = UwacDisplayNewEvent(output->display, UWAC_EVENT_OUTPUT_GEOMETRY); + event->output_geometry.output = output; + event->output_geometry.x = x; + event->output_geometry.y = y; + event->output_geometry.physical_width = physical_width; + event->output_geometry.physical_height = physical_height; + event->output_geometry.subpixel = subpixel; + event->output_geometry.make = output->make; + event->output_geometry.model = output->model; + event->output_geometry.transform = transform; } static void output_handle_done(void *data, struct wl_output *wl_output) From 52ef8079eae74dfe89e6779c873101843b8cc42b Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 25 Jan 2019 15:46:55 +0100 Subject: [PATCH 3/7] Added O_TMPFILE support for uwac tempfile generation. --- uwac/libuwac/uwac-os.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/uwac/libuwac/uwac-os.c b/uwac/libuwac/uwac-os.c index 135c5cd00..fb4474a5a 100644 --- a/uwac/libuwac/uwac-os.c +++ b/uwac/libuwac/uwac-os.c @@ -212,11 +212,11 @@ static int create_tmpfile_cloexec(char* tmpname) int uwac_create_anonymous_file(off_t size) { static const char template[] = "/weston-shared-XXXXXX"; - const char* path; + size_t length; char* name; + const char* path; int fd; int ret; - size_t length; path = getenv("XDG_RUNTIME_DIR"); if (!path) @@ -225,15 +225,20 @@ int uwac_create_anonymous_file(off_t size) return -1; } - length = strlen(path) + sizeof(template); - name = malloc(length); + fd = open(path, O_TMPFILE | O_RDWR | O_EXCL, 0600); - if (!name) - return -1; + if (fd < 0) + { + length = strlen(path) + sizeof(template); + name = malloc(length); - snprintf(name, length, "%s%s", path, template); - fd = create_tmpfile_cloexec(name); - free(name); + if (!name) + return -1; + + snprintf(name, length, "%s%s", path, template); + fd = create_tmpfile_cloexec(name); + free(name); + } if (fd < 0) return -1; From 2418c43cac26dc5f8c9976173ab6328540182299 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 28 Jan 2019 15:29:30 +0100 Subject: [PATCH 4/7] Fixed pointer image update. --- client/Wayland/wlf_pointer.c | 2 +- uwac/libuwac/uwac-input.c | 133 ++++++++++++++++++----------------- uwac/libuwac/uwac-priv.h | 3 +- 3 files changed, 71 insertions(+), 67 deletions(-) diff --git a/client/Wayland/wlf_pointer.c b/client/Wayland/wlf_pointer.c index b7982743b..18017db31 100644 --- a/client/Wayland/wlf_pointer.c +++ b/client/Wayland/wlf_pointer.c @@ -48,7 +48,7 @@ static BOOL wlf_Pointer_New(rdpContext* context, rdpPointer* pointer) return FALSE; if (!freerdp_image_copy_from_pointer_data( - ptr->data, PIXEL_FORMAT_ARGB32, + ptr->data, PIXEL_FORMAT_RGBA32, 0, 0, 0, pointer->width, pointer->height, pointer->xorMaskData, pointer->lengthXorMask, pointer->andMaskData, pointer->lengthAndMask, diff --git a/uwac/libuwac/uwac-input.c b/uwac/libuwac/uwac-input.c index 094ca0a3a..bd6a74bc3 100644 --- a/uwac/libuwac/uwac-input.c +++ b/uwac/libuwac/uwac-input.c @@ -36,6 +36,49 @@ #include "wayland-cursor.h" #include "wayland-client-protocol.h" +static struct wl_buffer* create_pointer_buffer(UwacSeat* seat, const void* src, size_t size) +{ + struct wl_buffer* buffer = NULL; + UwacReturnCode ret = UWAC_SUCCESS; + int fd; + void* data; + struct wl_shm_pool* pool; + + fd = uwac_create_anonymous_file(size); + + if (fd < 0) + return buffer; + + data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + if (data == MAP_FAILED) + { + ret = UWAC_ERROR_NOMEMORY; + goto error_mmap; + } + memcpy(data, src, size); + + pool = wl_shm_create_pool(seat->display->shm, fd, size); + + if (!pool) + { + munmap(data, size); + ret = UWAC_ERROR_NOMEMORY; + goto error_mmap; + } + + buffer = wl_shm_pool_create_buffer(pool, 0, + seat->pointer_image->width, + seat->pointer_image->height, + seat->pointer_image->width * 4, + WL_SHM_FORMAT_ARGB8888); + wl_shm_pool_destroy(pool); + +error_mmap: + close(fd); + return buffer; +} + static UwacReturnCode set_cursor_image(UwacSeat* seat, uint32_t serial) { @@ -50,11 +93,10 @@ set_cursor_image(UwacSeat* seat, uint32_t serial) switch(seat->pointer_type) { case 2: /* Custom poiner */ - if (!seat->pointer_buffer) - return UWAC_SUCCESS; image = seat->pointer_image; - buffer = seat->pointer_buffer; - seat->pointer_buffer = NULL; + buffer = create_pointer_buffer(seat, seat->pointer_data, seat->pointer_size); + if (!buffer) + return UWAC_ERROR_INTERNAL; surface = seat->pointer_surface; x = image->hotspot_x; y = image->hotspot_y; @@ -77,18 +119,22 @@ set_cursor_image(UwacSeat* seat, uint32_t serial) break; } - wl_pointer_set_cursor(seat->pointer, - serial, - surface, - x, y); - if (surface) { - wl_surface_attach(surface, buffer, 0, 0); + wl_surface_attach(surface, buffer, -x, -y); wl_surface_damage(surface, 0, 0, image->width, image->height); wl_surface_commit(surface); } + if (buffer) { + wl_buffer_destroy(buffer); + } + + wl_pointer_set_cursor(seat->pointer, + serial, + surface, + x, y); + return UWAC_SUCCESS; } @@ -937,10 +983,8 @@ void UwacSeatDestroy(UwacSeat *s) { if (s->pointer_surface) wl_surface_destroy(s->pointer_surface); - if (s->pointer_buffer) - wl_buffer_destroy(s->pointer_buffer); - free(s->pointer_image); + free(s->pointer_data); wl_list_remove(&s->link); free(s); @@ -970,54 +1014,6 @@ UwacReturnCode UwacSeatInhibitShortcuts(UwacSeat* s, bool inhibit) return UWAC_SUCCESS; } -UwacReturnCode create_pointer_buffer(UwacSeat* seat, const void* src, size_t size) -{ - UwacReturnCode ret = UWAC_SUCCESS; - UwacBuffer* newBuffers; - int fd; - void* data; - struct wl_shm_pool* pool; - - if (!newBuffers) - return UWAC_ERROR_NOMEMORY; - - fd = uwac_create_anonymous_file(size); - - if (fd < 0) - { - return UWAC_ERROR_INTERNAL; - } - - data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - - if (data == MAP_FAILED) - { - ret = UWAC_ERROR_NOMEMORY; - goto error_mmap; - } - memcpy(data, src, size); - - pool = wl_shm_create_pool(seat->display->shm, fd, size * 2); - - if (!pool) - { - munmap(data, size); - ret = UWAC_ERROR_NOMEMORY; - goto error_mmap; - } - - seat->pointer_buffer = wl_shm_pool_create_buffer(pool, size, - seat->pointer_image->width, - seat->pointer_image->height, - seat->pointer_image->width * 4, - WL_SHM_FORMAT_ARGB8888); - wl_shm_pool_destroy(pool); - -error_mmap: - close(fd); - return ret; -} - UwacReturnCode UwacSeatSetMouseCursor(UwacSeat* seat, const void* data, size_t length, size_t width, size_t height, size_t hot_x, size_t hot_y) @@ -1025,11 +1021,15 @@ UwacReturnCode UwacSeatSetMouseCursor(UwacSeat* seat, const void* data, size_t l if (!seat) return UWAC_ERROR_CLOSED; + fprintf(stderr, "%s: %p\n", __func__, data); + fflush(stderr); + free(seat->pointer_image); - if (seat->pointer_buffer) - wl_buffer_destroy(seat->pointer_buffer); seat->pointer_image = NULL; - seat->pointer_buffer = NULL; + + free(seat->pointer_data); + seat->pointer_data = NULL; + seat->pointer_size = 0; /* There is a cursor provided */ if ((data != NULL) && (length != 0)) @@ -1042,7 +1042,10 @@ UwacReturnCode UwacSeatSetMouseCursor(UwacSeat* seat, const void* data, size_t l seat->pointer_image->hotspot_x = hot_x; seat->pointer_image->hotspot_y = hot_y; - create_pointer_buffer(seat, data, length); + free(seat->pointer_data); + seat->pointer_data = malloc(length); + memcpy(seat->pointer_data, data, length); + seat->pointer_size = length; seat->pointer_type = 2; } diff --git a/uwac/libuwac/uwac-priv.h b/uwac/libuwac/uwac-priv.h index 64dc90607..125c92800 100644 --- a/uwac/libuwac/uwac-priv.h +++ b/uwac/libuwac/uwac-priv.h @@ -160,8 +160,9 @@ struct uwac_seat { struct wl_pointer *pointer; struct wl_surface *pointer_surface; struct wl_cursor_image *pointer_image; + void *pointer_data; + size_t pointer_size; int pointer_type; - struct wl_buffer *pointer_buffer; struct wl_keyboard *keyboard; struct wl_touch *touch; struct wl_data_offer* offer; From 99c92308a312a0ae0966f7fcc29f202defbfcbdb Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 28 Jan 2019 15:46:12 +0100 Subject: [PATCH 5/7] Fixed wayland library detection. --- cmake/FindWayland.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/FindWayland.cmake b/cmake/FindWayland.cmake index 6128c1433..e35173355 100644 --- a/cmake/FindWayland.cmake +++ b/cmake/FindWayland.cmake @@ -53,7 +53,7 @@ find_library(WAYLAND_CURSOR_LIB ) if (WAYLAND_CLIENT_LIB AND WAYLAND_CURSOR_LIB) - list(INSERT WAYLAND_LIBS ${WAYLAND_CLIENT_LIB} ${WAYLAND_CURSOR_LIB}) + list(APPEND WAYLAND_LIBS ${WAYLAND_CLIENT_LIB} ${WAYLAND_CURSOR_LIB}) endif (WAYLAND_CLIENT_LIB AND WAYLAND_CURSOR_LIB) find_path(XKBCOMMON_INCLUDE_DIR xkbcommon/xkbcommon.h From f64db12a2ed6564d41611c68c8457d9cd30f98f1 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 29 Jan 2019 11:07:44 +0100 Subject: [PATCH 6/7] Fixed uninitialized value. --- uwac/libuwac/uwac-input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uwac/libuwac/uwac-input.c b/uwac/libuwac/uwac-input.c index bd6a74bc3..17e1ffa99 100644 --- a/uwac/libuwac/uwac-input.c +++ b/uwac/libuwac/uwac-input.c @@ -82,7 +82,7 @@ error_mmap: static UwacReturnCode set_cursor_image(UwacSeat* seat, uint32_t serial) { - struct wl_buffer* buffer; + struct wl_buffer* buffer = NULL; struct wl_cursor* cursor; struct wl_cursor_image* image; struct wl_surface* surface = NULL; From 32d539b706cbaff96fab057e1bf3ce71f5941ede Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 29 Jan 2019 13:34:27 +0100 Subject: [PATCH 7/7] Removed debug messages. --- uwac/libuwac/uwac-input.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/uwac/libuwac/uwac-input.c b/uwac/libuwac/uwac-input.c index 17e1ffa99..cf1a9099d 100644 --- a/uwac/libuwac/uwac-input.c +++ b/uwac/libuwac/uwac-input.c @@ -1021,9 +1021,6 @@ UwacReturnCode UwacSeatSetMouseCursor(UwacSeat* seat, const void* data, size_t l if (!seat) return UWAC_ERROR_CLOSED; - fprintf(stderr, "%s: %p\n", __func__, data); - fflush(stderr); - free(seat->pointer_image); seat->pointer_image = NULL;