From c92e0c05e466f8cbf9c99ddcff969a1b36277248 Mon Sep 17 00:00:00 2001 From: Ching Pei Yang <59727193+horriblename@users.noreply.github.com> Date: Sat, 18 Feb 2023 23:35:31 +0100 Subject: [PATCH] Resize on border (#1347) --- src/Compositor.cpp | 45 ++++------- src/Window.cpp | 54 +++++++++++++ src/Window.hpp | 4 + src/config/ConfigManager.cpp | 3 + src/helpers/Vector2D.cpp | 8 +- src/helpers/Vector2D.hpp | 4 +- src/layout/IHyprLayout.cpp | 11 ++- src/managers/KeybindManager.cpp | 8 ++ src/managers/KeybindManager.hpp | 1 + src/managers/input/InputManager.cpp | 117 +++++++++++++++++++++++++--- src/managers/input/InputManager.hpp | 24 ++++-- 11 files changed, 228 insertions(+), 51 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index db86cd3e..365a2c12 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -571,22 +571,18 @@ CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) { return nullptr; } -void findExtensionForVector2D(wlr_surface* surface, int x, int y, void* data) { - const auto DATA = (SExtensionFindingData*)data; - - wlr_box box = {DATA->origin.x + x, DATA->origin.y + y, surface->current.width, surface->current.height}; - - if (wlr_box_contains_point(&box, DATA->vec.x, DATA->vec.y)) - *DATA->found = surface; -} - CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { - const auto PMONITOR = getMonitorFromVector(pos); + const auto PMONITOR = getMonitorFromVector(pos); + static auto* const PRESIZEONBORDER = &g_pConfigManager->getConfigValuePtr("general:resize_on_border")->intValue; + static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; + static auto* const PBORDERGRABEXTEND = &g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area")->intValue; + const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0; // special workspace if (PMONITOR->specialWorkspaceID) { for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) { - wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y}; + wlr_box box = {(*w)->m_vRealPosition.vec().x - BORDER_GRAB_AREA, (*w)->m_vRealPosition.vec().y - BORDER_GRAB_AREA, (*w)->m_vRealSize.vec().x + 2 * BORDER_GRAB_AREA, + (*w)->m_vRealSize.vec().y + 2 * BORDER_GRAB_AREA}; if ((*w)->m_bIsFloating && (*w)->m_iWorkspaceID == PMONITOR->specialWorkspaceID && (*w)->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !(*w)->isHidden() && !(*w)->m_bX11ShouldntFocus) return (*w).get(); @@ -602,18 +598,14 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { // pinned windows on top of floating regardless for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) { - wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y}; + wlr_box box = {(*w)->m_vRealPosition.vec().x - BORDER_GRAB_AREA, (*w)->m_vRealPosition.vec().y - BORDER_GRAB_AREA, (*w)->m_vRealSize.vec().x + 2 * BORDER_GRAB_AREA, + (*w)->m_vRealSize.vec().y + 2 * BORDER_GRAB_AREA}; if ((*w)->m_bIsFloating && (*w)->m_bIsMapped && !(*w)->isHidden() && !(*w)->m_bX11ShouldntFocus && (*w)->m_bPinned) { if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y)) return w->get(); if (!(*w)->m_bIsX11) { - wlr_surface* resultSurf = nullptr; - Vector2D origin = (*w)->m_vRealPosition.vec(); - SExtensionFindingData data = {origin, pos, &resultSurf}; - wlr_xdg_surface_for_each_popup_surface((*w)->m_uSurface.xdg, findExtensionForVector2D, &data); - - if (resultSurf) + if ((*w)->hasPopupAt(pos)) return w->get(); } } @@ -621,7 +613,8 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { // first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter. for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) { - wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y}; + wlr_box box = {(*w)->m_vRealPosition.vec().x - BORDER_GRAB_AREA, (*w)->m_vRealPosition.vec().y - BORDER_GRAB_AREA, (*w)->m_vRealSize.vec().x + 2 * BORDER_GRAB_AREA, + (*w)->m_vRealSize.vec().y + 2 * BORDER_GRAB_AREA}; if ((*w)->m_bIsFloating && (*w)->m_bIsMapped && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->isHidden() && !(*w)->m_bPinned) { // OR windows should add focus to parent if ((*w)->m_bX11ShouldntFocus && (*w)->m_iX11Type != 2) @@ -639,12 +632,7 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { } if (!(*w)->m_bIsX11) { - wlr_surface* resultSurf = nullptr; - Vector2D origin = (*w)->m_vRealPosition.vec(); - SExtensionFindingData data = {origin, pos, &resultSurf}; - wlr_xdg_surface_for_each_popup_surface((*w)->m_uSurface.xdg, findExtensionForVector2D, &data); - - if (resultSurf) + if ((*w)->hasPopupAt(pos)) return w->get(); } } @@ -653,12 +641,7 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { // for windows, we need to check their extensions too, first. for (auto& w : m_vWindows) { if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->isHidden() && !w->m_bX11ShouldntFocus) { - wlr_surface* resultSurf = nullptr; - Vector2D origin = w->m_vRealPosition.vec(); - SExtensionFindingData data = {origin, pos, &resultSurf}; - wlr_xdg_surface_for_each_popup_surface(w->m_uSurface.xdg, findExtensionForVector2D, &data); - - if (resultSurf) + if ((w)->hasPopupAt(pos)) return w.get(); } } diff --git a/src/Window.cpp b/src/Window.cpp index de44f28d..dd0f660c 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -413,3 +413,57 @@ void CWindow::updateDynamicRules() { applyDynamicRule(r); } } + +// check if the point is "hidden" under a rounded corner of the window +// it is assumed that the point is within the real window box (m_vRealPosition, m_vRealSize) +// otherwise behaviour is undefined +bool CWindow::isInCurvedCorner(double x, double y) { + static auto* const ROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue; + static auto* const BORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; + + if (BORDERSIZE >= ROUNDING || ROUNDING == 0) + return false; + + // (x0, y0), (x0, y1), ... are the center point of rounding at each corner + double x0 = m_vRealPosition.vec().x + *ROUNDING; + double y0 = m_vRealPosition.vec().y + *ROUNDING; + double x1 = m_vRealPosition.vec().x + m_vRealSize.vec().x - *ROUNDING; + double y1 = m_vRealPosition.vec().y + m_vRealSize.vec().y - *ROUNDING; + + if (x < x0 && y < y0) { + return Vector2D{x0, y0}.distance(Vector2D{x, y}) > (double)*ROUNDING; + } + if (x > x1 && y < y0) { + return Vector2D{x1, y0}.distance(Vector2D{x, y}) > (double)*ROUNDING; + } + if (x < x0 && y > y1) { + return Vector2D{x0, y1}.distance(Vector2D{x, y}) > (double)*ROUNDING; + } + if (x > x1 && y > y1) { + return Vector2D{x1, y1}.distance(Vector2D{x, y}) > (double)*ROUNDING; + } + + return false; +} + +void findExtensionForVector2D(wlr_surface* surface, int x, int y, void* data) { + const auto DATA = (SExtensionFindingData*)data; + + wlr_box box = {DATA->origin.x + x, DATA->origin.y + y, surface->current.width, surface->current.height}; + + if (wlr_box_contains_point(&box, DATA->vec.x, DATA->vec.y)) + *DATA->found = surface; +} + +// checks if the wayland window has a popup at pos +bool CWindow::hasPopupAt(const Vector2D& pos) { + if (m_bIsX11) + return false; + + wlr_surface* resultSurf = nullptr; + Vector2D origin = m_vRealPosition.vec(); + SExtensionFindingData data = {origin, pos, &resultSurf}; + wlr_xdg_surface_for_each_popup_surface(m_uSurface.xdg, findExtensionForVector2D, &data); + + return resultSurf; +} diff --git a/src/Window.hpp b/src/Window.hpp index 04be3a27..658bdceb 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -7,6 +7,7 @@ #include "render/decorations/IHyprWindowDecoration.hpp" #include #include "config/ConfigDataValues.hpp" +#include "helpers/Vector2D.hpp" enum eIdleInhibitMode { @@ -297,7 +298,10 @@ class CWindow { bool isHidden(); void applyDynamicRule(const SWindowRule& r); void updateDynamicRules(); + void onBorderAngleAnimEnd(void* ptr); + bool isInCurvedCorner(double x, double y); + bool hasPopupAt(const Vector2D& pos); private: // For hidden windows and stuff diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 573a51c0..f463f9e6 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -46,6 +46,9 @@ void CConfigManager::setDefaultVars() { ((CGradientValueData*)configValues["general:col.inactive_border"].data.get())->reset(0xff444444); configValues["general:cursor_inactive_timeout"].intValue = 0; configValues["general:no_cursor_warps"].intValue = 0; + configValues["general:resize_on_border"].intValue = 0; + configValues["general:extend_border_grab_area"].intValue = 15; + configValues["general:hover_icon_on_border"].intValue = 1; configValues["general:layout"].strValue = "dwindle"; diff --git a/src/helpers/Vector2D.cpp b/src/helpers/Vector2D.cpp index 97a9685c..3ab3ce43 100644 --- a/src/helpers/Vector2D.cpp +++ b/src/helpers/Vector2D.cpp @@ -29,4 +29,10 @@ Vector2D Vector2D::floor() { Vector2D Vector2D::clamp(const Vector2D& min, const Vector2D& max) { return Vector2D(std::clamp(this->x, min.x, max.x == 0 ? INFINITY : max.x), std::clamp(this->y, min.y, max.y == 0 ? INFINITY : max.y)); -} \ No newline at end of file +} + +double Vector2D::distance(const Vector2D& other) { + double dx = x - other.x; + double dy = y - other.y; + return std::sqrt(dx * dx + dy * dy); +} diff --git a/src/helpers/Vector2D.hpp b/src/helpers/Vector2D.hpp index f38e6a8d..f2943b28 100644 --- a/src/helpers/Vector2D.hpp +++ b/src/helpers/Vector2D.hpp @@ -42,8 +42,10 @@ class Vector2D { Vector2D operator/(const Vector2D& a) const { return Vector2D(this->x / a.x, this->y / a.y); } + + double distance(const Vector2D& other); Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D()); Vector2D floor(); -}; \ No newline at end of file +}; diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 888c159c..24e76035 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -195,10 +195,15 @@ void IHyprLayout::onBeginDragWindow() { void IHyprLayout::onEndDragWindow() { const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow; - g_pInputManager->unsetCursorImage(); - - if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW)) + if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW)) { + if (DRAGGINGWINDOW) { + g_pInputManager->unsetCursorImage(); + g_pInputManager->currentlyDraggedWindow = nullptr; + } return; + } + + g_pInputManager->unsetCursorImage(); g_pInputManager->currentlyDraggedWindow = nullptr; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 26bc3565..1965c935 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -294,6 +294,14 @@ bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) { return !found && !mouseBindWasActive; } +void CKeybindManager::resizeWithBorder(wlr_pointer_button_event* e) { + if (e->state == WLR_BUTTON_PRESSED) { + mouse("1resizewindow"); + } else { + mouse("0resizewindow"); + } +} + void CKeybindManager::onSwitchEvent(const std::string& switchName) { handleKeybinds(0, "switch:" + switchName, 0, 0, true, 0); } diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 3ed09cb4..1c910873 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -39,6 +39,7 @@ class CKeybindManager { bool onKeyEvent(wlr_keyboard_key_event*, SKeyboard*); bool onAxisEvent(wlr_pointer_axis_event*); bool onMouseEvent(wlr_pointer_button_event*); + void resizeWithBorder(wlr_pointer_button_event*); void onSwitchEvent(const std::string&); void onSwitchOnEvent(const std::string&); void onSwitchOffEvent(const std::string&); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 342eaaa6..05b7f950 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -45,12 +45,17 @@ void CInputManager::simulateMouseMovement() { } void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { - static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue; - static auto* const PMOUSEDPMS = &g_pConfigManager->getConfigValuePtr("misc:mouse_move_enables_dpms")->intValue; - static auto* const PFOLLOWONDND = &g_pConfigManager->getConfigValuePtr("misc:always_follow_on_dnd")->intValue; - static auto* const PHOGFOCUS = &g_pConfigManager->getConfigValuePtr("misc:layers_hog_keyboard_focus")->intValue; - static auto* const PFLOATBEHAVIOR = &g_pConfigManager->getConfigValuePtr("input:float_switch_override_focus")->intValue; - static auto* const PMOUSEFOCUSMON = &g_pConfigManager->getConfigValuePtr("misc:mouse_move_focuses_monitor")->intValue; + static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue; + static auto* const PMOUSEDPMS = &g_pConfigManager->getConfigValuePtr("misc:mouse_move_enables_dpms")->intValue; + static auto* const PFOLLOWONDND = &g_pConfigManager->getConfigValuePtr("misc:always_follow_on_dnd")->intValue; + static auto* const PHOGFOCUS = &g_pConfigManager->getConfigValuePtr("misc:layers_hog_keyboard_focus")->intValue; + static auto* const PFLOATBEHAVIOR = &g_pConfigManager->getConfigValuePtr("input:float_switch_override_focus")->intValue; + static auto* const PMOUSEFOCUSMON = &g_pConfigManager->getConfigValuePtr("misc:mouse_move_focuses_monitor")->intValue; + static auto* const PRESIZEONBORDER = &g_pConfigManager->getConfigValuePtr("general:resize_on_border")->intValue; + static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; + static auto* const PBORDERGRABEXTEND = &g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area")->intValue; + static auto* const PRESIZECURSORICON = &g_pConfigManager->getConfigValuePtr("general:hover_icon_on_border")->intValue; + const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0; m_pFoundSurfaceToFocus = nullptr; m_pFoundLSToFocus = nullptr; @@ -180,7 +185,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { // only check floating because tiled cant be over fullscreen for (auto w = g_pCompositor->m_vWindows.rbegin(); w != g_pCompositor->m_vWindows.rend(); w++) { - wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y}; + wlr_box box = {(*w)->m_vRealPosition.vec().x - BORDER_GRAB_AREA, (*w)->m_vRealPosition.vec().y - BORDER_GRAB_AREA, (*w)->m_vRealSize.vec().x + 2 * BORDER_GRAB_AREA, + (*w)->m_vRealSize.vec().y + 2 * BORDER_GRAB_AREA}; if ((((*w)->m_bIsFloating && (*w)->m_bIsMapped && ((*w)->m_bCreatedOverFullscreen || (*w)->m_bPinned)) || (g_pCompositor->isWorkspaceSpecial((*w)->m_iWorkspaceID) && PMONITOR->specialWorkspaceID)) && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->isHidden()) { @@ -298,6 +304,11 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { } if (pFoundWindow) { + // change cursor icon if hovering over border, skip if mouse bind is active + if (*PRESIZEONBORDER && *PRESIZECURSORICON && !pFoundWindow->m_bIsFullscreen && !pFoundWindow->hasPopupAt(mouseCoords)) { + setCursorIconOnBorder(pFoundWindow); + } + if (*PFOLLOWMOUSE != 1 && !refocus) { if (pFoundWindow != g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow && ((pFoundWindow->m_bIsFloating && *PFLOATBEHAVIOR == 2) || (g_pCompositor->m_pLastWindow->m_bIsFloating != pFoundWindow->m_bIsFloating && *PFLOATBEHAVIOR != 0))) { @@ -417,13 +428,28 @@ void CInputManager::setClickMode(eClickBehaviorMode mode) { void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) { // notify the keybind manager - static auto* const PPASSMOUSE = &g_pConfigManager->getConfigValuePtr("binds:pass_mouse_when_bound")->intValue; - const auto PASS = g_pKeybindManager->onMouseEvent(e); - static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue; + static auto* const PPASSMOUSE = &g_pConfigManager->getConfigValuePtr("binds:pass_mouse_when_bound")->intValue; + const auto PASS = g_pKeybindManager->onMouseEvent(e); + static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue; + static auto* const PRESIZEONBORDER = &g_pConfigManager->getConfigValuePtr("general:resize_on_border")->intValue; if (!PASS && !*PPASSMOUSE) return; + // clicking on border triggers resize + // TODO detect click on LS properly + if (*PRESIZEONBORDER && !m_bLastFocusOnLS) { + const auto mouseCoords = g_pInputManager->getMouseCoordsInternal(); + const auto w = g_pCompositor->vectorToWindowIdeal(mouseCoords); + if (w && !w->m_bIsFullscreen) { + const wlr_box real = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; + if ((!wlr_box_contains_point(&real, mouseCoords.x, mouseCoords.y) || w->isInCurvedCorner(mouseCoords.x, mouseCoords.y)) && !w->hasPopupAt(mouseCoords)) { + g_pKeybindManager->resizeWithBorder(e); + return; + } + } + } + switch (e->state) { case WLR_BUTTON_PRESSED: if (*PFOLLOWMOUSE == 3) // don't refocus on full loose @@ -1340,3 +1366,74 @@ void CInputManager::releaseAllMouseButtons() { m_lCurrentlyHeldButtons.clear(); } + +void CInputManager::setCursorIconOnBorder(CWindow* w) { + // do not override cursor icons set by mouse binds + if (g_pKeybindManager->m_bIsMouseBindActive) { + m_eBorderIconDirection = BORDERICON_NONE; + return; + } + + static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue; + static const auto* PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; + // give a small leeway (10 px) for corner icon + const auto CORNER = *PROUNDING + *PBORDERSIZE + 10; + const auto mouseCoords = getMouseCoordsInternal(); + wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; + eBorderIconDirection direction = BORDERICON_NONE; + if (wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y)) { + if (!w->isInCurvedCorner(mouseCoords.x, mouseCoords.y)) { + direction = BORDERICON_NONE; + } else { + if (mouseCoords.y < box.y + CORNER) { + if (mouseCoords.x < box.x + CORNER) + direction = BORDERICON_UP_LEFT; + else + direction = BORDERICON_UP_RIGHT; + } else { + if (mouseCoords.x < box.x + CORNER) + direction = BORDERICON_DOWN_LEFT; + else + direction = BORDERICON_DOWN_RIGHT; + } + } + } else { + if (mouseCoords.y < box.y + CORNER) { + if (mouseCoords.x < box.x + CORNER) + direction = BORDERICON_UP_LEFT; + else if (mouseCoords.x > box.x + box.width - CORNER) + direction = BORDERICON_UP_RIGHT; + else + direction = BORDERICON_UP; + } else if (mouseCoords.y > box.y + box.height - CORNER) { + if (mouseCoords.x < box.x + CORNER) + direction = BORDERICON_DOWN_LEFT; + else if (mouseCoords.x > box.x + box.width - CORNER) + direction = BORDERICON_DOWN_RIGHT; + else + direction = BORDERICON_DOWN; + } else { + if (mouseCoords.x < box.x + CORNER) + direction = BORDERICON_LEFT; + else if (mouseCoords.x > box.x + box.width - CORNER) + direction = BORDERICON_RIGHT; + } + } + + if (direction == m_eBorderIconDirection) + return; + + m_eBorderIconDirection = direction; + + switch (direction) { + case BORDERICON_NONE: unsetCursorImage(); break; + case BORDERICON_UP: setCursorImageUntilUnset("top_side"); break; + case BORDERICON_DOWN: setCursorImageUntilUnset("bottom_side"); break; + case BORDERICON_LEFT: setCursorImageUntilUnset("left_side"); break; + case BORDERICON_RIGHT: setCursorImageUntilUnset("right_side"); break; + case BORDERICON_UP_LEFT: setCursorImageUntilUnset("top_left_corner"); break; + case BORDERICON_DOWN_LEFT: setCursorImageUntilUnset("bottom_left_corner"); break; + case BORDERICON_UP_RIGHT: setCursorImageUntilUnset("top_right_corner"); break; + case BORDERICON_DOWN_RIGHT: setCursorImageUntilUnset("bottom_right_corner"); break; + } +} diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 525b5c85..af31118c 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -7,19 +7,29 @@ #include "../../helpers/Timer.hpp" #include "InputMethodRelay.hpp" -enum eClickBehaviorMode -{ +enum eClickBehaviorMode { CLICKMODE_DEFAULT = 0, CLICKMODE_KILL }; -enum eMouseBindMode -{ +enum eMouseBindMode { MBIND_INVALID = -1, MBIND_MOVE = 0, MBIND_RESIZE }; +enum eBorderIconDirection { + BORDERICON_NONE, + BORDERICON_UP, + BORDERICON_DOWN, + BORDERICON_LEFT, + BORDERICON_RIGHT, + BORDERICON_UP_LEFT, + BORDERICON_DOWN_LEFT, + BORDERICON_UP_RIGHT, + BORDERICON_DOWN_RIGHT, +}; + struct STouchData { CWindow* touchFocusWindow = nullptr; SLayerSurface* touchFocusLS = nullptr; @@ -165,7 +175,8 @@ class CInputManager { bool m_bLastInputTouch = false; private: - bool m_bCursorImageOverriden = false; + bool m_bCursorImageOverriden = false; + eBorderIconDirection m_eBorderIconDirection = BORDERICON_NONE; // for click behavior override eClickBehaviorMode m_ecbClickBehavior = CLICKMODE_DEFAULT; @@ -196,6 +207,9 @@ class CInputManager { // swipe void beginWorkspaceSwipe(); + void setBorderCursorIcon(eBorderIconDirection); + void setCursorIconOnBorder(CWindow* w); + friend class CKeybindManager; };