diff options
Diffstat (limited to 'backend')
-rw-r--r-- | backend/backend.c | 39 | ||||
-rw-r--r-- | backend/meson.build | 1 | ||||
-rw-r--r-- | backend/rdp/backend.c | 133 | ||||
-rw-r--r-- | backend/rdp/keyboard.c | 219 | ||||
-rw-r--r-- | backend/rdp/listener.c | 61 | ||||
-rw-r--r-- | backend/rdp/meson.build | 36 | ||||
-rw-r--r-- | backend/rdp/output.c | 331 | ||||
-rw-r--r-- | backend/rdp/peer.c | 360 | ||||
-rw-r--r-- | backend/rdp/pointer.c | 40 |
9 files changed, 0 insertions, 1220 deletions
diff --git a/backend/backend.c b/backend/backend.c index 6b804d3c..c71b072f 100644 --- a/backend/backend.c +++ b/backend/backend.c @@ -21,9 +21,6 @@ #if WLR_HAS_X11_BACKEND #include <wlr/backend/x11.h> #endif -#if WLR_HAS_RDP_BACKEND -#include <wlr/backend/rdp.h> -#endif void wlr_backend_init(struct wlr_backend *backend, const struct wlr_backend_impl *impl) { @@ -137,38 +134,6 @@ static struct wlr_backend *attempt_headless_backend( return backend; } -#if WLR_HAS_RDP_BACKEND -static struct wlr_backend *attempt_rdp_backend(struct wl_display *display, - wlr_renderer_create_func_t create_renderer_func) { - const char *cert_path = getenv("WLR_RDP_TLS_CERT_PATH"); - const char *key_path = getenv("WLR_RDP_TLS_KEY_PATH"); - if (!cert_path || !key_path) { - wlr_log(WLR_ERROR, "The RDP backend requires WLR_RDP_TLS_CERT_PATH " - "and WLR_RDP_TLS_KEY_PATH to be set."); - return NULL; - } - struct wlr_backend *backend = wlr_rdp_backend_create( - display, create_renderer_func, cert_path, key_path); - const char *address = getenv("WLR_RDP_ADDRESS"); - if (address) { - wlr_rdp_backend_set_address(backend, address); - } - const char *_port = getenv("WLR_RDP_PORT"); - if (_port) { - char *endptr; - int port = strtol(_port, &endptr, 10); - if (*endptr || port <= 0 || port > 65535) { - wlr_log(WLR_ERROR, "Expected WLR_RDP_PORT to be a " - "positive integer less or equal to 65535"); - wlr_backend_destroy(backend); - return NULL; - } - wlr_rdp_backend_set_port(backend, port); - } - return backend; -} -#endif - static struct wlr_backend *attempt_noop_backend(struct wl_display *display) { struct wlr_backend *backend = wlr_noop_backend_create(display); if (backend == NULL) { @@ -220,10 +185,6 @@ static struct wlr_backend *attempt_backend_by_name(struct wl_display *display, #endif } else if (strcmp(name, "headless") == 0) { return attempt_headless_backend(display, create_renderer_func); -#if WLR_HAS_RDP_BACKEND - } else if (strcmp(name, "rdp") == 0) { - return attempt_rdp_backend(display, create_renderer_func); -#endif } else if (strcmp(name, "noop") == 0) { return attempt_noop_backend(display); } else if (strcmp(name, "drm") == 0 || strcmp(name, "libinput") == 0) { diff --git a/backend/meson.build b/backend/meson.build index 373102b6..3cd24b39 100644 --- a/backend/meson.build +++ b/backend/meson.build @@ -5,7 +5,6 @@ subdir('headless') subdir('libinput') subdir('multi') subdir('noop') -subdir('rdp') subdir('wayland') subdir('x11') diff --git a/backend/rdp/backend.c b/backend/rdp/backend.c deleted file mode 100644 index c0b63921..00000000 --- a/backend/rdp/backend.c +++ /dev/null @@ -1,133 +0,0 @@ -#define _POSIX_C_SOURCE 200809L -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include <wlr/render/egl.h> -#include <wlr/render/gles2.h> -#include <wlr/util/log.h> -#include "backend/rdp.h" -#include "util/signal.h" - -struct wlr_rdp_backend *rdp_backend_from_backend( - struct wlr_backend *wlr_backend) { - assert(wlr_backend_is_rdp(wlr_backend)); - return (struct wlr_rdp_backend *)wlr_backend; -} - -static bool backend_start(struct wlr_backend *wlr_backend) { - struct wlr_rdp_backend *backend = - rdp_backend_from_backend(wlr_backend); - assert(backend->listener == NULL); - wlr_log(WLR_INFO, "Starting RDP backend"); - if (!rdp_configure_listener(backend)) { - return false; - } - return true; -} - -void wlr_rdp_backend_set_address(struct wlr_backend *wlr_backend, - const char *address) { - struct wlr_rdp_backend *backend = - rdp_backend_from_backend(wlr_backend); - assert(backend->listener == NULL); - backend->address = strdup(address); -} - -void wlr_rdp_backend_set_port(struct wlr_backend *wlr_backend, int port) { - struct wlr_rdp_backend *backend = - rdp_backend_from_backend(wlr_backend); - assert(backend->listener == NULL); - backend->port = port; -} - -static void backend_destroy(struct wlr_backend *wlr_backend) { - struct wlr_rdp_backend *backend = - rdp_backend_from_backend(wlr_backend); - if (!wlr_backend) { - return; - } - - wl_list_remove(&backend->display_destroy.link); - - struct wlr_rdp_peer_context *client; - wl_list_for_each(client, &backend->clients, link) { - freerdp_peer_context_free(client->peer); - freerdp_peer_free(client->peer); - } - - wlr_signal_emit_safe(&wlr_backend->events.destroy, backend); - - wlr_renderer_destroy(backend->renderer); - wlr_egl_finish(&backend->egl); - free(backend->address); - free(backend); -} - -static struct wlr_renderer *backend_get_renderer( - struct wlr_backend *wlr_backend) { - struct wlr_rdp_backend *backend = - rdp_backend_from_backend(wlr_backend); - return backend->renderer; -} - -static const struct wlr_backend_impl backend_impl = { - .start = backend_start, - .destroy = backend_destroy, - .get_renderer = backend_get_renderer, -}; - -static void handle_display_destroy(struct wl_listener *listener, void *data) { - struct wlr_rdp_backend *backend = - wl_container_of(listener, backend, display_destroy); - backend_destroy(&backend->backend); -} - -struct wlr_backend *wlr_rdp_backend_create(struct wl_display *display, - wlr_renderer_create_func_t create_renderer_func, - const char *tls_cert_path, const char *tls_key_path) { - wlr_log(WLR_INFO, "Creating RDP backend"); - - struct wlr_rdp_backend *backend = - calloc(1, sizeof(struct wlr_rdp_backend)); - if (!backend) { - wlr_log(WLR_ERROR, "Failed to allocate wlr_rdp_backend"); - return NULL; - } - wlr_backend_init(&backend->backend, &backend_impl); - backend->display = display; - backend->tls_cert_path = tls_cert_path; - backend->tls_key_path = tls_key_path; - backend->address = strdup("127.0.0.1"); - backend->port = 3389; - wl_list_init(&backend->clients); - - static const EGLint config_attribs[] = { - EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, - EGL_ALPHA_SIZE, 0, - EGL_BLUE_SIZE, 1, - EGL_GREEN_SIZE, 1, - EGL_RED_SIZE, 1, - EGL_NONE, - }; - - if (!create_renderer_func) { - create_renderer_func = wlr_renderer_autocreate; - } - - backend->renderer = create_renderer_func(&backend->egl, - EGL_PLATFORM_SURFACELESS_MESA, NULL, (EGLint*)config_attribs, 0); - if (!backend->renderer) { - wlr_log(WLR_ERROR, "Failed to create renderer"); - free(backend); - return NULL; - } - - backend->display_destroy.notify = handle_display_destroy; - wl_display_add_destroy_listener(display, &backend->display_destroy); - - return &backend->backend; -} - -bool wlr_backend_is_rdp(struct wlr_backend *backend) { - return backend->impl == &backend_impl; -} diff --git a/backend/rdp/keyboard.c b/backend/rdp/keyboard.c deleted file mode 100644 index 78dd8b08..00000000 --- a/backend/rdp/keyboard.c +++ /dev/null @@ -1,219 +0,0 @@ -#include <stdlib.h> -#include <wayland-server-core.h> -#include <wlr/types/wlr_input_device.h> -#include <wlr/types/wlr_keyboard.h> -#include <wlr/interfaces/wlr_keyboard.h> -#include <wlr/interfaces/wlr_input_device.h> -#include <wlr/util/log.h> -#include <xkbcommon/xkbcommon.h> -#include "backend/rdp.h" -#include "util/signal.h" - -struct rdp_to_xkb_keyboard_layout { - UINT32 rdp_layout_code; - const char *xkb_layout; - const char *xkb_variant; -}; - -/* table reversed from - https://github.com/awakecoding/FreeRDP/blob/master/libfreerdp/locale/xkb_layout_ids.c#L811 */ -static struct rdp_to_xkb_keyboard_layout rdp_keyboards[] = { - {KBD_ARABIC_101, "ara", 0}, - {KBD_BULGARIAN, 0, 0}, - {KBD_CHINESE_TRADITIONAL_US, 0, 0}, - {KBD_CZECH, "cz", 0}, - {KBD_CZECH_PROGRAMMERS, "cz", "bksl"}, - {KBD_CZECH_QWERTY, "cz", "qwerty"}, - {KBD_DANISH, "dk", 0}, - {KBD_GERMAN, "de", 0}, - {KBD_GERMAN_NEO, "de", "neo"}, - {KBD_GERMAN_IBM, "de", "qwerty"}, - {KBD_GREEK, "gr", 0}, - {KBD_GREEK_220, "gr", "simple"}, - {KBD_GREEK_319, "gr", "extended"}, - {KBD_GREEK_POLYTONIC, "gr", "polytonic"}, - {KBD_US, "us", 0}, - {KBD_US_ENGLISH_TABLE_FOR_IBM_ARABIC_238_L, "ara", "buckwalter"}, - {KBD_SPANISH, "es", 0}, - {KBD_SPANISH_VARIATION, "es", "nodeadkeys"}, - {KBD_FINNISH, "fi", 0}, - {KBD_FRENCH, "fr", 0}, - {KBD_HEBREW, "il", 0}, - {KBD_HUNGARIAN, "hu", 0}, - {KBD_HUNGARIAN_101_KEY, "hu", "standard"}, - {KBD_ICELANDIC, "is", 0}, - {KBD_ITALIAN, "it", 0}, - {KBD_ITALIAN_142, "it", "nodeadkeys"}, - {KBD_JAPANESE, "jp", 0}, - {KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002, "jp", "kana"}, - {KBD_KOREAN, "kr", 0}, - {KBD_KOREAN_INPUT_SYSTEM_IME_2000, "kr", "kr104"}, - {KBD_DUTCH, "nl", 0}, - {KBD_NORWEGIAN, "no", 0}, - {KBD_POLISH_PROGRAMMERS, "pl", 0}, - {KBD_POLISH_214, "pl", "qwertz"}, - {KBD_ROMANIAN, "ro", 0}, - {KBD_RUSSIAN, "ru", 0}, - {KBD_RUSSIAN_TYPEWRITER, "ru", "typewriter"}, - {KBD_CROATIAN, "hr", 0}, - {KBD_SLOVAK, "sk", 0}, - {KBD_SLOVAK_QWERTY, "sk", "qwerty"}, - {KBD_ALBANIAN, 0, 0}, - {KBD_SWEDISH, "se", 0}, - {KBD_THAI_KEDMANEE, "th", 0}, - {KBD_THAI_KEDMANEE_NON_SHIFTLOCK, "th", "tis"}, - {KBD_TURKISH_Q, "tr", 0}, - {KBD_TURKISH_F, "tr", "f"}, - {KBD_URDU, "in", "urd-phonetic3"}, - {KBD_UKRAINIAN, "ua", 0}, - {KBD_BELARUSIAN, "by", 0}, - {KBD_SLOVENIAN, "si", 0}, - {KBD_ESTONIAN, "ee", 0}, - {KBD_LATVIAN, "lv", 0}, - {KBD_LITHUANIAN_IBM, "lt", "ibm"}, - {KBD_FARSI, "af", 0}, - {KBD_VIETNAMESE, "vn", 0}, - {KBD_ARMENIAN_EASTERN, "am", 0}, - {KBD_AZERI_LATIN, 0, 0}, - {KBD_FYRO_MACEDONIAN, "mk", 0}, - {KBD_GEORGIAN, "ge", 0}, - {KBD_FAEROESE, 0, 0}, - {KBD_DEVANAGARI_INSCRIPT, 0, 0}, - {KBD_MALTESE_47_KEY, 0, 0}, - {KBD_NORWEGIAN_WITH_SAMI, "no", "smi"}, - {KBD_KAZAKH, "kz", 0}, - {KBD_KYRGYZ_CYRILLIC, "kg", "phonetic"}, - {KBD_TATAR, "ru", "tt"}, - {KBD_BENGALI, "bd", 0}, - {KBD_BENGALI_INSCRIPT, "bd", "probhat"}, - {KBD_PUNJABI, 0, 0}, - {KBD_GUJARATI, "in", "guj"}, - {KBD_TAMIL, "in", "tam"}, - {KBD_TELUGU, "in", "tel"}, - {KBD_KANNADA, "in", "kan"}, - {KBD_MALAYALAM, "in", "mal"}, - {KBD_HINDI_TRADITIONAL, "in", 0}, - {KBD_MARATHI, 0, 0}, - {KBD_MONGOLIAN_CYRILLIC, "mn", 0}, - {KBD_UNITED_KINGDOM_EXTENDED, "gb", "intl"}, - {KBD_SYRIAC, "syc", 0}, - {KBD_SYRIAC_PHONETIC, "syc", "syc_phonetic"}, - {KBD_NEPALI, "np", 0}, - {KBD_PASHTO, "af", "ps"}, - {KBD_DIVEHI_PHONETIC, 0, 0}, - {KBD_LUXEMBOURGISH, 0, 0}, - {KBD_MAORI, "mao", 0}, - {KBD_CHINESE_SIMPLIFIED_US, 0, 0}, - {KBD_SWISS_GERMAN, "ch", "de_nodeadkeys"}, - {KBD_UNITED_KINGDOM, "gb", 0}, - {KBD_LATIN_AMERICAN, "latam", 0}, - {KBD_BELGIAN_FRENCH, "be", 0}, - {KBD_BELGIAN_PERIOD, "be", "oss_sundeadkeys"}, - {KBD_PORTUGUESE, "pt", 0}, - {KBD_SERBIAN_LATIN, "rs", 0}, - {KBD_AZERI_CYRILLIC, "az", "cyrillic"}, - {KBD_SWEDISH_WITH_SAMI, "se", "smi"}, - {KBD_UZBEK_CYRILLIC, "af", "uz"}, - {KBD_INUKTITUT_LATIN, "ca", "ike"}, - {KBD_CANADIAN_FRENCH_LEGACY, "ca", "fr-legacy"}, - {KBD_SERBIAN_CYRILLIC, "rs", 0}, - {KBD_CANADIAN_FRENCH, "ca", "fr-legacy"}, - {KBD_SWISS_FRENCH, "ch", "fr"}, - {KBD_BOSNIAN, "ba", 0}, - {KBD_IRISH, 0, 0}, - {KBD_BOSNIAN_CYRILLIC, "ba", "us"}, - {KBD_UNITED_STATES_DVORAK, "us", "dvorak"}, - {KBD_PORTUGUESE_BRAZILIAN_ABNT2, "br", "nativo"}, - {KBD_CANADIAN_MULTILINGUAL_STANDARD, "ca", "multix"}, - {KBD_GAELIC, "ie", "CloGaelach"}, - - {0x00000000, 0, 0}, -}; - -/* taken from 2.2.7.1.6 Input Capability Set (TS_INPUT_CAPABILITYSET) */ -static char *rdp_keyboard_types[] = { - "", /* 0: unused */ - "", /* 1: IBM PC/XT or compatible (83-key) keyboard */ - "", /* 2: Olivetti "ICO" (102-key) keyboard */ - "", /* 3: IBM PC/AT (84-key) or similar keyboard */ - "pc102",/* 4: IBM enhanced (101- or 102-key) keyboard */ - "", /* 5: Nokia 1050 and similar keyboards */ - "", /* 6: Nokia 9140 and similar keyboards */ - "" /* 7: Japanese keyboard */ -}; - -static void keyboard_destroy(struct wlr_input_device *wlr_device) { - struct wlr_rdp_keyboard *keyboard = - (struct wlr_rdp_keyboard *)wlr_device->keyboard; - xkb_keymap_unref(keyboard->keymap); - free(keyboard); -} - -static struct wlr_input_device_impl input_device_impl = { - .destroy = keyboard_destroy, -}; - -struct wlr_rdp_input_device *wlr_rdp_keyboard_create( - struct wlr_rdp_backend *backend, rdpSettings *settings) { - struct wlr_rdp_input_device *device = - calloc(1, sizeof(struct wlr_rdp_input_device)); - if (!device) { - wlr_log(WLR_ERROR, "Failed to allcoate RDP input device"); - return NULL; - } - - int vendor = 0; - int product = 0; - const char *name = "rdp"; - struct wlr_input_device *wlr_device = &device->wlr_input_device; - wlr_input_device_init(wlr_device, WLR_INPUT_DEVICE_KEYBOARD, - &input_device_impl, name, vendor, product); - - struct wlr_rdp_keyboard *keyboard = - calloc(1, sizeof(struct wlr_rdp_keyboard)); - if (!keyboard) { - wlr_log(WLR_ERROR, "Failed to allocate RDP pointer device"); - goto error; - } - wlr_device->keyboard = (struct wlr_keyboard *)keyboard; - wlr_keyboard_init(wlr_device->keyboard, NULL); - - wlr_log(WLR_DEBUG, "RDP keyboard layout: 0x%x type: 0x%x subtype: 0x%x " - "function_keys 0x%x", settings->KeyboardLayout, - settings->KeyboardType, settings->KeyboardSubType, - settings->KeyboardFunctionKey); - - // We need to set up an XKB context and jump through some hoops to convert - // RDP input events into scancodes - struct xkb_rule_names xkb_rule_names = { 0 }; - if (settings->KeyboardType <= 7) { - xkb_rule_names.model = rdp_keyboard_types[settings->KeyboardType]; - } - for (int i = 0; rdp_keyboards[i].rdp_layout_code; ++i) { - if (rdp_keyboards[i].rdp_layout_code == settings->KeyboardLayout) { - xkb_rule_names.layout = rdp_keyboards[i].xkb_layout; - xkb_rule_names.variant = rdp_keyboards[i].xkb_variant; - wlr_log(WLR_DEBUG, "Mapped RDP keyboard to xkb layout %s variant " - "%s", xkb_rule_names.layout, xkb_rule_names.variant); - break; - } - } - if (xkb_rule_names.layout) { - struct xkb_context *xkb_context = xkb_context_new(0); - if (!xkb_context) { - wlr_log(WLR_DEBUG, "Failed to allocate xkb context"); - goto error; - } - keyboard->keymap = - xkb_keymap_new_from_names(xkb_context, &xkb_rule_names, 0); - xkb_context_unref(xkb_context); - } - - wlr_keyboard_set_keymap(wlr_device->keyboard, keyboard->keymap); - - wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_device); - return device; -error: - wlr_input_device_destroy(wlr_device); - return NULL; -} diff --git a/backend/rdp/listener.c b/backend/rdp/listener.c deleted file mode 100644 index cfbdc537..00000000 --- a/backend/rdp/listener.c +++ /dev/null @@ -1,61 +0,0 @@ -#include <stdlib.h> -#include <wlr/util/log.h> -#include "backend/rdp.h" - -static int rdp_incoming_peer( - freerdp_listener *listener, freerdp_peer *client) { - struct wlr_rdp_backend *backend = - (struct wlr_rdp_backend *)listener->param4; - if (rdp_peer_init(client, backend) < 0) { - wlr_log(WLR_ERROR, "Error initializing incoming peer"); - return false; - } - return true; -} - -static int rdp_listener_activity(int fd, uint32_t mask, void *data) { - freerdp_listener *listener = data; - if (!(mask & WL_EVENT_READABLE)) { - return 0; - } - if (!listener->CheckFileDescriptor(listener)) { - wlr_log(WLR_ERROR, "Failed to check FreeRDP file descriptor"); - return -1; - } - return 0; -} - -bool rdp_configure_listener(struct wlr_rdp_backend *backend) { - backend->listener = freerdp_listener_new(); - if (!backend->listener) { - wlr_log(WLR_ERROR, "Failed to allocate FreeRDP listener"); - return false; - } - backend->listener->PeerAccepted = rdp_incoming_peer; - backend->listener->param4 = backend; - if (!backend->listener->Open(backend->listener, - backend->address, backend->port)) { - wlr_log(WLR_ERROR, "Failed to bind to RDP socket"); - return false; - } - int rcount = 0; - void *rfds[MAX_FREERDP_FDS]; - if (!backend->listener->GetFileDescriptor( - backend->listener, rfds, &rcount)) { - wlr_log(WLR_ERROR, "Failed to get FreeRDP file descriptors"); - return false; - } - struct wl_event_loop *event_loop = - wl_display_get_event_loop(backend->display); - int i; - for (i = 0; i < rcount; ++i) { - int fd = (int)(long)(rfds[i]); - backend->listener_events[i] = wl_event_loop_add_fd( - event_loop, fd, WL_EVENT_READABLE, rdp_listener_activity, - backend->listener); - } - for (; i < MAX_FREERDP_FDS; ++i) { - backend->listener_events[i] = NULL; - } - return true; -} diff --git a/backend/rdp/meson.build b/backend/rdp/meson.build deleted file mode 100644 index 40259c65..00000000 --- a/backend/rdp/meson.build +++ /dev/null @@ -1,36 +0,0 @@ -rdp_libs = [] -rdp_required = [ - 'freerdp2', - 'winpr2', -] - -msg = [] -if get_option('freerdp').enabled() - msg += 'Install "@0@" or pass "-Dfreerdp=disabled".' -endif -if not get_option('freerdp').disabled() - msg += 'Required for RDP backend support.' -endif - -foreach lib : rdp_required - dep = dependency(lib, - required: get_option('freerdp'), - not_found_message: '\n'.join(msg).format(lib), - ) - if not dep.found() - subdir_done() - endif - - rdp_libs += dep -endforeach - -wlr_files += files( - 'backend.c', - 'keyboard.c', - 'listener.c', - 'output.c', - 'peer.c', - 'pointer.c', -) -wlr_deps += rdp_libs -conf_data.set10('WLR_HAS_RDP_BACKEND', true) diff --git a/backend/rdp/output.c b/backend/rdp/output.c deleted file mode 100644 index 3043d2c8..00000000 --- a/backend/rdp/output.c +++ /dev/null @@ -1,331 +0,0 @@ -#include <assert.h> -#include <EGL/egl.h> -#include <EGL/eglext.h> -#include <stdlib.h> -#include <wayland-server-core.h> -#include <wlr/types/wlr_output.h> -#include <wlr/interfaces/wlr_output.h> -#include <wlr/util/log.h> -#include <wlr/render/wlr_renderer.h> -#include "backend/rdp.h" -#include "util/signal.h" - -static struct wlr_rdp_output *rdp_output_from_output( - struct wlr_output *wlr_output) { - assert(wlr_output_is_rdp(wlr_output)); - return (struct wlr_rdp_output *)wlr_output; -} - -static EGLSurface egl_create_surface(struct wlr_egl *egl, unsigned int width, - unsigned int height) { - EGLint attribs[] = { - EGL_WIDTH, width, - EGL_HEIGHT, height, - EGL_NONE, - }; - EGLSurface surf = eglCreatePbufferSurface(egl->display, egl->config, attribs); - if (surf == EGL_NO_SURFACE) { - wlr_log(WLR_ERROR, "Failed to create EGL surface"); - return EGL_NO_SURFACE; - } - return surf; -} - -static bool output_set_custom_mode(struct wlr_output *wlr_output, int32_t width, - int32_t height, int32_t refresh) { - struct wlr_rdp_output *output = - rdp_output_from_output(wlr_output); - struct wlr_rdp_backend *backend = output->backend; - - if (refresh <= 0) { - refresh = 60 * 1000; // 60 Hz - } - - wlr_egl_destroy_surface(&backend->egl, output->egl_surface); - - output->egl_surface = egl_create_surface(&backend->egl, width, height); - if (output->egl_surface == EGL_NO_SURFACE) { - wlr_log(WLR_ERROR, "Failed to recreate EGL surface"); - wlr_output_destroy(wlr_output); - return false; - } - - output->frame_delay = 1000000 / refresh; - - if (output->shadow_surface) { - pixman_image_unref(output->shadow_surface); - } - output->shadow_surface = pixman_image_create_bits(PIXMAN_x8r8g8b8, - width, height, NULL, width * 4); - - wlr_output_update_custom_mode(&output->wlr_output, width, height, refresh); - return true; -} - -static bool output_attach_render(struct wlr_output *wlr_output, - int *buffer_age) { - struct wlr_rdp_output *output = - rdp_output_from_output(wlr_output); - return wlr_egl_make_current(&output->backend->egl, output->egl_surface, - buffer_age); -} - -static bool rfx_swap_buffers( - struct wlr_rdp_output *output, pixman_region32_t *damage) { - if (!pixman_region32_not_empty(damage)) { - return true; - } - struct wlr_rdp_peer_context *context = output->context; - freerdp_peer *peer = context->peer; - rdpUpdate *update = peer->update; - - Stream_Clear(context->encode_stream); - Stream_SetPosition(context->encode_stream, 0); - int width = damage->extents.x2 - damage->extents.x1; - int height = damage->extents.y2 - damage->extents.y1; - - SURFACE_BITS_COMMAND cmd; - cmd.skipCompression = TRUE; - cmd.destLeft = damage->extents.x1; - cmd.destTop = damage->extents.y1; - cmd.destRight = damage->extents.x2; - cmd.destBottom = damage->extents.y2; - cmd.bmp.bpp = pixman_image_get_depth(output->shadow_surface); - cmd.bmp.codecID = peer->settings->RemoteFxCodecId; - cmd.bmp.width = width; - cmd.bmp.height = height; - - uint32_t *ptr = pixman_image_get_data(output->shadow_surface) + - damage->extents.x1 + damage->extents.y1 * - (pixman_image_get_stride(output->shadow_surface) / sizeof(uint32_t)); - - RFX_RECT *rfx_rect; - int nrects; - pixman_box32_t *rects = - pixman_region32_rectangles(damage, &nrects); - rfx_rect = realloc(context->rfx_rects, nrects * sizeof(*rfx_rect)); - if (rfx_rect == NULL) { - wlr_log(WLR_ERROR, "RDP swap buffers failed: could not realloc rects"); - return false; - } - context->rfx_rects = rfx_rect; - - for (int i = 0; i < nrects; ++i) { - pixman_box32_t *region = &rects[i]; - rfx_rect = &context->rfx_rects[i]; - rfx_rect->x = region->x1 - damage->extents.x1; - rfx_rect->y = region->y1 - damage->extents.y1; - rfx_rect->width = region->x2 - region->x1; - rfx_rect->height = region->y2 - region->y1; - } - - rfx_compose_message(context->rfx_context, context->encode_stream, - context->rfx_rects, nrects, (BYTE *)ptr, width, height, - pixman_image_get_stride(output->shadow_surface)); - cmd.bmp.bitmapDataLength = Stream_GetPosition(context->encode_stream); - cmd.bmp.bitmapData = Stream_Buffer(context->encode_stream); - - update->SurfaceBits(update->context, &cmd); - return true; -} - -static bool nsc_swap_buffers( - struct wlr_rdp_output *output, pixman_region32_t *damage) { - struct wlr_rdp_peer_context *context = output->context; - freerdp_peer *peer = context->peer; - rdpUpdate *update = peer->update; - - Stream_Clear(context->encode_stream); - Stream_SetPosition(context->encode_stream, 0); - int width = damage->extents.x2 - damage->extents.x1; - int height = damage->extents.y2 - damage->extents.y1; - - SURFACE_BITS_COMMAND cmd; - cmd.skipCompression = TRUE; - cmd.destLeft = damage->extents.x1; - cmd.destTop = damage->extents.y1; - cmd.destRight = damage->extents.x2; - cmd.destBottom = damage->extents.y2; - cmd.bmp.bpp = pixman_image_get_depth(output->shadow_surface); - cmd.bmp.codecID = peer->settings->NSCodecId; - cmd.bmp.width = width; - cmd.bmp.height = height; - - uint32_t *ptr = pixman_image_get_data(output->shadow_surface) + - damage->extents.x1 + damage->extents.y1 * - (pixman_image_get_stride(output->shadow_surface) / sizeof(uint32_t)); - - nsc_compose_message(context->nsc_context, context->encode_stream, - (BYTE *)ptr, width, height, - pixman_image_get_stride(output->shadow_surface)); - - cmd.bmp.bitmapDataLength = Stream_GetPosition(context->encode_stream); - cmd.bmp.bitmapData = Stream_Buffer(context->encode_stream); - - update->SurfaceBits(update->context, &cmd); - return true; -} - -static bool output_commit_buffer(struct wlr_rdp_output *output) { - struct wlr_output *wlr_output = &output->wlr_output; - - bool ret = false; - - pixman_region32_t output_region; - pixman_region32_init(&output_region); - pixman_region32_union_rect(&output_region, &output_region, - 0, 0, wlr_output->width, wlr_output->height); - - pixman_region32_t *damage = &output_region; - if (wlr_output->pending.committed & WLR_OUTPUT_STATE_DAMAGE) { - damage = &wlr_output->pending.damage; - } - - int x = damage->extents.x1; - int y = damage->extents.y1; - int width = damage->extents.x2 - damage->extents.x1; - int height = damage->extents.y2 - damage->extents.y1; - - // Update shadow buffer - struct wlr_renderer *renderer = - wlr_backend_get_renderer(&output->backend->backend); - // TODO performance: add support for flags - ret = wlr_renderer_read_pixels(renderer, WL_SHM_FORMAT_XRGB8888, - NULL, pixman_image_get_stride(output->shadow_surface), - width, height, x, y, x, y, - pixman_image_get_data(output->shadow_surface)); - if (!ret) { - goto out; - } - - // Send along to clients - rdpSettings *settings = output->context->peer->settings; - if (settings->RemoteFxCodec) { - ret = rfx_swap_buffers(output, damage); - } else if (settings->NSCodec) { - ret = nsc_swap_buffers(output, damage); - } else { - // This would perform like ass so why bother - wlr_log(WLR_ERROR, "Raw updates are not supported; use rfx or nsc"); - ret = false; - } - if (!ret) { - goto out; - } - - wlr_output_send_present(wlr_output, NULL); - -out: - pixman_region32_fini(&output_region); - return ret; -} - -static bool output_commit(struct wlr_output *wlr_output) { - struct wlr_rdp_output *output = rdp_output_from_output(wlr_output); - - if (wlr_output->pending.committed & WLR_OUTPUT_STATE_ENABLED) { - wlr_log(WLR_DEBUG, "Cannot disable an RDP output"); - return false; - } - - if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) { - assert(wlr_output->pending.mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM); - if (!output_set_custom_mode(wlr_output, - wlr_output->pending.custom_mode.width, - wlr_output->pending.custom_mode.height, - wlr_output->pending.custom_mode.refresh)) { - return false; - } - } - - if (wlr_output->pending.committed & WLR_OUTPUT_STATE_BUFFER) { - if (!output_commit_buffer(output)) { - return false; - } - } - - return true; -} - -static void output_destroy(struct wlr_output *wlr_output) { - struct wlr_rdp_output *output = - rdp_output_from_output(wlr_output); - if (output->frame_timer) { - wl_event_source_remove(output->frame_timer); - } - wlr_egl_destroy_surface(&output->backend->egl, output->egl_surface); - if (output->shadow_surface) { - pixman_image_unref(output->shadow_surface); - } - free(output); -} - -static const struct wlr_output_impl output_impl = { - .destroy = output_destroy, - .attach_render = output_attach_render, - .commit = output_commit, -}; - -bool wlr_output_is_rdp(struct wlr_output *wlr_output) { - return wlr_output->impl == &output_impl; -} - -static int signal_frame(void *data) { - struct wlr_rdp_output *output = data; - wlr_output_send_frame(&output->wlr_output); - wl_event_source_timer_update(output->frame_timer, output->frame_delay); - return 0; -} - -struct wlr_rdp_output *wlr_rdp_output_create(struct wlr_rdp_backend *backend, - struct wlr_rdp_peer_context *context, unsigned int width, - unsigned int height) { - struct wlr_rdp_output *output = - calloc(1, sizeof(struct wlr_rdp_output)); - if (output == NULL) { - wlr_log(WLR_ERROR, "Failed to allocate wlr_rdp_output"); - return NULL; - } - output->backend = backend; - output->context = context; - wlr_output_init(&output->wlr_output, &backend->backend, &output_impl, - backend->display); - struct wlr_output *wlr_output = &output->wlr_output; - - output->egl_surface = egl_create_surface(&backend->egl, width, height); - if (output->egl_surface == EGL_NO_SURFACE) { - wlr_log(WLR_ERROR, "Failed to create EGL surface"); - goto error; - } - - output_set_custom_mode(wlr_output, width, height, 0); - strncpy(wlr_output->make, "RDP", sizeof(wlr_output->make)); - strncpy(wlr_output->model, "RDP", sizeof(wlr_output->model)); - snprintf(wlr_output->name, sizeof(wlr_output->name), "RDP-%d", - wl_list_length(&backend->clients)); - - char description[128]; - snprintf(description, sizeof(description), - "RDP output %d", wl_list_length(&backend->clients)); - wlr_output_set_description(wlr_output, description); - - if (!wlr_egl_make_current(&output->backend->egl, output->egl_surface, - NULL)) { - goto error; - } - - wlr_renderer_begin(backend->renderer, wlr_output->width, wlr_output->height); - wlr_renderer_clear(backend->renderer, (float[]){ 1.0, 1.0, 1.0, 1.0 }); - wlr_renderer_end(backend->renderer); - - struct wl_event_loop *ev = wl_display_get_event_loop(backend->display); - output->frame_timer = wl_event_loop_add_timer(ev, signal_frame, output); - wl_event_source_timer_update(output->frame_timer, output->frame_delay); - wlr_output_update_enabled(wlr_output, true); - wlr_signal_emit_safe(&backend->backend.events.new_output, wlr_output); - return output; - -error: - wlr_output_destroy(&output->wlr_output); - return NULL; -} diff --git a/backend/rdp/peer.c b/backend/rdp/peer.c deleted file mode 100644 index 350a4721..00000000 --- a/backend/rdp/peer.c +++ /dev/null @@ -1,360 +0,0 @@ -#define _POSIX_C_SOURCE 200809L -#include <linux/input.h> -#include <stdlib.h> -#include <string.h> -#include <wlr/types/wlr_output.h> -#include <wlr/interfaces/wlr_input_device.h> -#include <wlr/interfaces/wlr_keyboard.h> -#include <wlr/interfaces/wlr_output.h> -#include <wlr/util/log.h> -#include "backend/rdp.h" -#include "util/signal.h" - -static BOOL xf_peer_capabilities(freerdp_peer *client) { - return TRUE; -} - -static BOOL xf_peer_post_connect(freerdp_peer *client) { - return TRUE; -} - -static BOOL xf_peer_activate(freerdp_peer *client) { - struct wlr_rdp_peer_context *context = - (struct wlr_rdp_peer_context *)client->context; - struct wlr_rdp_backend *backend = context->backend; - rdpSettings *settings = client->settings; - - if (!settings->SurfaceCommandsEnabled) { - wlr_log(WLR_ERROR, "RDP peer does not support SurfaceCommands"); - return FALSE; - } - - context->output = wlr_rdp_output_create(backend, context, - (int)settings->DesktopWidth, (int)settings->DesktopHeight); - if (!context->output) { - wlr_log(WLR_ERROR, "Failed to allcoate output for RDP peer"); - return FALSE; - } - rfx_context_reset(context->rfx_context, - context->output->wlr_output.width, - context->output->wlr_output.height); - nsc_context_reset(context->nsc_context, - context->output->wlr_output.width, - context->output->wlr_output.height); - - if (context->flags & RDP_PEER_ACTIVATED) { - return TRUE; - } - - context->pointer = wlr_rdp_pointer_create(backend, context); - if (!context->pointer) { - wlr_log(WLR_ERROR, "Failed to allocate pointer for RDP peer"); - return FALSE; - } - - // Use wlroots' software cursors instead of remote cursors - POINTER_SYSTEM_UPDATE pointer_system; - rdpPointerUpdate *pointer = client->update->pointer; - pointer_system.type = SYSPTR_NULL; - pointer->PointerSystem(client->context, &pointer_system); - - context->keyboard = wlr_rdp_keyboard_create(backend, settings); - if (!context->keyboard) { - wlr_log(WLR_ERROR, "Failed to allocate keyboard for RDP peer"); - return FALSE; - } - - context->flags |= RDP_PEER_ACTIVATED; - return TRUE; -} - -static int xf_suppress_output(rdpContext *context, - BYTE allow, const RECTANGLE_16 *area) { - struct wlr_rdp_peer_context *peer_context = - (struct wlr_rdp_peer_context *)context; - if (allow) { - peer_context->flags |= RDP_PEER_OUTPUT_ENABLED; - } else { - peer_context->flags &= ~RDP_PEER_OUTPUT_ENABLED; - } - return true; -} - -static int xf_input_synchronize_event(rdpInput *input, UINT32 flags) { - struct wlr_rdp_peer_context *context = - (struct wlr_rdp_peer_context *)input->context; - wlr_output_damage_whole(&context->output->wlr_output); - return true; -} - -static inline int64_t timespec_to_msec(const struct timespec *a) { - return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000; -} - -static int xf_input_mouse_event(rdpInput *input, - UINT16 flags, UINT16 x, UINT16 y) { - struct wlr_rdp_peer_context *context = - (struct wlr_rdp_peer_context *)input->context; - struct wlr_input_device *wlr_device = &context->pointer->wlr_input_device; - struct wlr_pointer *pointer = wlr_device->pointer; - bool frame = false; - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - - if (flags & PTR_FLAGS_MOVE) { - struct wlr_event_pointer_motion_absolute event = { 0 }; - event.device = wlr_device; - event.time_msec = timespec_to_msec(&now); - event.x = x / (double)context->output->wlr_output.width; - event.y = y / (double)context->output->wlr_output.height; - wlr_signal_emit_safe(&pointer->events.motion_absolute, &event); - frame = true; - } - - uint32_t button = 0; - if (flags & PTR_FLAGS_BUTTON1) { - button = BTN_LEFT; - } else if (flags & PTR_FLAGS_BUTTON2) { - button = BTN_RIGHT; - } else if (flags & PTR_FLAGS_BUTTON3) { - button = BTN_MIDDLE; - } - - if (button) { - struct wlr_event_pointer_button event = { 0 }; - event.device = wlr_device; - event.time_msec = timespec_to_msec(&now); - event.button = button; - event.state = (flags & PTR_FLAGS_DOWN) ? - WLR_BUTTON_PRESSED : WLR_BUTTON_RELEASED; - wlr_signal_emit_safe(&pointer->events.button, &event); - frame = true; - } - - if (flags & PTR_FLAGS_WHEEL) { - double value = -(flags & 0xFF) / 120.0; - if (flags & PTR_FLAGS_WHEEL_NEGATIVE) { - value = -value; - } - struct wlr_event_pointer_axis event = { 0 }; - event.device = &context->pointer->wlr_input_device; - event.time_msec = timespec_to_msec(&now); - event.source = WLR_AXIS_SOURCE_WHEEL; - event.orientation = WLR_AXIS_ORIENTATION_VERTICAL; - event.delta = value; - event.delta_discrete = (int32_t)value; - wlr_signal_emit_safe(&pointer->events.axis, &event); - frame = true; - } - - if (frame) { - wlr_signal_emit_safe(&pointer->events.frame, pointer); - } - - return true; -} - -static int xf_input_extended_mouse_event( - rdpInput *input, UINT16 flags, UINT16 x, UINT16 y) { - struct wlr_rdp_peer_context *context = - (struct wlr_rdp_peer_context *)input->context; - struct wlr_input_device *wlr_device = &context->pointer->wlr_input_device; - struct wlr_pointer *pointer = wlr_device->pointer; - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - struct wlr_event_pointer_motion_absolute event = { 0 }; - event.device = wlr_device; - event.time_msec = timespec_to_msec(&now); - event.x = x / (double)context->output->wlr_output.width; - event.y = y / (double)context->output->wlr_output.height; - wlr_signal_emit_safe(&pointer->events.motion_absolute, &event); - wlr_signal_emit_safe(&pointer->events.frame, pointer); - return true; -} - -static int xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code) { - struct wlr_rdp_peer_context *context = - (struct wlr_rdp_peer_context *)input->context; - struct wlr_input_device *wlr_device = &context->keyboard->wlr_input_device; - struct wlr_keyboard *keyboard = wlr_device->keyboard; - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - - if (!(context->flags & RDP_PEER_ACTIVATED)) { - return true; - } - - bool notify = false; - enum wlr_key_state state; - if ((flags & KBD_FLAGS_DOWN)) { - state = WLR_KEY_PRESSED; - notify = true; - } else if ((flags & KBD_FLAGS_RELEASE)) { - state = WLR_KEY_RELEASED; - notify = true; - } - - if (notify) { - uint32_t full_code = code; - if (flags & KBD_FLAGS_EXTENDED) { - full_code |= KBD_FLAGS_EXTENDED; - } - uint32_t vk_code = GetVirtualKeyCodeFromVirtualScanCode(full_code, 4); - if (flags & KBD_FLAGS_EXTENDED) { - vk_code |= KBDEXT; - } - uint32_t scan_code = GetKeycodeFromVirtualKeyCode( - vk_code, KEYCODE_TYPE_EVDEV); - struct wlr_event_keyboard_key event = { 0 }; - event.time_msec = timespec_to_msec(&now); - event.keycode = scan_code - 8; - event.state = state; - event.update_state = true; - wlr_keyboard_notify_key(keyboard, &event); - } - - return true; -} - -static int xf_input_unicode_keyboard_event(rdpInput *input, - UINT16 flags, UINT16 code) { - wlr_log(WLR_DEBUG, "Unhandled RDP unicode keyboard event " - "(flags:0x%X code:0x%X)\n", flags, code); - return true; -} - -static int rdp_client_activity(int fd, uint32_t mask, void *data) { - freerdp_peer *client = (freerdp_peer *)data; - if (!client->CheckFileDescriptor(client)) { - wlr_log(WLR_ERROR, - "Unable to check client file descriptor for %p", client); - freerdp_peer_context_free(client); - freerdp_peer_free(client); - } - return 0; -} - -static int rdp_peer_context_new( - freerdp_peer *client, struct wlr_rdp_peer_context *context) { - context->peer = client; - context->flags = RDP_PEER_OUTPUT_ENABLED; - context->rfx_context = rfx_context_new(TRUE); - if (!context->rfx_context) { - return false; - } - context->rfx_context->mode = RLGR3; - context->rfx_context->width = client->settings->DesktopWidth; - context->rfx_context->height = client->settings->DesktopHeight; - rfx_context_set_pixel_format(context->rfx_context, PIXEL_FORMAT_BGRA32); - - context->nsc_context = nsc_context_new(); - if (!context->nsc_context) { - rfx_context_free(context->rfx_context); - return false; - } - - nsc_context_set_pixel_format(context->nsc_context, PIXEL_FORMAT_BGRA32); - - context->encode_stream = Stream_New(NULL, 65536); - if (!context->encode_stream) { - nsc_context_free(context->nsc_context); - rfx_context_free(context->rfx_context); - return false; - } - return true; -} - -static void rdp_peer_context_free( - freerdp_peer *client, struct wlr_rdp_peer_context *context) { - if (!context) { - return; - } - - for (int i = 0; i < MAX_FREERDP_FDS; ++i) { - if (context->events[i]) { - wl_event_source_remove(context->events[i]); - } - } - - if (context->flags & RDP_PEER_ACTIVATED) { - wlr_output_destroy(&context->output->wlr_output); - wlr_input_device_destroy(&context->pointer->wlr_input_device); - wlr_input_device_destroy(&context->keyboard->wlr_input_device); - } - - wl_list_remove(&context->link); - wlr_output_destroy(&context->output->wlr_output); - - Stream_Free(context->encode_stream, TRUE); - nsc_context_free(context->nsc_context); - rfx_context_free(context->rfx_context); - free(context->rfx_rects); -} - -int rdp_peer_init(freerdp_peer *client, - struct wlr_rdp_backend *backend) { - client->ContextSize = sizeof(struct wlr_rdp_peer_context); - client->ContextNew = (psPeerContextNew)rdp_peer_context_new; - client->ContextFree = (psPeerContextFree)rdp_peer_context_free; - freerdp_peer_context_new(client); - - struct wlr_rdp_peer_context *peer_context = - (struct wlr_rdp_peer_context *)client->context; - peer_context->backend = backend; - - client->settings->CertificateFile = strdup(backend->tls_cert_path); - client->settings->PrivateKeyFile = strdup(backend->tls_key_path); - client->settings->NlaSecurity = FALSE; - - if (!client->Initialize(client)) { - wlr_log(WLR_ERROR, "Failed to initialize FreeRDP peer"); - goto err_init; - } - - client->settings->OsMajorType = OSMAJORTYPE_UNIX; - client->settings->OsMinorType = OSMINORTYPE_PSEUDO_XSERVER; - client->settings->ColorDepth = 32; - client->settings->RefreshRect = TRUE; - client->settings->RemoteFxCodec = TRUE; - client->settings->NSCodec = TRUE; - client->settings->FrameMarkerCommandEnabled = TRUE; - client->settings->SurfaceFrameMarkerEnabled = TRUE; - - client->Capabilities = xf_peer_capabilities; - client->PostConnect = xf_peer_post_connect; - client->Activate = xf_peer_activate; - - client->update->SuppressOutput = (pSuppressOutput)xf_suppress_output; - - client->input->SynchronizeEvent = xf_input_synchronize_event; - client->input->MouseEvent = xf_input_mouse_event; - client->input->ExtendedMouseEvent = xf_input_extended_mouse_event; - client->input->KeyboardEvent = xf_input_keyboard_event; - client->input->UnicodeKeyboardEvent = xf_input_unicode_keyboard_event; - - int rcount = 0; - void *rfds[MAX_FREERDP_FDS]; - if (!client->GetFileDescriptor(client, rfds, &rcount)) { - wlr_log(WLR_ERROR, "Unable to retrieve client file descriptors"); - goto err_init; - } - struct wl_event_loop *event_loop = - wl_display_get_event_loop(backend->display); - int i; - for (i = 0; i < rcount; ++i) { - int fd = (int)(long)(rfds[i]); - peer_context->events[i] = wl_event_loop_add_fd( - event_loop, fd, WL_EVENT_READABLE, rdp_client_activity, - client); - } - for (; i < MAX_FREERDP_FDS; ++i) { - peer_context->events[i] = NULL; - } - - wl_list_insert(&backend->clients, &peer_context->link); - return 0; - -err_init: - client->Close(client); - return -1; -} diff --git a/backend/rdp/pointer.c b/backend/rdp/pointer.c deleted file mode 100644 index b3fdcd73..00000000 --- a/backend/rdp/pointer.c +++ /dev/null @@ -1,40 +0,0 @@ -#define _POSIX_C_SOURCE 200809L -#include <stdlib.h> -#include <string.h> -#include <wayland-server-core.h> -#include <wlr/types/wlr_input_device.h> -#include <wlr/types/wlr_pointer.h> -#include <wlr/interfaces/wlr_pointer.h> -#include <wlr/interfaces/wlr_input_device.h> -#include <wlr/util/log.h> -#include "backend/rdp.h" -#include "util/signal.h" - -static struct wlr_input_device_impl input_device_impl = { 0 }; - -struct wlr_rdp_input_device *wlr_rdp_pointer_create( - struct wlr_rdp_backend *backend, struct wlr_rdp_peer_context *context) { - struct wlr_rdp_input_device *device = - calloc(1, sizeof(struct wlr_rdp_input_device)); - if (!device) { - wlr_log(WLR_ERROR, "Failed to allocate RDP input device"); - return NULL; - } - - int vendor = 0; - int product = 0; - const char *name = "rdp"; - struct wlr_input_device *wlr_device = &device->wlr_input_device; - wlr_input_device_init(wlr_device, WLR_INPUT_DEVICE_POINTER, - &input_device_impl, name, vendor, product); - - if (!(wlr_device->pointer = calloc(1, sizeof(struct wlr_pointer)))) { - wlr_log(WLR_ERROR, "Failed to allocate RDP pointer device"); - return NULL; - } - wlr_device->output_name = strdup(context->output->wlr_output.name); - wlr_pointer_init(wlr_device->pointer, NULL); - - wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_device); - return device; -} |