Mouse handling

This commit is contained in:
vaxerski 2023-04-20 22:54:18 +01:00
parent 1f6cc8206f
commit 75bb8cc156
5 changed files with 105 additions and 25 deletions

View File

@ -12,9 +12,8 @@ CInputContext::CInputContext (CX11OpenGLDriver& videoDriver) :
#ifdef ENABLE_WAYLAND #ifdef ENABLE_WAYLAND
CInputContext::CInputContext (CWaylandOpenGLDriver& videoDriver) : CInputContext::CInputContext (CWaylandOpenGLDriver& videoDriver) :
m_mouse (nullptr) m_mouse (&videoDriver)
{ {
// todo
} }
#endif #endif

View File

@ -5,10 +5,20 @@ using namespace WallpaperEngine::Input;
CMouseInput::CMouseInput (GLFWwindow* window) : position (), m_mousePosition (), m_window (window) {} CMouseInput::CMouseInput (GLFWwindow* window) : position (), m_mousePosition (), m_window (window) {}
CMouseInput::CMouseInput(WallpaperEngine::Render::Drivers::CWaylandOpenGLDriver* driver) {
waylandDriver = driver;
}
void CMouseInput::update () void CMouseInput::update ()
{ {
if (!m_window) if (!m_window) {
if (!waylandDriver || !waylandDriver->lastLSInFocus)
return;
this->position = waylandDriver->lastLSInFocus->mousePos;
return; return;
}
// update current mouse position // update current mouse position
glfwGetCursorPos (this->m_window, &this->m_mousePosition.x, &this->m_mousePosition.y); glfwGetCursorPos (this->m_window, &this->m_mousePosition.x, &this->m_mousePosition.y);

View File

@ -1,8 +1,11 @@
#pragma once #pragma once
#include "../Render/Drivers/CWaylandOpenGLDriver.h"
#include <glm/vec2.hpp> #include <glm/vec2.hpp>
#include "GLFW/glfw3.h" #include "GLFW/glfw3.h"
namespace WallpaperEngine::Input namespace WallpaperEngine::Input
{ {
/** /**
@ -13,6 +16,9 @@ namespace WallpaperEngine::Input
public: public:
explicit CMouseInput(GLFWwindow* window); explicit CMouseInput(GLFWwindow* window);
explicit CMouseInput(WallpaperEngine::Render::Drivers::CWaylandOpenGLDriver* driver);
/** /**
* Takes current mouse position and updates it * Takes current mouse position and updates it
*/ */
@ -27,12 +33,17 @@ namespace WallpaperEngine::Input
/** /**
* The GLFW window to get mouse position from * The GLFW window to get mouse position from
*/ */
GLFWwindow* m_window; GLFWwindow* m_window = nullptr;
/** /**
* The current mouse position * The current mouse position
*/ */
glm::dvec2 m_mousePosition; glm::dvec2 m_mousePosition;
/**
* Wayland: Driver
*/
WallpaperEngine::Render::Drivers::CWaylandOpenGLDriver* waylandDriver = nullptr;
}; };
} }

View File

