From 5b1934dd5dc3245fcfd4a771fd45ed30dcaace54 Mon Sep 17 00:00:00 2001 From: Mavridis Philippe Date: Thu, 22 Jun 2023 19:34:06 +0300 Subject: TWin: Add active corner support to quick tiling Signed-off-by: Mavridis Philippe --- doc/kcontrol/windowbehavior/index.docbook | 2 +- twin/client.h | 3 + twin/geometry.cpp | 73 +++++++++++++----- twin/kcmtwin/twinoptions/windows.cpp | 79 ++++++++++++------- twin/kcmtwin/twinoptions/windows.h | 3 + twin/options.cpp | 6 ++ twin/options.h | 3 + twin/utils.h | 8 +- twin/workspace.cpp | 121 ++++++++++++++---------------- 9 files changed, 181 insertions(+), 117 deletions(-) diff --git a/doc/kcontrol/windowbehavior/index.docbook b/doc/kcontrol/windowbehavior/index.docbook index 215a82a5e..b503636c7 100644 --- a/doc/kcontrol/windowbehavior/index.docbook +++ b/doc/kcontrol/windowbehavior/index.docbook @@ -771,7 +771,7 @@ Use the slider widget to configure the delay. Tile window -Dragging a window into a desktop border will tile that window at that side of the screen. This feature is also known as Aerosnap or Quick Tile. +Dragging a window into a desktop border will tile that window at that side or corner of the screen. This feature is also known as Aerosnap or Quick Tile. Maximize windows by dragging them to the top of the screen changes the behaviour of the top border of the desktop. If this option is enabled, dragging a window into the top border will not result in tiling, but the window will become maximized instead. By default dragging a tiled window does not reset its original size. This behaviour is controlled by an option in the Moving tab of this control module. diff --git a/twin/client.h b/twin/client.h index 332501f88..ae90fb619 100644 --- a/twin/client.h +++ b/twin/client.h @@ -233,7 +233,9 @@ class Client : public TQObject, public KDecorationDefines void resizeWithChecks( const TQSize& s, ForceGeometry_t force = NormalGeometrySet ); void keepInArea( TQRect area, bool partial = false ); void setActiveBorderMode( ActiveMaximizingMode mode ); + void setActiveBorder( ActiveBorder border); ActiveMaximizingMode activeBorderMode() const; + ActiveBorder activeBorder() const; void setActiveBorderMaximizing(bool maximizing); bool isActiveBorderMaximizing() const; TQRect activeBorderMaximizeGeometry(); @@ -609,6 +611,7 @@ class Client : public TQObject, public KDecorationDefines bool activeTiled; TQRect activeTiledOrigGeom; ActiveMaximizingMode activeMode; + ActiveBorder currentActiveBorder; friend bool performTransiencyCheck(); bool minimized_before_suspend; diff --git a/twin/geometry.cpp b/twin/geometry.cpp index 7dd38bee2..fc5f919cf 100644 --- a/twin/geometry.cpp +++ b/twin/geometry.cpp @@ -2718,6 +2718,14 @@ ActiveMaximizingMode Client::activeBorderMode() const return activeMode; } +void Client::setActiveBorder(ActiveBorder border) { + currentActiveBorder = border; +} + +ActiveBorder Client::activeBorder() const { + return currentActiveBorder; +} + bool Client::isActiveBorderMaximizing() const { return activeMaximizing; @@ -2740,7 +2748,7 @@ TQRect Client::activeBorderMaximizeGeometry() { TQRect ret; TQRect max = workspace()->clientArea(MaximizeArea, TQCursor::pos(), workspace()->currentDesktop()); - switch (activeMode) + switch (activeBorderMode()) { case ActiveMaximizeMode: { @@ -2750,25 +2758,52 @@ TQRect Client::activeBorderMaximizeGeometry() ret = max; break; } - case ActiveLeftMode: - { - ret = TQRect( max.x(), max.y(), max.width()/2, max.height() ); - break; - } - case ActiveRightMode: - { - ret = TQRect( max.x() + max.width()/2, max.y(), max.width()/2, max.height() ); - break; - } - case ActiveTopMode: - { - ret = TQRect( max.x(), max.y(), max.width(), max.height()/2 ); - break; - } - case ActiveBottomMode: + + case ActiveTilingMode: { - ret = TQRect( max.x(), max.y() + max.height()/2, max.width(), max.height()/2 ); - break; + switch (activeBorder()) + { + case ActiveLeft: + { + ret = TQRect( max.x(), max.y(), max.width()/2, max.height() ); + break; + } + case ActiveRight: + { + ret = TQRect( max.x() + max.width()/2, max.y(), max.width()/2, max.height() ); + break; + } + case ActiveTop: + { + ret = TQRect( max.x(), max.y(), max.width(), max.height()/2 ); + break; + } + case ActiveBottom: + { + ret = TQRect( max.x(), max.y() + max.height()/2, max.width(), max.height()/2 ); + break; + } + case ActiveTopLeft: + { + ret = TQRect( max.x(), max.y(), max.width()/2, max.height()/2 ); + break; + } + case ActiveTopRight: + { + ret = TQRect( max.x() + max.width()/2, max.y(), max.width()/2, max.height()/2 ); + break; + } + case ActiveBottomLeft: + { + ret = TQRect( max.x(), max.y() + max.height()/2, max.width()/2, max.height()/2 ); + break; + } + case ActiveBottomRight: + { + ret = TQRect( max.x() + max.width()/2, max.y() + max.height()/2, max.width()/2, max.height()/2); + break; + } + } } } return ret; diff --git a/twin/kcmtwin/twinoptions/windows.cpp b/twin/kcmtwin/twinoptions/windows.cpp index 3610eb443..f675ed1c4 100644 --- a/twin/kcmtwin/twinoptions/windows.cpp +++ b/twin/kcmtwin/twinoptions/windows.cpp @@ -56,33 +56,34 @@ // twin config keywords -#define KWIN_FOCUS "FocusPolicy" -#define KWIN_PLACEMENT "Placement" -#define KWIN_MOVE "MoveMode" -#define KWIN_MINIMIZE_ANIM "AnimateMinimize" -#define KWIN_MINIMIZE_ANIM_SPEED "AnimateMinimizeSpeed" -#define KWIN_RESIZE_OPAQUE "ResizeMode" -#define KWIN_GEOMETRY "GeometryTip" -#define KWIN_AUTORAISE_INTERVAL "AutoRaiseInterval" -#define KWIN_AUTORAISE "AutoRaise" -#define KWIN_DELAYFOCUS_INTERVAL "DelayFocusInterval" -#define KWIN_DELAYFOCUS "DelayFocus" -#define KWIN_CLICKRAISE "ClickRaise" -#define KWIN_ANIMSHADE "AnimateShade" -#define KWIN_MOVE_RESIZE_MAXIMIZED "MoveResizeMaximizedWindows" -#define KWIN_RESET_MAX_WIN_GEOM "ResetMaximizedWindowGeometry" -#define KWIN_ALTTABMODE "AltTabStyle" -#define KWIN_TRAVERSE_ALL "TraverseAll" -#define KWIN_SHOW_POPUP "ShowPopup" -#define KWIN_ROLL_OVER_DESKTOPS "RollOverDesktops" -#define KWIN_SHADEHOVER "ShadeHover" -#define KWIN_SHADEHOVER_INTERVAL "ShadeHoverInterval" -#define KWIN_FOCUS_STEALING "FocusStealingPreventionLevel" -#define KWIN_HIDE_UTILITY "HideUtilityWindowsForInactive" -#define KWIN_SEPARATE_SCREEN_FOCUS "SeparateScreenFocus" -#define KWIN_ACTIVE_MOUSE_SCREEN "ActiveMouseScreen" -#define KWIN_ACTIVE_BORDERS "ActiveBorders" -#define KWIN_ACTIVE_BORDER_DELAY "ActiveBorderDelay" +#define KWIN_FOCUS "FocusPolicy" +#define KWIN_PLACEMENT "Placement" +#define KWIN_MOVE "MoveMode" +#define KWIN_MINIMIZE_ANIM "AnimateMinimize" +#define KWIN_MINIMIZE_ANIM_SPEED "AnimateMinimizeSpeed" +#define KWIN_RESIZE_OPAQUE "ResizeMode" +#define KWIN_GEOMETRY "GeometryTip" +#define KWIN_AUTORAISE_INTERVAL "AutoRaiseInterval" +#define KWIN_AUTORAISE "AutoRaise" +#define KWIN_DELAYFOCUS_INTERVAL "DelayFocusInterval" +#define KWIN_DELAYFOCUS "DelayFocus" +#define KWIN_CLICKRAISE "ClickRaise" +#define KWIN_ANIMSHADE "AnimateShade" +#define KWIN_MOVE_RESIZE_MAXIMIZED "MoveResizeMaximizedWindows" +#define KWIN_RESET_MAX_WIN_GEOM "ResetMaximizedWindowGeometry" +#define KWIN_ALTTABMODE "AltTabStyle" +#define KWIN_TRAVERSE_ALL "TraverseAll" +#define KWIN_SHOW_POPUP "ShowPopup" +#define KWIN_ROLL_OVER_DESKTOPS "RollOverDesktops" +#define KWIN_SHADEHOVER "ShadeHover" +#define KWIN_SHADEHOVER_INTERVAL "ShadeHoverInterval" +#define KWIN_FOCUS_STEALING "FocusStealingPreventionLevel" +#define KWIN_HIDE_UTILITY "HideUtilityWindowsForInactive" +#define KWIN_SEPARATE_SCREEN_FOCUS "SeparateScreenFocus" +#define KWIN_ACTIVE_MOUSE_SCREEN "ActiveMouseScreen" +#define KWIN_ACTIVE_BORDERS "ActiveBorders" +#define KWIN_ACTIVE_BORDER_DELAY "ActiveBorderDelay" +#define KWIN_ACTIVE_BORDER_DISTANCE "ActiveBorderDistance" // legacy options #define KWIN_OLD_ACTIVE_BORDERS "ElectricBorders" @@ -700,6 +701,16 @@ KAdvancedConfig::KAdvancedConfig (bool _standAlone, TDEConfig *_config, TQWidget " active borders feature. The selected action will be performed after the mouse " " has been pushed against a screen border for the specified number of milliseconds.") ); + distance = new KIntNumInput(10, active_box); + distance->setRange(1, 100, 1, true); + distance->setSuffix(i18n(" px")); + distance->setLabel(i18n("Border &activation distance:")); + TQWhatsThis::add( distance, i18n("The distance from which an active border can" + " be activated. A lower value requires you to push repeatedly into the edge." + " Setting this to a higher value (e.g. 30) activates the borders when the" + " mouse is close enough, making them easier to activate but also more prone" + " to false activations.")); + active_vbox->addSpacing(10); active_vbox->addWidget(active_func_label); active_vbox->addWidget(active_disable); @@ -709,6 +720,7 @@ KAdvancedConfig::KAdvancedConfig (bool _standAlone, TDEConfig *_config, TQWidget active_vbox->addWidget(active_tile_conf); active_vbox->addSpacing(15); active_vbox->addWidget(delays); + active_vbox->addWidget(distance); connect(active_box, TQT_SIGNAL(clicked(int)), this, TQT_SLOT(setEBorders())); @@ -716,7 +728,8 @@ KAdvancedConfig::KAdvancedConfig (bool _standAlone, TDEConfig *_config, TQWidget connect(active_box, TQT_SIGNAL(clicked(int)), this, TQT_SLOT(changed())); connect(active_move, TQT_SIGNAL(clicked()), this, TQT_SLOT(changed())); connect(active_maximize, TQT_SIGNAL(clicked()), this, TQT_SLOT(changed())); - connect(delays, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(changed())); + connect(delays, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(changed())); + connect(distance, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(changed())); lay->addWidget(active_box); @@ -781,6 +794,7 @@ void KAdvancedConfig::load( void ) setActiveBorders(active_borders); setActiveBorderDelay(active_borders_delay); + setActiveBorderDistance(config->readNumEntry(KWIN_ACTIVE_BORDER_DISTANCE, 10)); setHideUtilityWindowsForInactive( config->readBoolEntry( KWIN_HIDE_UTILITY, true )); @@ -804,6 +818,7 @@ void KAdvancedConfig::save( void ) config->writeEntry(KWIN_ACTIVE_BORDERS, getActiveBorders()); config->writeEntry(KWIN_ACTIVE_BORDER_DELAY, getActiveBorderDelay()); + config->writeEntry(KWIN_ACTIVE_BORDER_DISTANCE, getActiveBorderDistance()); config->writeEntry(KWIN_HIDE_UTILITY, hideUtilityWindowsForInactive->isChecked()); @@ -828,6 +843,7 @@ void KAdvancedConfig::defaults() setShadeHoverInterval(250); setActiveBorders(0); setActiveBorderDelay(150); + setActiveBorderDistance(10); setHideUtilityWindowsForInactive( true ); emit TDECModule::changed(true); } @@ -858,6 +874,10 @@ int KAdvancedConfig::getActiveBorderDelay() return delays->value(); } +int KAdvancedConfig::getActiveBorderDistance() { + return distance->value(); +} + void KAdvancedConfig::setActiveBorders(int i){ switch(i) { @@ -883,6 +903,9 @@ void KAdvancedConfig::setActiveBorderDelay(int delay) delays->setValue(delay); } +void KAdvancedConfig::setActiveBorderDistance(int d) { + distance->setValue(d); +} KMovingConfig::~KMovingConfig () { diff --git a/twin/kcmtwin/twinoptions/windows.h b/twin/kcmtwin/twinoptions/windows.h index 435bd0521..63bf75331 100644 --- a/twin/kcmtwin/twinoptions/windows.h +++ b/twin/kcmtwin/twinoptions/windows.h @@ -228,8 +228,10 @@ private: int getActiveBorders( void ); int getActiveBorderDelay(); + int getActiveBorderDistance(); void setActiveBorders( int ); void setActiveBorderDelay( int ); + void setActiveBorderDistance( int ); TQButtonGroup *active_box; TQRadioButton *active_disable; @@ -238,6 +240,7 @@ private: TQRadioButton *active_tile; TQCheckBox *active_maximize; KIntNumInput *delays; + KIntNumInput *distance; TQWidget *active_desktop_conf; TQWidget *active_tile_conf; diff --git a/twin/options.cpp b/twin/options.cpp index 3d237255b..6a0963910 100644 --- a/twin/options.cpp +++ b/twin/options.cpp @@ -136,6 +136,7 @@ unsigned long Options::updateSettings() if (active_border_delay == -1) { active_border_delay = config->readNumEntry("ElectricBorderDelay", 150); } + active_border_distance = config->readNumEntry("ActiveBorderDistance", 10); OpTitlebarDblClick = windowOperation( config->readEntry("TitlebarDoubleClickCommand", "Shade"), true ); d->OpMaxButtonLeftClick = windowOperation( config->readEntry("MaximizeButtonLeftClickCommand", "Maximize"), true ); @@ -397,6 +398,11 @@ int Options::activeBorderDelay() return active_border_delay; } +int Options::borderActivationDistance() + { + return active_border_distance; + } + bool Options::checkIgnoreFocusStealing( const Client* c ) { return ignoreFocusStealingClasses.contains(TQString::fromLatin1(c->resourceClass())); diff --git a/twin/options.h b/twin/options.h index 55183e6bd..3227e57d7 100644 --- a/twin/options.h +++ b/twin/options.h @@ -326,6 +326,8 @@ class Options : public KDecorationOptions */ int activeBorders(); + int borderActivationDistance(); + /** * @returns the activation delay for active borders in milliseconds. */ @@ -386,6 +388,7 @@ class Options : public KDecorationOptions int active_borders; int active_border_delay; + int active_border_distance; bool show_geometry_tip; bool reset_maximized_window_geometry; bool topmenus; diff --git a/twin/utils.h b/twin/utils.h index 65c766690..e2e6e2a31 100644 --- a/twin/utils.h +++ b/twin/utils.h @@ -124,11 +124,9 @@ enum ActiveBorder enum ActiveMaximizingMode { - ActiveMaximizeMode, - ActiveLeftMode, - ActiveRightMode, - ActiveTopMode, - ActiveBottomMode + ActiveNoMode, + ActiveTilingMode, + ActiveMaximizeMode }; class Shape diff --git a/twin/workspace.cpp b/twin/workspace.cpp index 03a2e4e50..b8e6a2731 100644 --- a/twin/workspace.cpp +++ b/twin/workspace.cpp @@ -2524,54 +2524,65 @@ void Workspace::checkActiveBorder(const TQPoint &pos, Time now) Time treshold_set = options->activeBorderDelay(); // set timeout Time treshold_trigger = 250; // Minimum time between triggers Time treshold_reset = 250; // reset timeout - int distance_reset = 30; // Mouse should not move more than this many pixels + int activation_distance = options->borderActivationDistance(); - if ((pos.x() > activeLeft + distance_reset) && - (pos.x() < activeRight - distance_reset) && - (pos.y() > activeTop + distance_reset) && - (pos.y() < activeBottom - distance_reset)) + bool have_borders = false; + for (int i = 0; i < ACTIVE_BORDER_COUNT; ++i) + { + if (active_windows[ i ] != None) + { + have_borders = true; + } + } + if( !have_borders ) + return; + + // Mouse should not move more than this many pixels + int distance_reset = activation_distance + 10; + + // Leave active maximizing mode when window moved away + if (active_current_border != ActiveNone && + (pos.x() > activeLeft + distance_reset) && + (pos.x() < activeRight - distance_reset) && + (pos.y() > activeTop + distance_reset) && + (pos.y() < activeBottom - distance_reset)) { if (movingClient && (options->activeBorders() == Options::ActiveTileMaximize || options->activeBorders() == Options::ActiveTileOnly)) { movingClient->setActiveBorderMaximizing(false); + return; } } - if ((pos.x() != activeLeft) && - (pos.x() != activeRight) && - (pos.y() != activeTop) && - (pos.y() != activeBottom)) + bool active_left = pos.x() < activeLeft + activation_distance, + active_right = pos.x() > activeRight - activation_distance, + active_top = pos.y() < activeTop + activation_distance, + active_bottom = pos.y() > activeBottom - activation_distance; + + if (!active_left && !active_right && !active_top && !active_bottom) return; - bool have_borders = false; - for (int i = 0; i < ACTIVE_BORDER_COUNT; ++i) - { - if (active_windows[ i ] != None) - { - have_borders = true; - } - } - if( !have_borders ) - return; + kdDebug() << "active border activated " + << pos.x() << ":" << pos.y() << endl; - ActiveBorder border; - if( pos.x() == activeLeft && pos.y() == activeTop ) + ActiveBorder border = ActiveNone; + if (active_left && active_top) border = ActiveTopLeft; - else if( pos.x() == activeRight && pos.y() == activeTop ) + else if (active_right && active_top) border = ActiveTopRight; - else if( pos.x() == activeLeft && pos.y() == activeBottom ) + else if (active_left && active_bottom) border = ActiveBottomLeft; - else if( pos.x() == activeRight && pos.y() == activeBottom ) + else if (active_right && active_bottom) border = ActiveBottomRight; - else if( pos.x() == activeLeft ) + else if (active_left) border = ActiveLeft; - else if( pos.x() == activeRight ) + else if (active_right) border = ActiveRight; - else if( pos.y() == activeTop ) + else if (active_top) border = ActiveTop; - else if( pos.y() == activeBottom ) + else if (active_bottom) border = ActiveBottom; else abort(); @@ -2586,6 +2597,9 @@ void Workspace::checkActiveBorder(const TQPoint &pos, Time now) { active_time_last = now; + kdDebug() << "time diff between first time and now is: " + << timestampDiff(active_time_first, now) + << " vs threshold " << treshold_set << endl; if (timestampDiff(active_time_first, now) > treshold_set) { active_time_last_trigger = now; @@ -2608,43 +2622,19 @@ void Workspace::checkActiveBorder(const TQPoint &pos, Time now) border == ActiveTop && movingClient->isMaximizable()) { if (!movingClient->isResizable()) return; - bool enable = !movingClient->isActiveBorderMaximizing(); movingClient->setActiveBorderMode(ActiveMaximizeMode); - movingClient->setActiveBorderMaximizing(enable); + movingClient->setActiveBorder(ActiveNone); + movingClient->setActiveBorderMaximizing(true); } // Tiling else if ((options->activeBorders() == Options::ActiveTileMaximize || - options->activeBorders() == Options::ActiveTileOnly) && isSide) + options->activeBorders() == Options::ActiveTileOnly)) { if (!movingClient->isResizable()) return; - bool enable = !movingClient->isActiveBorderMaximizing(); - bool activate = false; - if (border == ActiveLeft) - { - movingClient->setActiveBorderMode( ActiveLeftMode ); - activate = true; - } - else if (border == ActiveRight) - { - movingClient->setActiveBorderMode( ActiveRightMode ); - activate = true; - } - else if (border == ActiveTop) - { - movingClient->setActiveBorderMode( ActiveTopMode ); - activate = true; - } - else if (border == ActiveBottom) - { - movingClient->setActiveBorderMode( ActiveBottomMode ); - activate = true; - } - - if (activate) - { - movingClient->setActiveBorderMaximizing(enable); - } + movingClient->setActiveBorderMode(ActiveTilingMode); + movingClient->setActiveBorder(border); + movingClient->setActiveBorderMaximizing(true); } else @@ -2671,13 +2661,16 @@ void Workspace::checkActiveBorder(const TQPoint &pos, Time now) active_push_point = pos; } - // reset the pointer to find out wether the user is really pushing - // (the direction back from which it came, starting from top clockwise) - const int xdiff[ ACTIVE_BORDER_COUNT ] = { 0, -1, -1, -1, 0, 1, 1, 1 }; - const int ydiff[ ACTIVE_BORDER_COUNT ] = { 1, 1, 0, -1, -1, -1, 0, 1 }; - TQCursor::setPos(pos.x() + xdiff[border], pos.y() + ydiff[border]); - + if ((options->activeBorders() == Options::ActiveSwitchAlways && !movingClient) || + activation_distance < 2) + { + // reset the pointer to find out whether the user is really pushing + // (the direction back from which it came, starting from top clockwise) + const int xdiff[ ACTIVE_BORDER_COUNT ] = { 0, -1, -1, -1, 0, 1, 1, 1 }; + const int ydiff[ ACTIVE_BORDER_COUNT ] = { 1, 1, 0, -1, -1, -1, 0, 1 }; + TQCursor::setPos(pos.x() + xdiff[border], pos.y() + ydiff[border]); } +} void Workspace::activeBorderSwitchDesktop(ActiveBorder border, const TQPoint& _pos) { -- cgit v1.2.1