#include #include #include #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-parameter" #pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection" #undef LOGV #define LOGV(fmt ...) LorieCompositor::LorieCompositor() : renderer(*this), toplevel(renderer.toplevel_surface), cursor(renderer.cursor_surface), client_created_listener(*this) {} int proc(int fd, uint32_t mask, void *data) { LorieCompositor *b = static_cast(data); if (b == nullptr) {LOGF("b == nullptr"); return 0;} b->queue.run(); return 0; }; void LorieCompositor::start() { LogInit(); LOGV("Starting compositor"); display = wl_display_create(); wl_display_add_socket_auto(display); wl_event_loop_add_fd(wl_display_get_event_loop(display), queue.get_fd(), WL_EVENT_READABLE, &proc, this); wl_display_add_client_created_listener(display, &client_created_listener); wl_display_init_shm (display); wl_resource_t::global_create(display, this); wl_resource_t::global_create(display, this); wl_resource_t::global_create(display, this); wl_resource_t::global_create(display, this); wl_registry *registry = wl_display_get_registry(this->display); wl_registry_bind(registry, id, &xdg_wm_base_interface, 1); backend_init(); wl_display_run(display); } void LorieCompositor::post(std::function f) { queue.write(f); } struct wl_event_source* LorieCompositor::add_fd_listener(int fd, uint32_t mask, wl_event_loop_fd_func_t func, void *data) { LOGV("Adding fd %d to event loop", fd); struct wl_event_loop* loop = nullptr; if (display != nullptr) loop = wl_display_get_event_loop(display); if (loop != nullptr) return wl_event_loop_add_fd(loop, fd, mask, func, data); return nullptr; } void LorieCompositor::terminate() { LOGV("Terminating compositor"); if (display != nullptr) wl_display_terminate(display); } void LorieCompositor::set_toplevel(LorieSurface *surface) { renderer.set_toplevel(surface); } void LorieCompositor::set_cursor(LorieSurface *surface, uint32_t hotspot_x, uint32_t hotspot_y) { renderer.set_cursor(surface, hotspot_x, hotspot_y); } void LorieCompositor::output_redraw() { LOGV("Requested redraw"); renderer.requestRedraw(); } void LorieCompositor::output_resize(uint32_t width, uint32_t height, uint32_t physical_width, uint32_t physical_height) { // Xwayland segfaults without that line if (width == 0 || height == 0 || physical_width == 0 || physical_height == 0) return; renderer.resize(width, height, physical_width, physical_height); post([this]() { output_redraw(); }); } void LorieCompositor::touch_down(uint32_t id, uint32_t x, uint32_t y) { LorieClient *client = get_toplevel_client(); if (toplevel == nullptr || client == nullptr) return; wl_fixed_t surface_x = wl_fixed_from_int (x); wl_fixed_t surface_y = wl_fixed_from_int (y); client->touch.send_down(next_serial(), LorieUtils::timestamp(), toplevel->resource, id, surface_x, surface_y); renderer.setCursorVisibility(false); } void LorieCompositor::touch_motion(uint32_t id, uint32_t x, uint32_t y) { LorieClient *client = get_toplevel_client(); if (toplevel == nullptr || client == nullptr) return; wl_fixed_t surface_x = wl_fixed_from_int (x); wl_fixed_t surface_y = wl_fixed_from_int (y); client->touch.send_motion(LorieUtils::timestamp(), id, surface_x, surface_y); renderer.setCursorVisibility(false); } void LorieCompositor::touch_up(uint32_t id) { LorieClient *client = get_toplevel_client(); if (toplevel == nullptr || client == nullptr) return; client->touch.send_up(next_serial(), LorieUtils::timestamp(), id); renderer.setCursorVisibility(false); } void LorieCompositor::touch_frame() { LorieClient *client = get_toplevel_client(); if (toplevel == nullptr || client == nullptr) return; client->touch.send_frame(); renderer.setCursorVisibility(false); } void LorieCompositor::pointer_motion(uint32_t x, uint32_t y) { LorieClient *client = get_toplevel_client(); if (client == nullptr) return; wl_fixed_t surface_x = wl_fixed_from_int (x); wl_fixed_t surface_y = wl_fixed_from_int (y); client->pointer.send_motion(LorieUtils::timestamp(), surface_x, surface_y); client->pointer.send_frame(); renderer.setCursorVisibility(true); renderer.cursorMove(x, y); } void LorieCompositor::pointer_scroll(uint32_t axis, float value) { LorieClient *client = get_toplevel_client(); if (client == nullptr) return; wl_fixed_t scroll = wl_fixed_from_double (value); client->pointer.send_axis_discrete(axis, (scroll>=0)?1:-1); client->pointer.send_axis(LorieUtils::timestamp(), axis, scroll); client->pointer.send_frame(); renderer.setCursorVisibility(true); } void LorieCompositor::pointer_button(uint32_t button, uint32_t state) { LorieClient *client = get_toplevel_client(); if (client == nullptr) return; LOGI("pointer button: %d %d", button, state); client->pointer.send_button (next_serial(), LorieUtils::timestamp(), button, state); client->pointer.send_frame(); renderer.setCursorVisibility(true); } void LorieCompositor::keyboard_key(uint32_t key, uint32_t state) { LorieClient *client = get_toplevel_client(); if (client == nullptr) return; client->keyboard.send_key (next_serial(), LorieUtils::timestamp(), key, state); } void LorieCompositor::keyboard_key_modifiers(uint8_t depressed, uint8_t latched, uint8_t locked, uint8_t group) { LorieClient *client = get_toplevel_client(); if (client == nullptr) return; if (key_modifiers.depressed == depressed && key_modifiers.latched == latched && key_modifiers.locked == locked && key_modifiers.group == group) return; key_modifiers.depressed = depressed; key_modifiers.latched = latched; key_modifiers.locked = locked; key_modifiers.group = group; client->keyboard.send_modifiers (next_serial(), depressed, latched, locked, group); } void LorieCompositor::keyboard_keymap_changed() { LorieClient *client = get_toplevel_client(); if (client == nullptr) return; client->keyboard.keymap_changed(); } LorieClient* LorieCompositor::get_toplevel_client() { if (toplevel != nullptr && toplevel->client != nullptr && *(toplevel->client) != nullptr) return *(toplevel->client); return nullptr; } uint32_t LorieCompositor::next_serial() { if (display == nullptr) return 0; return wl_display_next_serial(display); } #pragma clang diagnostic pop