@ -20,12 +20,54 @@ extern "C" {
using namespace WallpaperEngine::Render::Drivers; using namespace WallpaperEngine::Render::Drivers;
void geometry(void* data, wl_output* output, int32_t x, int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, const char* make, const char* model, static void handlePointerEnter(void* data, struct wl_pointer* wl_pointer, uint32_t serial, struct wl_surface* surface, wl_fixed_t surface_x, wl_fixed_t surface_y) {
const auto PDRIVER = (CWaylandOpenGLDriver*)data;
const auto PLS = PDRIVER->surfaceToLS(surface);
PDRIVER->lastLSInFocus = PLS;
wl_surface_set_buffer_scale(PLS->cursorSurface, PLS->output->scale);
wl_surface_attach(PLS->cursorSurface, wl_cursor_image_get_buffer(PLS->pointer->images[0]), 0, 0);
wl_pointer_set_cursor(wl_pointer, serial, PLS->cursorSurface, PLS->pointer->images[0]->hotspot_x, PLS->pointer->images[0]->hotspot_y);
wl_surface_commit(PLS->cursorSurface);
}
static void handlePointerLeave(void* data, struct wl_pointer* wl_pointer, uint32_t serial, struct wl_surface* surface) {
// ignored
}
static void handlePointerAxis(void* data, wl_pointer* wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value) {
// ignored
}
static void handlePointerMotion(void* data, struct wl_pointer* wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) {
auto x = wl_fixed_to_double(surface_x);
auto y = wl_fixed_to_double(surface_y);
const auto PDRIVER = (CWaylandOpenGLDriver*)data;
if (!PDRIVER->lastLSInFocus)
return;
PDRIVER->lastLSInFocus->mousePos = {x, y};
}
static void handlePointerButton(void* data, struct wl_pointer* wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t button_state) {
// ignored
}
const struct wl_pointer_listener pointerListener = { .enter = handlePointerEnter, .leave = handlePointerLeave, .motion = handlePointerMotion, .button = handlePointerButton, .axis = handlePointerAxis };
static void handleCapabilities(void* data, wl_seat* wl_seat, uint32_t capabilities) {
if (capabilities & WL_SEAT_CAPABILITY_POINTER)
wl_pointer_add_listener(wl_seat_get_pointer(wl_seat), &pointerListener, data);
}
const struct wl_seat_listener seatListener = { .capabilities = handleCapabilities };
static void geometry(void* data, wl_output* output, int32_t x, int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, const char* make, const char* model,
int32_t transform) { int32_t transform) {
// ignored // ignored
} }
void mode(void* data, wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) { static void mode(void* data, wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) {
const auto PMONITOR = (SWaylandOutput*)data; const auto PMONITOR = (SWaylandOutput*)data;
PMONITOR->size = {width, height}; PMONITOR->size = {width, height};
PMONITOR->lsSize = {width, height}; PMONITOR->lsSize = {width, height};
@ -37,13 +79,13 @@ void mode(void* data, wl_output* output, uint32_t flags, int32_t width, int32_t
PMONITOR->driver->wallpaperApplication->getOutput()->reset(); PMONITOR->driver->wallpaperApplication->getOutput()->reset();
} }
void done(void* data, wl_output* wl_output) { static void done(void* data, wl_output* wl_output) {
const auto PMONITOR = (SWaylandOutput*)data; const auto PMONITOR = (SWaylandOutput*)data;
PMONITOR->initialized = true; PMONITOR->initialized = true;
} }
void scale(void* data, wl_output* wl_output, int32_t scale) { static void scale(void* data, wl_output* wl_output, int32_t scale) {
const auto PMONITOR = (SWaylandOutput*)data; const auto PMONITOR = (SWaylandOutput*)data;
PMONITOR->scale = scale; PMONITOR->scale = scale;
@ -55,14 +97,14 @@ void scale(void* data, wl_output* wl_output, int32_t scale) {
PMONITOR->driver->wallpaperApplication->getOutput()->reset(); PMONITOR->driver->wallpaperApplication->getOutput()->reset();
} }
void name(void* data, wl_output* wl_output, const char* name) { static void name(void* data, wl_output* wl_output, const char* name) {
const auto PMONITOR = (SWaylandOutput*)data; const auto PMONITOR = (SWaylandOutput*)data;
if (name) if (name)
PMONITOR->name = name; PMONITOR->name = name;
} }
void description(void* data, wl_output* wl_output, const char* description) { static void description(void* data, wl_output* wl_output, const char* description) {
// ignored // ignored
} }
@ -85,6 +127,9 @@ static void handleGlobal(void *data, struct wl_registry *registry, uint32_t name
wl_output_add_listener(POUTPUT->output, &outputListener, POUTPUT); wl_output_add_listener(POUTPUT->output, &outputListener, POUTPUT);
} else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
PDRIVER->waylandContext.layerShell = (zwlr_layer_shell_v1*)wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 1); PDRIVER->waylandContext.layerShell = (zwlr_layer_shell_v1*)wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 1);
} else if (strcmp(interface, wl_seat_interface.name) == 0) {
PDRIVER->waylandContext.seat = (wl_seat*)wl_registry_bind(registry, name, &wl_seat_interface, 1);
wl_seat_add_listener(PDRIVER->waylandContext.seat, &seatListener, PDRIVER);
} }
} }
@ -237,6 +282,7 @@ CLayerSurface::CLayerSurface(CWaylandOpenGLDriver* pDriver, SWaylandOutput* pOut
sLog.exception("Failed to get a layer surface"); sLog.exception("Failed to get a layer surface");
wl_region* region = wl_compositor_create_region(pDriver->waylandContext.compositor); wl_region* region = wl_compositor_create_region(pDriver->waylandContext.compositor);
wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX);
zwlr_layer_surface_v1_set_size(layerSurface, 0, 0); zwlr_layer_surface_v1_set_size(layerSurface, 0, 0);
zwlr_layer_surface_v1_set_anchor(layerSurface, ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM); zwlr_layer_surface_v1_set_anchor(layerSurface, ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM);
@ -254,6 +300,18 @@ CLayerSurface::CLayerSurface(CWaylandOpenGLDriver* pDriver, SWaylandOutput* pOut
wl_display_roundtrip(pDriver->waylandContext.display); wl_display_roundtrip(pDriver->waylandContext.display);
wl_display_flush(pDriver->waylandContext.display); wl_display_flush(pDriver->waylandContext.display);
static const auto XCURSORSIZE = getenv("XCURSOR_SIZE") ? std::stoi(getenv("XCURSOR_SIZE")) : 24;
const auto PRCURSORTHEME = wl_cursor_theme_load(getenv("XCURSOR_THEME"), XCURSORSIZE * output->scale, pDriver->waylandContext.shm);
if (!PRCURSORTHEME)
sLog.exception("Failed to get a cursor theme");
pointer = wl_cursor_theme_get_cursor(PRCURSORTHEME, "left_ptr");
cursorSurface = wl_compositor_create_surface(pDriver->waylandContext.compositor);
if (!cursorSurface)
sLog.exception("Failed to get a cursor surface");
if (eglMakeCurrent(pDriver->eglContext.display, eglSurface, eglSurface, pDriver->eglContext.context) == EGL_FALSE) if (eglMakeCurrent(pDriver->eglContext.display, eglSurface, eglSurface, pDriver->eglContext.context) == EGL_FALSE)
sLog.exception("Failed to make egl current"); sLog.exception("Failed to make egl current");
} }
@ -291,18 +349,6 @@ CWaylandOpenGLDriver::CWaylandOpenGLDriver(const char* windowTitle, CApplication
outputToUse = m_outputs[0].get(); outputToUse = m_outputs[0].get();
} }
const auto XCURSORSIZE = getenv("XCURSOR_SIZE") ? std::stoi(getenv("XCURSOR_SIZE")) : 24;
const auto PRCURSORTHEME = wl_cursor_theme_load(NULL, XCURSORSIZE, waylandContext.shm);
if (!PRCURSORTHEME)
sLog.exception("Failed to get a cursor theme");
waylandContext.pointer = wl_cursor_theme_get_cursor(PRCURSORTHEME, "left_ptr");
waylandContext.cursorSurface = wl_compositor_create_surface(waylandContext.compositor);
if (!waylandContext.cursorSurface)
sLog.exception("Failed to get a cursor surface");
initEGL(); initEGL();
const auto PLS = (outputToUse->layerSurface = std::make_unique<CLayerSurface>(this, outputToUse)).get(); const auto PLS = (outputToUse->layerSurface = std::make_unique<CLayerSurface>(this, outputToUse)).get();
@ -409,3 +455,12 @@ void CWaylandOpenGLDriver::makeCurrent(const std::string& outputName) const {
} }
} }
} }
CLayerSurface* CWaylandOpenGLDriver::surfaceToLS(wl_surface* surface) {
for (auto& o : m_outputs) {
if (o->layerSurface->surface == surface)
return o->layerSurface.get();
}
return nullptr;
}

