mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-29 21:45:58 +01:00
Resize on border (#1347)
This commit is contained in:
parent
b944386ca5
commit
c92e0c05e4
11 changed files with 228 additions and 51 deletions
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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";
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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&);
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue