termux-x11/app/src/main/jni/lorie/compositor.cpp

212 lines
6.3 KiB
C++

#include <lorie-compositor.hpp>
#include <lorie-client.hpp>
#include <LorieImpls.hpp>
#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<LorieCompositor*>(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<LorieCompositor_>(display, this);
wl_resource_t::global_create<LorieSeat>(display, this);
wl_resource_t::global_create<LorieOutput>(display, this);
wl_resource_t::global_create<LorieShell>(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<void()> 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