diff --git a/client/Wayland/CMakeLists.txt b/client/Wayland/CMakeLists.txt index 182fb2bea..66cb0d18b 100644 --- a/client/Wayland/CMakeLists.txt +++ b/client/Wayland/CMakeLists.txt @@ -21,7 +21,14 @@ set(MODULE_PREFIX "FREERDP_CLIENT_WAYLAND") include_directories(${WAYLAND_INCLUDE_DIRS}) set(${MODULE_PREFIX}_SRCS - wlfreerdp.c) + wlf_display.c + wlf_display.h + wlf_window.c + wlf_window.h + wlf_input.c + wlf_input.h + wlfreerdp.c + wlfreerdp.h) add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) diff --git a/client/Wayland/wlf_display.c b/client/Wayland/wlf_display.c new file mode 100644 index 000000000..183444759 --- /dev/null +++ b/client/Wayland/wlf_display.c @@ -0,0 +1,110 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Wayland Displays + * + * Copyright 2014 Manuel Bachmann + * + * 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. + */ + +#include +#include + +#include "wlf_display.h" + +static void wl_registry_handle_global(void* data, struct wl_registry* registry, uint32_t id, const char *interface, uint32_t version) +{ + wlfDisplay* display = data; + + if (strcmp(interface, "wl_compositor") == 0) + display->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 1); + else if (strcmp(interface, "wl_shell") == 0) + display->shell = wl_registry_bind(registry, id, &wl_shell_interface, 1); + else if (strcmp(interface, "wl_shm") == 0) + display->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); + else if (strcmp(interface, "wl_seat") == 0) + display->seat = wl_registry_bind(registry, id, &wl_seat_interface, 1); +} + +static void wl_registry_handle_global_remove(void* data, struct wl_registry* registry, uint32_t name) +{ + +} + +static const struct wl_registry_listener wl_registry_listener = +{ + wl_registry_handle_global, + wl_registry_handle_global_remove +}; + + +wlfDisplay* wlf_CreateDisplay(void) +{ + wlfDisplay* display; + + display = (wlfDisplay*) calloc(1, sizeof(wlfDisplay)); + + if (display) + { + display->display = wl_display_connect(NULL); + + if (!display->display) + { + WLog_ERR(TAG, "wl_pre_connect: failed to connect to Wayland compositor"); + WLog_ERR(TAG, "Please check that the XDG_RUNTIME_DIR environment variable is properly set."); + free(display); + return NULL; + } + + display->registry = wl_display_get_registry(display->display); + wl_registry_add_listener(display->registry, &wl_registry_listener, display); + wl_display_roundtrip(display->display); + + if (!display->compositor || !display->shell || !display->shm) + { + WLog_ERR(TAG, "wl_pre_connect: failed to find needed compositor interfaces"); + free(display); + return NULL; + } + } + + return display; +} + +void wlf_RefreshDisplay(wlfDisplay* display) +{ + wl_display_dispatch(display->display); +} + +void wlf_DestroyDisplay(wlfContext* wlfc, wlfDisplay* display) +{ + if (display == NULL) + return; + + if (wlfc->display == display) + wlfc->display = NULL; + + if (display->seat) + wl_seat_destroy(display->seat); + if (display->shm) + wl_shm_destroy(display->shm); + if (display->shell) + wl_shell_destroy(display->shell); + if (display->compositor) + wl_compositor_destroy(display->compositor); + if (display->registry) + wl_registry_destroy(display->registry); + wl_display_disconnect(display->display); + + free(display); +} diff --git a/client/Wayland/wlf_display.h b/client/Wayland/wlf_display.h new file mode 100644 index 000000000..9301eec77 --- /dev/null +++ b/client/Wayland/wlf_display.h @@ -0,0 +1,43 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Wayland Displays + * + * Copyright 2014 Manuel Bachmann + * + * 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 __WLF_DISPLAY_H +#define __WLF_DISPLAY_H + +#include + +typedef struct wlf_display wlfDisplay; + +#include "wlfreerdp.h" + +struct wlf_display +{ + struct wl_display* display; + struct wl_registry* registry; + struct wl_compositor* compositor; + struct wl_shell* shell; + struct wl_shm* shm; + struct wl_seat* seat; +}; + +wlfDisplay* wlf_CreateDisplay(void); +void wlf_RefreshDisplay(wlfDisplay* display); +void wlf_DestroyDisplay(wlfContext* wlfc, wlfDisplay* display); + +#endif /* __WLF_DISPLAY_H */ diff --git a/client/Wayland/wlf_input.c b/client/Wayland/wlf_input.c new file mode 100644 index 000000000..210c704a7 --- /dev/null +++ b/client/Wayland/wlf_input.c @@ -0,0 +1,207 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Wayland Input + * + * Copyright 2014 Manuel Bachmann + * + * 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. + */ + +#include +#include + +#include + +#include "wlf_input.h" + +static void wl_pointer_enter(void* data, struct wl_pointer* pointer, uint32_t serial, struct wl_surface* surface, wl_fixed_t sx_w, wl_fixed_t sy_w) +{ + +} + +static void wl_pointer_leave(void* data, struct wl_pointer* pointer, uint32_t serial, struct wl_surface* surface) +{ + +} + +static void wl_pointer_motion(void* data, struct wl_pointer* pointer, uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w) +{ + wlfInput* input_w = data; + rdpInput* input; + UINT16 x; + UINT16 y; + + input = input_w->input; + + x = wl_fixed_to_int(sx_w); + y = wl_fixed_to_int(sy_w); + + input->MouseEvent(input, PTR_FLAGS_MOVE, x, 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; + + input = input_w->input; + + if (state == WL_POINTER_BUTTON_STATE_PRESSED) + flags = PTR_FLAGS_DOWN; + + switch (button) + { + case BTN_LEFT: + flags |= PTR_FLAGS_BUTTON1; + break; + case BTN_RIGHT: + flags |= PTR_FLAGS_BUTTON2; + break; + case BTN_MIDDLE: + flags |= PTR_FLAGS_BUTTON3; + break; + default: + break; + } + + input->MouseEvent(input, flags, 0, 0); +} + +static const struct wl_pointer_listener wl_pointer_listener = +{ + wl_pointer_enter, + wl_pointer_leave, + wl_pointer_motion, + wl_pointer_button, + NULL +}; + +static void wl_keyboard_keymap(void* data, struct wl_keyboard* keyboard, uint32_t format, int fd, uint32_t size) +{ + +} + +static void wl_keyboard_enter(void* data, struct wl_keyboard* keyboard, uint32_t serial, struct wl_surface* surface, struct wl_array* keys) +{ + +} + +static void wl_keyboard_leave(void* data, struct wl_keyboard* keyboard, uint32_t serial, struct wl_surface* surface) +{ + +} + +static void wl_keyboard_key(void* data, struct wl_keyboard* keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) +{ + wlfInput* input_w = data; + rdpInput* input; + BOOL key_down; + DWORD rdp_scancode; + + input = input_w->input; + + if (state == WL_KEYBOARD_KEY_STATE_PRESSED) + key_down = TRUE; + else + key_down = FALSE; + + rdp_scancode = freerdp_keyboard_get_rdp_scancode_from_x11_keycode(key); + + if (rdp_scancode == RDP_SCANCODE_UNKNOWN) + return; + + freerdp_input_send_keyboard_event_ex(input, key_down, rdp_scancode); +} + +static void wl_keyboard_modifiers(void* data, struct wl_keyboard* keyboard, uint32_t serial, uint32_t mods_depr, uint32_t mods_latch, uint32_t mods_lock, uint32_t group) +{ + +} + +static const struct wl_keyboard_listener wl_keyboard_listener = +{ + wl_keyboard_keymap, + wl_keyboard_enter, + wl_keyboard_leave, + wl_keyboard_key, + wl_keyboard_modifiers +}; + +static void wl_seat_handle_capabilities(void* data, struct wl_seat* seat, enum wl_seat_capability capabilities) +{ + wlfInput* input = data; + struct wl_pointer* pointer; + struct wl_keyboard* keyboard; + + if (capabilities & WL_SEAT_CAPABILITY_POINTER) + { + pointer = wl_seat_get_pointer(seat); + + input->pointer = pointer; + wl_pointer_add_listener(pointer, &wl_pointer_listener, input); + } + + if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) + { + keyboard = wl_seat_get_keyboard(seat); + + input->keyboard = keyboard; + wl_keyboard_add_listener(keyboard, &wl_keyboard_listener, input); + } + +} + +static const struct wl_seat_listener wl_seat_listener = { + wl_seat_handle_capabilities +}; + + +wlfInput* wlf_CreateInput(wlfContext* wlfc) +{ + wlfInput* input; + struct wl_seat* seat; + + if (!wlfc->display) + return NULL; + if (!wlfc->display->seat) + return NULL; + seat = wlfc->display->seat; + + input = (wlfInput*) calloc(1, sizeof(wlfInput)); + + if (input) + { + input->input = wlfc->context.input; + + wl_seat_add_listener(seat, &wl_seat_listener, input); + } + + return input; +} + +void wlf_DestroyInput(wlfContext* wlfc, wlfInput* input) +{ + if (input == NULL) + return; + + if (wlfc->input == input) + wlfc->input = NULL; + + if (input->pointer) + wl_pointer_release(input->pointer); + if (input->keyboard) + wl_keyboard_release(input->keyboard); + + free(input); +} diff --git a/client/Wayland/wlf_input.h b/client/Wayland/wlf_input.h new file mode 100644 index 000000000..2d738fcd8 --- /dev/null +++ b/client/Wayland/wlf_input.h @@ -0,0 +1,40 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Wayland Input + * + * Copyright 2014 Manuel Bachmann + * + * 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 __WLF_INPUT_H +#define __WLF_INPUT_H + +#include + +typedef struct wlf_input wlfInput; + +#include "wlfreerdp.h" + +struct wlf_input +{ + rdpInput *input; + + struct wl_pointer *pointer; + struct wl_keyboard *keyboard; +}; + +wlfInput* wlf_CreateInput(wlfContext* wlfc); +void wlf_DestroyInput(wlfContext* wlfc, wlfInput* input); + +#endif /* __WLF_INPUT_H */ diff --git a/client/Wayland/wlf_window.c b/client/Wayland/wlf_window.c new file mode 100644 index 000000000..acff11e44 --- /dev/null +++ b/client/Wayland/wlf_window.c @@ -0,0 +1,213 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Wayland Windows + * + * Copyright 2014 Manuel Bachmann + * + * 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. + */ + +#include +#include +#include +#include +#include + +#include "wlf_window.h" + +static void wl_shell_surface_handle_ping(void* data, struct wl_shell_surface* shell_surface, uint32_t serial) +{ + wl_shell_surface_pong(shell_surface, serial); +} + +static void wl_shell_surface_handle_configure(void* data, struct wl_shell_surface* shell_surface, unsigned int edges, int32_t width, int32_t height) +{ + wlfWindow* window = data; + + window->width = width; + window->height = height; +} + +static const struct wl_shell_surface_listener wl_shell_surface_listener = +{ + wl_shell_surface_handle_ping, + wl_shell_surface_handle_configure, + NULL +}; + +static void wl_buffer_release(void* data, struct wl_buffer* wl_buffer) +{ + wlfBuffer* buffer = data; + + buffer->busy = FALSE; +} + +static const struct wl_buffer_listener wl_buffer_listener = +{ + wl_buffer_release +}; + +static const struct wl_callback_listener wl_callback_listener; + +static void wl_callback_done(void* data, struct wl_callback* callback, uint32_t time) +{ + wlfWindow* window = data; + wlfBuffer* buffer; + struct wl_shm_pool* shm_pool; + int fd; + int fdt; + + if (!window->buffers[0].busy) + buffer = &window->buffers[0]; + else if (!window->buffers[1].busy) + buffer = &window->buffers[1]; + 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; + } + + 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_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); + + /* this is the real surface data */ + memcpy(buffer->shm_data, (void*) window->data, window->width * window->height * 4); + wl_surface_attach(window->surface, buffer->buffer, 0, 0); + wl_surface_damage(window->surface, 0, 0, window->width, window->height); + + if (callback) wl_callback_destroy(callback); + window->callback = wl_surface_frame(window->surface); + wl_callback_add_listener(window->callback, &wl_callback_listener, window); + 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 = +{ + wl_callback_done +}; + + +wlfWindow* wlf_CreateDesktopWindow(wlfContext* wlfc, char* name, int width, int height, BOOL decorations) +{ + wlfWindow* window; + + window = (wlfWindow*) calloc(1, sizeof(wlfWindow)); + + if (window) + { + window->width = width; + window->height = height; + window->fullscreen = FALSE; + window->buffers[0].busy = FALSE; + window->buffers[1].busy = FALSE; + window->callback = NULL; + window->display = wlfc->display; + + window->surface = wl_compositor_create_surface(window->display->compositor); + window->shell_surface = wl_shell_get_shell_surface(window->display->shell, window->surface); + wl_shell_surface_add_listener(window->shell_surface, &wl_shell_surface_listener, window); + wl_shell_surface_set_toplevel(window->shell_surface); + + wlf_ResizeDesktopWindow(wlfc, window, width, height); + + wl_surface_damage(window->surface, 0, 0, window->width, window->height); + } + + wlf_SetWindowText(wlfc, window, name); + + return window; +} + +void wlf_ResizeDesktopWindow(wlfContext* wlfc, wlfWindow* window, int width, int height) +{ + window->width = width; + window->height = height; +} + +void wlf_SetWindowText(wlfContext* wlfc, wlfWindow* window, char* name) +{ + wl_shell_surface_set_title(window->shell_surface, name); +} + +void wlf_SetWindowFullscreen(wlfContext* wlfc, wlfWindow* window, BOOL fullscreen) +{ + if (fullscreen) + { + wl_shell_surface_set_fullscreen(window->shell_surface, WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, NULL); + window->fullscreen = TRUE; + } +} + +void wlf_ShowWindow(wlfContext* wlfc, wlfWindow* window, BYTE state) +{ + switch (state) + { + case WINDOW_HIDE: + case WINDOW_SHOW_MINIMIZED: + /* xdg_surface_set_minimized(window->xdg_surface); */ + break; + case WINDOW_SHOW_MAXIMIZED: + wl_shell_surface_set_maximized(window->shell_surface, NULL); + break; + case WINDOW_SHOW: + wl_shell_surface_set_toplevel(window->shell_surface); + break; + } +} + +void wlf_UpdateWindowArea(wlfContext* wlfc, wlfWindow* window, int x, int y, int width, int height) +{ + wl_callback_done(window, NULL, 0); +} + +void wlf_DestroyWindow(wlfContext* wlfc, wlfWindow* window) +{ + if (window == NULL) + return; + + if (wlfc->window == window) + wlfc->window = NULL; + + if (window->buffers[0].buffer) + wl_buffer_destroy(window->buffers[0].buffer); + if (window->buffers[1].buffer) + wl_buffer_destroy(window->buffers[1].buffer); + if (window->shell_surface) + wl_shell_surface_destroy(window->shell_surface); + if (window->surface) + wl_surface_destroy(window->surface); + + free(window->data); + free(window); +} diff --git a/client/Wayland/wlf_window.h b/client/Wayland/wlf_window.h new file mode 100644 index 000000000..df3628909 --- /dev/null +++ b/client/Wayland/wlf_window.h @@ -0,0 +1,58 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Wayland Windows + * + * Copyright 2014 Manuel Bachmann + * + * 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 __WLF_WINDOW_H +#define __WLF_WINDOW_H + +#include + +typedef struct wlf_window wlfWindow; + +#include "wlfreerdp.h" + +struct wlf_buffer +{ + struct wl_buffer* buffer; + void* shm_data; + BOOL busy; +}; +typedef struct wlf_buffer wlfBuffer; + +struct wlf_window +{ + int width; + int height; + struct wl_surface* surface; + struct wl_shell_surface* shell_surface; + struct wl_callback* callback; + wlfBuffer buffers[2]; + wlfDisplay* display; + void* data; + BOOL fullscreen; +}; + +wlfWindow* wlf_CreateDesktopWindow(wlfContext* wlfc, char* name, int width, int height, BOOL decorations); +void wlf_ResizeDesktopWindow(wlfContext* wlfc, wlfWindow* window, int width, int height); +void wlf_SetWindowText(wlfContext* wlfc, wlfWindow* window, char* name); +void wlf_SetWindowFullscreen(wlfContext* wlfc, wlfWindow* window, BOOL fullscree); +void wlf_ShowWindow(wlfContext* wlfc, wlfWindow* window, BYTE state); +void wlf_UpdateWindowArea(wlfContext* wlfc, wlfWindow* window, int x, int y, int width, int height); +void wlf_DestroyWindow(wlfContext* wlfc, wlfWindow* window); + +#endif /* __WLF_WINDOW_H */ diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c index e7f296444..dfa5c5bd6 100644 --- a/client/Wayland/wlfreerdp.c +++ b/client/Wayland/wlfreerdp.c @@ -1,6 +1,6 @@ /** * FreeRDP: A Remote Desktop Protocol Implementation - * Wayland Client Interface + * Wayland Client * * Copyright 2014 Manuel Bachmann * @@ -19,157 +19,12 @@ #include #include -#include -#include -#include -#include -#include #include #include #include -#include - -#define TAG CLIENT_TAG("wayland") - -struct display -{ - struct wl_display* display; - struct wl_registry* registry; - struct wl_compositor* compositor; - struct wl_shell* shell; - struct wl_shm* shm; -}; - -struct buffer -{ - struct wl_buffer* buffer; - void* shm_data; - int busy; -}; - -struct window -{ - int width, height; - struct wl_surface* surface; - struct wl_shell_surface* shell_surface; - struct wl_callback* callback; - struct buffer buffers[2]; - struct display* display; - void* data; -}; - -struct wl_context -{ - rdpContext _p; - struct display* display; - struct window* window; -}; - -static void wl_buffer_release(void* data, struct wl_buffer* wl_buffer) -{ - struct buffer* buffer = data; - - buffer->busy = 0; -} - -static const struct wl_buffer_listener wl_buffer_listener = -{ - wl_buffer_release -}; - -static void window_redraw(void* data, struct wl_callback* callback, uint32_t time); -static const struct wl_callback_listener wl_callback_listener = -{ - window_redraw -}; - -static void window_redraw(void* data, struct wl_callback* callback, uint32_t time) -{ - struct window* window = data; - struct wl_shm_pool* shm_pool; - struct buffer* buffer; - int fd; - int fdt; - - if (!window->buffers[0].busy) - buffer = &window->buffers[0]; - else if (!window->buffers[1].busy) - buffer = &window->buffers[1]; - 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; - } - - 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_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); - - /* this is the real surface data */ - memcpy(buffer->shm_data, (void*) window->data, window->width * window->height * 4); - wl_surface_attach(window->surface, buffer->buffer, 0, 0); - wl_surface_damage(window->surface, 0, 0, window->width, window->height); - - if (callback) wl_callback_destroy(callback); - window->callback = wl_surface_frame(window->surface); - wl_callback_add_listener(window->callback, &wl_callback_listener, window); - wl_surface_commit(window->surface); - - buffer->busy = 1; - munmap(buffer->shm_data, window->width * window->height * 4); -} - -static void wl_shell_surface_handle_ping(void* data, struct wl_shell_surface* shell_surface, uint32_t serial) -{ - wl_shell_surface_pong(shell_surface, serial); -} - -static const struct wl_shell_surface_listener wl_shell_surface_listener = -{ - wl_shell_surface_handle_ping -}; - -static void wl_registry_handle_global(void* data, struct wl_registry* registry, uint32_t id, const char *interface, uint32_t version) -{ - struct display* display = data; - - if (strcmp(interface, "wl_compositor") == 0) - display->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 1); - else if (strcmp(interface, "wl_shell") == 0) - display->shell = wl_registry_bind(registry, id, &wl_shell_interface, 1); - else if (strcmp(interface, "wl_shm") == 0) - display->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); -} - -static void wl_registry_handle_global_remove(void* data, struct wl_registry* registry, uint32_t name) -{ - -} - -static const struct wl_registry_listener wl_registry_listener = -{ - wl_registry_handle_global, - wl_registry_handle_global_remove -}; +#include "wlfreerdp.h" int wl_context_new(freerdp* instance, rdpContext* context) { @@ -195,15 +50,15 @@ void wl_end_paint(rdpContext* context) { char *data; rdpGdi* gdi; - struct display* display; - struct window* window; - struct wl_context* context_w; + wlfDisplay* display; + wlfWindow* window; + wlfContext* context_w; gdi = context->gdi; if (gdi->primary->hdc->hwnd->invalid->null) return; - context_w = (struct wl_context*) context; + context_w = (wlfContext*) context; display = context_w->display; window = context_w->window; @@ -220,73 +75,41 @@ void wl_end_paint(rdpContext* context) window->data = data; memcpy(window->data, (void*) gdi->primary_buffer, gdi->width * gdi->height * 4); } - wl_display_dispatch(display->display); + + wlf_RefreshDisplay(display); } BOOL wl_pre_connect(freerdp* instance) { - struct display* display; - struct wl_context* context; + wlfDisplay* display; + wlfInput* input; + wlfContext* context; freerdp_channels_pre_connect(instance->context->channels, instance); - display = malloc(sizeof(*display)); - display->display = wl_display_connect(NULL); + context = (wlfContext*) instance->context; - if (!display->display) - { - WLog_ERR(TAG, "wl_pre_connect: failed to connect to Wayland compositor"); - WLog_ERR(TAG, "Please check that the XDG_RUNTIME_DIR environment variable is properly set."); - free(display); - return FALSE; - } - - display->registry = wl_display_get_registry(display->display); - wl_registry_add_listener(display->registry, &wl_registry_listener, display); - wl_display_roundtrip(display->display); - - if (!display->compositor || !display->shell || !display->shm) - { - WLog_ERR(TAG, "wl_pre_connect: failed to find needed compositor interfaces"); - free(display); - return FALSE; - } - - /* put Wayland data in the context here */ - context = (struct wl_context*) instance->context; + display = wlf_CreateDisplay(); context->display = display; + input = wlf_CreateInput(context); + context->input = input; + return TRUE; } BOOL wl_post_connect(freerdp* instance) { - struct window* window; - struct wl_context* context; - - context = (struct wl_context*) instance->context; - - window = malloc(sizeof(*window)); - window->width = instance->settings->DesktopWidth; - window->height = instance->settings->DesktopHeight; - window->buffers[0].busy = 0; - window->buffers[1].busy = 0; - window->callback = NULL; - window->display = context->display; - window->surface = wl_compositor_create_surface(window->display->compositor); - window->shell_surface = wl_shell_get_shell_surface(window->display->shell, window->surface); - - wl_shell_surface_add_listener(window->shell_surface, &wl_shell_surface_listener, NULL); - wl_shell_surface_set_title(window->shell_surface, "FreeRDP"); - wl_shell_surface_set_toplevel(window->shell_surface); - wl_surface_damage(window->surface, 0, 0, window->width, window->height); - - /* GC/GDI logic here */ rdpGdi* gdi; + wlfWindow* window; + wlfContext* context; gdi_init(instance, CLRCONV_ALPHA | CLRCONV_INVERT | CLRBUF_32BPP, NULL); gdi = instance->context->gdi; + context = (wlfContext*) instance->context; + window = wlf_CreateDesktopWindow(context, "FreeRDP", gdi->width, gdi->height, FALSE); + /* fill buffer with first image here */ window->data = malloc (gdi->width * gdi->height *4); memcpy(window->data, (void*) gdi->primary_buffer, gdi->width * gdi->height * 4); @@ -298,7 +121,7 @@ BOOL wl_post_connect(freerdp* instance) freerdp_channels_post_connect(instance->context->channels, instance); - window_redraw(window, NULL, 0); + wlf_UpdateWindowArea(context, window, 0, 0, gdi->width, gdi->height); return TRUE; } @@ -416,26 +239,12 @@ int wlfreerdp_run(freerdp* instance) } } - struct display* display; - struct window* window; - struct wl_context* context; + wlfContext* context; - context = (struct wl_context*) instance->context; - display = context->display; - window = context->window; - free(window->buffers[0].shm_data); - free(window->buffers[1].shm_data); - free(window->data); - - wl_buffer_destroy(window->buffers[0].buffer); - wl_buffer_destroy(window->buffers[1].buffer); - wl_shell_surface_destroy(window->shell_surface); - wl_surface_destroy(window->surface); - wl_shm_destroy(display->shm); - wl_shell_destroy(display->shell); - wl_compositor_destroy(display->compositor); - wl_registry_destroy(display->registry); - wl_display_disconnect(display->display); + context = (wlfContext*) instance->context; + wlf_DestroyWindow(context, context->window); + wlf_DestroyInput(context, context->input); + wlf_DestroyDisplay(context, context->display); freerdp_channels_close(instance->context->channels, instance); freerdp_channels_free(instance->context->channels); @@ -454,14 +263,14 @@ int main(int argc, char* argv[]) instance->PostConnect = wl_post_connect; instance->VerifyCertificate = wl_verify_certificate; - instance->ContextSize = sizeof(struct wl_context); + instance->ContextSize = sizeof(wlfContext); instance->ContextNew = wl_context_new; instance->ContextFree = wl_context_free; freerdp_context_new(instance); status = freerdp_client_settings_parse_command_line_arguments(instance->settings, argc, argv); - status = freerdp_client_settings_command_line_status_print(instance->settings, status, argc, argv); + status = freerdp_client_settings_command_line_status_print(instance->settings, argc, argv); if (status) exit(0); diff --git a/client/Wayland/wlfreerdp.h b/client/Wayland/wlfreerdp.h new file mode 100644 index 000000000..bf4da6faf --- /dev/null +++ b/client/Wayland/wlfreerdp.h @@ -0,0 +1,45 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Wayland Client + * + * Copyright 2014 Manuel Bachmann + * + * 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 __WLFREERDP_H +#define __WLFREERDP_H + +#include +#include +#include + +#define TAG CLIENT_TAG("wayland") + +typedef struct wlf_context wlfContext; + +#include "wlf_display.h" +#include "wlf_window.h" +#include "wlf_input.h" + +struct wlf_context +{ + rdpContext context; + + wlfDisplay* display; + wlfWindow* window; + wlfInput* input; +}; + +#endif /* __WLFREERDP_H */ +