aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChing Pei Yang <[email protected]>2023-02-18 23:35:31 +0100
committerGitHub <[email protected]>2023-02-18 22:35:31 +0000
commitc92e0c05e466f8cbf9c99ddcff969a1b36277248 (patch)
treed461585fc9df2880848378128942403f7990f08e
parentb944386ca54cf650d660caac31f065c0211168b1 (diff)
downloadHyprland-c92e0c05e466f8cbf9c99ddcff969a1b36277248.tar.gz
Hyprland-c92e0c05e466f8cbf9c99ddcff969a1b36277248.zip
Resize on border (#1347)
-rw-r--r--src/Compositor.cpp45
-rw-r--r--src/Window.cpp54
-rw-r--r--src/Window.hpp4
-rw-r--r--src/config/ConfigManager.cpp3
-rw-r--r--src/helpers/Vector2D.cpp8
-rw-r--r--src/helpers/Vector2D.hpp4
-rw-r--r--src/layout/IHyprLayout.cpp11
-rw-r--r--src/managers/KeybindManager.cpp8
-rw-r--r--src/managers/KeybindManager.hpp1
-rw-r--r--src/managers/input/InputManager.cpp117
-rw-r--r--src/managers/input/InputManager.hpp24
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 <deque>
#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;
};