Resize on border (#1347)

This commit is contained in:
Ching Pei Yang 2023-02-18 23:35:31 +01:00 committed by GitHub
parent b944386ca5
commit c92e0c05e4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 228 additions and 51 deletions

View file

@ -571,22 +571,18 @@ CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
return nullptr; 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) { 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 // special workspace
if (PMONITOR->specialWorkspaceID) { if (PMONITOR->specialWorkspaceID) {
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) { 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) && 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) !(*w)->isHidden() && !(*w)->m_bX11ShouldntFocus)
return (*w).get(); return (*w).get();
@ -602,18 +598,14 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
// pinned windows on top of floating regardless // pinned windows on top of floating regardless
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) { 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 ((*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)) if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y))
return w->get(); return w->get();
if (!(*w)->m_bIsX11) { if (!(*w)->m_bIsX11) {
wlr_surface* resultSurf = nullptr; if ((*w)->hasPopupAt(pos))
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)
return w->get(); 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. // 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++) { 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) { if ((*w)->m_bIsFloating && (*w)->m_bIsMapped && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->isHidden() && !(*w)->m_bPinned) {
// OR windows should add focus to parent // OR windows should add focus to parent
if ((*w)->m_bX11ShouldntFocus && (*w)->m_iX11Type != 2) if ((*w)->m_bX11ShouldntFocus && (*w)->m_iX11Type != 2)
@ -639,12 +632,7 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
} }
if (!(*w)->m_bIsX11) { if (!(*w)->m_bIsX11) {
wlr_surface* resultSurf = nullptr; if ((*w)->hasPopupAt(pos))
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)
return w->get(); return w->get();
} }
} }
@ -653,12 +641,7 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
// for windows, we need to check their extensions too, first. // for windows, we need to check their extensions too, first.
for (auto& w : m_vWindows) { 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) { if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->isHidden() && !w->m_bX11ShouldntFocus) {
wlr_surface* resultSurf = nullptr; if ((w)->hasPopupAt(pos))
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)
return w.get(); return w.get();
} }
} }

View file

@ -413,3 +413,57 @@ void CWindow::updateDynamicRules() {
applyDynamicRule(r); 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;
}

View file

@ -7,6 +7,7 @@
#include "render/decorations/IHyprWindowDecoration.hpp" #include "render/decorations/IHyprWindowDecoration.hpp"
#include <deque> #include <deque>
#include "config/ConfigDataValues.hpp" #include "config/ConfigDataValues.hpp"
#include "helpers/Vector2D.hpp"
enum eIdleInhibitMode enum eIdleInhibitMode
{ {
@ -297,7 +298,10 @@ class CWindow {
bool isHidden(); bool isHidden();
void applyDynamicRule(const SWindowRule& r); void applyDynamicRule(const SWindowRule& r);
void updateDynamicRules(); void updateDynamicRules();
void onBorderAngleAnimEnd(void* ptr); void onBorderAngleAnimEnd(void* ptr);
bool isInCurvedCorner(double x, double y);
bool hasPopupAt(const Vector2D& pos);
private: private:
// For hidden windows and stuff // For hidden windows and stuff

View file

@ -46,6 +46,9 @@ void CConfigManager::setDefaultVars() {
((CGradientValueData*)configValues["general:col.inactive_border"].data.get())->reset(0xff444444); ((CGradientValueData*)configValues["general:col.inactive_border"].data.get())->reset(0xff444444);
configValues["general:cursor_inactive_timeout"].intValue = 0; configValues["general:cursor_inactive_timeout"].intValue = 0;
configValues["general:no_cursor_warps"].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"; configValues["general:layout"].strValue = "dwindle";

View file

@ -30,3 +30,9 @@ Vector2D Vector2D::floor() {
Vector2D Vector2D::clamp(const Vector2D& min, const Vector2D& max) { 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)); 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));
} }
double Vector2D::distance(const Vector2D& other) {
double dx = x - other.x;
double dy = y - other.y;
return std::sqrt(dx * dx + dy * dy);
}

View file

@ -43,6 +43,8 @@ class Vector2D {
return Vector2D(this->x / a.x, this->y / a.y); 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 clamp(const Vector2D& min, const Vector2D& max = Vector2D());
Vector2D floor(); Vector2D floor();

View file

@ -195,10 +195,15 @@ void IHyprLayout::onBeginDragWindow() {
void IHyprLayout::onEndDragWindow() { void IHyprLayout::onEndDragWindow() {
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow; const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
g_pInputManager->unsetCursorImage(); if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW)) {
if (DRAGGINGWINDOW) {
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW)) g_pInputManager->unsetCursorImage();
g_pInputManager->currentlyDraggedWindow = nullptr;
}
return; return;
}
g_pInputManager->unsetCursorImage();
g_pInputManager->currentlyDraggedWindow = nullptr; g_pInputManager->currentlyDraggedWindow = nullptr;

