cursor: move to a hyprland impl
This moves wlr_cursor to a completely new impl mostly under CPointerManager Also adds beginSimple to OpenGL for simple render passes (e.g. cursor)
This commit is contained in:
parent
e4e84064f2
commit
ed411f53bd
51 changed files with 1550 additions and 496 deletions
|
|
@ -1,6 +1,7 @@
|
|||
#include "CursorManager.hpp"
|
||||
#include "Compositor.hpp"
|
||||
#include "../config/ConfigValue.hpp"
|
||||
#include "PointerManager.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include <wlr/interfaces/wlr_buffer.h>
|
||||
|
|
@ -73,8 +74,8 @@ static bool cursorBufferBeginDataPtr(struct wlr_buffer* wlr_buffer, uint32_t fla
|
|||
if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE)
|
||||
return false;
|
||||
|
||||
*data = cairo_image_surface_get_data(buffer->surface);
|
||||
*stride = cairo_image_surface_get_stride(buffer->surface);
|
||||
*data = buffer->pixelData ? buffer->pixelData : cairo_image_surface_get_data(buffer->surface);
|
||||
*stride = buffer->stride;
|
||||
*format = DRM_FORMAT_ARGB8888;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -94,6 +95,14 @@ CCursorManager::CCursorBuffer::CCursorBuffer(cairo_surface_t* surf, const Vector
|
|||
wlrBuffer.surface = surf;
|
||||
wlr_buffer_init(&wlrBuffer.base, &bufferImpl, size.x, size.y);
|
||||
wlrBuffer.parent = this;
|
||||
wlrBuffer.stride = cairo_image_surface_get_stride(surf);
|
||||
}
|
||||
|
||||
CCursorManager::CCursorBuffer::CCursorBuffer(uint8_t* pixelData, const Vector2D& size_, const Vector2D& hot_) : size(size_), hotspot(hot_) {
|
||||
wlrBuffer.pixelData = pixelData;
|
||||
wlr_buffer_init(&wlrBuffer.base, &bufferImpl, size.x, size.y);
|
||||
wlrBuffer.parent = this;
|
||||
wlrBuffer.stride = 4 * size_.x;
|
||||
}
|
||||
|
||||
CCursorManager::CCursorBuffer::~CCursorBuffer() {
|
||||
|
|
@ -104,18 +113,53 @@ wlr_buffer* CCursorManager::getCursorBuffer() {
|
|||
return !m_vCursorBuffers.empty() ? &m_vCursorBuffers.back()->wlrBuffer.base : nullptr;
|
||||
}
|
||||
|
||||
void CCursorManager::setCursorSurface(wlr_surface* surf, const Vector2D& hotspot) {
|
||||
wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, surf, hotspot.x, hotspot.y);
|
||||
void CCursorManager::setCursorSurface(CWLSurface* surf, const Vector2D& hotspot) {
|
||||
if (!surf || !surf->wlr())
|
||||
g_pPointerManager->resetCursorImage();
|
||||
else
|
||||
g_pPointerManager->setCursorSurface(surf, hotspot);
|
||||
|
||||
m_bOurBufferConnected = false;
|
||||
}
|
||||
|
||||
void CCursorManager::setXCursor(const std::string& name) {
|
||||
if (!m_pWLRXCursorMgr) {
|
||||
g_pPointerManager->resetCursorImage();
|
||||
return;
|
||||
}
|
||||
|
||||
float scale = std::ceil(m_fCursorScale);
|
||||
wlr_xcursor_manager_load(m_pWLRXCursorMgr, scale);
|
||||
|
||||
auto xcursor = wlr_xcursor_manager_get_xcursor(m_pWLRXCursorMgr, name.c_str(), scale);
|
||||
if (!xcursor) {
|
||||
Debug::log(ERR, "XCursor has no shape {}, retrying with left-ptr", name);
|
||||
xcursor = wlr_xcursor_manager_get_xcursor(m_pWLRXCursorMgr, "left-ptr", scale);
|
||||
}
|
||||
|
||||
if (!xcursor || !xcursor->images[0]) {
|
||||
Debug::log(ERR, "XCursor is broken. F this garbage.");
|
||||
g_pPointerManager->resetCursorImage();
|
||||
return;
|
||||
}
|
||||
|
||||
auto image = xcursor->images[0];
|
||||
|
||||
m_vCursorBuffers.emplace_back(std::make_unique<CCursorBuffer>(image->buffer, Vector2D{image->width, image->height}, Vector2D{image->hotspot_x, image->hotspot_y}));
|
||||
|
||||
g_pPointerManager->setCursorBuffer(getCursorBuffer(), Vector2D{image->hotspot_x, image->hotspot_y} / scale, scale);
|
||||
if (m_vCursorBuffers.size() > 1)
|
||||
wlr_buffer_drop(&m_vCursorBuffers.front()->wlrBuffer.base);
|
||||
|
||||
m_bOurBufferConnected = true;
|
||||
}
|
||||
|
||||
void CCursorManager::setCursorFromName(const std::string& name) {
|
||||
|
||||
static auto PUSEHYPRCURSOR = CConfigValue<Hyprlang::INT>("misc:enable_hyprcursor");
|
||||
|
||||
if (!m_pHyprcursor->valid() || !*PUSEHYPRCURSOR) {
|
||||
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, m_pWLRXCursorMgr, name.c_str());
|
||||
setXCursor(name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -142,7 +186,7 @@ void CCursorManager::setCursorFromName(const std::string& name) {
|
|||
|
||||
if (m_sCurrentCursorShapeData.images.size() < 1) {
|
||||
Debug::log(ERR, "BUG THIS: No fallback found for a cursor in setCursorFromName");
|
||||
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, m_pWLRXCursorMgr, name.c_str());
|
||||
setXCursor(name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -151,12 +195,10 @@ void CCursorManager::setCursorFromName(const std::string& name) {
|
|||
Vector2D{m_sCurrentCursorShapeData.images[0].size, m_sCurrentCursorShapeData.images[0].size},
|
||||
Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY}));
|
||||
|
||||
if (g_pCompositor->m_sWLRCursor) {
|
||||
wlr_cursor_set_buffer(g_pCompositor->m_sWLRCursor, getCursorBuffer(), m_sCurrentCursorShapeData.images[0].hotspotX / m_fCursorScale,
|
||||
m_sCurrentCursorShapeData.images[0].hotspotY / m_fCursorScale, m_fCursorScale);
|
||||
if (m_vCursorBuffers.size() > 1)
|
||||
wlr_buffer_drop(&m_vCursorBuffers.front()->wlrBuffer.base);
|
||||
}
|
||||
g_pPointerManager->setCursorBuffer(getCursorBuffer(), Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY} / m_fCursorScale,
|
||||
m_fCursorScale);
|
||||
if (m_vCursorBuffers.size() > 1)
|
||||
wlr_buffer_drop(&m_vCursorBuffers.front()->wlrBuffer.base);
|
||||
|
||||
m_bOurBufferConnected = true;
|
||||
|
||||
|
|
@ -183,9 +225,10 @@ void CCursorManager::tickAnimatedCursor() {
|
|||
Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size},
|
||||
Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY}));
|
||||
|
||||
if (g_pCompositor->m_sWLRCursor)
|
||||
wlr_cursor_set_buffer(g_pCompositor->m_sWLRCursor, getCursorBuffer(), m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX / m_fCursorScale,
|
||||
m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY / m_fCursorScale, m_fCursorScale);
|
||||
g_pPointerManager->setCursorBuffer(
|
||||
getCursorBuffer(),
|
||||
Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY} / m_fCursorScale,
|
||||
m_fCursorScale);
|
||||
|
||||
wl_event_source_timer_update(m_pAnimationTimer, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].delay);
|
||||
}
|
||||
|
|
@ -223,8 +266,6 @@ void CCursorManager::updateTheme() {
|
|||
highestScale = m->scale;
|
||||
}
|
||||
|
||||
highestScale = std::ceil(highestScale);
|
||||
|
||||
if (std::round(highestScale * m_iSize) == m_sCurrentStyleInfo.size)
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
struct wlr_buffer;
|
||||
struct wlr_xcursor_manager;
|
||||
struct wlr_xwayland;
|
||||
class CWLSurface;
|
||||
|
||||
class CCursorManager {
|
||||
public:
|
||||
|
|
@ -18,7 +19,8 @@ class CCursorManager {
|
|||
wlr_buffer* getCursorBuffer();
|
||||
|
||||
void setCursorFromName(const std::string& name);
|
||||
void setCursorSurface(wlr_surface* surf, const Vector2D& hotspot);
|
||||
void setCursorSurface(CWLSurface* surf, const Vector2D& hotspot);
|
||||
void setXCursor(const std::string& name);
|
||||
|
||||
void changeTheme(const std::string& name, const int size);
|
||||
void updateTheme();
|
||||
|
|
@ -30,13 +32,16 @@ class CCursorManager {
|
|||
class CCursorBuffer {
|
||||
public:
|
||||
CCursorBuffer(cairo_surface_t* surf, const Vector2D& size, const Vector2D& hotspot);
|
||||
CCursorBuffer(uint8_t* pixelData, const Vector2D& size, const Vector2D& hotspot);
|
||||
~CCursorBuffer();
|
||||
|
||||
struct SCursorWlrBuffer {
|
||||
wlr_buffer base;
|
||||
cairo_surface_t* surface = nullptr;
|
||||
bool dropped = false;
|
||||
CCursorBuffer* parent = nullptr;
|
||||
cairo_surface_t* surface = nullptr;
|
||||
bool dropped = false;
|
||||
CCursorBuffer* parent = nullptr;
|
||||
uint8_t* pixelData = nullptr;
|
||||
size_t stride = 0;
|
||||
} wlrBuffer;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ bool CKeybindManager::tryMoveFocusToMonitor(CMonitor* monitor) {
|
|||
if (!monitor)
|
||||
return false;
|
||||
|
||||
const auto LASTMONITOR = g_pCompositor->m_pLastMonitor;
|
||||
const auto LASTMONITOR = g_pCompositor->m_pLastMonitor.get();
|
||||
if (LASTMONITOR == monitor) {
|
||||
Debug::log(LOG, "Tried to move to active monitor");
|
||||
return false;
|
||||
|
|
@ -407,7 +407,7 @@ bool CKeybindManager::onKeyEvent(std::any event, SP<IKeyboard> pKeyboard) {
|
|||
return !suppressEvent && !mouseBindWasActive;
|
||||
}
|
||||
|
||||
bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) {
|
||||
bool CKeybindManager::onAxisEvent(const IPointer::SAxisEvent& e) {
|
||||
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
|
||||
|
||||
static auto PDELAY = CConfigValue<Hyprlang::INT>("binds:scroll_event_delay");
|
||||
|
|
@ -426,13 +426,13 @@ bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) {
|
|||
}
|
||||
|
||||
bool found = false;
|
||||
if (e->source == WL_POINTER_AXIS_SOURCE_WHEEL && e->orientation == WL_POINTER_AXIS_VERTICAL_SCROLL) {
|
||||
if (e->delta < 0)
|
||||
if (e.source == WL_POINTER_AXIS_SOURCE_WHEEL && e.axis == WL_POINTER_AXIS_VERTICAL_SCROLL) {
|
||||
if (e.delta < 0)
|
||||
found = handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_down"}, true);
|
||||
else
|
||||
found = handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_up"}, true);
|
||||
} else if (e->source == WL_POINTER_AXIS_SOURCE_WHEEL && e->orientation == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
|
||||
if (e->delta < 0)
|
||||
} else if (e.source == WL_POINTER_AXIS_SOURCE_WHEEL && e.axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
|
||||
if (e.delta < 0)
|
||||
found = handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_left"}, true);
|
||||
else
|
||||
found = handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_right"}, true);
|
||||
|
|
@ -444,18 +444,18 @@ bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) {
|
|||
return !found;
|
||||
}
|
||||
|
||||
bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) {
|
||||
bool CKeybindManager::onMouseEvent(const IPointer::SButtonEvent& e) {
|
||||
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
|
||||
|
||||
bool suppressEvent = false;
|
||||
|
||||
m_uLastMouseCode = e->button;
|
||||
m_uLastMouseCode = e.button;
|
||||
m_uLastCode = 0;
|
||||
m_uTimeLastMs = e->time_msec;
|
||||
m_uTimeLastMs = e.timeMs;
|
||||
|
||||
bool mouseBindWasActive = ensureMouseBindState();
|
||||
|
||||
const auto KEY_NAME = "mouse:" + std::to_string(e->button);
|
||||
const auto KEY_NAME = "mouse:" + std::to_string(e.button);
|
||||
|
||||
const auto KEY = SPressedKeyWithMods{
|
||||
.keyName = KEY_NAME,
|
||||
|
|
@ -468,7 +468,7 @@ bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) {
|
|||
m_pActiveKeybind = nullptr;
|
||||
}
|
||||
|
||||
if (e->state == WL_POINTER_BUTTON_STATE_PRESSED) {
|
||||
if (e.state == WL_POINTER_BUTTON_STATE_PRESSED) {
|
||||
m_dPressedKeys.push_back(KEY);
|
||||
|
||||
suppressEvent = handleKeybinds(MODS, KEY, true);
|
||||
|
|
@ -501,12 +501,11 @@ bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) {
|
|||
return !suppressEvent && !mouseBindWasActive;
|
||||
}
|
||||
|
||||
void CKeybindManager::resizeWithBorder(wlr_pointer_button_event* e) {
|
||||
if (e->state == WL_POINTER_BUTTON_STATE_PRESSED) {
|
||||
void CKeybindManager::resizeWithBorder(const IPointer::SButtonEvent& e) {
|
||||
if (e.state == WL_POINTER_BUTTON_STATE_PRESSED)
|
||||
mouse("1resizewindow");
|
||||
} else {
|
||||
else
|
||||
mouse("0resizewindow");
|
||||
}
|
||||
}
|
||||
|
||||
void CKeybindManager::onSwitchEvent(const std::string& switchName) {
|
||||
|
|
@ -965,7 +964,7 @@ void CKeybindManager::changeworkspace(std::string args) {
|
|||
static auto PALLOWWORKSPACECYCLES = CConfigValue<Hyprlang::INT>("binds:allow_workspace_cycles");
|
||||
static auto PWORKSPACECENTERON = CConfigValue<Hyprlang::INT>("binds:workspace_center_on");
|
||||
|
||||
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
||||
const auto PMONITOR = g_pCompositor->m_pLastMonitor.get();
|
||||
|
||||
if (!PMONITOR)
|
||||
return;
|
||||
|
|
@ -1445,20 +1444,20 @@ void CKeybindManager::moveCursorToCorner(std::string arg) {
|
|||
switch (CORNER) {
|
||||
case 0:
|
||||
// bottom left
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y + PWINDOW->m_vRealSize.value().y);
|
||||
g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y + PWINDOW->m_vRealSize.value().y}, true);
|
||||
break;
|
||||
case 1:
|
||||
// bottom right
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PWINDOW->m_vRealPosition.value().x + PWINDOW->m_vRealSize.value().x,
|
||||
PWINDOW->m_vRealPosition.value().y + PWINDOW->m_vRealSize.value().y);
|
||||
g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition.value().x + PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealPosition.value().y + PWINDOW->m_vRealSize.value().y},
|
||||
true);
|
||||
break;
|
||||
case 2:
|
||||
// top right
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PWINDOW->m_vRealPosition.value().x + PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealPosition.value().y);
|
||||
g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition.value().x + PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealPosition.value().y}, true);
|
||||
break;
|
||||
case 3:
|
||||
// top left
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y);
|
||||
g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y}, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1488,7 +1487,7 @@ void CKeybindManager::moveCursor(std::string args) {
|
|||
x = std::stoi(x_str);
|
||||
y = std::stoi(y_str);
|
||||
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, x, y);
|
||||
g_pCompositor->warpCursorTo({x, y}, true);
|
||||
}
|
||||
|
||||
void CKeybindManager::workspaceOpt(std::string args) {
|
||||
|
|
@ -1624,7 +1623,7 @@ void CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) {
|
|||
return;
|
||||
}
|
||||
|
||||
const auto PCURRMONITOR = g_pCompositor->m_pLastMonitor;
|
||||
const auto PCURRMONITOR = g_pCompositor->m_pLastMonitor.get();
|
||||
|
||||
if (!PCURRMONITOR) {
|
||||
Debug::log(ERR, "focusWorkspaceOnCurrentMonitor monitor doesn't exist!");
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "../Compositor.hpp"
|
||||
#include <unordered_map>
|
||||
#include <functional>
|
||||
#include "../devices/IPointer.hpp"
|
||||
|
||||
class CInputManager;
|
||||
class CConfigManager;
|
||||
|
|
@ -62,9 +63,9 @@ class CKeybindManager {
|
|||
~CKeybindManager();
|
||||
|
||||
bool onKeyEvent(std::any, SP<IKeyboard>);
|
||||
bool onAxisEvent(wlr_pointer_axis_event*);
|
||||
bool onMouseEvent(wlr_pointer_button_event*);
|
||||
void resizeWithBorder(wlr_pointer_button_event*);
|
||||
bool onAxisEvent(const IPointer::SAxisEvent&);
|
||||
bool onMouseEvent(const IPointer::SButtonEvent&);
|
||||
void resizeWithBorder(const IPointer::SButtonEvent&);
|
||||
void onSwitchEvent(const std::string&);
|
||||
void onSwitchOnEvent(const std::string&);
|
||||
void onSwitchOffEvent(const std::string&);
|
||||
|
|
|
|||
864
src/managers/PointerManager.cpp
Normal file
864
src/managers/PointerManager.cpp
Normal file
|
|
@ -0,0 +1,864 @@
|
|||
#include "PointerManager.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "../config/ConfigValue.hpp"
|
||||
#include "../protocols/PointerGestures.hpp"
|
||||
#include "../protocols/FractionalScale.hpp"
|
||||
#include <wlr/interfaces/wlr_output.h>
|
||||
#include <wlr/render/interface.h>
|
||||
#include <wlr/render/wlr_renderer.h>
|
||||
|
||||
// TODO: make nicer
|
||||
// this will come with the eventual rewrite of wlr_drm, etc...
|
||||
static bool wlr_drm_format_intersect(wlr_drm_format* dst, const wlr_drm_format* a, const wlr_drm_format* b) {
|
||||
ASSERT(a->format == b->format);
|
||||
|
||||
size_t capacity = a->len < b->len ? a->len : b->len;
|
||||
uint64_t* modifiers = (uint64_t*)malloc(sizeof(*modifiers) * capacity);
|
||||
if (!modifiers)
|
||||
return false;
|
||||
|
||||
struct wlr_drm_format fmt = {
|
||||
.format = a->format,
|
||||
.len = 0,
|
||||
.capacity = capacity,
|
||||
.modifiers = modifiers,
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < a->len; i++) {
|
||||
for (size_t j = 0; j < b->len; j++) {
|
||||
if (a->modifiers[i] == b->modifiers[j]) {
|
||||
ASSERT(fmt.len < fmt.capacity);
|
||||
fmt.modifiers[fmt.len++] = a->modifiers[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wlr_drm_format_finish(dst);
|
||||
*dst = fmt;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool wlr_drm_format_copy(wlr_drm_format* dst, const wlr_drm_format* src) {
|
||||
ASSERT(src->len <= src->capacity);
|
||||
|
||||
uint64_t* modifiers = (uint64_t*)malloc(sizeof(*modifiers) * src->len);
|
||||
if (!modifiers)
|
||||
return false;
|
||||
|
||||
memcpy(modifiers, src->modifiers, sizeof(*modifiers) * src->len);
|
||||
|
||||
wlr_drm_format_finish(dst);
|
||||
dst->capacity = src->len;
|
||||
dst->len = src->len;
|
||||
dst->format = src->format;
|
||||
dst->modifiers = modifiers;
|
||||
return true;
|
||||
}
|
||||
|
||||
static const wlr_drm_format_set* wlr_renderer_get_render_formats(wlr_renderer* r) {
|
||||
if (!r->impl->get_render_formats)
|
||||
return nullptr;
|
||||
|
||||
return r->impl->get_render_formats(r);
|
||||
}
|
||||
|
||||
static bool output_pick_format(wlr_output* output, const wlr_drm_format_set* display_formats, wlr_drm_format* format, uint32_t fmt) {
|
||||
|
||||
const wlr_drm_format_set* render_formats = wlr_renderer_get_render_formats(g_pCompositor->m_sWLRRenderer);
|
||||
if (render_formats == NULL) {
|
||||
wlr_log(WLR_ERROR, "Failed to get render formats");
|
||||
return false;
|
||||
}
|
||||
|
||||
const wlr_drm_format* render_format = wlr_drm_format_set_get(render_formats, fmt);
|
||||
if (render_format == NULL) {
|
||||
wlr_log(WLR_DEBUG, "Renderer doesn't support format 0x%" PRIX32, fmt);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (display_formats != NULL) {
|
||||
const wlr_drm_format* display_format = wlr_drm_format_set_get(display_formats, fmt);
|
||||
if (display_format == NULL) {
|
||||
wlr_log(WLR_DEBUG, "Output doesn't support format 0x%" PRIX32, fmt);
|
||||
return false;
|
||||
}
|
||||
if (!wlr_drm_format_intersect(format, display_format, render_format)) {
|
||||
wlr_log(WLR_DEBUG,
|
||||
"Failed to intersect display and render "
|
||||
"modifiers for format 0x%" PRIX32 " on output %s",
|
||||
fmt, output->name);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// The output can display any format
|
||||
if (!wlr_drm_format_copy(format, render_format))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (format->len == 0) {
|
||||
wlr_drm_format_finish(format);
|
||||
wlr_log(WLR_DEBUG, "Failed to pick output format");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool output_pick_cursor_format(struct wlr_output* output, struct wlr_drm_format* format) {
|
||||
struct wlr_allocator* allocator = output->allocator;
|
||||
ASSERT(allocator != NULL);
|
||||
|
||||
const struct wlr_drm_format_set* display_formats = NULL;
|
||||
if (output->impl->get_cursor_formats) {
|
||||
display_formats = output->impl->get_cursor_formats(output, allocator->buffer_caps);
|
||||
if (display_formats == NULL) {
|
||||
wlr_log(WLR_DEBUG, "Failed to get cursor display formats");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return output_pick_format(output, display_formats, format, DRM_FORMAT_ARGB8888);
|
||||
}
|
||||
|
||||
CPointerManager::CPointerManager() {
|
||||
hooks.monitorAdded = g_pHookSystem->hookDynamic("newMonitor", [this](void* self, SCallbackInfo& info, std::any data) {
|
||||
auto PMONITOR = std::any_cast<SP<CMonitor>>(data);
|
||||
|
||||
onMonitorLayoutChange();
|
||||
|
||||
PMONITOR->events.modeChanged.registerStaticListener([this](void* owner, std::any data) { onMonitorLayoutChange(); }, nullptr);
|
||||
PMONITOR->events.disconnect.registerStaticListener([this](void* owner, std::any data) { onMonitorLayoutChange(); }, nullptr);
|
||||
PMONITOR->events.destroy.registerStaticListener(
|
||||
[this](void* owner, std::any data) { std::erase_if(monitorStates, [](const auto& other) { return other->monitor.expired(); }); }, nullptr);
|
||||
});
|
||||
}
|
||||
|
||||
void CPointerManager::lockSoftwareForMonitor(SP<CMonitor> mon) {
|
||||
auto state = stateFor(mon);
|
||||
state->softwareLocks++;
|
||||
|
||||
if (state->softwareLocks == 1)
|
||||
updateCursorBackend();
|
||||
}
|
||||
|
||||
void CPointerManager::unlockSoftwareForMonitor(SP<CMonitor> mon) {
|
||||
auto state = stateFor(mon);
|
||||
state->softwareLocks--;
|
||||
if (state->softwareLocks < 0)
|
||||
state->softwareLocks = 0;
|
||||
|
||||
if (state->softwareLocks == 0)
|
||||
updateCursorBackend();
|
||||
}
|
||||
|
||||
Vector2D CPointerManager::position() {
|
||||
return pointerPos;
|
||||
}
|
||||
|
||||
bool CPointerManager::hasCursor() {
|
||||
return currentCursorImage.pBuffer || currentCursorImage.surface;
|
||||
}
|
||||
|
||||
SP<CPointerManager::SMonitorPointerState> CPointerManager::stateFor(SP<CMonitor> mon) {
|
||||
auto it = std::find_if(monitorStates.begin(), monitorStates.end(), [mon](const auto& other) { return other->monitor == mon; });
|
||||
if (it == monitorStates.end())
|
||||
return monitorStates.emplace_back(makeShared<CPointerManager::SMonitorPointerState>(mon));
|
||||
return *it;
|
||||
}
|
||||
|
||||
void CPointerManager::setCursorBuffer(wlr_buffer* buf, const Vector2D& hotspot, const float& scale) {
|
||||
if (buf == currentCursorImage.pBuffer) {
|
||||
if (hotspot != currentCursorImage.hotspot || scale != currentCursorImage.scale) {
|
||||
currentCursorImage.hotspot = hotspot;
|
||||
currentCursorImage.scale = scale;
|
||||
updateCursorBackend();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
resetCursorImage(false);
|
||||
|
||||
if (buf) {
|
||||
currentCursorImage.size = {buf->width, buf->height};
|
||||
currentCursorImage.pBuffer = wlr_buffer_lock(buf);
|
||||
|
||||
currentCursorImage.hyprListener_destroyBuffer.initCallback(
|
||||
&buf->events.destroy, [this](void* owner, void* data) { resetCursorImage(); }, this, "CPointerManager");
|
||||
}
|
||||
|
||||
currentCursorImage.hotspot = hotspot;
|
||||
currentCursorImage.scale = scale;
|
||||
|
||||
updateCursorBackend();
|
||||
}
|
||||
|
||||
void CPointerManager::setCursorSurface(CWLSurface* surf, const Vector2D& hotspot) {
|
||||
if (surf == currentCursorImage.surface) {
|
||||
if (hotspot != currentCursorImage.hotspot || (surf && surf->wlr() ? surf->wlr()->current.scale : 1.F) != currentCursorImage.scale) {
|
||||
currentCursorImage.hotspot = hotspot;
|
||||
currentCursorImage.scale = surf && surf->wlr() ? surf->wlr()->current.scale : 1.F;
|
||||
updateCursorBackend();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
resetCursorImage(false);
|
||||
|
||||
if (surf) {
|
||||
currentCursorImage.size = {surf->wlr()->current.buffer_width, surf->wlr()->current.buffer_height};
|
||||
currentCursorImage.surface = surf;
|
||||
currentCursorImage.scale = surf->wlr()->current.scale;
|
||||
|
||||
currentCursorImage.destroySurface = surf->events.destroy.registerListener([this](std::any data) { resetCursorImage(); });
|
||||
currentCursorImage.hyprListener_commitSurface.initCallback(
|
||||
&surf->wlr()->events.commit,
|
||||
[this](void* owner, void* data) {
|
||||
currentCursorImage.size = {currentCursorImage.surface->wlr()->current.buffer_width, currentCursorImage.surface->wlr()->current.buffer_height};
|
||||
currentCursorImage.scale = currentCursorImage.surface && currentCursorImage.surface->wlr() ? currentCursorImage.surface->wlr()->current.scale : 1.F;
|
||||
recheckEnteredOutputs();
|
||||
updateCursorBackend();
|
||||
},
|
||||
nullptr, "CPointerManager");
|
||||
|
||||
if (surf->wlr()->current.buffer) {
|
||||
timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
wlr_surface_send_frame_done(surf->wlr(), &now);
|
||||
}
|
||||
}
|
||||
|
||||
currentCursorImage.hotspot = hotspot;
|
||||
|
||||
recheckEnteredOutputs();
|
||||
updateCursorBackend();
|
||||
}
|
||||
|
||||
void CPointerManager::recheckEnteredOutputs() {
|
||||
if (!hasCursor())
|
||||
return;
|
||||
|
||||
auto box = getCursorBoxGlobal();
|
||||
|
||||
for (auto& s : monitorStates) {
|
||||
if (s->monitor.expired() || s->monitor->isMirror() || !s->monitor->m_bEnabled)
|
||||
continue;
|
||||
|
||||
const bool overlaps = box.overlaps(s->monitor->logicalBox());
|
||||
|
||||
if (!s->entered && overlaps) {
|
||||
s->entered = true;
|
||||
|
||||
if (!currentCursorImage.surface)
|
||||
continue;
|
||||
|
||||
wlr_surface_send_enter(currentCursorImage.surface->wlr(), s->monitor->output);
|
||||
PROTO::fractional->sendScale(currentCursorImage.surface->wlr(), s->monitor->scale);
|
||||
g_pCompositor->setPreferredScaleForSurface(currentCursorImage.surface->wlr(), s->monitor->scale);
|
||||
} else if (s->entered && !overlaps) {
|
||||
s->entered = false;
|
||||
|
||||
// if we are using hw cursors, prevent
|
||||
// the cursor from being stuck at the last point.
|
||||
// if we are leaving it, move it to narnia.
|
||||
if (!s->hardwareFailed && s->monitor->output->impl->move_cursor)
|
||||
s->monitor->output->impl->move_cursor(s->monitor->output, -1337, -420);
|
||||
|
||||
if (!currentCursorImage.surface)
|
||||
continue;
|
||||
|
||||
wlr_surface_send_leave(currentCursorImage.surface->wlr(), s->monitor->output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CPointerManager::resetCursorImage(bool apply) {
|
||||
if (currentCursorImage.surface) {
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
wlr_surface_send_leave(currentCursorImage.surface->wlr(), m->output);
|
||||
}
|
||||
|
||||
currentCursorImage.destroySurface.reset();
|
||||
currentCursorImage.hyprListener_commitSurface.removeCallback();
|
||||
currentCursorImage.surface = nullptr;
|
||||
} else if (currentCursorImage.pBuffer) {
|
||||
wlr_buffer_unlock(currentCursorImage.pBuffer);
|
||||
currentCursorImage.hyprListener_destroyBuffer.removeCallback();
|
||||
currentCursorImage.pBuffer = nullptr;
|
||||
}
|
||||
|
||||
if (currentCursorImage.pBufferTexture) {
|
||||
wlr_texture_destroy(currentCursorImage.pBufferTexture);
|
||||
currentCursorImage.pBufferTexture = nullptr;
|
||||
}
|
||||
|
||||
currentCursorImage.scale = 1.F;
|
||||
currentCursorImage.hotspot = {0, 0};
|
||||
|
||||
if (!apply)
|
||||
return;
|
||||
|
||||
for (auto& ms : monitorStates) {
|
||||
if (ms->cursorFrontBuffer) {
|
||||
if (ms->monitor->output->impl->set_cursor)
|
||||
ms->monitor->output->impl->set_cursor(ms->monitor->output, nullptr, 0, 0);
|
||||
wlr_buffer_unlock(ms->cursorFrontBuffer);
|
||||
ms->cursorFrontBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CPointerManager::updateCursorBackend() {
|
||||
static auto PNOHW = CConfigValue<Hyprlang::INT>("cursor:no_hardware_cursors");
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
auto state = stateFor(m);
|
||||
|
||||
if (state->softwareLocks > 0 || *PNOHW || !attemptHardwareCursor(state)) {
|
||||
Debug::log(TRACE, "Output {} rejected hardware cursors, falling back to sw", m->szName);
|
||||
state->box = getCursorBoxLogicalForMonitor(state->monitor.lock());
|
||||
state->hardwareFailed = true;
|
||||
|
||||
if (state->hwApplied)
|
||||
setHWCursorBuffer(state, nullptr);
|
||||
|
||||
state->hwApplied = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
state->hardwareFailed = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CPointerManager::onCursorMoved() {
|
||||
if (!hasCursor())
|
||||
return;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
auto state = stateFor(m);
|
||||
|
||||
state->box = getCursorBoxLogicalForMonitor(state->monitor.lock());
|
||||
|
||||
if (state->hardwareFailed || !state->entered)
|
||||
continue;
|
||||
|
||||
const auto CURSORPOS = getCursorPosForMonitor(m);
|
||||
m->output->impl->move_cursor(m->output, CURSORPOS.x, CURSORPOS.y);
|
||||
}
|
||||
}
|
||||
|
||||
bool CPointerManager::attemptHardwareCursor(SP<CPointerManager::SMonitorPointerState> state) {
|
||||
auto output = state->monitor->output;
|
||||
|
||||
if (!output->impl->set_cursor)
|
||||
return false;
|
||||
|
||||
const auto CURSORPOS = getCursorPosForMonitor(state->monitor.lock());
|
||||
state->monitor->output->impl->move_cursor(state->monitor->output, CURSORPOS.x, CURSORPOS.y);
|
||||
|
||||
auto texture = getCurrentCursorTexture();
|
||||
|
||||
if (!texture) {
|
||||
Debug::log(TRACE, "[pointer] no texture for hw cursor -> hiding");
|
||||
setHWCursorBuffer(state, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto buffer = renderHWCursorBuffer(state, texture);
|
||||
|
||||
if (!buffer) {
|
||||
Debug::log(TRACE, "[pointer] hw cursor failed rendering");
|
||||
setHWCursorBuffer(state, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = setHWCursorBuffer(state, buffer);
|
||||
|
||||
if (!success) {
|
||||
Debug::log(TRACE, "[pointer] hw cursor failed applying, hiding");
|
||||
setHWCursorBuffer(state, nullptr);
|
||||
return false;
|
||||
} else
|
||||
state->hwApplied = true;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool CPointerManager::setHWCursorBuffer(SP<SMonitorPointerState> state, wlr_buffer* buf) {
|
||||
if (!state->monitor->output->impl->set_cursor)
|
||||
return false;
|
||||
|
||||
const auto HOTSPOT = transformedHotspot(state->monitor.lock());
|
||||
|
||||
Debug::log(TRACE, "[pointer] hw transformed hotspot for {}: {}", state->monitor->szName, HOTSPOT);
|
||||
|
||||
if (!state->monitor->output->impl->set_cursor(state->monitor->output, buf, HOTSPOT.x, HOTSPOT.y))
|
||||
return false;
|
||||
|
||||
wlr_buffer_unlock(state->cursorFrontBuffer);
|
||||
state->cursorFrontBuffer = buf;
|
||||
|
||||
g_pCompositor->scheduleFrameForMonitor(state->monitor.get());
|
||||
|
||||
if (buf)
|
||||
wlr_buffer_lock(buf);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
wlr_buffer* CPointerManager::renderHWCursorBuffer(SP<CPointerManager::SMonitorPointerState> state, wlr_texture* texture) {
|
||||
auto output = state->monitor->output;
|
||||
|
||||
int w = currentCursorImage.size.x, h = currentCursorImage.size.y;
|
||||
if (output->impl->get_cursor_size) {
|
||||
output->impl->get_cursor_size(output, &w, &h);
|
||||
|
||||
if (w < currentCursorImage.size.x || h < currentCursorImage.size.y) {
|
||||
Debug::log(TRACE, "hardware cursor too big! {} > {}x{}", currentCursorImage.size, w, h);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (w <= 0 || h <= 0) {
|
||||
Debug::log(TRACE, "hw cursor for output {} failed the size checks ({}x{} is invalid)", state->monitor->szName, w, h);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!output->cursor_swapchain || Vector2D{w, h} != Vector2D{output->cursor_swapchain->width, output->cursor_swapchain->height}) {
|
||||
wlr_drm_format fmt = {0};
|
||||
if (!output_pick_cursor_format(output, &fmt)) {
|
||||
Debug::log(TRACE, "Failed to pick cursor format");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wlr_swapchain_destroy(output->cursor_swapchain);
|
||||
output->cursor_swapchain = wlr_swapchain_create(output->allocator, w, h, &fmt);
|
||||
wlr_drm_format_finish(&fmt);
|
||||
|
||||
if (!output->cursor_swapchain) {
|
||||
Debug::log(TRACE, "Failed to create cursor swapchain");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
wlr_buffer* buf = wlr_swapchain_acquire(output->cursor_swapchain, nullptr);
|
||||
if (!buf) {
|
||||
Debug::log(TRACE, "Failed to acquire a buffer from the cursor swapchain");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CRegion damage = {0, 0, INT16_MAX, INT16_MAX};
|
||||
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor.get(); // has to be set cuz allocs
|
||||
|
||||
const auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, DRM_FORMAT_ARGB8888);
|
||||
RBO->bind();
|
||||
|
||||
g_pHyprOpenGL->beginSimple(state->monitor.get(), damage, RBO);
|
||||
g_pHyprOpenGL->clear(CColor{0.F, 0.F, 0.F, 0.F});
|
||||
|
||||
CBox xbox = {{}, Vector2D{currentCursorImage.size / currentCursorImage.scale * state->monitor->scale}.round()};
|
||||
Debug::log(TRACE, "[pointer] monitor: {}, size: {}, hw buf: {}, scale: {:.2f}, monscale: {:.2f}, xbox: {}", state->monitor->szName, currentCursorImage.size, Vector2D{w, h},
|
||||
currentCursorImage.scale, state->monitor->scale, xbox.size());
|
||||
|
||||
g_pHyprOpenGL->renderTexture(texture, &xbox, 1.F);
|
||||
|
||||
g_pHyprOpenGL->end();
|
||||
glFlush();
|
||||
g_pHyprOpenGL->m_RenderData.pMonitor = nullptr;
|
||||
|
||||
g_pHyprRenderer->onRenderbufferDestroy(RBO);
|
||||
|
||||
wlr_buffer_unlock(buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void CPointerManager::renderSoftwareCursorsFor(SP<CMonitor> pMonitor, timespec* now, CRegion& damage, std::optional<Vector2D> overridePos) {
|
||||
if (!hasCursor())
|
||||
return;
|
||||
|
||||
auto state = stateFor(pMonitor);
|
||||
|
||||
if ((!state->hardwareFailed && state->softwareLocks == 0)) {
|
||||
if (currentCursorImage.surface)
|
||||
wlr_surface_send_frame_done(currentCursorImage.surface->wlr(), now);
|
||||
return;
|
||||
}
|
||||
|
||||
auto box = state->box.copy();
|
||||
if (overridePos.has_value()) {
|
||||
box.x = overridePos->x;
|
||||
box.y = overridePos->y;
|
||||
}
|
||||
|
||||
if (box.intersection(CBox{{}, {pMonitor->vecSize}}).empty())
|
||||
return;
|
||||
|
||||
auto texture = getCurrentCursorTexture();
|
||||
if (!texture)
|
||||
return;
|
||||
|
||||
box.scale(pMonitor->scale);
|
||||
|
||||
g_pHyprOpenGL->renderTextureWithDamage(texture, &box, &damage, 1.F);
|
||||
|
||||
if (currentCursorImage.surface)
|
||||
wlr_surface_send_frame_done(currentCursorImage.surface->wlr(), now);
|
||||
}
|
||||
|
||||
Vector2D CPointerManager::getCursorPosForMonitor(SP<CMonitor> pMonitor) {
|
||||
return CBox{pointerPos - pMonitor->vecPosition, {0, 0}}
|
||||
//.transform(pMonitor->transform, pMonitor->vecTransformedSize.x / pMonitor->scale, pMonitor->vecTransformedSize.y / pMonitor->scale)
|
||||
.pos() *
|
||||
pMonitor->scale;
|
||||
}
|
||||
|
||||
Vector2D CPointerManager::transformedHotspot(SP<CMonitor> pMonitor) {
|
||||
return CBox{currentCursorImage.hotspot, {0, 0}}
|
||||
.transform(wlr_output_transform_invert(pMonitor->transform), pMonitor->output->cursor_swapchain->width, pMonitor->output->cursor_swapchain->height)
|
||||
.pos();
|
||||
}
|
||||
|
||||
CBox CPointerManager::getCursorBoxLogicalForMonitor(SP<CMonitor> pMonitor) {
|
||||
return getCursorBoxGlobal().translate(-pMonitor->vecPosition);
|
||||
}
|
||||
|
||||
CBox CPointerManager::getCursorBoxGlobal() {
|
||||
return CBox{pointerPos, currentCursorImage.size / currentCursorImage.scale}.translate(-currentCursorImage.hotspot / currentCursorImage.scale);
|
||||
}
|
||||
|
||||
Vector2D CPointerManager::closestValid(const Vector2D& pos) {
|
||||
static auto PADDING = CConfigValue<Hyprlang::INT>("cursor:hotspot_padding");
|
||||
|
||||
auto CURSOR_PADDING = std::clamp((int)*PADDING, 1, 100); // 1px
|
||||
CBox hotBox = {{pos.x - CURSOR_PADDING, pos.y - CURSOR_PADDING}, {2 * CURSOR_PADDING, 2 * CURSOR_PADDING}};
|
||||
|
||||
//
|
||||
static auto INSIDE_LAYOUT = [this](const CBox& box) -> bool {
|
||||
for (auto& b : currentMonitorLayout.monitorBoxes) {
|
||||
if (box.inside(b))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
static auto INSIDE_LAYOUT_COORD = [this](const Vector2D& vec) -> bool {
|
||||
for (auto& b : currentMonitorLayout.monitorBoxes) {
|
||||
if (b.containsPoint(vec))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
static auto NEAREST_LAYOUT = [this](const Vector2D& vec) -> Vector2D {
|
||||
Vector2D leader;
|
||||
float distanceSq = __FLT_MAX__;
|
||||
|
||||
for (auto& b : currentMonitorLayout.monitorBoxes) {
|
||||
auto p = b.closestPoint(vec);
|
||||
auto distSq = p.distanceSq(vec);
|
||||
|
||||
if (distSq < distanceSq) {
|
||||
leader = p;
|
||||
distanceSq = distSq;
|
||||
}
|
||||
}
|
||||
|
||||
if (distanceSq > 1337.69420e+20F)
|
||||
return {0, 0}; // ???
|
||||
|
||||
return leader;
|
||||
};
|
||||
|
||||
if (INSIDE_LAYOUT(hotBox))
|
||||
return pos;
|
||||
|
||||
Vector2D leader = NEAREST_LAYOUT(pos);
|
||||
|
||||
hotBox.x = leader.x - CURSOR_PADDING;
|
||||
hotBox.y = leader.y - CURSOR_PADDING;
|
||||
|
||||
// push the hotbox around so that it fits in the layout
|
||||
|
||||
if (!INSIDE_LAYOUT_COORD(hotBox.middle() + Vector2D{CURSOR_PADDING, CURSOR_PADDING})) {
|
||||
auto delta = NEAREST_LAYOUT(hotBox.middle() + Vector2D{CURSOR_PADDING, CURSOR_PADDING}) - (hotBox.middle() + Vector2D{CURSOR_PADDING, CURSOR_PADDING});
|
||||
hotBox.translate(delta);
|
||||
}
|
||||
|
||||
if (!INSIDE_LAYOUT_COORD(hotBox.middle() - Vector2D{CURSOR_PADDING, CURSOR_PADDING})) {
|
||||
auto delta = NEAREST_LAYOUT(hotBox.middle() - Vector2D{CURSOR_PADDING, CURSOR_PADDING}) - (hotBox.middle() - Vector2D{CURSOR_PADDING, CURSOR_PADDING});
|
||||
hotBox.translate(delta);
|
||||
}
|
||||
|
||||
if (!INSIDE_LAYOUT_COORD(hotBox.middle() + Vector2D{CURSOR_PADDING, -CURSOR_PADDING})) {
|
||||
auto delta = NEAREST_LAYOUT(hotBox.middle() + Vector2D{CURSOR_PADDING, -CURSOR_PADDING}) - (hotBox.middle() + Vector2D{CURSOR_PADDING, -CURSOR_PADDING});
|
||||
hotBox.translate(delta);
|
||||
}
|
||||
|
||||
if (!INSIDE_LAYOUT_COORD(hotBox.middle() + Vector2D{-CURSOR_PADDING, CURSOR_PADDING})) {
|
||||
auto delta = NEAREST_LAYOUT(hotBox.middle() + Vector2D{-CURSOR_PADDING, CURSOR_PADDING}) - (hotBox.middle() + Vector2D{-CURSOR_PADDING, CURSOR_PADDING});
|
||||
hotBox.translate(delta);
|
||||
}
|
||||
|
||||
return hotBox.middle();
|
||||
}
|
||||
|
||||
void CPointerManager::damageIfSoftware() {
|
||||
auto b = getCursorBoxGlobal();
|
||||
|
||||
static auto PNOHW = CConfigValue<Hyprlang::INT>("cursor:no_hardware_cursors");
|
||||
|
||||
for (auto& mw : monitorStates) {
|
||||
if (mw->monitor.expired())
|
||||
continue;
|
||||
|
||||
if ((mw->softwareLocks > 0 || mw->hardwareFailed || *PNOHW) && b.overlaps({mw->monitor->vecPosition, mw->monitor->vecSize})) {
|
||||
g_pHyprRenderer->damageBox(&b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CPointerManager::warpTo(const Vector2D& logical) {
|
||||
damageIfSoftware();
|
||||
|
||||
pointerPos = closestValid(logical);
|
||||
recheckEnteredOutputs();
|
||||
onCursorMoved();
|
||||
|
||||
damageIfSoftware();
|
||||
}
|
||||
|
||||
void CPointerManager::move(const Vector2D& deltaLogical) {
|
||||
const auto oldPos = pointerPos;
|
||||
auto newPos = oldPos + deltaLogical;
|
||||
|
||||
warpTo(newPos);
|
||||
}
|
||||
|
||||
void CPointerManager::warpAbsolute(const Vector2D& abs, SP<IHID> dev) {
|
||||
|
||||
SP<CMonitor> currentMonitor = g_pCompositor->m_pLastMonitor.lock();
|
||||
|
||||
switch (dev->getType()) {
|
||||
case HID_TYPE_TABLET:
|
||||
//TODO:
|
||||
break;
|
||||
case HID_TYPE_TOUCH: {
|
||||
auto TOUCH = SP<ITouch>(dev);
|
||||
if (!TOUCH->boundOutput.empty()) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromString(TOUCH->boundOutput);
|
||||
if (PMONITOR)
|
||||
currentMonitor = PMONITOR->self.lock();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (!currentMonitor)
|
||||
return;
|
||||
|
||||
damageIfSoftware();
|
||||
|
||||
pointerPos = currentMonitor->vecPosition + currentMonitor->vecSize * abs;
|
||||
onCursorMoved();
|
||||
recheckEnteredOutputs();
|
||||
|
||||
damageIfSoftware();
|
||||
}
|
||||
|
||||
void CPointerManager::onMonitorLayoutChange() {
|
||||
currentMonitorLayout.monitorBoxes.clear();
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (m->isMirror() || !m->m_bEnabled)
|
||||
continue;
|
||||
|
||||
currentMonitorLayout.monitorBoxes.emplace_back(CBox{m->vecPosition, m->vecSize});
|
||||
}
|
||||
|
||||
damageIfSoftware();
|
||||
|
||||
pointerPos = closestValid(pointerPos);
|
||||
updateCursorBackend();
|
||||
recheckEnteredOutputs();
|
||||
|
||||
damageIfSoftware();
|
||||
}
|
||||
|
||||
wlr_texture* CPointerManager::getCurrentCursorTexture() {
|
||||
if (!currentCursorImage.pBuffer && (!currentCursorImage.surface || !wlr_surface_get_texture(currentCursorImage.surface->wlr())))
|
||||
return nullptr;
|
||||
|
||||
if (currentCursorImage.pBuffer) {
|
||||
if (!currentCursorImage.pBufferTexture)
|
||||
currentCursorImage.pBufferTexture = wlr_texture_from_buffer(g_pCompositor->m_sWLRRenderer, currentCursorImage.pBuffer);
|
||||
return currentCursorImage.pBufferTexture;
|
||||
}
|
||||
|
||||
return wlr_surface_get_texture(currentCursorImage.surface->wlr());
|
||||
}
|
||||
|
||||
void CPointerManager::attachPointer(SP<IPointer> pointer) {
|
||||
if (!pointer)
|
||||
return;
|
||||
|
||||
auto listener = pointerListeners.emplace_back(makeShared<SPointerListener>());
|
||||
|
||||
listener->pointer = pointer;
|
||||
|
||||
// clang-format off
|
||||
listener->destroy = pointer->events.destroy.registerListener([this] (std::any d) {
|
||||
detachPointer(nullptr);
|
||||
});
|
||||
|
||||
listener->motion = pointer->pointerEvents.motion.registerListener([this] (std::any e) {
|
||||
auto E = std::any_cast<IPointer::SMotionEvent>(e);
|
||||
|
||||
g_pInputManager->onMouseMoved(E);
|
||||
});
|
||||
|
||||
listener->motionAbsolute = pointer->pointerEvents.motionAbsolute.registerListener([this] (std::any e) {
|
||||
auto E = std::any_cast<IPointer::SMotionAbsoluteEvent>(e);
|
||||
|
||||
g_pInputManager->onMouseWarp(E);
|
||||
});
|
||||
|
||||
listener->button = pointer->pointerEvents.button.registerListener([this] (std::any e) {
|
||||
auto E = std::any_cast<IPointer::SButtonEvent>(e);
|
||||
|
||||
g_pInputManager->onMouseButton(E);
|
||||
});
|
||||
|
||||
listener->axis = pointer->pointerEvents.axis.registerListener([this] (std::any e) {
|
||||
auto E = std::any_cast<IPointer::SAxisEvent>(e);
|
||||
|
||||
g_pInputManager->onMouseWheel(E);
|
||||
});
|
||||
|
||||
listener->frame = pointer->pointerEvents.frame.registerListener([this] (std::any e) {
|
||||
wlr_seat_pointer_notify_frame(g_pCompositor->m_sSeat.seat);
|
||||
});
|
||||
|
||||
listener->swipeBegin = pointer->pointerEvents.swipeBegin.registerListener([this] (std::any e) {
|
||||
auto E = std::any_cast<IPointer::SSwipeBeginEvent>(e);
|
||||
|
||||
g_pInputManager->onSwipeBegin(E);
|
||||
});
|
||||
|
||||
listener->swipeEnd = pointer->pointerEvents.swipeEnd.registerListener([this] (std::any e) {
|
||||
auto E = std::any_cast<IPointer::SSwipeEndEvent>(e);
|
||||
|
||||
g_pInputManager->onSwipeEnd(E);
|
||||
});
|
||||
|
||||
listener->swipeUpdate = pointer->pointerEvents.swipeUpdate.registerListener([this] (std::any e) {
|
||||
auto E = std::any_cast<IPointer::SSwipeUpdateEvent>(e);
|
||||
|
||||
g_pInputManager->onSwipeUpdate(E);
|
||||
});
|
||||
|
||||
listener->pinchBegin = pointer->pointerEvents.pinchBegin.registerListener([this] (std::any e) {
|
||||
auto E = std::any_cast<IPointer::SPinchBeginEvent>(e);
|
||||
|
||||
PROTO::pointerGestures->pinchBegin(E.timeMs, E.fingers);
|
||||
});
|
||||
|
||||
listener->pinchEnd = pointer->pointerEvents.pinchEnd.registerListener([this] (std::any e) {
|
||||
auto E = std::any_cast<IPointer::SPinchEndEvent>(e);
|
||||
|
||||
PROTO::pointerGestures->pinchEnd(E.timeMs, E.cancelled);
|
||||
});
|
||||
|
||||
listener->pinchUpdate = pointer->pointerEvents.pinchUpdate.registerListener([this] (std::any e) {
|
||||
auto E = std::any_cast<IPointer::SPinchUpdateEvent>(e);
|
||||
|
||||
PROTO::pointerGestures->pinchUpdate(E.timeMs, E.delta, E.scale, E.rotation);
|
||||
});
|
||||
|
||||
listener->holdBegin = pointer->pointerEvents.holdBegin.registerListener([this] (std::any e) {
|
||||
auto E = std::any_cast<IPointer::SHoldBeginEvent>(e);
|
||||
|
||||
PROTO::pointerGestures->holdBegin(E.timeMs, E.fingers);
|
||||
});
|
||||
|
||||
listener->holdEnd = pointer->pointerEvents.holdEnd.registerListener([this] (std::any e) {
|
||||
auto E = std::any_cast<IPointer::SHoldEndEvent>(e);
|
||||
|
||||
PROTO::pointerGestures->holdEnd(E.timeMs, E.cancelled);
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
Debug::log(LOG, "Attached pointer {} to global", pointer->hlName);
|
||||
}
|
||||
|
||||
void CPointerManager::attachTouch(SP<ITouch> touch) {
|
||||
if (!touch)
|
||||
return;
|
||||
|
||||
auto listener = touchListeners.emplace_back(makeShared<STouchListener>());
|
||||
|
||||
listener->touch = touch;
|
||||
|
||||
// clang-format off
|
||||
listener->destroy = touch->events.destroy.registerListener([this] (std::any d) {
|
||||
detachTouch(nullptr);
|
||||
});
|
||||
|
||||
listener->down = touch->touchEvents.down.registerListener([this] (std::any e) {
|
||||
auto E = std::any_cast<ITouch::SDownEvent>(e);
|
||||
|
||||
g_pInputManager->onTouchDown(E);
|
||||
});
|
||||
|
||||
listener->up = touch->touchEvents.up.registerListener([this] (std::any e) {
|
||||
auto E = std::any_cast<ITouch::SUpEvent>(e);
|
||||
|
||||
g_pInputManager->onTouchUp(E);
|
||||
});
|
||||
|
||||
listener->motion = touch->touchEvents.motion.registerListener([this] (std::any e) {
|
||||
auto E = std::any_cast<ITouch::SMotionEvent>(e);
|
||||
|
||||
g_pInputManager->onTouchMove(E);
|
||||
});
|
||||
|
||||
listener->cancel = touch->touchEvents.cancel.registerListener([this] (std::any e) {
|
||||
//
|
||||
});
|
||||
|
||||
listener->frame = touch->touchEvents.frame.registerListener([this] (std::any e) {
|
||||
wlr_seat_touch_notify_frame(g_pCompositor->m_sSeat.seat);
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
Debug::log(LOG, "Attached touch {} to global", touch->hlName);
|
||||
}
|
||||
|
||||
void CPointerManager::detachPointer(SP<IPointer> pointer) {
|
||||
std::erase_if(pointerListeners, [pointer](const auto& e) { return e->pointer.expired() || e->pointer == pointer; });
|
||||
}
|
||||
|
||||
void CPointerManager::detachTouch(SP<ITouch> touch) {
|
||||
std::erase_if(touchListeners, [touch](const auto& e) { return e->touch.expired() || e->touch == touch; });
|
||||
}
|
||||
|
||||
void CPointerManager::damageCursor(SP<CMonitor> pMonitor) {
|
||||
for (auto& mw : monitorStates) {
|
||||
if (mw->monitor != pMonitor)
|
||||
continue;
|
||||
|
||||
auto b = getCursorBoxGlobal().intersection(pMonitor->logicalBox());
|
||||
|
||||
if (b.empty())
|
||||
return;
|
||||
|
||||
g_pHyprRenderer->damageBox(&b);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
158
src/managers/PointerManager.hpp
Normal file
158
src/managers/PointerManager.hpp
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
#pragma once
|
||||
|
||||
#include "../devices/IPointer.hpp"
|
||||
#include "../devices/ITouch.hpp"
|
||||
#include "../helpers/Box.hpp"
|
||||
#include "../helpers/Region.hpp"
|
||||
#include "../desktop/WLSurface.hpp"
|
||||
#include <tuple>
|
||||
|
||||
class CMonitor;
|
||||
struct wlr_input_device;
|
||||
class IHID;
|
||||
|
||||
/*
|
||||
The naming here is a bit confusing.
|
||||
CPointerManager manages the _position_ and _displaying_ of the cursor,
|
||||
but the CCursorManager _only_ manages the actual image (texture) and size
|
||||
of the cursor.
|
||||
*/
|
||||
|
||||
class CPointerManager {
|
||||
public:
|
||||
CPointerManager();
|
||||
|
||||
// pointers will move the cursor on their respective events
|
||||
void attachPointer(SP<IPointer> pointer);
|
||||
// touch inputs won't move the cursor, it needs to be done manually
|
||||
void attachTouch(SP<ITouch> touch);
|
||||
|
||||
void detachPointer(SP<IPointer> pointer);
|
||||
void detachTouch(SP<ITouch> touch);
|
||||
|
||||
// only clamps to the layout.
|
||||
void warpTo(const Vector2D& logical);
|
||||
void move(const Vector2D& deltaLogical);
|
||||
void warpAbsolute(const Vector2D& abs, SP<IHID> dev);
|
||||
|
||||
void setCursorBuffer(wlr_buffer* buf, const Vector2D& hotspot, const float& scale);
|
||||
void setCursorSurface(CWLSurface* buf, const Vector2D& hotspot);
|
||||
void resetCursorImage(bool apply = true);
|
||||
|
||||
void lockSoftwareForMonitor(SP<CMonitor> pMonitor);
|
||||
void unlockSoftwareForMonitor(SP<CMonitor> pMonitor);
|
||||
|
||||
void renderSoftwareCursorsFor(SP<CMonitor> pMonitor, timespec* now, CRegion& damage /* logical */, std::optional<Vector2D> overridePos = {} /* monitor-local */);
|
||||
|
||||
// this is needed e.g. during screensharing where
|
||||
// the software cursors aren't locked during the cursor move, but they
|
||||
// are rendered later.
|
||||
void damageCursor(SP<CMonitor> pMonitor);
|
||||
|
||||
//
|
||||
Vector2D position();
|
||||
|
||||
private:
|
||||
void recheckPointerPosition();
|
||||
void onMonitorLayoutChange();
|
||||
void onMonitorDisconnect();
|
||||
void updateCursorBackend();
|
||||
void onCursorMoved();
|
||||
bool hasCursor();
|
||||
void damageIfSoftware();
|
||||
void recheckEnteredOutputs();
|
||||
|
||||
// closest valid point to a given one
|
||||
Vector2D closestValid(const Vector2D& pos);
|
||||
|
||||
// returns the thing in device coordinates. Is NOT offset by the hotspot, relies on set_cursor with hotspot.
|
||||
Vector2D getCursorPosForMonitor(SP<CMonitor> pMonitor);
|
||||
// returns the thing in logical coordinates of the monitor
|
||||
CBox getCursorBoxLogicalForMonitor(SP<CMonitor> pMonitor);
|
||||
// returns the thing in global coords
|
||||
CBox getCursorBoxGlobal();
|
||||
|
||||
Vector2D transformedHotspot(SP<CMonitor> pMonitor);
|
||||
|
||||
wlr_texture* getCurrentCursorTexture();
|
||||
|
||||
struct SPointerListener {
|
||||
CHyprSignalListener destroy;
|
||||
CHyprSignalListener motion;
|
||||
CHyprSignalListener motionAbsolute;
|
||||
CHyprSignalListener button;
|
||||
CHyprSignalListener axis;
|
||||
CHyprSignalListener frame;
|
||||
|
||||
CHyprSignalListener swipeBegin;
|
||||
CHyprSignalListener swipeEnd;
|
||||
CHyprSignalListener swipeUpdate;
|
||||
|
||||
CHyprSignalListener pinchBegin;
|
||||
CHyprSignalListener pinchEnd;
|
||||
CHyprSignalListener pinchUpdate;
|
||||
|
||||
CHyprSignalListener holdBegin;
|
||||
CHyprSignalListener holdEnd;
|
||||
|
||||
WP<IPointer> pointer;
|
||||
};
|
||||
std::vector<SP<SPointerListener>> pointerListeners;
|
||||
|
||||
struct STouchListener {
|
||||
CHyprSignalListener destroy;
|
||||
CHyprSignalListener down;
|
||||
CHyprSignalListener up;
|
||||
CHyprSignalListener motion;
|
||||
CHyprSignalListener cancel;
|
||||
CHyprSignalListener frame;
|
||||
|
||||
WP<ITouch> touch;
|
||||
};
|
||||
std::vector<SP<STouchListener>> touchListeners;
|
||||
|
||||
struct {
|
||||
std::vector<CBox> monitorBoxes;
|
||||
} currentMonitorLayout;
|
||||
|
||||
struct {
|
||||
wlr_buffer* pBuffer = nullptr;
|
||||
CWLSurface* surface = nullptr;
|
||||
wlr_texture* pBufferTexture = nullptr;
|
||||
|
||||
Vector2D hotspot;
|
||||
Vector2D size;
|
||||
float scale = 1.F;
|
||||
|
||||
CHyprSignalListener destroySurface;
|
||||
DYNLISTENER(commitSurface);
|
||||
DYNLISTENER(destroyBuffer);
|
||||
} currentCursorImage; // TODO: support various sizes per-output so we can have pixel-perfect cursors
|
||||
|
||||
Vector2D pointerPos = {0, 0};
|
||||
|
||||
struct SMonitorPointerState {
|
||||
SMonitorPointerState(SP<CMonitor> m) : monitor(m) {}
|
||||
WP<CMonitor> monitor;
|
||||
|
||||
int softwareLocks = 0;
|
||||
bool hardwareFailed = false;
|
||||
CBox box; // logical
|
||||
bool entered = false;
|
||||
bool hwApplied = false;
|
||||
|
||||
wlr_buffer* cursorFrontBuffer = nullptr;
|
||||
};
|
||||
|
||||
std::vector<SP<SMonitorPointerState>> monitorStates;
|
||||
SP<SMonitorPointerState> stateFor(SP<CMonitor> mon);
|
||||
bool attemptHardwareCursor(SP<SMonitorPointerState> state);
|
||||
wlr_buffer* renderHWCursorBuffer(SP<SMonitorPointerState> state, wlr_texture* texture);
|
||||
bool setHWCursorBuffer(SP<SMonitorPointerState> state, wlr_buffer* buf);
|
||||
|
||||
struct {
|
||||
SP<HOOK_CALLBACK_FN> monitorAdded;
|
||||
} hooks;
|
||||
};
|
||||
|
||||
inline UP<CPointerManager> g_pPointerManager;
|
||||
|
|
@ -20,6 +20,8 @@
|
|||
#include "../../devices/VirtualKeyboard.hpp"
|
||||
#include "../../devices/TouchDevice.hpp"
|
||||
|
||||
#include "../../managers/PointerManager.hpp"
|
||||
|
||||
CInputManager::CInputManager() {
|
||||
m_sListeners.setCursorShape = PROTO::cursorShape->events.setShape.registerListener([this](std::any data) {
|
||||
if (!cursorImageUnlocked())
|
||||
|
|
@ -63,31 +65,31 @@ CInputManager::~CInputManager() {
|
|||
m_lSwitches.clear();
|
||||
}
|
||||
|
||||
void CInputManager::onMouseMoved(wlr_pointer_motion_event* e) {
|
||||
void CInputManager::onMouseMoved(IPointer::SMotionEvent e) {
|
||||
static auto PSENS = CConfigValue<Hyprlang::FLOAT>("general:sensitivity");
|
||||
static auto PNOACCEL = CConfigValue<Hyprlang::INT>("input:force_no_accel");
|
||||
static auto PSENSTORAW = CConfigValue<Hyprlang::INT>("general:apply_sens_to_raw");
|
||||
|
||||
const auto DELTA = *PNOACCEL == 1 ? Vector2D(e->unaccel_dx, e->unaccel_dy) : Vector2D(e->delta_x, e->delta_y);
|
||||
const auto DELTA = *PNOACCEL == 1 ? e.unaccel : e.delta;
|
||||
|
||||
if (*PSENSTORAW == 1)
|
||||
PROTO::relativePointer->sendRelativeMotion((uint64_t)e->time_msec * 1000, DELTA * *PSENS, Vector2D{e->unaccel_dx, e->unaccel_dy} * *PSENS);
|
||||
PROTO::relativePointer->sendRelativeMotion((uint64_t)e.timeMs * 1000, DELTA * *PSENS, e.unaccel * *PSENS);
|
||||
else
|
||||
PROTO::relativePointer->sendRelativeMotion((uint64_t)e->time_msec * 1000, DELTA, Vector2D{e->unaccel_dx, e->unaccel_dy});
|
||||
PROTO::relativePointer->sendRelativeMotion((uint64_t)e.timeMs * 1000, DELTA, e.unaccel);
|
||||
|
||||
wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, DELTA.x * *PSENS, DELTA.y * *PSENS);
|
||||
g_pPointerManager->move(DELTA * *PSENS);
|
||||
|
||||
mouseMoveUnified(e->time_msec);
|
||||
mouseMoveUnified(e.timeMs);
|
||||
|
||||
m_tmrLastCursorMovement.reset();
|
||||
|
||||
m_bLastInputTouch = false;
|
||||
}
|
||||
|
||||
void CInputManager::onMouseWarp(wlr_pointer_motion_absolute_event* e) {
|
||||
wlr_cursor_warp_absolute(g_pCompositor->m_sWLRCursor, &e->pointer->base, e->x, e->y);
|
||||
void CInputManager::onMouseWarp(IPointer::SMotionAbsoluteEvent e) {
|
||||
g_pPointerManager->warpAbsolute(e.absolute, e.device);
|
||||
|
||||
mouseMoveUnified(e->time_msec);
|
||||
mouseMoveUnified(e.timeMs);
|
||||
|
||||
m_tmrLastCursorMovement.reset();
|
||||
|
||||
|
|
@ -194,14 +196,14 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
|||
if (SURF && CONSTRAINT) {
|
||||
if (CONSTRAINT->isLocked()) {
|
||||
const auto HINT = CONSTRAINT->logicPositionHint();
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, HINT.x, HINT.y);
|
||||
g_pCompositor->warpCursorTo(HINT, true);
|
||||
} else {
|
||||
const auto RG = CONSTRAINT->logicConstraintRegion();
|
||||
const auto CLOSEST = RG.closestPoint(mouseCoords);
|
||||
const auto BOX = SURF->getSurfaceBoxGlobal();
|
||||
const auto CLOSESTLOCAL = (CLOSEST - (BOX.has_value() ? BOX->pos() : Vector2D{})) * (SURF->getWindow() ? SURF->getWindow()->m_fX11SurfaceScaledBy : 1.0);
|
||||
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, CLOSEST.x, CLOSEST.y);
|
||||
g_pCompositor->warpCursorTo(CLOSEST, true);
|
||||
wlr_seat_pointer_send_motion(g_pCompositor->m_sSeat.seat, time, CLOSESTLOCAL.x, CLOSESTLOCAL.y);
|
||||
PROTO::relativePointer->sendRelativeMotion((uint64_t)time * 1000, {}, {});
|
||||
}
|
||||
|
|
@ -241,7 +243,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
|||
|
||||
g_pLayoutManager->getCurrentLayout()->onMouseMove(getMouseCoordsInternal());
|
||||
|
||||
if (PMONITOR && PMONITOR != g_pCompositor->m_pLastMonitor && (*PMOUSEFOCUSMON || refocus) && m_pForcedFocus.expired())
|
||||
if (PMONITOR && PMONITOR != g_pCompositor->m_pLastMonitor.get() && (*PMOUSEFOCUSMON || refocus) && m_pForcedFocus.expired())
|
||||
g_pCompositor->setActiveMonitor(PMONITOR);
|
||||
|
||||
if (g_pSessionLockManager->isSessionLocked()) {
|
||||
|
|
@ -350,7 +352,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
|||
g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords, &pFoundLayerSurface);
|
||||
|
||||
if (g_pCompositor->m_pLastMonitor->output->software_cursor_locks > 0)
|
||||
g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor);
|
||||
g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor.get());
|
||||
|
||||
if (!foundSurface) {
|
||||
if (!m_bEmptyFocusCursorSet) {
|
||||
|
|
@ -491,19 +493,19 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
|||
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, time, surfaceLocal.x, surfaceLocal.y);
|
||||
}
|
||||
|
||||
void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
|
||||
void CInputManager::onMouseButton(IPointer::SButtonEvent e) {
|
||||
EMIT_HOOK_EVENT_CANCELLABLE("mouseButton", e);
|
||||
|
||||
PROTO::idle->onActivity();
|
||||
|
||||
m_tmrLastCursorMovement.reset();
|
||||
|
||||
if (e->state == WL_POINTER_BUTTON_STATE_PRESSED) {
|
||||
m_lCurrentlyHeldButtons.push_back(e->button);
|
||||
if (e.state == WL_POINTER_BUTTON_STATE_PRESSED) {
|
||||
m_lCurrentlyHeldButtons.push_back(e.button);
|
||||
} else {
|
||||
if (std::find_if(m_lCurrentlyHeldButtons.begin(), m_lCurrentlyHeldButtons.end(), [&](const auto& other) { return other == e->button; }) == m_lCurrentlyHeldButtons.end())
|
||||
if (std::find_if(m_lCurrentlyHeldButtons.begin(), m_lCurrentlyHeldButtons.end(), [&](const auto& other) { return other == e.button; }) == m_lCurrentlyHeldButtons.end())
|
||||
return;
|
||||
std::erase_if(m_lCurrentlyHeldButtons, [&](const auto& other) { return other == e->button; });
|
||||
std::erase_if(m_lCurrentlyHeldButtons, [&](const auto& other) { return other == e.button; });
|
||||
}
|
||||
|
||||
switch (m_ecbClickBehavior) {
|
||||
|
|
@ -512,7 +514,7 @@ void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
|
|||
default: break;
|
||||
}
|
||||
|
||||
if (m_bFocusHeldByButtons && m_lCurrentlyHeldButtons.empty() && e->state == WL_POINTER_BUTTON_STATE_RELEASED) {
|
||||
if (m_bFocusHeldByButtons && m_lCurrentlyHeldButtons.empty() && e.state == WL_POINTER_BUTTON_STATE_RELEASED) {
|
||||
if (m_bRefocusHeldByButtons)
|
||||
refocus();
|
||||
else
|
||||
|
|
@ -549,7 +551,7 @@ void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_even
|
|||
m_sCursorSurfaceInfo.name = "";
|
||||
|
||||
m_sCursorSurfaceInfo.inUse = true;
|
||||
g_pHyprRenderer->setCursorSurface(e->surface, e->hotspot_x, e->hotspot_y);
|
||||
g_pHyprRenderer->setCursorSurface(&m_sCursorSurfaceInfo.wlSurface, e->hotspot_x, e->hotspot_y);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -564,7 +566,7 @@ void CInputManager::restoreCursorIconToApp() {
|
|||
|
||||
if (m_sCursorSurfaceInfo.name.empty()) {
|
||||
if (m_sCursorSurfaceInfo.wlSurface.exists())
|
||||
g_pHyprRenderer->setCursorSurface(m_sCursorSurfaceInfo.wlSurface.wlr(), m_sCursorSurfaceInfo.vHotspot.x, m_sCursorSurfaceInfo.vHotspot.y);
|
||||
g_pHyprRenderer->setCursorSurface(&m_sCursorSurfaceInfo.wlSurface, m_sCursorSurfaceInfo.vHotspot.x, m_sCursorSurfaceInfo.vHotspot.y);
|
||||
} else {
|
||||
g_pHyprRenderer->setCursorFromName(m_sCursorSurfaceInfo.name);
|
||||
}
|
||||
|
|
@ -617,7 +619,7 @@ void CInputManager::setClickMode(eClickBehaviorMode mode) {
|
|||
}
|
||||
}
|
||||
|
||||
void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
|
||||
void CInputManager::processMouseDownNormal(const IPointer::SButtonEvent& e) {
|
||||
|
||||
// notify the keybind manager
|
||||
static auto PPASSMOUSE = CConfigValue<Hyprlang::INT>("binds:pass_mouse_when_bound");
|
||||
|
|
@ -639,7 +641,7 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
|
|||
|
||||
// clicking on border triggers resize
|
||||
// TODO detect click on LS properly
|
||||
if (*PRESIZEONBORDER && !m_bLastFocusOnLS && e->state == WL_POINTER_BUTTON_STATE_PRESSED) {
|
||||
if (*PRESIZEONBORDER && !m_bLastFocusOnLS && e.state == WL_POINTER_BUTTON_STATE_PRESSED) {
|
||||
if (w && !w->m_bIsFullscreen) {
|
||||
const CBox real = {w->m_vRealPosition.value().x, w->m_vRealPosition.value().y, w->m_vRealSize.value().x, w->m_vRealSize.value().y};
|
||||
const CBox grab = {real.x - BORDER_GRAB_AREA, real.y - BORDER_GRAB_AREA, real.width + 2 * BORDER_GRAB_AREA, real.height + 2 * BORDER_GRAB_AREA};
|
||||
|
|
@ -651,7 +653,7 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
|
|||
}
|
||||
}
|
||||
|
||||
switch (e->state) {
|
||||
switch (e.state) {
|
||||
case WL_POINTER_BUTTON_STATE_PRESSED:
|
||||
if (*PFOLLOWMOUSE == 3) // don't refocus on full loose
|
||||
break;
|
||||
|
|
@ -679,14 +681,14 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
|
|||
|
||||
// notify app if we didnt handle it
|
||||
if (g_pCompositor->doesSeatAcceptInput(g_pCompositor->m_pLastFocus))
|
||||
wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, e->time_msec, e->button, e->state);
|
||||
wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, e.timeMs, e.button, e.state);
|
||||
|
||||
if (const auto PMON = g_pCompositor->getMonitorFromVector(mouseCoords); PMON != g_pCompositor->m_pLastMonitor && PMON)
|
||||
if (const auto PMON = g_pCompositor->getMonitorFromVector(mouseCoords); PMON != g_pCompositor->m_pLastMonitor.get() && PMON)
|
||||
g_pCompositor->setActiveMonitor(PMON);
|
||||
}
|
||||
|
||||
void CInputManager::processMouseDownKill(wlr_pointer_button_event* e) {
|
||||
switch (e->state) {
|
||||
void CInputManager::processMouseDownKill(const IPointer::SButtonEvent& e) {
|
||||
switch (e.state) {
|
||||
case WL_POINTER_BUTTON_STATE_PRESSED: {
|
||||
const auto PWINDOW = g_pCompositor->vectorToWindowUnified(getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||
|
||||
|
|
@ -707,12 +709,12 @@ void CInputManager::processMouseDownKill(wlr_pointer_button_event* e) {
|
|||
m_ecbClickBehavior = CLICKMODE_DEFAULT;
|
||||
}
|
||||
|
||||
void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) {
|
||||
void CInputManager::onMouseWheel(IPointer::SAxisEvent e) {
|
||||
static auto POFFWINDOWAXIS = CConfigValue<Hyprlang::INT>("input:off_window_axis_events");
|
||||
static auto PINPUTSCROLLFACTOR = CConfigValue<Hyprlang::FLOAT>("input:scroll_factor");
|
||||
static auto PTOUCHPADSCROLLFACTOR = CConfigValue<Hyprlang::FLOAT>("input:touchpad:scroll_factor");
|
||||
|
||||
auto factor = (*PTOUCHPADSCROLLFACTOR <= 0.f || e->source == WL_POINTER_AXIS_SOURCE_FINGER ? *PTOUCHPADSCROLLFACTOR : *PINPUTSCROLLFACTOR);
|
||||
auto factor = (*PTOUCHPADSCROLLFACTOR <= 0.f || e.source == WL_POINTER_AXIS_SOURCE_FINGER ? *PTOUCHPADSCROLLFACTOR : *PINPUTSCROLLFACTOR);
|
||||
|
||||
const auto EMAP = std::unordered_map<std::string, std::any>{{"event", e}};
|
||||
EMIT_HOOK_EVENT_CANCELLABLE("mouseAxis", EMAP);
|
||||
|
|
@ -742,20 +744,20 @@ void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) {
|
|||
const auto TEMPCURY = std::clamp(MOUSECOORDS.y, BOX.y, BOX.y + BOX.h - 1);
|
||||
|
||||
if (*POFFWINDOWAXIS == 3)
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, TEMPCURX, TEMPCURY);
|
||||
g_pCompositor->warpCursorTo({TEMPCURX, TEMPCURY}, true);
|
||||
|
||||
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, TEMPCURX - BOX.x, TEMPCURY - BOX.y);
|
||||
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, e.timeMs, TEMPCURX - BOX.x, TEMPCURY - BOX.y);
|
||||
wlr_seat_pointer_notify_frame(g_pCompositor->m_sSeat.seat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e->time_msec, e->orientation, factor * e->delta, std::round(factor * e->delta_discrete), e->source,
|
||||
wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e.timeMs, e.axis, factor * e.delta, std::round(factor * e.deltaDiscrete), e.source,
|
||||
WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL);
|
||||
}
|
||||
|
||||
Vector2D CInputManager::getMouseCoordsInternal() {
|
||||
return Vector2D(g_pCompositor->m_sWLRCursor->x, g_pCompositor->m_sWLRCursor->y);
|
||||
return g_pPointerManager->position();
|
||||
}
|
||||
|
||||
void CInputManager::newKeyboard(wlr_input_device* keyboard) {
|
||||
|
|
@ -989,7 +991,7 @@ void CInputManager::setupMouse(SP<IPointer> mauz) {
|
|||
(int)libinput_device_config_accel_get_default_profile(LIBINPUTDEV));
|
||||
}
|
||||
|
||||
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, &mauz->wlr()->base);
|
||||
g_pPointerManager->attachPointer(mauz);
|
||||
|
||||
mauz->connected = true;
|
||||
|
||||
|
|
@ -1020,10 +1022,10 @@ void CInputManager::setPointerConfigs() {
|
|||
if (HASCONFIG) {
|
||||
const auto ENABLED = g_pConfigManager->getDeviceInt(devname, "enabled");
|
||||
if (ENABLED && !m->connected) {
|
||||
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, &m->wlr()->base);
|
||||
g_pPointerManager->attachPointer(m);
|
||||
m->connected = true;
|
||||
} else if (!ENABLED && m->connected) {
|
||||
wlr_cursor_detach_input_device(g_pCompositor->m_sWLRCursor, &m->wlr()->base);
|
||||
g_pPointerManager->detachPointer(m);
|
||||
m->connected = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1386,7 +1388,7 @@ void CInputManager::newTouchDevice(wlr_input_device* pDevice) {
|
|||
}
|
||||
|
||||
setTouchDeviceConfigs(PNEWDEV);
|
||||
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, pDevice);
|
||||
g_pPointerManager->attachTouch(PNEWDEV);
|
||||
|
||||
PNEWDEV->events.destroy.registerStaticListener(
|
||||
[this](void* owner, std::any data) {
|
||||
|
|
@ -1431,7 +1433,7 @@ void CInputManager::setTouchDeviceConfigs(SP<ITouch> dev) {
|
|||
const auto PMONITOR = bound ? g_pCompositor->getMonitorFromName(output) : nullptr;
|
||||
if (PMONITOR) {
|
||||
Debug::log(LOG, "Binding touch device {} to output {}", PTOUCHDEV->hlName, PMONITOR->szName);
|
||||
wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, &PTOUCHDEV->wlr()->base, PMONITOR->output);
|
||||
// wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, &PTOUCHDEV->wlr()->base, PMONITOR->output);
|
||||
} else if (bound)
|
||||
Debug::log(ERR, "Failed to bind touch device {} to output '{}': monitor not found", PTOUCHDEV->hlName, output);
|
||||
}
|
||||
|
|
@ -1468,17 +1470,17 @@ void CInputManager::setTabletConfigs() {
|
|||
const auto PMONITOR = g_pCompositor->getMonitorFromString(OUTPUT);
|
||||
if (!OUTPUT.empty() && OUTPUT != STRVAL_EMPTY && PMONITOR) {
|
||||
Debug::log(LOG, "Binding tablet {} to output {}", t.name, PMONITOR->szName);
|
||||
wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, t.wlrDevice, PMONITOR->output);
|
||||
wlr_cursor_map_input_to_region(g_pCompositor->m_sWLRCursor, t.wlrDevice, nullptr);
|
||||
// wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, t.wlrDevice, PMONITOR->output);
|
||||
// wlr_cursor_map_input_to_region(g_pCompositor->m_sWLRCursor, t.wlrDevice, nullptr);
|
||||
t.boundOutput = OUTPUT;
|
||||
} else if (!PMONITOR)
|
||||
Debug::log(ERR, "Failed to bind tablet {} to output '{}': monitor not found", t.name, OUTPUT);
|
||||
|
||||
const auto REGION_POS = g_pConfigManager->getDeviceVec(t.name, "region_position", "input:tablet:region_position");
|
||||
const auto REGION_SIZE = g_pConfigManager->getDeviceVec(t.name, "region_size", "input:tablet:region_size");
|
||||
auto regionBox = CBox{REGION_POS.x, REGION_POS.y, REGION_SIZE.x, REGION_SIZE.y};
|
||||
if (!regionBox.empty())
|
||||
wlr_cursor_map_input_to_region(g_pCompositor->m_sWLRCursor, t.wlrDevice, regionBox.pWlr());
|
||||
//auto regionBox = CBox{REGION_POS.x, REGION_POS.y, REGION_SIZE.x, REGION_SIZE.y};
|
||||
// if (!regionBox.empty())
|
||||
// wlr_cursor_map_input_to_region(g_pCompositor->m_sWLRCursor, t.wlrDevice, regionBox.pWlr());
|
||||
|
||||
const auto ACTIVE_AREA_SIZE = g_pConfigManager->getDeviceVec(t.name, "active_area_size", "input:tablet:active_area_size");
|
||||
const auto ACTIVE_AREA_POS = g_pConfigManager->getDeviceVec(t.name, "active_area_position", "input:tablet:active_area_position");
|
||||
|
|
|
|||
|
|
@ -7,15 +7,15 @@
|
|||
#include "../../helpers/Timer.hpp"
|
||||
#include "InputMethodRelay.hpp"
|
||||
#include "../../helpers/signal/Listener.hpp"
|
||||
#include "../../devices/IPointer.hpp"
|
||||
#include "../../devices/ITouch.hpp"
|
||||
|
||||
class CPointerConstraint;
|
||||
class CWindow;
|
||||
class CIdleInhibitor;
|
||||
class CVirtualKeyboardV1Resource;
|
||||
class CVirtualPointerV1Resource;
|
||||
class IPointer;
|
||||
class IKeyboard;
|
||||
class ITouch;
|
||||
|
||||
enum eClickBehaviorMode {
|
||||
CLICKMODE_DEFAULT = 0,
|
||||
|
|
@ -74,10 +74,10 @@ class CInputManager {
|
|||
CInputManager();
|
||||
~CInputManager();
|
||||
|
||||
void onMouseMoved(wlr_pointer_motion_event*);
|
||||
void onMouseWarp(wlr_pointer_motion_absolute_event*);
|
||||
void onMouseButton(wlr_pointer_button_event*);
|
||||
void onMouseWheel(wlr_pointer_axis_event*);
|
||||
void onMouseMoved(IPointer::SMotionEvent);
|
||||
void onMouseWarp(IPointer::SMotionAbsoluteEvent);
|
||||
void onMouseButton(IPointer::SButtonEvent);
|
||||
void onMouseWheel(IPointer::SAxisEvent);
|
||||
void onKeyboardKey(std::any, SP<IKeyboard>);
|
||||
void onKeyboardMod(SP<IKeyboard>);
|
||||
|
||||
|
|
@ -112,9 +112,9 @@ class CInputManager {
|
|||
eClickBehaviorMode getClickMode();
|
||||
void processMouseRequest(wlr_seat_pointer_request_set_cursor_event* e);
|
||||
|
||||
void onTouchDown(wlr_touch_down_event*);
|
||||
void onTouchUp(wlr_touch_up_event*);
|
||||
void onTouchMove(wlr_touch_motion_event*);
|
||||
void onTouchDown(ITouch::SDownEvent);
|
||||
void onTouchUp(ITouch::SUpEvent);
|
||||
void onTouchMove(ITouch::SMotionEvent);
|
||||
|
||||
STouchData m_sTouchData;
|
||||
|
||||
|
|
@ -153,9 +153,9 @@ class CInputManager {
|
|||
void newIdleInhibitor(std::any);
|
||||
void recheckIdleInhibitorStatus();
|
||||
|
||||
void onSwipeBegin(wlr_pointer_swipe_begin_event*);
|
||||
void onSwipeEnd(wlr_pointer_swipe_end_event*);
|
||||
void onSwipeUpdate(wlr_pointer_swipe_update_event*);
|
||||
void onSwipeBegin(IPointer::SSwipeBeginEvent);
|
||||
void onSwipeEnd(IPointer::SSwipeEndEvent);
|
||||
void onSwipeUpdate(IPointer::SSwipeUpdateEvent);
|
||||
|
||||
SSwipeGesture m_sActiveSwipe;
|
||||
|
||||
|
|
@ -212,8 +212,8 @@ class CInputManager {
|
|||
void setupKeyboard(SP<IKeyboard> keeb);
|
||||
void setupMouse(SP<IPointer> mauz);
|
||||
|
||||
void processMouseDownNormal(wlr_pointer_button_event* e);
|
||||
void processMouseDownKill(wlr_pointer_button_event* e);
|
||||
void processMouseDownNormal(const IPointer::SButtonEvent& e);
|
||||
void processMouseDownKill(const IPointer::SButtonEvent& e);
|
||||
|
||||
bool cursorImageUnlocked();
|
||||
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@
|
|||
#include "../../Compositor.hpp"
|
||||
#include "../../config/ConfigValue.hpp"
|
||||
|
||||
void CInputManager::onSwipeBegin(wlr_pointer_swipe_begin_event* e) {
|
||||
void CInputManager::onSwipeBegin(IPointer::SSwipeBeginEvent e) {
|
||||
static auto PSWIPE = CConfigValue<Hyprlang::INT>("gestures:workspace_swipe");
|
||||
static auto PSWIPEFINGERS = CConfigValue<Hyprlang::INT>("gestures:workspace_swipe_fingers");
|
||||
static auto PSWIPENEW = CConfigValue<Hyprlang::INT>("gestures:workspace_swipe_create_new");
|
||||
|
||||
EMIT_HOOK_EVENT_CANCELLABLE("swipeBegin", e);
|
||||
|
||||
if (e->fingers != *PSWIPEFINGERS || *PSWIPE == 0 || g_pSessionLockManager->isSessionLocked())
|
||||
if (e.fingers != *PSWIPEFINGERS || *PSWIPE == 0 || g_pSessionLockManager->isSessionLocked())
|
||||
return;
|
||||
|
||||
int onMonitor = 0;
|
||||
|
|
@ -32,7 +32,7 @@ void CInputManager::beginWorkspaceSwipe() {
|
|||
|
||||
m_sActiveSwipe.pWorkspaceBegin = PWORKSPACE;
|
||||
m_sActiveSwipe.delta = 0;
|
||||
m_sActiveSwipe.pMonitor = g_pCompositor->m_pLastMonitor;
|
||||
m_sActiveSwipe.pMonitor = g_pCompositor->m_pLastMonitor.get();
|
||||
m_sActiveSwipe.avgSpeed = 0;
|
||||
m_sActiveSwipe.speedPoints = 0;
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ void CInputManager::beginWorkspaceSwipe() {
|
|||
}
|
||||
}
|
||||
|
||||
void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
void CInputManager::onSwipeEnd(IPointer::SSwipeEndEvent e) {
|
||||
EMIT_HOOK_EVENT_CANCELLABLE("swipeEnd", e);
|
||||
|
||||
if (!m_sActiveSwipe.pWorkspaceBegin)
|
||||
|
|
@ -198,7 +198,7 @@ void CInputManager::endWorkspaceSwipe() {
|
|||
}
|
||||
}
|
||||
|
||||
void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
|
||||
void CInputManager::onSwipeUpdate(IPointer::SSwipeUpdateEvent e) {
|
||||
EMIT_HOOK_EVENT_CANCELLABLE("swipeUpdate", e);
|
||||
|
||||
if (!m_sActiveSwipe.pWorkspaceBegin)
|
||||
|
|
@ -207,7 +207,7 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
|
|||
const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" ||
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert");
|
||||
|
||||
const double delta = m_sActiveSwipe.delta + (VERTANIMS ? (*PSWIPEINVR ? -e->dy : e->dy) : (*PSWIPEINVR ? -e->dx : e->dx));
|
||||
const double delta = m_sActiveSwipe.delta + (VERTANIMS ? (*PSWIPEINVR ? -e.delta.y : e.delta.y) : (*PSWIPEINVR ? -e.delta.x : e.delta.x));
|
||||
updateWorkspaceSwipe(delta);
|
||||
}
|
||||
|
||||
|
|
@ -348,7 +348,7 @@ void CInputManager::updateWorkspaceSwipe(double delta) {
|
|||
|
||||
if (*PSWIPEFOREVER) {
|
||||
if (abs(m_sActiveSwipe.delta) >= SWIPEDISTANCE) {
|
||||
onSwipeEnd(nullptr);
|
||||
onSwipeEnd({});
|
||||
beginWorkspaceSwipe();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
|
|||
|
||||
Debug::log(LOG, "Attaching tablet to cursor!");
|
||||
|
||||
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, pDevice);
|
||||
// wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, pDevice);
|
||||
|
||||
PNEWTABLET->hyprListener_Destroy.initCallback(
|
||||
&pDevice->events.destroy,
|
||||
|
|
@ -39,7 +39,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
|
|||
|
||||
switch (EVENT->tool->type) {
|
||||
case WLR_TABLET_TOOL_TYPE_MOUSE:
|
||||
wlr_cursor_move(g_pCompositor->m_sWLRCursor, PTAB->wlrDevice, EVENT->dx, EVENT->dy);
|
||||
// wlr_cursor_move(g_pCompositor->m_sWLRCursor, PTAB->wlrDevice, EVENT->dx, EVENT->dy);
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
g_pInputManager->focusTablet(PTAB, EVENT->tool, true);
|
||||
g_pInputManager->m_tmrLastCursorMovement.reset();
|
||||
|
|
@ -50,16 +50,16 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
|
|||
double y = (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_Y) ? EVENT->y : NAN;
|
||||
double dy = (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_Y) ? EVENT->dy : NAN;
|
||||
|
||||
if (PTAB->relativeInput)
|
||||
wlr_cursor_move(g_pCompositor->m_sWLRCursor, PTAB->wlrDevice, dx, dy);
|
||||
else {
|
||||
// Calculate transformations if active area is set
|
||||
if (!PTAB->activeArea.empty()) {
|
||||
x = (x - PTAB->activeArea.x) / (PTAB->activeArea.w - PTAB->activeArea.x);
|
||||
y = (y - PTAB->activeArea.y) / (PTAB->activeArea.h - PTAB->activeArea.y);
|
||||
}
|
||||
wlr_cursor_warp_absolute(g_pCompositor->m_sWLRCursor, PTAB->wlrDevice, x, y);
|
||||
}
|
||||
// if (PTAB->relativeInput)
|
||||
// wlr_cursor_move(g_pCompositor->m_sWLRCursor, PTAB->wlrDevice, dx, dy);
|
||||
// else {
|
||||
// Calculate transformations if active area is set
|
||||
// if (!PTAB->activeArea.empty()) {
|
||||
// x = (x - PTAB->activeArea.x) / (PTAB->activeArea.w - PTAB->activeArea.x);
|
||||
// y = (y - PTAB->activeArea.y) / (PTAB->activeArea.h - PTAB->activeArea.y);
|
||||
// }
|
||||
// wlr_cursor_warp_absolute(g_pCompositor->m_sWLRCursor, PTAB->wlrDevice, x, y);
|
||||
// }
|
||||
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
g_pInputManager->focusTablet(PTAB, EVENT->tool, true);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include "../../protocols/IdleNotify.hpp"
|
||||
#include "../../devices/ITouch.hpp"
|
||||
|
||||
void CInputManager::onTouchDown(wlr_touch_down_event* e) {
|
||||
void CInputManager::onTouchDown(ITouch::SDownEvent e) {
|
||||
static auto PSWIPETOUCH = CConfigValue<Hyprlang::INT>("gestures:workspace_swipe_touch");
|
||||
static auto PGAPSOUTDATA = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_out");
|
||||
auto* const PGAPSOUT = (CCssGapData*)(PGAPSOUTDATA.ptr())->getData();
|
||||
|
|
@ -14,23 +14,18 @@ void CInputManager::onTouchDown(wlr_touch_down_event* e) {
|
|||
static auto PSWIPEINVR = CConfigValue<Hyprlang::INT>("gestures:workspace_swipe_invert");
|
||||
EMIT_HOOK_EVENT_CANCELLABLE("touchDown", e);
|
||||
|
||||
auto PMONITOR = g_pCompositor->getMonitorFromName(e->touch->output_name ? e->touch->output_name : "");
|
||||
auto PMONITOR = g_pCompositor->getMonitorFromName(!e.device->boundOutput.empty() ? e.device->boundOutput : "");
|
||||
|
||||
const auto PDEVIT = std::find_if(m_vTouches.begin(), m_vTouches.end(), [&](const auto& other) { return other->wlr() == e->touch; });
|
||||
PMONITOR = PMONITOR ? PMONITOR : g_pCompositor->m_pLastMonitor.get();
|
||||
|
||||
if (PDEVIT != m_vTouches.end() && !(*PDEVIT)->boundOutput.empty())
|
||||
PMONITOR = g_pCompositor->getMonitorFromName((*PDEVIT)->boundOutput);
|
||||
|
||||
PMONITOR = PMONITOR ? PMONITOR : g_pCompositor->m_pLastMonitor;
|
||||
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PMONITOR->vecPosition.x + e->x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e->y * PMONITOR->vecSize.y);
|
||||
g_pCompositor->warpCursorTo({PMONITOR->vecPosition.x + e.pos.x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e.pos.y * PMONITOR->vecSize.y}, true);
|
||||
|
||||
refocus();
|
||||
|
||||
if (m_ecbClickBehavior == CLICKMODE_KILL) {
|
||||
wlr_pointer_button_event e;
|
||||
IPointer::SButtonEvent e;
|
||||
e.state = WL_POINTER_BUTTON_STATE_PRESSED;
|
||||
g_pInputManager->processMouseDownKill(&e);
|
||||
g_pInputManager->processMouseDownKill(e);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -45,10 +40,10 @@ void CInputManager::onTouchDown(wlr_touch_down_event* e) {
|
|||
// TODO: support no_gaps_when_only?
|
||||
const double TARGETLEFT = ((VERTANIMS ? gapsOut.top : gapsOut.left) + *PBORDERSIZE) / (VERTANIMS ? PMONITOR->vecSize.y : PMONITOR->vecSize.x);
|
||||
const double TARGETRIGHT = 1 - (((VERTANIMS ? gapsOut.bottom : gapsOut.right) + *PBORDERSIZE) / (VERTANIMS ? PMONITOR->vecSize.y : PMONITOR->vecSize.x));
|
||||
const double POSITION = (VERTANIMS ? e->y : e->x);
|
||||
const double POSITION = (VERTANIMS ? e.pos.y : e.pos.x);
|
||||
if (POSITION < TARGETLEFT || POSITION > TARGETRIGHT) {
|
||||
beginWorkspaceSwipe();
|
||||
m_sActiveSwipe.touch_id = e->touch_id;
|
||||
m_sActiveSwipe.touch_id = e.touchID;
|
||||
// Set the initial direction based on which edge you started from
|
||||
if (POSITION > 0.5)
|
||||
m_sActiveSwipe.initialDirection = *PSWIPEINVR ? -1 : 1;
|
||||
|
|
@ -78,34 +73,33 @@ void CInputManager::onTouchDown(wlr_touch_down_event* e) {
|
|||
local = g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchFocusLS->geometry.pos();
|
||||
|
||||
m_sTouchData.touchSurfaceOrigin = g_pInputManager->getMouseCoordsInternal() - local;
|
||||
} else {
|
||||
} else
|
||||
return; // oops, nothing found.
|
||||
}
|
||||
|
||||
wlr_seat_touch_notify_down(g_pCompositor->m_sSeat.seat, m_sTouchData.touchFocusSurface, e->time_msec, e->touch_id, local.x, local.y);
|
||||
wlr_seat_touch_notify_down(g_pCompositor->m_sSeat.seat, m_sTouchData.touchFocusSurface, e.timeMs, e.touchID, local.x, local.y);
|
||||
|
||||
PROTO::idle->onActivity();
|
||||
}
|
||||
|
||||
void CInputManager::onTouchUp(wlr_touch_up_event* e) {
|
||||
void CInputManager::onTouchUp(ITouch::SUpEvent e) {
|
||||
EMIT_HOOK_EVENT_CANCELLABLE("touchUp", e);
|
||||
if (m_sActiveSwipe.pWorkspaceBegin) {
|
||||
// If there was a swipe from this finger, end it.
|
||||
if (e->touch_id == m_sActiveSwipe.touch_id)
|
||||
if (e.touchID == m_sActiveSwipe.touch_id)
|
||||
endWorkspaceSwipe();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_sTouchData.touchFocusSurface) {
|
||||
wlr_seat_touch_notify_up(g_pCompositor->m_sSeat.seat, e->time_msec, e->touch_id);
|
||||
wlr_seat_touch_notify_up(g_pCompositor->m_sSeat.seat, e.timeMs, e.touchID);
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::onTouchMove(wlr_touch_motion_event* e) {
|
||||
void CInputManager::onTouchMove(ITouch::SMotionEvent e) {
|
||||
EMIT_HOOK_EVENT_CANCELLABLE("touchMove", e);
|
||||
if (m_sActiveSwipe.pWorkspaceBegin) {
|
||||
// Do nothing if this is using a different finger.
|
||||
if (e->touch_id != m_sActiveSwipe.touch_id)
|
||||
if (e.touchID != m_sActiveSwipe.touch_id)
|
||||
return;
|
||||
const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" ||
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert");
|
||||
|
|
@ -116,37 +110,37 @@ void CInputManager::onTouchMove(wlr_touch_motion_event* e) {
|
|||
if (m_sActiveSwipe.initialDirection == -1) {
|
||||
if (*PSWIPEINVR)
|
||||
// go from 0 to -SWIPEDISTANCE
|
||||
updateWorkspaceSwipe(SWIPEDISTANCE * ((VERTANIMS ? e->y : e->x) - 1));
|
||||
updateWorkspaceSwipe(SWIPEDISTANCE * ((VERTANIMS ? e.pos.y : e.pos.x) - 1));
|
||||
else
|
||||
// go from 0 to -SWIPEDISTANCE
|
||||
updateWorkspaceSwipe(SWIPEDISTANCE * (-1 * (VERTANIMS ? e->y : e->x)));
|
||||
updateWorkspaceSwipe(SWIPEDISTANCE * (-1 * (VERTANIMS ? e.pos.y : e.pos.x)));
|
||||
} else if (*PSWIPEINVR)
|
||||
// go from 0 to SWIPEDISTANCE
|
||||
updateWorkspaceSwipe(SWIPEDISTANCE * (VERTANIMS ? e->y : e->x));
|
||||
updateWorkspaceSwipe(SWIPEDISTANCE * (VERTANIMS ? e.pos.y : e.pos.x));
|
||||
else
|
||||
// go from 0 to SWIPEDISTANCE
|
||||
updateWorkspaceSwipe(SWIPEDISTANCE * (1 - (VERTANIMS ? e->y : e->x)));
|
||||
updateWorkspaceSwipe(SWIPEDISTANCE * (1 - (VERTANIMS ? e.pos.y : e.pos.x)));
|
||||
return;
|
||||
}
|
||||
if (validMapped(m_sTouchData.touchFocusWindow)) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_sTouchData.touchFocusWindow->m_iMonitorID);
|
||||
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PMONITOR->vecPosition.x + e->x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e->y * PMONITOR->vecSize.y);
|
||||
g_pCompositor->warpCursorTo({PMONITOR->vecPosition.x + e.pos.x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e.pos.y * PMONITOR->vecSize.y}, true);
|
||||
|
||||
auto local = g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchSurfaceOrigin;
|
||||
if (m_sTouchData.touchFocusWindow->m_bIsX11)
|
||||
local = local * m_sTouchData.touchFocusWindow->m_fX11SurfaceScaledBy;
|
||||
|
||||
wlr_seat_touch_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, e->touch_id, local.x, local.y);
|
||||
wlr_seat_touch_notify_motion(g_pCompositor->m_sSeat.seat, e.timeMs, e.touchID, local.x, local.y);
|
||||
// wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, local.x, local.y);
|
||||
} else if (!m_sTouchData.touchFocusLS.expired()) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_sTouchData.touchFocusLS->monitorID);
|
||||
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PMONITOR->vecPosition.x + e->x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e->y * PMONITOR->vecSize.y);
|
||||
g_pCompositor->warpCursorTo({PMONITOR->vecPosition.x + e.pos.x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e.pos.y * PMONITOR->vecSize.y}, true);
|
||||
|
||||
const auto local = g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchSurfaceOrigin;
|
||||
|
||||
wlr_seat_touch_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, e->touch_id, local.x, local.y);
|
||||
wlr_seat_touch_notify_motion(g_pCompositor->m_sSeat.seat, e.timeMs, e.touchID, local.x, local.y);
|
||||
// wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, local.x, local.y);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue