Added mouse cursor callback stubs.
This commit is contained in:
parent
05d9d89796
commit
23fa6b9182
@ -27,6 +27,8 @@ set(${MODULE_PREFIX}_SRCS
|
|||||||
wlfreerdp.h
|
wlfreerdp.h
|
||||||
wlf_disp.c
|
wlf_disp.c
|
||||||
wlf_disp.h
|
wlf_disp.h
|
||||||
|
wlf_pointer.c
|
||||||
|
wlf_pointer.h
|
||||||
wlf_input.c
|
wlf_input.c
|
||||||
wlf_input.h
|
wlf_input.h
|
||||||
wlf_cliprdr.c
|
wlf_cliprdr.c
|
||||||
|
136
client/Wayland/wlf_pointer.c
Normal file
136
client/Wayland/wlf_pointer.c
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
* Wayland Mouse Pointer
|
||||||
|
*
|
||||||
|
* Copyright 2019 Armin Novak <armin.novak@thincast.com>
|
||||||
|
* 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 <freerdp/log.h>
|
||||||
|
#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;
|
||||||
|
}
|
28
client/Wayland/wlf_pointer.h
Normal file
28
client/Wayland/wlf_pointer.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
* Wayland Mouse Pointer
|
||||||
|
*
|
||||||
|
* Copyright 2019 Armin Novak <armin.novak@thincast.com>
|
||||||
|
* 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 <freerdp/graphics.h>
|
||||||
|
|
||||||
|
BOOL wlf_register_pointer(rdpGraphics* graphics);
|
||||||
|
|
||||||
|
#endif /* FREERDP_CLIENT_WAYLAND_POINTER_H */
|
@ -39,6 +39,7 @@
|
|||||||
#include "wlf_cliprdr.h"
|
#include "wlf_cliprdr.h"
|
||||||
#include "wlf_disp.h"
|
#include "wlf_disp.h"
|
||||||
#include "wlf_channels.h"
|
#include "wlf_channels.h"
|
||||||
|
#include "wlf_pointer.h"
|
||||||
|
|
||||||
static BOOL wl_begin_paint(rdpContext* context)
|
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))
|
if (!gdi || (gdi->width < 0) || (gdi->height < 0))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
if (!wlf_register_pointer(instance->context->graphics))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
w = (UINT32)gdi->width;
|
w = (UINT32)gdi->width;
|
||||||
h = (UINT32)gdi->height;
|
h = (UINT32)gdi->height;
|
||||||
context = (wlfContext*) instance->context;
|
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);*/
|
/*printf("UWAC event type %d\n", event.type);*/
|
||||||
switch (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:
|
case UWAC_EVENT_FRAME_DONE:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ struct wlf_context
|
|||||||
UwacDisplay* display;
|
UwacDisplay* display;
|
||||||
HANDLE displayHandle;
|
HANDLE displayHandle;
|
||||||
UwacWindow* window;
|
UwacWindow* window;
|
||||||
|
UwacSeat* seat;
|
||||||
|
|
||||||
BOOL fullscreen;
|
BOOL fullscreen;
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ include(FindPkgConfig)
|
|||||||
if(PKG_CONFIG_FOUND)
|
if(PKG_CONFIG_FOUND)
|
||||||
pkg_check_modules(WAYLAND_SCANNER_PC wayland-scanner)
|
pkg_check_modules(WAYLAND_SCANNER_PC wayland-scanner)
|
||||||
pkg_check_modules(WAYLAND_CLIENT_PC wayland-client)
|
pkg_check_modules(WAYLAND_CLIENT_PC wayland-client)
|
||||||
|
pkg_check_modules(WAYLAND_CURSOR_PC wayland-cursor)
|
||||||
pkg_check_modules(XKBCOMMON_PC xkbcommon)
|
pkg_check_modules(XKBCOMMON_PC xkbcommon)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -41,11 +42,20 @@ find_path(WAYLAND_INCLUDE_DIR wayland-client.h
|
|||||||
HINTS ${WAYLAND_CLIENT_PC_INCLUDE_DIRS}
|
HINTS ${WAYLAND_CLIENT_PC_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
find_library(WAYLAND_LIBS
|
find_library(WAYLAND_CLIENT_LIB
|
||||||
NAMES "wayland-client"
|
NAMES "wayland-client"
|
||||||
HINTS "${WAYLAND_CLIENT_PC_LIBRARY_DIRS}"
|
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
|
find_path(XKBCOMMON_INCLUDE_DIR xkbcommon/xkbcommon.h
|
||||||
HINTS ${XKBCOMMON_PC_INCLUDE_DIRS}
|
HINTS ${XKBCOMMON_PC_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
@ -564,6 +564,25 @@ UWAC_API void* UwacClipboardDataGet(UwacSeat* seat, const char* mime, size_t* si
|
|||||||
*/
|
*/
|
||||||
UWAC_API UwacReturnCode UwacSeatInhibitShortcuts(UwacSeat* seat, bool inhibit);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
|
|
||||||
#include "uwac-os.h"
|
#include "uwac-os.h"
|
||||||
|
#include "wayland-cursor.h"
|
||||||
|
|
||||||
#define TARGET_COMPOSITOR_INTERFACE 3
|
#define TARGET_COMPOSITOR_INTERFACE 3
|
||||||
#define TARGET_SHM_INTERFACE 1
|
#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);
|
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,
|
static void registry_handle_global(void* data, struct wl_registry* registry, uint32_t id,
|
||||||
const char* interface, uint32_t version)
|
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));
|
d->shm = wl_registry_bind(registry, id, &wl_shm_interface, min(TARGET_SHM_INTERFACE, version));
|
||||||
wl_shm_add_listener(d->shm, &shm_listener, d);
|
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)
|
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);
|
UwacSeatRegisterDDM(seat);
|
||||||
UwacSeatRegisterClipboard(seat);
|
UwacSeatRegisterClipboard(seat);
|
||||||
|
UwacRegisterCursor(seat);
|
||||||
ev = (UwacSeatNewEvent*)UwacDisplayNewEvent(d, UWAC_EVENT_NEW_SEAT);
|
ev = (UwacSeatNewEvent*)UwacDisplayNewEvent(d, UWAC_EVENT_NEW_SEAT);
|
||||||
|
|
||||||
if (!ev)
|
if (!ev)
|
||||||
@ -224,6 +246,7 @@ static void registry_handle_global(void* data, struct wl_registry* registry, uin
|
|||||||
{
|
{
|
||||||
UwacSeatRegisterDDM(seat);
|
UwacSeatRegisterDDM(seat);
|
||||||
UwacSeatRegisterClipboard(seat);
|
UwacSeatRegisterClipboard(seat);
|
||||||
|
UwacRegisterCursor(seat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp(interface, "wl_shell") == 0)
|
else if (strcmp(interface, "wl_shell") == 0)
|
||||||
@ -573,6 +596,9 @@ UwacReturnCode UwacCloseDisplay(UwacDisplay** pdisplay)
|
|||||||
if (display->shell)
|
if (display->shell)
|
||||||
wl_shell_destroy(display->shell);
|
wl_shell_destroy(display->shell);
|
||||||
|
|
||||||
|
if (display->cursor_theme)
|
||||||
|
wl_cursor_theme_destroy(display->cursor_theme);
|
||||||
|
|
||||||
if (display->shm)
|
if (display->shm)
|
||||||
wl_shm_destroy(display->shm);
|
wl_shm_destroy(display->shm);
|
||||||
|
|
||||||
|
@ -32,6 +32,62 @@
|
|||||||
#include <sys/timerfd.h>
|
#include <sys/timerfd.h>
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
|
|
||||||
|
#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)
|
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->window = window;
|
||||||
event->x = sx;
|
event->x = sx;
|
||||||
event->y = sy;
|
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,
|
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)
|
if (s->data_source)
|
||||||
wl_data_source_destroy(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);
|
wl_list_remove(&s->link);
|
||||||
free(s);
|
free(s);
|
||||||
}
|
}
|
||||||
@ -898,3 +966,90 @@ UwacReturnCode UwacSeatInhibitShortcuts(UwacSeat* s, bool inhibit)
|
|||||||
return UWAC_ERROR_INTERNAL;
|
return UWAC_ERROR_INTERNAL;
|
||||||
return UWAC_SUCCESS;
|
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);
|
||||||
|
}
|
||||||
|
@ -121,7 +121,7 @@ struct uwac_display {
|
|||||||
uint32_t serial;
|
uint32_t serial;
|
||||||
|
|
||||||
struct wl_cursor_theme *cursor_theme;
|
struct wl_cursor_theme *cursor_theme;
|
||||||
struct wl_cursor **cursors;
|
struct wl_cursor *default_cursor;
|
||||||
|
|
||||||
struct wl_list windows;
|
struct wl_list windows;
|
||||||
|
|
||||||
@ -158,6 +158,10 @@ struct uwac_seat {
|
|||||||
struct wl_data_device* data_device;
|
struct wl_data_device* data_device;
|
||||||
struct wl_data_source* data_source;
|
struct wl_data_source* data_source;
|
||||||
struct wl_pointer *pointer;
|
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_keyboard *keyboard;
|
||||||
struct wl_touch *touch;
|
struct wl_touch *touch;
|
||||||
struct wl_data_offer* offer;
|
struct wl_data_offer* offer;
|
||||||
|
Loading…
Reference in New Issue
Block a user