wlfreerdp: add keyboard and mouse wheel support, fix bugs

This commit does the following:

* fix the keyboard logic (which now fully works), add support for vertical mouse wheel events ;
* make the rendering a lot more efficient, by using RDP damage information to refresh only the relevant part of the buffer ;
* fix two race conditions. wlfreerdp should not crash anymore now ;
* fix shm_open() and shm_unlink() calls ;
* improve the code style.

Signed-off-by: Manuel Bachmann <tarnyko@tarnyko.net>
This commit is contained in:
Manuel Bachmann 2014-11-26 10:38:12 +01:00 committed by Manuel Bachmann
parent 3992e5e650
commit a9cf8b5838
4 changed files with 98 additions and 45 deletions

View File

@ -43,22 +43,29 @@ static void wl_pointer_motion(void* data, struct wl_pointer* pointer, uint32_t t
input = input_w->input;
x = wl_fixed_to_int(sx_w);
y = wl_fixed_to_int(sy_w);
x = (UINT16) wl_fixed_to_int(sx_w);
y = (UINT16) wl_fixed_to_int(sy_w);
input->MouseEvent(input, PTR_FLAGS_MOVE, x, y);
input_w->last_x = x;
input_w->last_y = y;
}
static void wl_pointer_button(void* data, struct wl_pointer* pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
{
wlfInput* input_w = data;
rdpInput* input;
int flags;
UINT16 x;
UINT16 y;
UINT16 flags;
input = input_w->input;
if (state == WL_POINTER_BUTTON_STATE_PRESSED)
flags = PTR_FLAGS_DOWN;
else
flags = 0;
switch (button)
{
@ -72,7 +79,33 @@ static void wl_pointer_button(void* data, struct wl_pointer* pointer, uint32_t s
flags |= PTR_FLAGS_BUTTON3;
break;
default:
break;
return;
}
x = input_w->last_x;
y = input_w->last_y;
input->MouseEvent(input, flags, x, y);
}
static void wl_pointer_axis(void* data, struct wl_pointer* pointer, uint32_t time, uint32_t axis, wl_fixed_t value)
{
wlfInput* input_w = data;
rdpInput* input;
UINT16 flags;
int direction;
input = input_w->input;
flags = PTR_FLAGS_WHEEL;
if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
{
direction = wl_fixed_to_int(value);
if (direction < 0)
flags |= 0x0078;
else
flags |= PTR_FLAGS_WHEEL_NEGATIVE | 0x0088;
}
input->MouseEvent(input, flags, 0, 0);
@ -84,7 +117,7 @@ static const struct wl_pointer_listener wl_pointer_listener =
wl_pointer_leave,
wl_pointer_motion,
wl_pointer_button,
NULL
wl_pointer_axis
};
static void wl_keyboard_keymap(void* data, struct wl_keyboard* keyboard, uint32_t format, int fd, uint32_t size)
@ -94,7 +127,17 @@ static void wl_keyboard_keymap(void* data, struct wl_keyboard* keyboard, uint32_
static void wl_keyboard_enter(void* data, struct wl_keyboard* keyboard, uint32_t serial, struct wl_surface* surface, struct wl_array* keys)
{
wlfInput* input_w = data;
rdpInput* input;
UINT16 x;
UINT16 y;
input = input_w->input;
x = input_w->last_x;
y = input_w->last_y;
input->FocusInEvent(input, 0, x, y);
}
static void wl_keyboard_leave(void* data, struct wl_keyboard* keyboard, uint32_t serial, struct wl_surface* surface)
@ -116,7 +159,7 @@ static void wl_keyboard_key(void* data, struct wl_keyboard* keyboard, uint32_t s
else
key_down = FALSE;
rdp_scancode = freerdp_keyboard_get_rdp_scancode_from_x11_keycode(key);
rdp_scancode = (DWORD) key;
if (rdp_scancode == RDP_SCANCODE_UNKNOWN)
return;
@ -183,6 +226,8 @@ wlfInput* wlf_CreateInput(wlfContext* wlfc)
if (input)
{
input->input = wlfc->context.input;
input->last_x = 0;
input->last_y = 0;
wl_seat_add_listener(seat, &wl_seat_listener, input);
}

View File

@ -28,10 +28,12 @@ typedef struct wlf_input wlfInput;
struct wlf_input
{
rdpInput *input;
rdpInput* input;
UINT16 last_x;
UINT16 last_y;
struct wl_pointer *pointer;
struct wl_keyboard *keyboard;
struct wl_pointer* pointer;
struct wl_keyboard* keyboard;
};
wlfInput* wlf_CreateInput(wlfContext* wlfc);

View File

@ -64,6 +64,8 @@ static void wl_callback_done(void* data, struct wl_callback* callback, uint32_t
wlfWindow* window = data;
wlfBuffer* buffer;
struct wl_shm_pool* shm_pool;
void* shm_data;
void* free_data;
int fd;
int fdt;
@ -74,29 +76,35 @@ static void wl_callback_done(void* data, struct wl_callback* callback, uint32_t
else
return;
fd = shm_open("wlfreerdp_shm", O_CREAT | O_TRUNC | O_RDWR, 0666);
fdt = ftruncate(fd, window->width * window->height * 4);
if (fdt != 0)
{
WLog_ERR(TAG, "window_redraw: could not allocate memory");
close(fd);
return;
}
if (!buffer->buffer) {
fd = shm_open("/wlfreerdp_shm", O_CREAT | O_RDWR, 0666);
fdt = ftruncate(fd, window->width * window->height * 4);
if (fdt != 0)
{
WLog_ERR(TAG, "window_redraw: could not allocate memory");
close(fd);
return;
}
buffer->shm_data = mmap(0, window->width * window->height * 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (buffer->shm_data == MAP_FAILED)
{
WLog_ERR(TAG, "window_redraw: failed to memory map buffer");
close(fd);
return;
}
shm_data = mmap(NULL, window->width * window->height * 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (shm_data == MAP_FAILED)
{
WLog_ERR(TAG, "window_redraw: failed to memory map buffer");
close(fd);
return;
}
shm_pool = wl_shm_create_pool(window->display->shm, fd, window->width * window->height * 4);
buffer->buffer = wl_shm_pool_create_buffer(shm_pool, 0, window->width, window->height, window->width* 4, WL_SHM_FORMAT_XRGB8888);
wl_buffer_add_listener(buffer->buffer, &wl_buffer_listener, buffer);
wl_shm_pool_destroy(shm_pool);
shm_unlink("wlfreerdp_shm");
close(fd);
shm_pool = wl_shm_create_pool(window->display->shm, fd, window->width * window->height * 4);
buffer->buffer = wl_shm_pool_create_buffer(shm_pool, 0, window->width, window->height, window->width* 4, WL_SHM_FORMAT_XRGB8888);
wl_buffer_add_listener(buffer->buffer, &wl_buffer_listener, buffer);
wl_shm_pool_destroy(shm_pool);
shm_unlink("/wlfreerdp_shm");
close(fd);
free_data = buffer->shm_data;
buffer->shm_data = shm_data;
munmap(free_data, window->width * window->height * 4);
}
/* this is the real surface data */
memcpy(buffer->shm_data, (void*) window->data, window->width * window->height * 4);
@ -109,7 +117,6 @@ static void wl_callback_done(void* data, struct wl_callback* callback, uint32_t
wl_surface_commit(window->surface);
buffer->busy = TRUE;
munmap(buffer->shm_data, window->width * window->height * 4);
}
static const struct wl_callback_listener wl_callback_listener =

View File

@ -48,33 +48,32 @@ void wl_begin_paint(rdpContext* context)
void wl_end_paint(rdpContext* context)
{
char *data;
rdpGdi* gdi;
wlfDisplay* display;
wlfWindow* window;
wlfContext* context_w;
void* data;
INT32 x, y;
UINT32 w, h;
int i;
gdi = context->gdi;
if (gdi->primary->hdc->hwnd->invalid->null)
return;
x = gdi->primary->hdc->hwnd->invalid->x;
y = gdi->primary->hdc->hwnd->invalid->y;
w = gdi->primary->hdc->hwnd->invalid->w;
h = gdi->primary->hdc->hwnd->invalid->h;
context_w = (wlfContext*) context;
display = context_w->display;
window = context_w->window;
data = realloc(window->data, gdi->width * gdi->height * 4);
if (!data)
{
if (window->data)
free(window->data);
window->data = NULL;
}
else
{
window->data = data;
memcpy(window->data, (void*) gdi->primary_buffer, gdi->width * gdi->height * 4);
}
for (i = 0; i < h; i++)
memcpy(window->data + ((i+y)*(gdi->width*4)) + x*4,
gdi->primary_buffer + ((i+y)*(gdi->width*4)) + x*4,
w*4);
wlf_RefreshDisplay(display);
}