View File

@ -51,6 +51,9 @@ namespace WallpaperEngine::Render::Drivers
glm::ivec2 size; glm::ivec2 size;
wl_callback* frameCallback = nullptr; wl_callback* frameCallback = nullptr;
SWaylandOutput* output = nullptr; SWaylandOutput* output = nullptr;
glm::dvec2 mousePos = {0, 0};
wl_cursor* pointer = nullptr;
wl_surface* cursorSurface = nullptr;
}; };
class CWaylandOpenGLDriver : public CVideoDriver class CWaylandOpenGLDriver : public CVideoDriver
@ -80,12 +83,12 @@ namespace WallpaperEngine::Render::Drivers
wl_compositor* compositor = nullptr; wl_compositor* compositor = nullptr;
wl_shm* shm = nullptr; wl_shm* shm = nullptr;
zwlr_layer_shell_v1* layerShell = nullptr; zwlr_layer_shell_v1* layerShell = nullptr;
wl_cursor* pointer = nullptr; wl_seat* seat = nullptr;
wl_surface* cursorSurface = nullptr;
} waylandContext; } waylandContext;
void onLayerClose(CLayerSurface*); void onLayerClose(CLayerSurface*);
void resizeLSSurfaceEGL(CLayerSurface*); void resizeLSSurfaceEGL(CLayerSurface*);
CLayerSurface* surfaceToLS(wl_surface*);
std::vector<std::unique_ptr<SWaylandOutput>> m_outputs; std::vector<std::unique_ptr<SWaylandOutput>> m_outputs;
@ -98,6 +101,8 @@ namespace WallpaperEngine::Render::Drivers
PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC eglCreatePlatformWindowSurfaceEXT = nullptr; PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC eglCreatePlatformWindowSurfaceEXT = nullptr;
} eglContext; } eglContext;
CLayerSurface* lastLSInFocus = nullptr;
private: private:
void initEGL(); void initEGL();