View file

@ -294,6 +294,14 @@ bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) {
return !found && !mouseBindWasActive; 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) { void CKeybindManager::onSwitchEvent(const std::string& switchName) {
handleKeybinds(0, "switch:" + switchName, 0, 0, true, 0); handleKeybinds(0, "switch:" + switchName, 0, 0, true, 0);
} }

View file

@ -39,6 +39,7 @@ class CKeybindManager {
bool onKeyEvent(wlr_keyboard_key_event*, SKeyboard*); bool onKeyEvent(wlr_keyboard_key_event*, SKeyboard*);
bool onAxisEvent(wlr_pointer_axis_event*); bool onAxisEvent(wlr_pointer_axis_event*);
bool onMouseEvent(wlr_pointer_button_event*); bool onMouseEvent(wlr_pointer_button_event*);
void resizeWithBorder(wlr_pointer_button_event*);
void onSwitchEvent(const std::string&); void onSwitchEvent(const std::string&);
void onSwitchOnEvent(const std::string&); void onSwitchOnEvent(const std::string&);
void onSwitchOffEvent(const std::string&); void onSwitchOffEvent(const std::string&);

View file

@ -45,12 +45,17 @@ void CInputManager::simulateMouseMovement() {
} }
void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->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 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 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 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 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 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_pFoundSurfaceToFocus = nullptr;
m_pFoundLSToFocus = 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 // only check floating because tiled cant be over fullscreen
for (auto w = g_pCompositor->m_vWindows.rbegin(); w != g_pCompositor->m_vWindows.rend(); w++) { 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)) || if ((((*w)->m_bIsFloating && (*w)->m_bIsMapped && ((*w)->m_bCreatedOverFullscreen || (*w)->m_bPinned)) ||
(g_pCompositor->isWorkspaceSpecial((*w)->m_iWorkspaceID) && PMONITOR->specialWorkspaceID)) && (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()) { 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) { 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 (*PFOLLOWMOUSE != 1 && !refocus) {
if (pFoundWindow != g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow && 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))) { ((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) { void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
// notify the keybind manager // notify the keybind manager
static auto* const PPASSMOUSE = &g_pConfigManager->getConfigValuePtr("binds:pass_mouse_when_bound")->intValue; static auto* const PPASSMOUSE = &g_pConfigManager->getConfigValuePtr("binds:pass_mouse_when_bound")->intValue;
const auto PASS = g_pKeybindManager->onMouseEvent(e); const auto PASS = g_pKeybindManager->onMouseEvent(e);
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue; 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) if (!PASS && !*PPASSMOUSE)
return; 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) { switch (e->state) {
case WLR_BUTTON_PRESSED: case WLR_BUTTON_PRESSED:
if (*PFOLLOWMOUSE == 3) // don't refocus on full loose if (*PFOLLOWMOUSE == 3) // don't refocus on full loose
@ -1340,3 +1366,74 @@ void CInputManager::releaseAllMouseButtons() {
m_lCurrentlyHeldButtons.clear(); 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;
}
}

View file

@ -7,19 +7,29 @@
#include "../../helpers/Timer.hpp" #include "../../helpers/Timer.hpp"
#include "InputMethodRelay.hpp" #include "InputMethodRelay.hpp"
enum eClickBehaviorMode enum eClickBehaviorMode {
{
CLICKMODE_DEFAULT = 0, CLICKMODE_DEFAULT = 0,
CLICKMODE_KILL CLICKMODE_KILL
}; };
enum eMouseBindMode enum eMouseBindMode {
{
MBIND_INVALID = -1, MBIND_INVALID = -1,
MBIND_MOVE = 0, MBIND_MOVE = 0,
MBIND_RESIZE 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 { struct STouchData {
CWindow* touchFocusWindow = nullptr; CWindow* touchFocusWindow = nullptr;
SLayerSurface* touchFocusLS = nullptr; SLayerSurface* touchFocusLS = nullptr;
@ -165,7 +175,8 @@ class CInputManager {
bool m_bLastInputTouch = false; bool m_bLastInputTouch = false;
private: private:
bool m_bCursorImageOverriden = false; bool m_bCursorImageOverriden = false;
eBorderIconDirection m_eBorderIconDirection = BORDERICON_NONE;
// for click behavior override // for click behavior override
eClickBehaviorMode m_ecbClickBehavior = CLICKMODE_DEFAULT; eClickBehaviorMode m_ecbClickBehavior = CLICKMODE_DEFAULT;
@ -196,6 +207,9 @@ class CInputManager {
// swipe // swipe
void beginWorkspaceSwipe(); void beginWorkspaceSwipe();
void setBorderCursorIcon(eBorderIconDirection);
void setCursorIconOnBorder(CWindow* w);
friend class CKeybindManager; friend class CKeybindManager;
}; };