TWin: Active borders and snap tiling

This commit is a squash of the commits of TDE/tdebase#331.

In short, this backports some improvements to existing electric border
functionality from KDE, adds the snap tiling (or aerosnap) feature and
brings rudimentary support for active corners, which will be fully
implemented in a later PR.

The options dialog and the documentation has been updated to reflect
these changes.

Additionally, a new relevant option is introduced: an option for
restoring the original size of maximized/tiled windows when the user
starts dragging them. The option is set to be off by default,
preserving the traditional behaviour of KDE 3.x/TDE.

Last but not least, the term "electric" in relation to borders and
corners is replaced by "active" for clarity to the users.

Signed-off-by: Mavridis Philippe <mavridisf@gmail.com>
pull/331/head
Mavridis Philippe 1 year ago
parent 3285a47d5d
commit 31335a04ed
No known key found for this signature in database
GPG Key ID: 93F66F98F906147D

@ -615,6 +615,13 @@ to allow moving or resizing maximized windows.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><guilabel>Restore size of maximized/tiled windows when moving</guilabel></term>
<listitem>
<para>When enabled, this feature restores the original size of a maximized or <link linkend="active-borders">tiled</link> window when the window is dragged.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><guilabel>Placement</guilabel></term> <term><guilabel>Placement</guilabel></term>
<listitem> <listitem>
@ -739,36 +746,46 @@ Use the slider widget to configure the delay.
</variablelist> </variablelist>
<variablelist> <variablelist id="active-borders">
<title>Active Desktop Borders</title> <title>Active Borders</title>
<para>Active Borders is a feature which allows you to quickly perform window management actions by moving your mouse into a desktop border.</para>
<para>The corresponding section allows you to configure the function that will be performed when pushing your mouse cursor against a border or moving a window into it:</para>
<varlistentry> <varlistentry>
<term><guilabel>Disabled</guilabel></term> <term><guilabel>Disabled</guilabel></term>
<listitem> <listitem>
<para>When this option is enabled, moving the mouse pointer to a screen <para>This option disables the Active Borders feature.</para>
border will change your desktop. This is useful when you want to drag
windows from one desktop to another.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><guilabel>Only when moving windows</guilabel></term> <term><guilabel>Switch desktop</guilabel></term>
<listitem> <listitem>
<para>Moving your mouse pointer against the side of the screen will <para>Moving your mouse pointer against the side of the screen will switch to another desktop.</para>
switch to a new desktop only while moving a window.</para> <para>By default the switch occurs both when moving your mouse pointer into a border and dragging a window into it. The <guilabel>Switch desktop only when moving a window</guilabel> checkbox disables the former behaviour and only switches to another desktop when a window is being dragged into a desktop border.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><guilabel>Always enabled</guilabel></term> <term><guilabel>Tile window</guilabel></term>
<listitem> <listitem>
<para>Moving your mouse pointer against the side of the screen will <para>Dragging a window into a desktop border will tile that window at that side of the screen. This feature is also known as <quote>Aerosnap</quote> or <quote>Quick Tile</quote>.</para>
always switch to a new desktop.</para> <para><guilabel>Maximize windows by dragging them to the top of the screen</guilabel> 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.</para>
<para>By default dragging a tiled window does not reset its original size. This behaviour is controlled by an option in the <link linkend="moving">Moving</link> tab of this control module.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>
<para>
<guilabel>Border activation delay</guilabel>.
This option controls the delay before the designated active border function is performed. A higher value can prevent accidental activations of this feature.
</para>
<sect3>
<title>Other</title>
<para> <para>
<guilabel>Hide utility windows for inactive applications</guilabel>. When <guilabel>Hide utility windows for inactive applications</guilabel>. When
enabled, utility windows (tool windows, torn-off menus) of enabled, utility windows (tool windows, torn-off menus) of
@ -776,6 +793,7 @@ inactive applications will be hidden and will be shown only when the
application becomes active. Note that applications have to mark the windows application becomes active. Note that applications have to mark the windows
with the proper window type for this feature to work. with the proper window type for this feature to work.
</para> </para>
</sect3>
</sect2> </sect2>

@ -120,7 +120,9 @@ Client::Client( Workspace *ws )
border_top( 0 ), border_top( 0 ),
border_bottom( 0 ), border_bottom( 0 ),
opacity_( 0 ), opacity_( 0 ),
demandAttentionKNotifyTimer( NULL ) demandAttentionKNotifyTimer( NULL ),
activeMaximizing(false),
activeTiled(false)
// SELI do all as initialization // SELI do all as initialization
{ {
autoRaiseTimer = 0; autoRaiseTimer = 0;

@ -232,6 +232,11 @@ class Client : public TQObject, public KDecorationDefines
void resizeWithChecks( int w, int h, ForceGeometry_t force = NormalGeometrySet ); void resizeWithChecks( int w, int h, ForceGeometry_t force = NormalGeometrySet );
void resizeWithChecks( const TQSize& s, ForceGeometry_t force = NormalGeometrySet ); void resizeWithChecks( const TQSize& s, ForceGeometry_t force = NormalGeometrySet );
void keepInArea( TQRect area, bool partial = false ); void keepInArea( TQRect area, bool partial = false );
void setActiveBorderMode( ActiveMaximizingMode mode );
ActiveMaximizingMode activeBorderMode() const;
void setActiveBorderMaximizing(bool maximizing);
bool isActiveBorderMaximizing() const;
TQRect activeBorderMaximizeGeometry();
void growHorizontal(); void growHorizontal();
void shrinkHorizontal(); void shrinkHorizontal();
@ -600,6 +605,11 @@ class Client : public TQObject, public KDecorationDefines
bool isBMP_; bool isBMP_;
TQTimer* demandAttentionKNotifyTimer; TQTimer* demandAttentionKNotifyTimer;
bool activeMaximizing;
bool activeTiled;
TQRect activeTiledOrigGeom;
ActiveMaximizingMode activeMode;
friend bool performTransiencyCheck(); friend bool performTransiencyCheck();
bool minimized_before_suspend; bool minimized_before_suspend;
}; };

@ -389,7 +389,7 @@ bool Workspace::workspaceEvent( XEvent * e )
if ( w ) if ( w )
TQWhatsThis::leaveWhatsThisMode(); TQWhatsThis::leaveWhatsThisMode();
} }
if( electricBorder(e)) if (activeBorderEvent(e))
return true; return true;
break; break;
} }
@ -454,7 +454,7 @@ bool Workspace::workspaceEvent( XEvent * e )
case FocusOut: case FocusOut:
return true; // always eat these, they would tell Qt that KWin is the active app return true; // always eat these, they would tell Qt that KWin is the active app
case ClientMessage: case ClientMessage:
if( electricBorder( e )) if (activeBorderEvent(e))
return true; return true;
break; break;
default: default:

@ -40,7 +40,7 @@ namespace KWinInternal
Resizes the workspace after an XRANDR screen size change Resizes the workspace after an XRANDR screen size change
*/ */
void Workspace::desktopResized() void Workspace::desktopResized()
{ {
//printf("Workspace::desktopResized()\n"); //printf("Workspace::desktopResized()\n");
TQRect geom = TDEApplication::desktop()->geometry(); TQRect geom = TDEApplication::desktop()->geometry();
NETSize desktop_geometry; NETSize desktop_geometry;
@ -49,24 +49,17 @@ void Workspace::desktopResized()
rootInfo->setDesktopGeometry( -1, desktop_geometry ); rootInfo->setDesktopGeometry( -1, desktop_geometry );
updateClientArea( true ); updateClientArea( true );
checkElectricBorders( true ); destroyActiveBorders();
} updateActiveBorders();
}
/*! /*!
Resizes the workspace after kdesktop signals a desktop resize Resizes the workspace after kdesktop signals a desktop resize
*/ */
void Workspace::kDestopResized() void Workspace::kDestopResized()
{ {
//printf("Workspace::kDesktopResized()\n"); desktopResized();
TQRect geom = TDEApplication::desktop()->geometry(); }
NETSize desktop_geometry;
desktop_geometry.width = geom.width();
desktop_geometry.height = geom.height();
rootInfo->setDesktopGeometry( -1, desktop_geometry );
updateClientArea( true );
checkElectricBorders( true );
}
/*! /*!
Updates the current client areas according to the current clients. Updates the current client areas according to the current clients.
@ -2302,7 +2295,7 @@ class EatAllPaintEvents
static EatAllPaintEvents* eater = 0; static EatAllPaintEvents* eater = 0;
bool Client::startMoveResize() bool Client::startMoveResize()
{ {
assert( !moveResizeMode ); assert( !moveResizeMode );
assert( TQWidget::keyboardGrabber() == NULL ); assert( TQWidget::keyboardGrabber() == NULL );
assert( TQWidget::mouseGrabber() == NULL ); assert( TQWidget::mouseGrabber() == NULL );
@ -2324,28 +2317,55 @@ bool Client::startMoveResize()
if( XGrabKeyboard( tqt_xdisplay(), frameId(), False, GrabModeAsync, GrabModeAsync, GET_QT_X_TIME() ) == Success ) if( XGrabKeyboard( tqt_xdisplay(), frameId(), False, GrabModeAsync, GrabModeAsync, GET_QT_X_TIME() ) == Success )
has_grab = true; has_grab = true;
if( !has_grab ) // at least one grab is necessary in order to be able to finish move/resize if( !has_grab ) // at least one grab is necessary in order to be able to finish move/resize
{ {
XDestroyWindow( tqt_xdisplay(), move_resize_grab_window ); XDestroyWindow( tqt_xdisplay(), move_resize_grab_window );
move_resize_grab_window = None; move_resize_grab_window = None;
return false; return false;
} }
if ( maximizeMode() != MaximizeRestore )
resetMaximize();
removeShadow(); removeShadow();
moveResizeMode = true; moveResizeMode = true;
initialMoveResizeGeom = geometry();
if (activeTiled)
{
// Restore original geometry
activeTiled = false;
if (options->resetMaximizedWindowGeometry() && isMove()) {
setGeometry(activeTiledOrigGeom);
}
}
if ( maximizeMode() != MaximizeRestore )
{
if (options->resetMaximizedWindowGeometry() && isMove()) {
maximize(MaximizeRestore);
}
else {
resetMaximize();
}
activeTiled = false;
}
moveResizeGeom = geometry();
workspace()->setClientIsMoving(this); workspace()->setClientIsMoving(this);
initialMoveResizeGeom = moveResizeGeom = geometry();
checkUnrestrictedMoveResize(); checkUnrestrictedMoveResize();
// rule out non opaque windows from useless translucency settings, maybe resizes? // rule out non opaque windows from useless translucency settings, maybe resizes?
if ((isResize() && options->removeShadowsOnResize) || (isMove() && options->removeShadowsOnMove)) if ((isResize() && options->removeShadowsOnResize) || (isMove() && options->removeShadowsOnMove))
{
setShadowSize(0); setShadowSize(0);
if (rules()->checkMoveResizeMode( options->moveMode ) == Options::Opaque){ }
if (rules()->checkMoveResizeMode( options->moveMode ) == Options::Opaque)
{
savedOpacity_ = opacity_; savedOpacity_ = opacity_;
setOpacity(options->translucentMovingWindows, options->movingWindowOpacity); setOpacity(options->translucentMovingWindows, options->movingWindowOpacity);
} }
if ( ( isMove() && rules()->checkMoveResizeMode( options->moveMode ) != Options::Opaque ) if ( ( isMove() && rules()->checkMoveResizeMode( options->moveMode ) != Options::Opaque )
|| ( isResize() && rules()->checkMoveResizeMode( options->resizeMode ) != Options::Opaque ) ) || ( isResize() && rules()->checkMoveResizeMode( options->resizeMode ) != Options::Opaque ) )
{ {
grabXServer(); grabXServer();
kapp->sendPostedEvents(); kapp->sendPostedEvents();
// we have server grab -> nothing should cause paint events // we have server grab -> nothing should cause paint events
@ -2355,25 +2375,57 @@ bool Client::startMoveResize()
// paint events for the geometrytip need to be allowed, though // paint events for the geometrytip need to be allowed, though
eater = new EatAllPaintEvents; eater = new EatAllPaintEvents;
// not needed anymore? kapp->installEventFilter( eater ); // not needed anymore? kapp->installEventFilter( eater );
} }
Notify::raise( isResize() ? Notify::ResizeStart : Notify::MoveStart ); Notify::raise( isResize() ? Notify::ResizeStart : Notify::MoveStart );
return true;
if (options->activeBorders() == Options::ActiveSwitchOnMove ||
options->activeBorders() == Options::ActiveTileMaximize ||
options->activeBorders() == Options::ActiveTileOnly)
{
workspace()->reserveActiveBorderSwitching(true);
} }
return true;
}
void Client::finishMoveResize( bool cancel ) void Client::finishMoveResize( bool cancel )
{ {
leaveMoveResize(); leaveMoveResize();
if( cancel )
setGeometry( initialMoveResizeGeom ); if (!isActiveBorderMaximizing()) {
setGeometry(cancel ? initialMoveResizeGeom : moveResizeGeom);
}
else else
setGeometry( moveResizeGeom ); {
kdDebug() <<"finishing moveresize in active mode, cancel is " << cancel << endl;
activeMaximizing = false;
activeTiled = true;
activeTiledOrigGeom = initialMoveResizeGeom;
switch(activeMode)
{
case ActiveMaximizeMode:
{
if (!cancel) {
bool full = (maximizeMode() == MaximizeFull);
setMaximize(!full, !full);
}
break;
}
default:
setGeometry(cancel ? initialMoveResizeGeom
: activeBorderMaximizeGeometry());
}
}
checkMaximizeGeometry(); checkMaximizeGeometry();
// FRAME update(); // FRAME update();
Notify::raise( isResize() ? Notify::ResizeEnd : Notify::MoveEnd ); Notify::raise( isResize() ? Notify::ResizeEnd : Notify::MoveEnd );
} }
void Client::leaveMoveResize() void Client::leaveMoveResize()
{ {
// rule out non opaque windows from useless translucency settings, maybe resizes? // rule out non opaque windows from useless translucency settings, maybe resizes?
if (rules()->checkMoveResizeMode( options->moveMode ) == Options::Opaque) if (rules()->checkMoveResizeMode( options->moveMode ) == Options::Opaque)
setOpacity(true, savedOpacity_); setOpacity(true, savedOpacity_);
@ -2401,12 +2453,19 @@ void Client::leaveMoveResize()
delete eater; delete eater;
eater = 0; eater = 0;
if (options->shadowEnabled(isActive())) if (options->shadowEnabled(isActive()))
{ {
drawIntersectingShadows(); drawIntersectingShadows();
updateOpacityCache(); updateOpacityCache();
}
} }
if (options->activeBorders() == Options::ActiveSwitchOnMove ||
options->activeBorders() == Options::ActiveTileMaximize ||
options->activeBorders() == Options::ActiveTileOnly)
{
workspace()->reserveActiveBorderSwitching(false);
}
}
// This function checks if it actually makes sense to perform a restricted move/resize. // This function checks if it actually makes sense to perform a restricted move/resize.
// If e.g. the titlebar is already outside of the workarea, there's no point in performing // If e.g. the titlebar is already outside of the workarea, there's no point in performing
// a restricted move resize, because then e.g. resize would also move the window (#74555). // a restricted move resize, because then e.g. resize would also move the window (#74555).
@ -2454,25 +2513,25 @@ void Client::checkUnrestrictedMoveResize()
void Client::handleMoveResize( int x, int y, int x_root, int y_root ) void Client::handleMoveResize( int x, int y, int x_root, int y_root )
{ {
if(( mode == PositionCenter && !isMovable()) if ( (mode == PositionCenter && !isMovable())
|| ( mode != PositionCenter && ( isShade() || !isResizable()))) || (mode != PositionCenter && (isShade() || !isResizable())) )
return; return;
if ( !moveResizeMode ) if (!moveResizeMode)
{ {
TQPoint p( TQPoint( x, y ) - moveOffset ); TQPoint p(TQPoint( x, y ) - moveOffset);
if (p.manhattanLength() >= 6) if (p.manhattanLength() >= 6)
{
if(!startMoveResize())
{ {
if( !startMoveResize())
{
buttonDown = false; buttonDown = false;
setCursor( mode ); setCursor( mode );
return; return;
}
} }
}
else else
return; return;
} }
// ShadeHover or ShadeActive, ShadeNormal was already avoided above // ShadeHover or ShadeActive, ShadeNormal was already avoided above
if ( mode != PositionCenter && shade_mode != ShadeNone ) if ( mode != PositionCenter && shade_mode != ShadeNone )
@ -2494,7 +2553,7 @@ void Client::handleMoveResize( int x, int y, int x_root, int y_root )
if( unrestrictedMoveResize ) // unrestricted, just don't let it go out completely if( unrestrictedMoveResize ) // unrestricted, just don't let it go out completely
left_marge = right_marge = top_marge = bottom_marge = titlebar_marge = 5; left_marge = right_marge = top_marge = bottom_marge = titlebar_marge = 5;
else // restricted move/resize - keep at least part of the titlebar always visible else // restricted move/resize - keep at least part of the titlebar always visible
{ {
// how much must remain visible when moved away in that direction // how much must remain visible when moved away in that direction
left_marge = KMIN( 100 + border_right, moveResizeGeom.width()); left_marge = KMIN( 100 + border_right, moveResizeGeom.width());
right_marge = KMIN( 100 + border_left, moveResizeGeom.width()); right_marge = KMIN( 100 + border_left, moveResizeGeom.width());
@ -2502,16 +2561,16 @@ void Client::handleMoveResize( int x, int y, int x_root, int y_root )
titlebar_marge = initialMoveResizeGeom.height(); titlebar_marge = initialMoveResizeGeom.height();
top_marge = border_bottom; top_marge = border_bottom;
bottom_marge = border_top; bottom_marge = border_top;
} }
bool update = false; bool update = false;
if( isResize()) if (isResize())
{ {
// first resize (without checking constraints), then snap, then check bounds, then check constraints // first resize (without checking constraints), then snap, then check bounds, then check constraints
TQRect orig = initialMoveResizeGeom; TQRect orig = initialMoveResizeGeom;
Sizemode sizemode = SizemodeAny; Sizemode sizemode = SizemodeAny;
switch ( mode ) switch ( mode )
{ {
case PositionTopLeft: case PositionTopLeft:
moveResizeGeom = TQRect( topleft, orig.bottomRight() ) ; moveResizeGeom = TQRect( topleft, orig.bottomRight() ) ;
break; break;
@ -2544,7 +2603,7 @@ void Client::handleMoveResize( int x, int y, int x_root, int y_root )
default: default:
assert( false ); assert( false );
break; break;
} }
// adjust new size to snap to other windows/borders // adjust new size to snap to other windows/borders
moveResizeGeom = workspace()->adjustClientSize( this, moveResizeGeom, mode ); moveResizeGeom = workspace()->adjustClientSize( this, moveResizeGeom, mode );
@ -2567,7 +2626,7 @@ void Client::handleMoveResize( int x, int y, int x_root, int y_root )
bottomright = TQPoint( moveResizeGeom.left() + size.width() - 1, moveResizeGeom.top() + size.height() - 1 ); bottomright = TQPoint( moveResizeGeom.left() + size.width() - 1, moveResizeGeom.top() + size.height() - 1 );
orig = moveResizeGeom; orig = moveResizeGeom;
switch ( mode ) switch ( mode )
{ // these 4 corners ones are copied from above { // these 4 corners ones are copied from above
case PositionTopLeft: case PositionTopLeft:
moveResizeGeom = TQRect( topleft, orig.bottomRight() ) ; moveResizeGeom = TQRect( topleft, orig.bottomRight() ) ;
break; break;
@ -2599,12 +2658,12 @@ void Client::handleMoveResize( int x, int y, int x_root, int y_root )
default: default:
assert( false ); assert( false );
break; break;
}
if( moveResizeGeom.size() != previousMoveResizeGeom.size())
update = true;
} }
else if( isMove()) if (moveResizeGeom.size() != previousMoveResizeGeom.size())
{ update = true;
}
else if (isMove())
{
assert( mode == PositionCenter ); assert( mode == PositionCenter );
// first move, then snap, then check bounds // first move, then snap, then check bounds
moveResizeGeom.moveTopLeft( topleft ); moveResizeGeom.moveTopLeft( topleft );
@ -2621,29 +2680,98 @@ void Client::handleMoveResize( int x, int y, int x_root, int y_root )
moveResizeGeom.moveLeft(desktopArea.right() - right_marge ); moveResizeGeom.moveLeft(desktopArea.right() - right_marge );
if( moveResizeGeom.topLeft() != previousMoveResizeGeom.topLeft()) if( moveResizeGeom.topLeft() != previousMoveResizeGeom.topLeft())
update = true; update = true;
} }
else else
assert( false ); assert(false);
if( update ) if (update)
{
if (rules()->checkMoveResizeMode(isResize() ? options->resizeMode : options->moveMode) == Options::Opaque
&& !isActiveBorderMaximizing())
{ {
if( rules()->checkMoveResizeMode
( isResize() ? options->resizeMode : options->moveMode ) == Options::Opaque )
{
setGeometry( moveResizeGeom ); setGeometry( moveResizeGeom );
positionGeometryTip(); positionGeometryTip();
}
else if( rules()->checkMoveResizeMode
( isResize() ? options->resizeMode : options->moveMode ) == Options::Transparent )
{
clearbound(); // it's necessary to move the geometry tip when there's no outline
positionGeometryTip(); // shown, otherwise it would cause repaint problems in case
drawbound( moveResizeGeom ); // they overlap; the paint event will come after this,
} // so the geometry tip will be painted above the outline
} }
if ( isMove() ) else if (rules()->checkMoveResizeMode(isResize() ? options->resizeMode : options->moveMode) == Options::Transparent )
workspace()->clientMoved(globalPos, GET_QT_X_TIME()); {
/* It's necessary to move the geometry tip when there's no outline
* shown, otherwise it would cause repaint problems in case
* they overlap; the paint event will come after this,
* so the geometry tip will be painted above the outline
*/
clearbound();
positionGeometryTip();
drawbound(isActiveBorderMaximizing() ? activeBorderMaximizeGeometry() : moveResizeGeom);
}
} }
if (isMove())
workspace()->checkActiveBorder(globalPos, GET_QT_X_TIME());
}
void Client::setActiveBorderMode( ActiveMaximizingMode mode )
{
activeMode = mode;
}
ActiveMaximizingMode Client::activeBorderMode() const
{
return activeMode;
}
bool Client::isActiveBorderMaximizing() const
{
return activeMaximizing;
}
void Client::setActiveBorderMaximizing( bool maximizing )
{
activeMaximizing = maximizing;
if (maximizing || rules()->checkMoveResizeMode(isResize() ? options->resizeMode : options->moveMode) == Options::Opaque) {
clearbound();
}
if (maximizing) {
drawbound(activeBorderMaximizeGeometry());
}
}
TQRect Client::activeBorderMaximizeGeometry()
{
TQRect ret;
TQRect max = workspace()->clientArea(MaximizeArea, TQCursor::pos(), workspace()->currentDesktop());
switch (activeMode)
{
case ActiveMaximizeMode:
{
if (maximizeMode() == MaximizeFull)
ret = geometryRestore();
else
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:
{
ret = TQRect( max.x(), max.y() + max.height()/2, max.width(), max.height()/2 );
break;
}
}
return ret;
}
} // namespace } // namespace

@ -29,6 +29,7 @@
#include <tqslider.h> #include <tqslider.h>
#include <tqwhatsthis.h> #include <tqwhatsthis.h>
#include <tqvbuttongroup.h> #include <tqvbuttongroup.h>
#include <tqhbox.h>
#include <tqcheckbox.h> #include <tqcheckbox.h>
#include <tqradiobutton.h> #include <tqradiobutton.h>
#include <tqlabel.h> #include <tqlabel.h>
@ -69,6 +70,7 @@
#define KWIN_CLICKRAISE "ClickRaise" #define KWIN_CLICKRAISE "ClickRaise"
#define KWIN_ANIMSHADE "AnimateShade" #define KWIN_ANIMSHADE "AnimateShade"
#define KWIN_MOVE_RESIZE_MAXIMIZED "MoveResizeMaximizedWindows" #define KWIN_MOVE_RESIZE_MAXIMIZED "MoveResizeMaximizedWindows"
#define KWIN_RESET_MAX_WIN_GEOM "ResetMaximizedWindowGeometry"
#define KWIN_ALTTABMODE "AltTabStyle" #define KWIN_ALTTABMODE "AltTabStyle"
#define KWIN_TRAVERSE_ALL "TraverseAll" #define KWIN_TRAVERSE_ALL "TraverseAll"
#define KWIN_SHOW_POPUP "ShowPopup" #define KWIN_SHOW_POPUP "ShowPopup"
@ -79,10 +81,12 @@
#define KWIN_HIDE_UTILITY "HideUtilityWindowsForInactive" #define KWIN_HIDE_UTILITY "HideUtilityWindowsForInactive"
#define KWIN_SEPARATE_SCREEN_FOCUS "SeparateScreenFocus" #define KWIN_SEPARATE_SCREEN_FOCUS "SeparateScreenFocus"
#define KWIN_ACTIVE_MOUSE_SCREEN "ActiveMouseScreen" #define KWIN_ACTIVE_MOUSE_SCREEN "ActiveMouseScreen"
#define KWIN_ACTIVE_BORDERS "ActiveBorders"
#define KWIN_ACTIVE_BORDER_DELAY "ActiveBorderDelay"
// kwm config keywords // legacy options
#define KWM_ELECTRIC_BORDER "ElectricBorders" #define KWIN_OLD_ACTIVE_BORDERS "ElectricBorders"
#define KWM_ELECTRIC_BORDER_DELAY "ElectricBorderDelay" #define KWIN_OLD_ACTIVE_BORDER_DELAY "ElectricBorderDelay"
//CT 15mar 98 - magics //CT 15mar 98 - magics
#define KWM_BRDR_SNAP_ZONE "BorderSnapZone" #define KWM_BRDR_SNAP_ZONE "BorderSnapZone"
@ -662,31 +666,59 @@ KAdvancedConfig::KAdvancedConfig (bool _standAlone, TDEConfig *_config, TQWidget
connect(shadeHoverOn, TQT_SIGNAL(toggled(bool)), TQT_SLOT(changed())); connect(shadeHoverOn, TQT_SIGNAL(toggled(bool)), TQT_SLOT(changed()));
connect(shadeHover, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(changed())); connect(shadeHover, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(changed()));
electricBox = new TQVButtonGroup(i18n("Active Desktop Borders"), this); active_box = new TQButtonGroup(i18n("Active Desktop Borders"), this);
electricBox->setMargin(15); TQVBoxLayout *active_vbox = new TQVBoxLayout(active_box);
active_vbox->setSpacing(5);
TQWhatsThis::add( electricBox, i18n("If this option is enabled, moving the mouse to a screen border" active_vbox->setMargin(15);
" will change your desktop. This is e.g. useful if you want to drag windows from one desktop" TQWhatsThis::add( active_box, i18n("If this option is enabled, moving the mouse to a screen border"
" to the other.") ); " will perform an action. It will either change your desktop or tile the window that is currently"
active_disable = new TQRadioButton(i18n("D&isabled"), electricBox); " dragged.") );
active_move = new TQRadioButton(i18n("Only &when moving windows"), electricBox);
active_always = new TQRadioButton(i18n("A&lways enabled"), electricBox); TQLabel *active_func_label = new TQLabel(i18n("Function:"), active_box);
delays = new KIntNumInput(10, electricBox); active_disable = new TQRadioButton(i18n("D&isabled"), active_box);
active_desktop = new TQRadioButton(i18n("Switch &desktop"), active_box);
active_desktop_conf = new TQWidget(active_box);
TQHBoxLayout *active_desktop_conf_hbox = new TQHBoxLayout(active_desktop_conf);
active_desktop_conf_hbox->addSpacing(20);
active_desktop_conf_hbox->setAutoAdd(true);
active_move = new TQCheckBox(i18n("Switch desktop only when &moving a window"), active_desktop_conf);
active_tile = new TQRadioButton(i18n("Tile &window"), active_box);
active_tile_conf = new TQWidget(active_box);
TQHBoxLayout *active_tile_conf_hbox = new TQHBoxLayout(active_tile_conf);
active_tile_conf_hbox->addSpacing(20);
active_tile_conf_hbox->setAutoAdd(true);
active_maximize = new TQCheckBox(i18n("Maximize windows by dragging them to the &top of the screen"), active_tile_conf);
delays = new KIntNumInput(10, active_box);
delays->setRange(0, MAX_EDGE_RES, 50, true); delays->setRange(0, MAX_EDGE_RES, 50, true);
delays->setSuffix(i18n(" msec")); delays->setSuffix(i18n(" msec"));
delays->setLabel(i18n("Desktop &switch delay:")); delays->setLabel(i18n("Border &activation delay:"));
TQWhatsThis::add( delays, i18n("Here you can set a delay for switching desktops using the active" TQWhatsThis::add( delays, i18n("Here you can set a delay for the activation of"
" borders feature. Desktops will be switched after the mouse has been pushed against a screen border" " active borders feature. The selected action will be performed after the mouse "
" for the specified number of milliseconds.") ); " has been pushed against a screen border for the specified number of milliseconds.") );
connect( electricBox, TQT_SIGNAL(clicked(int)), this, TQT_SLOT(setEBorders())); active_vbox->addSpacing(10);
active_vbox->addWidget(active_func_label);
active_vbox->addWidget(active_disable);
active_vbox->addWidget(active_desktop);
active_vbox->addWidget(active_desktop_conf);
active_vbox->addWidget(active_tile);
active_vbox->addWidget(active_tile_conf);
active_vbox->addSpacing(15);
active_vbox->addWidget(delays);
connect(active_box, TQT_SIGNAL(clicked(int)), this, TQT_SLOT(setEBorders()));
// Any changes goes to slotChanged() // Any changes goes to slotChanged()
connect(electricBox, TQT_SIGNAL(clicked(int)), TQT_SLOT(changed())); connect(active_box, TQT_SIGNAL(clicked(int)), this, TQT_SLOT(changed()));
connect(delays, TQT_SIGNAL(valueChanged(int)), 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()));
lay->addWidget(electricBox); lay->addWidget(active_box);
hideUtilityWindowsForInactive = new TQCheckBox( i18n( "Hide utility windows for inactive applications" ), this ); hideUtilityWindowsForInactive = new TQCheckBox( i18n( "Hide utility windows for inactive applications" ), this );
TQWhatsThis::add( hideUtilityWindowsForInactive, TQWhatsThis::add( hideUtilityWindowsForInactive,
@ -736,8 +768,19 @@ void KAdvancedConfig::load( void )
setShadeHover(config->readBoolEntry(KWIN_SHADEHOVER, false)); setShadeHover(config->readBoolEntry(KWIN_SHADEHOVER, false));
setShadeHoverInterval(config->readNumEntry(KWIN_SHADEHOVER_INTERVAL, 250)); setShadeHoverInterval(config->readNumEntry(KWIN_SHADEHOVER_INTERVAL, 250));
setElectricBorders(config->readNumEntry(KWM_ELECTRIC_BORDER, 0)); // compatibility with old option names
setElectricBorderDelay(config->readNumEntry(KWM_ELECTRIC_BORDER_DELAY, 150)); int active_borders = config->readNumEntry(KWIN_ACTIVE_BORDERS, -1);
if (active_borders == -1) {
active_borders = config->readNumEntry(KWIN_OLD_ACTIVE_BORDERS, 0);
}
int active_borders_delay = config->readNumEntry(KWIN_ACTIVE_BORDER_DELAY, -1);
if (active_borders_delay == -1) {
active_borders_delay = config->readNumEntry(KWIN_OLD_ACTIVE_BORDER_DELAY, 150);
}
setActiveBorders(active_borders);
setActiveBorderDelay(active_borders_delay);
setHideUtilityWindowsForInactive( config->readBoolEntry( KWIN_HIDE_UTILITY, true )); setHideUtilityWindowsForInactive( config->readBoolEntry( KWIN_HIDE_UTILITY, true ));
@ -759,11 +802,15 @@ void KAdvancedConfig::save( void )
if (v<0) v = 0; if (v<0) v = 0;
config->writeEntry(KWIN_SHADEHOVER_INTERVAL, v); config->writeEntry(KWIN_SHADEHOVER_INTERVAL, v);
config->writeEntry(KWM_ELECTRIC_BORDER, getElectricBorders()); config->writeEntry(KWIN_ACTIVE_BORDERS, getActiveBorders());
config->writeEntry(KWM_ELECTRIC_BORDER_DELAY,getElectricBorderDelay()); config->writeEntry(KWIN_ACTIVE_BORDER_DELAY, getActiveBorderDelay());
config->writeEntry(KWIN_HIDE_UTILITY, hideUtilityWindowsForInactive->isChecked()); config->writeEntry(KWIN_HIDE_UTILITY, hideUtilityWindowsForInactive->isChecked());
// remove replaced legacy entries
config->deleteEntry(KWIN_OLD_ACTIVE_BORDERS);
config->deleteEntry(KWIN_OLD_ACTIVE_BORDER_DELAY);
if (standAlone) if (standAlone)
{ {
config->sync(); config->sync();
@ -779,42 +826,59 @@ void KAdvancedConfig::defaults()
setAnimateShade(true); setAnimateShade(true);
setShadeHover(false); setShadeHover(false);
setShadeHoverInterval(250); setShadeHoverInterval(250);
setElectricBorders(0); setActiveBorders(0);
setElectricBorderDelay(150); setActiveBorderDelay(150);
setHideUtilityWindowsForInactive( true ); setHideUtilityWindowsForInactive( true );
emit TDECModule::changed(true); emit TDECModule::changed(true);
} }
void KAdvancedConfig::setEBorders() void KAdvancedConfig::setEBorders()
{ {
delays->setEnabled(!active_disable->isChecked()); active_desktop_conf->setEnabled(active_desktop->isChecked());
active_tile_conf->setEnabled(active_tile->isChecked());
} }
int KAdvancedConfig::getElectricBorders() int KAdvancedConfig::getActiveBorders()
{ {
if (active_move->isChecked()) if (active_desktop->isChecked())
return 1; {
if (active_always->isChecked()) return active_move->isChecked() ? 1 : 2;
return 2; }
if (active_tile->isChecked())
{
return active_maximize->isChecked() ? 4 : 3;
}
return 0; return 0;
} }
int KAdvancedConfig::getElectricBorderDelay() int KAdvancedConfig::getActiveBorderDelay()
{ {
return delays->value(); return delays->value();
} }
void KAdvancedConfig::setElectricBorders(int i){ void KAdvancedConfig::setActiveBorders(int i){
switch(i) switch(i)
{ {
case 1: active_move->setChecked(true); break; case 1:
case 2: active_always->setChecked(true); break; active_move->setChecked(true);
default: active_disable->setChecked(true); break; case 2:
active_desktop->setChecked(true);
break;
case 4:
active_maximize->setChecked(true);
case 3:
active_tile->setChecked(true);
break;
default:
active_disable->setChecked(true);
break;
} }
setEBorders(); setEBorders();
} }
void KAdvancedConfig::setElectricBorderDelay(int delay) void KAdvancedConfig::setActiveBorderDelay(int delay)
{ {
delays->setValue(delay); delays->setValue(delay);
} }
@ -900,6 +964,11 @@ KMovingConfig::KMovingConfig (bool _standAlone, TDEConfig *_config, TQWidget *pa
" and allows you to move or resize them," " and allows you to move or resize them,"
" just like for normal windows")); " just like for normal windows"));
resetMaximizedWindowGeometry = new TQCheckBox( i18n("Restore size of maximized/tiled windows when moving"), windowsBox);
bLay->addWidget(resetMaximizedWindowGeometry);
TQWhatsThis::add(resetMaximizedWindowGeometry, i18n("If this feature is enabled, dragging a maximized or tiled window"
" will restore the window to its original size."));
TQBoxLayout *vLay = new TQHBoxLayout(bLay); TQBoxLayout *vLay = new TQHBoxLayout(bLay);
TQLabel *plcLabel = new TQLabel(i18n("&Placement:"),windowsBox); TQLabel *plcLabel = new TQLabel(i18n("&Placement:"),windowsBox);
@ -994,6 +1063,7 @@ KMovingConfig::KMovingConfig (bool _standAlone, TDEConfig *_config, TQWidget *pa
connect( minimizeAnimOn, TQT_SIGNAL(clicked() ), TQT_SLOT(changed())); connect( minimizeAnimOn, TQT_SIGNAL(clicked() ), TQT_SLOT(changed()));
connect( minimizeAnimSlider, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(changed())); connect( minimizeAnimSlider, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(changed()));
connect( moveResizeMaximized, TQT_SIGNAL(toggled(bool)), TQT_SLOT(changed())); connect( moveResizeMaximized, TQT_SIGNAL(toggled(bool)), TQT_SLOT(changed()));
connect( resetMaximizedWindowGeometry, TQT_SIGNAL(toggled(bool)), TQT_SLOT(changed()));
connect( placementCombo, TQT_SIGNAL(activated(int)), TQT_SLOT(changed())); connect( placementCombo, TQT_SIGNAL(activated(int)), TQT_SLOT(changed()));
connect( BrdrSnap, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(changed())); connect( BrdrSnap, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(changed()));
connect( BrdrSnap, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(slotBrdrSnapChanged(int))); connect( BrdrSnap, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(slotBrdrSnapChanged(int)));
@ -1074,6 +1144,10 @@ void KMovingConfig::setMoveResizeMaximized(bool a) {
moveResizeMaximized->setChecked(a); moveResizeMaximized->setChecked(a);
} }
void KMovingConfig::setResetMaximizedWindowGeometry(bool a) {
resetMaximizedWindowGeometry->setChecked(a);
}
void KMovingConfig::slotBrdrSnapChanged(int value) { void KMovingConfig::slotBrdrSnapChanged(int value) {
BrdrSnap->setSuffix(i18n(" pixel", " pixels", value)); BrdrSnap->setSuffix(i18n(" pixel", " pixels", value));
} }
@ -1149,6 +1223,7 @@ void KMovingConfig::load( void )
// } // }
setMoveResizeMaximized(config->readBoolEntry(KWIN_MOVE_RESIZE_MAXIMIZED, false)); setMoveResizeMaximized(config->readBoolEntry(KWIN_MOVE_RESIZE_MAXIMIZED, false));
setResetMaximizedWindowGeometry(config->readBoolEntry(KWIN_RESET_MAX_WIN_GEOM, false));
int v; int v;
@ -1212,6 +1287,7 @@ void KMovingConfig::save( void )
config->writeEntry(KWIN_RESIZE_OPAQUE, "Transparent"); config->writeEntry(KWIN_RESIZE_OPAQUE, "Transparent");
config->writeEntry(KWIN_MOVE_RESIZE_MAXIMIZED, moveResizeMaximized->isChecked()); config->writeEntry(KWIN_MOVE_RESIZE_MAXIMIZED, moveResizeMaximized->isChecked());
config->writeEntry(KWIN_RESET_MAX_WIN_GEOM, resetMaximizedWindowGeometry->isChecked());
config->writeEntry(KWM_BRDR_SNAP_ZONE,getBorderSnapZone()); config->writeEntry(KWM_BRDR_SNAP_ZONE,getBorderSnapZone());
@ -1235,6 +1311,7 @@ void KMovingConfig::defaults()
setGeometryTip(false); setGeometryTip(false);
setPlacement(SMART_PLACEMENT); setPlacement(SMART_PLACEMENT);
setMoveResizeMaximized(false); setMoveResizeMaximized(false);
setResetMaximizedWindowGeometry(false);
//copied from kcontrol/konq/twindesktop, aleXXX //copied from kcontrol/konq/twindesktop, aleXXX
setWindowSnapZone(KWM_WNDW_SNAP_ZONE_DEFAULT); setWindowSnapZone(KWM_WNDW_SNAP_ZONE_DEFAULT);

@ -68,6 +68,7 @@ class KIntNumInput;
#define FOCUS_STRICTLY_UNDER_MOUSE 3 #define FOCUS_STRICTLY_UNDER_MOUSE 3
class TQSpinBox; class TQSpinBox;
class TQHBox;
class KFocusConfig : public TDECModule class KFocusConfig : public TDECModule
{ {
@ -88,7 +89,7 @@ private slots:
void clickRaiseOnTog(bool); void clickRaiseOnTog(bool);
void updateAltTabMode(); void updateAltTabMode();
void updateActiveMouseScreen(); void updateActiveMouseScreen();
void changed() { emit TDECModule::changed(true); } void changed() { emit TDECModule::changed(true); }
private: private:
@ -163,6 +164,7 @@ private:
void setGeometryTip(bool); //KS void setGeometryTip(bool); //KS
void setPlacement(int); //CT void setPlacement(int); //CT
void setMoveResizeMaximized(bool); void setMoveResizeMaximized(bool);
void setResetMaximizedWindowGeometry(bool);
TQButtonGroup *windowsBox; TQButtonGroup *windowsBox;
TQCheckBox *opaque; TQCheckBox *opaque;
@ -172,6 +174,7 @@ private:
TQSlider *minimizeAnimSlider; TQSlider *minimizeAnimSlider;
TQLabel *minimizeAnimSlowLabel, *minimizeAnimFastLabel; TQLabel *minimizeAnimSlowLabel, *minimizeAnimFastLabel;
TQCheckBox *moveResizeMaximized; TQCheckBox *moveResizeMaximized;
TQCheckBox *resetMaximizedWindowGeometry;
TQComboBox *placementCombo; TQComboBox *placementCombo;
@ -223,17 +226,21 @@ private:
TDEConfig *config; TDEConfig *config;
bool standAlone; bool standAlone;
int getElectricBorders( void ); int getActiveBorders( void );
int getElectricBorderDelay(); int getActiveBorderDelay();
void setElectricBorders( int ); void setActiveBorders( int );
void setElectricBorderDelay( int ); void setActiveBorderDelay( int );
TQVButtonGroup *electricBox; TQButtonGroup *active_box;
TQRadioButton *active_disable; TQRadioButton *active_disable;
TQRadioButton *active_move; TQRadioButton *active_desktop;
TQRadioButton *active_always; TQCheckBox *active_move;
TQRadioButton *active_tile;
TQCheckBox *active_maximize;
KIntNumInput *delays; KIntNumInput *delays;
TQWidget *active_desktop_conf;
TQWidget *active_tile_conf;
void setHideUtilityWindowsForInactive( bool ); void setHideUtilityWindowsForInactive( bool );
TQCheckBox* hideUtilityWindowsForInactive; TQCheckBox* hideUtilityWindowsForInactive;

@ -129,43 +129,50 @@ void Workspace::updateStackingOrder( bool propagate_new_clients )
void Workspace::propagateClients( bool propagate_new_clients ) void Workspace::propagateClients( bool propagate_new_clients )
{ {
Window *cl; // MW we should not assume WId and Window to be compatible Window *cl; // MW we should not assume WId and Window to be compatible
// when passig pointers around. // when passing pointers around.
// restack the windows according to the stacking order // restack the windows according to the stacking order
#if 0
Window* new_stack = new Window[ stacking_order.count() + 2 ];
int pos = 0;
#endif
NET::WindowType t; NET::WindowType t;
Window shadow; Window shadow;
Window *dock_shadow_stack, *window_stack; Window *dock_shadow_stack, *window_stack;
int i, numDocks, pos, topmenu_space_pos; int i, numDocks, pos, topmenu_space_pos;
// Dock Stack size magic number explanation:
// -> (count * 2) because we might need to also store the shadow window
// for each dock window (Chakra shadow patch, introduced in 9cc1e2c1aa)
dock_shadow_stack = new Window[ stacking_order.count() * 2 ]; dock_shadow_stack = new Window[ stacking_order.count() * 2 ];
window_stack = new Window[ stacking_order.count() * 2 + 2 ];
// Window Stack size magic number explanation:
// -> (count * 2) because we might need to store shadow windows (see above)
// -> + 1 for supportWindow
// -> + 1 for topmenu_space
// -> + 8 for active borders
window_stack = new Window[ stacking_order.count() * 2 + 1 + 1 + 8 ];
i = 0; i = 0;
pos = 0; pos = 0;
topmenu_space_pos = 1; // not 0, that's supportWindow !!! topmenu_space_pos = 1; // not 0, that's supportWindow !!!
// Stack all windows under the support window. The support window is // Stack active windows under the support window.
// not used for anything (besides the NETWM property), and it's not shown, /* The support window is not used for anything (besides the NETWM property),
// but it was lowered after twin startup. Stacking all clients below * and it's not shown, but it was lowered after TWin startup.
// it ensures that no client will be ever shown above override-redirect * Stacking all clients below it ensures that no client will be ever shown
// windows (e.g. popups). * above override-redirect windows (e.g. popups).
#if 0 */
new_stack[ pos++ ] = supportWindow->winId(); for (int i = 0; i < ACTIVE_BORDER_COUNT; ++i)
int topmenu_space_pos = 1; // not 0, that's supportWindow !!! {
#endif if (active_windows[i] != None)
{
window_stack[pos++] = active_windows[i];
}
}
// Stack all windows under the support and active borders windows.
window_stack[pos++] = supportWindow->winId(); window_stack[pos++] = supportWindow->winId();
for( ClientList::ConstIterator it = stacking_order.fromLast(); for( ClientList::ConstIterator it = stacking_order.fromLast();
it != stacking_order.end(); it != stacking_order.end();
--it ) --it )
{ {
#if 0
new_stack[ pos++ ] = (*it)->frameId();
if( (*it)->belongsToLayer() >= DockLayer )
topmenu_space_pos = pos;
#endif
t = (*it)->windowType(); t = (*it)->windowType();
switch (t) switch (t)
{ {
@ -202,15 +209,14 @@ void Workspace::propagateClients( bool propagate_new_clients )
new_stack[ topmenu_space_pos ] = topmenu_space->winId(); new_stack[ topmenu_space_pos ] = topmenu_space->winId();
#endif #endif
window_stack[ i ] = window_stack[ i - 1 ]; window_stack[ i ] = window_stack[ i - 1 ];
window_stack[ topmenu_space_pos ] = topmenu_space->winId(); window_stack[ topmenu_space_pos ] = topmenu_space->winId();
++pos; ++pos;
} }
#if 0 #if 0
// TODO isn't it too inefficient to restart always all clients? // TODO isn't it too inefficient to restart always all clients?
// TODO don't restack not visible windows? // TODO don't restack not visible windows?
assert( new_stack[ 0 ] = supportWindow->winId()); assert( new_stack[ 0 ] = supportWindow->winId());
#endif
#if 0
XRestackWindows(tqt_xdisplay(), new_stack, pos); XRestackWindows(tqt_xdisplay(), new_stack, pos);
delete [] new_stack; delete [] new_stack;
#endif #endif

@ -31,8 +31,8 @@ namespace KWinInternal
#ifndef KCMRULES #ifndef KCMRULES
Options::Options() Options::Options()
: electric_borders( 0 ), : active_borders( 0 ),
electric_border_delay(0) active_border_delay(0)
{ {
d = new KDecorationOptionsPrivate; d = new KDecorationOptionsPrivate;
d->defaultKWinSettings(); d->defaultKWinSettings();
@ -54,6 +54,7 @@ unsigned long Options::updateSettings()
moveMode = stringToMoveResizeMode( config->readEntry("MoveMode", "Opaque" )); moveMode = stringToMoveResizeMode( config->readEntry("MoveMode", "Opaque" ));
resizeMode = stringToMoveResizeMode( config->readEntry("ResizeMode", "Opaque" )); resizeMode = stringToMoveResizeMode( config->readEntry("ResizeMode", "Opaque" ));
show_geometry_tip = config->readBoolEntry("GeometryTip", false); show_geometry_tip = config->readBoolEntry("GeometryTip", false);
reset_maximized_window_geometry = config->readBoolEntry("ResetMaximizedWindowGeometry", false);
tabboxOutline = config->readBoolEntry("TabboxOutline", true); tabboxOutline = config->readBoolEntry("TabboxOutline", true);
TQString val; TQString val;
@ -125,8 +126,16 @@ unsigned long Options::updateSettings()
borderSnapZone = config->readNumEntry("BorderSnapZone", 10); borderSnapZone = config->readNumEntry("BorderSnapZone", 10);
windowSnapZone = config->readNumEntry("WindowSnapZone", 10); windowSnapZone = config->readNumEntry("WindowSnapZone", 10);
snapOnlyWhenOverlapping=config->readBoolEntry("SnapOnlyWhenOverlapping",FALSE); snapOnlyWhenOverlapping=config->readBoolEntry("SnapOnlyWhenOverlapping",FALSE);
electric_borders = config->readNumEntry("ElectricBorders", 0);
electric_border_delay = config->readNumEntry("ElectricBorderDelay", 150); // active borders: compatibility with old option names (Electric*)
active_borders = config->readNumEntry("ActiveBorders", -1);
if (active_borders == -1) {
active_borders = config->readNumEntry("ElectricBorders", 0);
}
active_border_delay = config->readNumEntry("ActiveBorderDelay", -1);
if (active_border_delay == -1) {
active_border_delay = config->readNumEntry("ElectricBorderDelay", 150);
}
OpTitlebarDblClick = windowOperation( config->readEntry("TitlebarDoubleClickCommand", "Shade"), true ); OpTitlebarDblClick = windowOperation( config->readEntry("TitlebarDoubleClickCommand", "Shade"), true );
d->OpMaxButtonLeftClick = windowOperation( config->readEntry("MaximizeButtonLeftClickCommand", "Maximize"), true ); d->OpMaxButtonLeftClick = windowOperation( config->readEntry("MaximizeButtonLeftClickCommand", "Maximize"), true );
@ -308,6 +317,11 @@ bool Options::showGeometryTip()
return show_geometry_tip; return show_geometry_tip;
} }
bool Options::resetMaximizedWindowGeometry()
{
return reset_maximized_window_geometry;
}
TQColor &Options::shadowColour(bool active) TQColor &Options::shadowColour(bool active)
{ {
return active ? shadow_colour : shadow_inactive_colour; return active ? shadow_colour : shadow_inactive_colour;
@ -373,14 +387,14 @@ int Options::shadowYOffset(bool active)
return active ? shadow_y_offset : shadow_inactive_y_offset; return active ? shadow_y_offset : shadow_inactive_y_offset;
} }
int Options::electricBorders() int Options::activeBorders()
{ {
return electric_borders; return active_borders;
} }
int Options::electricBorderDelay() int Options::activeBorderDelay()
{ {
return electric_border_delay; return active_border_delay;
} }
bool Options::checkIgnoreFocusStealing( const Client* c ) bool Options::checkIgnoreFocusStealing( const Client* c )

@ -268,6 +268,13 @@ class Options : public KDecorationOptions
*/ */
bool showGeometryTip(); bool showGeometryTip();
/**
* @returns true if a maximized or tiled window should be reset to its original
* size when dragging it.
* @since R14.1.1
*/
bool resetMaximizedWindowGeometry();
/** /**
* @returns A TQColor representing the colour that window drop shadows should * @returns A TQColor representing the colour that window drop shadows should
* be. * be.
@ -307,18 +314,22 @@ class Options : public KDecorationOptions
*/ */
int shadowYOffset(bool active=true); int shadowYOffset(bool active=true);
enum { ElectricDisabled = 0, ElectricMoveOnly = 1, ElectricAlways = 2 }; enum { ActiveDisabled = 0,
ActiveSwitchOnMove = 1,
ActiveSwitchAlways = 2,
ActiveTileOnly = 3,
ActiveTileMaximize = 4 };
/** /**
* @returns true if electric borders are enabled. With electric borders * @returns true if active borders are enabled. With active borders
* you can change desktop by moving the mouse pointer towards the edge * you can change desktop by moving the mouse pointer towards the edge
* of the screen * of the screen
*/ */
int electricBorders(); int activeBorders();
/** /**
* @returns the activation delay for electric borders in milliseconds. * @returns the activation delay for active borders in milliseconds.
*/ */
int electricBorderDelay(); int activeBorderDelay();
bool topMenuEnabled() const { return topmenus; } bool topMenuEnabled() const { return topmenus; }
bool desktopTopMenu() const { return desktop_topmenu; } bool desktopTopMenu() const { return desktop_topmenu; }
@ -373,9 +384,10 @@ class Options : public KDecorationOptions
bool CmdAllRevWheel; bool CmdAllRevWheel;
uint CmdAllModKey; uint CmdAllModKey;
int electric_borders; int active_borders;
int electric_border_delay; int active_border_delay;
bool show_geometry_tip; bool show_geometry_tip;
bool reset_maximized_window_geometry;
bool topmenus; bool topmenus;
bool desktop_topmenu; bool desktop_topmenu;
TQColor shadow_colour; TQColor shadow_colour;

@ -108,6 +108,29 @@ enum ShadeMode
ShadeActivated // "shaded", but visible due to alt+tab to the window ShadeActivated // "shaded", but visible due to alt+tab to the window
}; };
enum ActiveBorder
{
ActiveTop,
ActiveTopRight,
ActiveRight,
ActiveBottomRight,
ActiveBottom,
ActiveBottomLeft,
ActiveLeft,
ActiveTopLeft,
ACTIVE_BORDER_COUNT,
ActiveNone
};
enum ActiveMaximizingMode
{
ActiveMaximizeMode,
ActiveLeftMode,
ActiveRightMode,
ActiveTopMode,
ActiveBottomMode
};
class Shape class Shape
{ {
public: public:

@ -167,12 +167,7 @@ Workspace::Workspace( bool restore )
global_shortcuts_disabled_for_client( false ), global_shortcuts_disabled_for_client( false ),
root (0), root (0),
workspaceInit (true), workspaceInit (true),
startup(0), electric_have_borders(false), startup(0),
electric_current_border(0),
electric_top_border(None),
electric_bottom_border(None),
electric_left_border(None),
electric_right_border(None),
layoutOrientation(Qt::Vertical), layoutOrientation(Qt::Vertical),
layoutX(-1), layoutX(-1),
layoutY(2), layoutY(2),
@ -194,6 +189,12 @@ Workspace::Workspace( bool restore )
installed_colormap = default_colormap; installed_colormap = default_colormap;
session.setAutoDelete( TRUE ); session.setAutoDelete( TRUE );
for (int i = 0; i < ACTIVE_BORDER_COUNT; ++i)
{
active_reserved[i] = 0;
active_windows[i] = None;
}
connect( &temporaryRulesMessages, TQT_SIGNAL( gotMessage( const TQString& )), connect( &temporaryRulesMessages, TQT_SIGNAL( gotMessage( const TQString& )),
this, TQT_SLOT( gotTemporaryRulesMessage( const TQString& ))); this, TQT_SLOT( gotTemporaryRulesMessage( const TQString& )));
connect( &rulesUpdatedTimer, TQT_SIGNAL( timeout()), this, TQT_SLOT( writeWindowRules())); connect( &rulesUpdatedTimer, TQT_SIGNAL( timeout()), this, TQT_SLOT( writeWindowRules()));
@ -202,8 +203,8 @@ Workspace::Workspace( bool restore )
delayFocusTimer = 0; delayFocusTimer = 0;
electric_time_first = GET_QT_X_TIME(); active_time_first = GET_QT_X_TIME();
electric_time_last = GET_QT_X_TIME(); active_time_last = GET_QT_X_TIME();
if ( restore ) if ( restore )
loadSessionInfo(); loadSessionInfo();
@ -304,8 +305,12 @@ Workspace::Workspace( bool restore )
void Workspace::init() void Workspace::init()
{
if (options->activeBorders() == Options::ActiveSwitchAlways)
{ {
checkElectricBorders(); reserveActiveBorderSwitching(true);
}
updateActiveBorders();
// not used yet // not used yet
// topDock = 0L; // topDock = 0L;
@ -483,7 +488,6 @@ void Workspace::init()
updateStackingOrder( true ); updateStackingOrder( true );
updateClientArea(); updateClientArea();
raiseElectricBorders();
// NETWM spec says we have to set it to (0,0) if we don't support it // NETWM spec says we have to set it to (0,0) if we don't support it
NETPoint* viewports = new NETPoint[ number_of_desktops ]; NETPoint* viewports = new NETPoint[ number_of_desktops ];
@ -514,12 +518,27 @@ void Workspace::init()
} }
if( new_active_client != NULL ) if( new_active_client != NULL )
activateClient( new_active_client ); activateClient( new_active_client );
// outline windows for active border maximize window mode
outline_left = XCreateWindow(tqt_xdisplay(), rootWin(), 0, 0, 1, 1, 0,
CopyFromParent, CopyFromParent, CopyFromParent,
CWOverrideRedirect, &attr);
outline_right = XCreateWindow(tqt_xdisplay(), rootWin(), 0, 0, 1, 1, 0,
CopyFromParent, CopyFromParent, CopyFromParent,
CWOverrideRedirect, &attr);
outline_top = XCreateWindow(tqt_xdisplay(), rootWin(), 0, 0, 1, 1, 0,
CopyFromParent, CopyFromParent, CopyFromParent,
CWOverrideRedirect, &attr);
outline_bottom = XCreateWindow(tqt_xdisplay(), rootWin(), 0, 0, 1, 1, 0,
CopyFromParent, CopyFromParent, CopyFromParent,
CWOverrideRedirect, &attr);
// SELI TODO this won't work with unreasonable focus policies, // SELI TODO this won't work with unreasonable focus policies,
// and maybe in rare cases also if the selected client doesn't // and maybe in rare cases also if the selected client doesn't
// want focus // want focus
workspaceInit = false; workspaceInit = false;
// TODO ungrabXServer() // TODO ungrabXServer()
} }
Workspace::~Workspace() Workspace::~Workspace()
{ {
@ -550,6 +569,12 @@ Workspace::~Workspace()
writeWindowRules(); writeWindowRules();
TDEGlobal::config()->sync(); TDEGlobal::config()->sync();
// destroy outline windows for active border maximize window mode
XDestroyWindow(tqt_xdisplay(), outline_left);
XDestroyWindow(tqt_xdisplay(), outline_right);
XDestroyWindow(tqt_xdisplay(), outline_top);
XDestroyWindow(tqt_xdisplay(), outline_bottom);
delete rootInfo; delete rootInfo;
delete supportWindow; delete supportWindow;
delete mgr; delete mgr;
@ -1038,6 +1063,11 @@ void Workspace::slotReconfigure()
kdDebug(1212) << "Workspace::slotReconfigure()" << endl; kdDebug(1212) << "Workspace::slotReconfigure()" << endl;
reconfigureTimer.stop(); reconfigureTimer.stop();
if (options->activeBorders() == Options::ActiveSwitchAlways)
{
reserveActiveBorderSwitching(false);
}
TDEGlobal::config()->reparseConfiguration(); TDEGlobal::config()->reparseConfiguration();
unsigned long changed = options->updateSettings(); unsigned long changed = options->updateSettings();
tab_box->reconfigure(); tab_box->reconfigure();
@ -1068,7 +1098,10 @@ void Workspace::slotReconfigure()
forEachClient( CheckBorderSizesProcedure()); forEachClient( CheckBorderSizesProcedure());
} }
checkElectricBorders(); if (options->activeBorders() == Options::ActiveSwitchAlways)
{
reserveActiveBorderSwitching(true);
}
if( options->topMenuEnabled() && !managingTopMenus()) if( options->topMenuEnabled() && !managingTopMenus())
{ {
@ -2357,7 +2390,7 @@ void Workspace::delayFocus()
requestFocus( delayfocus_client ); requestFocus( delayfocus_client );
cancelDelayFocus(); cancelDelayFocus();
} }
void Workspace::requestDelayFocus( Client* c ) void Workspace::requestDelayFocus( Client* c )
{ {
delayfocus_client = c; delayfocus_client = c;
@ -2366,283 +2399,353 @@ void Workspace::requestDelayFocus( Client* c )
connect( delayFocusTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( delayFocus() ) ); connect( delayFocusTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( delayFocus() ) );
delayFocusTimer->start( options->delayFocusInterval, TRUE ); delayFocusTimer->start( options->delayFocusInterval, TRUE );
} }
void Workspace::cancelDelayFocus() void Workspace::cancelDelayFocus()
{ {
delete delayFocusTimer; delete delayFocusTimer;
delayFocusTimer = 0; delayFocusTimer = 0;
} }
// Electric Borders /* Active (Electric) Borders
//========================================================================// * ========================================================================
// Electric Border Window management. Electric borders allow a user * Active Border Window management. Active borders allow a user to switch
// to change the virtual desktop by moving the mouse pointer to the * to another virtual desktop or activate other features by moving
// borders. Technically this is done with input only windows. Since * the mouse pointer to the borders or corners of the workspace.
// electric borders can be switched on and off, we have these two * Technically this is done with input only windows.
// functions to create and destroy them. */
void Workspace::checkElectricBorders( bool force ) void Workspace::updateActiveBorders()
{ {
if( force ) active_time_first = GET_QT_X_TIME();
destroyBorderWindows(); active_time_last = GET_QT_X_TIME();
active_time_last_trigger = GET_QT_X_TIME();
electric_current_border = 0; active_current_border = ActiveNone;
TQRect r = TQApplication::desktop()->geometry(); TQRect r = TQApplication::desktop()->geometry();
electricTop = r.top(); activeTop = r.top();
electricBottom = r.bottom(); activeBottom = r.bottom();
electricLeft = r.left(); activeLeft = r.left();
electricRight = r.right(); activeRight = r.right();
if (options->electricBorders() == Options::ElectricAlways) for (int pos = 0; pos < ACTIVE_BORDER_COUNT; ++pos)
createBorderWindows(); {
else if (active_reserved[pos] == 0)
destroyBorderWindows(); {
if (active_windows[pos] != None)
{
XDestroyWindow( tqt_xdisplay(), active_windows[pos] );
}
active_windows[pos] = None;
continue;
}
if (active_windows[pos] != None)
{
continue;
}
XSetWindowAttributes attributes;
attributes.override_redirect = True;
attributes.event_mask = EnterWindowMask;
unsigned long valuemask = CWOverrideRedirect | CWEventMask;
int xywh[ ACTIVE_BORDER_COUNT ][ 4 ] =
{
{ r.left() + 1, r.top(), r.width() - 2, 1 }, // top
{ r.right(), r.top(), 1, 1 }, // topright
{ r.right(), r.top() + 1, 1, r.height() - 2 }, // etc.
{ r.right(), r.bottom(), 1, 1 },
{ r.left() + 1, r.bottom(), r.width() - 2, 1 },
{ r.left(), r.bottom(), 1, 1 },
{ r.left(), r.top() + 1, 1, r.height() - 2 },
{ r.left(), r.top(), 1, 1 }
};
active_windows[pos] = XCreateWindow(tqt_xdisplay(), tqt_xrootwin(),
xywh[pos][0], xywh[pos][1],
xywh[pos][2], xywh[pos][3],
0, CopyFromParent, InputOnly,
CopyFromParent, valuemask,
&attributes);
XMapWindow(tqt_xdisplay(), active_windows[pos]);
// Set XdndAware on the windows, so that DND enter events are received (#86998)
Atom version = 4; // XDND version
XChangeProperty(tqt_xdisplay(), active_windows[pos],
atoms->xdnd_aware, XA_ATOM, 32, PropModeReplace,
(unsigned char*)&version, 1);
} }
}
void Workspace::createBorderWindows() void Workspace::destroyActiveBorders()
{
for (int pos = 0; pos < ACTIVE_BORDER_COUNT; ++pos)
{ {
if ( electric_have_borders ) if (active_windows[ pos ] != None)
{
XDestroyWindow( tqt_xdisplay(), active_windows[ pos ] );
}
active_windows[ pos ] = None;
}
}
void Workspace::reserveActiveBorderSwitching( bool reserve )
{
for (int pos = 0; pos < ACTIVE_BORDER_COUNT; ++pos)
{
if (reserve)
{
reserveActiveBorder(static_cast<ActiveBorder>(pos));
}
else
{
unreserveActiveBorder(static_cast<ActiveBorder>(pos));
}
}
}
void Workspace::reserveActiveBorder( ActiveBorder border )
{
if (border == ActiveNone)
return; return;
electric_have_borders = true; if (active_reserved[border]++ == 0)
TQTimer::singleShot(0, this, TQT_SLOT(updateActiveBorders()));
}
TQRect r = TQApplication::desktop()->geometry(); void Workspace::unreserveActiveBorder( ActiveBorder border )
XSetWindowAttributes attributes; {
unsigned long valuemask; if (border == ActiveNone)
attributes.override_redirect = True; return;
attributes.event_mask = ( EnterWindowMask | LeaveWindowMask );
valuemask= (CWOverrideRedirect | CWEventMask | CWCursor );
attributes.cursor = XCreateFontCursor(tqt_xdisplay(),
XC_sb_up_arrow);
electric_top_border = XCreateWindow (tqt_xdisplay(), tqt_xrootwin(),
0,0,
r.width(),1,
0,
CopyFromParent, InputOnly,
CopyFromParent,
valuemask, &attributes);
XMapWindow(tqt_xdisplay(), electric_top_border);
attributes.cursor = XCreateFontCursor(tqt_xdisplay(),
XC_sb_down_arrow);
electric_bottom_border = XCreateWindow (tqt_xdisplay(), tqt_xrootwin(),
0,r.height()-1,
r.width(),1,
0,
CopyFromParent, InputOnly,
CopyFromParent,
valuemask, &attributes);
XMapWindow(tqt_xdisplay(), electric_bottom_border);
attributes.cursor = XCreateFontCursor(tqt_xdisplay(),
XC_sb_left_arrow);
electric_left_border = XCreateWindow (tqt_xdisplay(), tqt_xrootwin(),
0,0,
1,r.height(),
0,
CopyFromParent, InputOnly,
CopyFromParent,
valuemask, &attributes);
XMapWindow(tqt_xdisplay(), electric_left_border);
attributes.cursor = XCreateFontCursor(tqt_xdisplay(),
XC_sb_right_arrow);
electric_right_border = XCreateWindow (tqt_xdisplay(), tqt_xrootwin(),
r.width()-1,0,
1,r.height(),
0,
CopyFromParent, InputOnly,
CopyFromParent,
valuemask, &attributes);
XMapWindow(tqt_xdisplay(), electric_right_border);
// Set XdndAware on the windows, so that DND enter events are received (#86998)
Atom version = 4; // XDND version
XChangeProperty( tqt_xdisplay(), electric_top_border, atoms->xdnd_aware, XA_ATOM,
32, PropModeReplace, ( unsigned char* )&version, 1 );
XChangeProperty( tqt_xdisplay(), electric_bottom_border, atoms->xdnd_aware, XA_ATOM,
32, PropModeReplace, ( unsigned char* )&version, 1 );
XChangeProperty( tqt_xdisplay(), electric_left_border, atoms->xdnd_aware, XA_ATOM,
32, PropModeReplace, ( unsigned char* )&version, 1 );
XChangeProperty( tqt_xdisplay(), electric_right_border, atoms->xdnd_aware, XA_ATOM,
32, PropModeReplace, ( unsigned char* )&version, 1 );
}
// Electric Border Window management. Electric borders allow a user
// to change the virtual desktop by moving the mouse pointer to the
// borders. Technically this is done with input only windows. Since
// electric borders can be switched on and off, we have these two
// functions to create and destroy them.
void Workspace::destroyBorderWindows()
{
if( !electric_have_borders)
return;
electric_have_borders = false;
if(electric_top_border)
XDestroyWindow(tqt_xdisplay(),electric_top_border);
if(electric_bottom_border)
XDestroyWindow(tqt_xdisplay(),electric_bottom_border);
if(electric_left_border)
XDestroyWindow(tqt_xdisplay(),electric_left_border);
if(electric_right_border)
XDestroyWindow(tqt_xdisplay(),electric_right_border);
electric_top_border = None;
electric_bottom_border = None;
electric_left_border = None;
electric_right_border = None;
}
void Workspace::clientMoved(const TQPoint &pos, Time now)
{
if (options->electricBorders() == Options::ElectricDisabled)
return;
if ((pos.x() != electricLeft) && assert(active_reserved[ border ] > 0);
(pos.x() != electricRight) && if (--active_reserved[ border ] == 0)
(pos.y() != electricTop) && TQTimer::singleShot(0, this, TQT_SLOT(updateActiveBorders()));
(pos.y() != electricBottom)) }
return;
Time treshold_set = options->electricBorderDelay(); // set timeout 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 Time treshold_reset = 250; // reset timeout
int distance_reset = 30; // Mouse should not move more than this many pixels int distance_reset = 30; // Mouse should not move more than this many pixels
int border = 0; if ((pos.x() > activeLeft + distance_reset) &&
if (pos.x() == electricLeft) (pos.x() < activeRight - distance_reset) &&
border = 1; (pos.y() > activeTop + distance_reset) &&
else if (pos.x() == electricRight) (pos.y() < activeBottom - distance_reset))
border = 2; {
else if (pos.y() == electricTop) if (movingClient &&
border = 3; (options->activeBorders() == Options::ActiveTileMaximize ||
else if (pos.y() == electricBottom) options->activeBorders() == Options::ActiveTileOnly))
border = 4; {
movingClient->setActiveBorderMaximizing(false);
}
}
if ((electric_current_border == border) && if ((pos.x() != activeLeft) &&
(timestampDiff(electric_time_last, now) < treshold_reset) && (pos.x() != activeRight) &&
((pos-electric_push_point).manhattanLength() < distance_reset)) (pos.y() != activeTop) &&
(pos.y() != activeBottom))
return;
bool have_borders = false;
for (int i = 0; i < ACTIVE_BORDER_COUNT; ++i)
{
if (active_windows[ i ] != None)
{ {
electric_time_last = now; have_borders = true;
}
}
if( !have_borders )
return;
ActiveBorder border;
if( pos.x() == activeLeft && pos.y() == activeTop )
border = ActiveTopLeft;
else if( pos.x() == activeRight && pos.y() == activeTop )
border = ActiveTopRight;
else if( pos.x() == activeLeft && pos.y() == activeBottom )
border = ActiveBottomLeft;
else if( pos.x() == activeRight && pos.y() == activeBottom )
border = ActiveBottomRight;
else if( pos.x() == activeLeft )
border = ActiveLeft;
else if( pos.x() == activeRight )
border = ActiveRight;
else if( pos.y() == activeTop )
border = ActiveTop;
else if( pos.y() == activeBottom )
border = ActiveBottom;
else
abort();
if (timestampDiff(electric_time_first, now) > treshold_set) if( active_windows[border] == None )
return;
if ((active_current_border == border) &&
(timestampDiff(active_time_last, now) < treshold_reset) &&
(timestampDiff(active_time_last_trigger, now) > treshold_trigger) &&
((pos-active_push_point).manhattanLength() < distance_reset))
{
active_time_last = now;
if (timestampDiff(active_time_first, now) > treshold_set)
{
active_time_last_trigger = now;
active_current_border = ActiveNone;
bool isSide = (border == ActiveTop || border == ActiveRight ||
border == ActiveBottom || border == ActiveLeft);
if (movingClient)
{ {
electric_current_border = 0; // Desktop switching
if (options->activeBorders() == Options::ActiveSwitchAlways ||
options->activeBorders() == Options::ActiveSwitchOnMove)
{
activeBorderSwitchDesktop(border, pos);
return; // Don't reset cursor position
}
TQRect r = TQApplication::desktop()->geometry(); // Tiling maximize
int offset; else if (options->activeBorders() == Options::ActiveTileMaximize &&
border == ActiveTop && movingClient->isMaximizable())
{
if (!movingClient->isResizable()) return;
bool enable = !movingClient->isActiveBorderMaximizing();
movingClient->setActiveBorderMode(ActiveMaximizeMode);
movingClient->setActiveBorderMaximizing(enable);
}
int desk_before = currentDesktop(); // Tiling
switch(border) else if ((options->activeBorders() == Options::ActiveTileMaximize ||
options->activeBorders() == Options::ActiveTileOnly) && isSide)
{ {
case 1: if (!movingClient->isResizable()) return;
slotSwitchDesktopLeft(); bool enable = !movingClient->isActiveBorderMaximizing();
if (currentDesktop() != desk_before) bool activate = false;
if (border == ActiveLeft)
{ {
offset = r.width() / 5; movingClient->setActiveBorderMode( ActiveLeftMode );
TQCursor::setPos(r.width() - offset, pos.y()); activate = true;
} }
break; else if (border == ActiveRight)
case 2:
slotSwitchDesktopRight();
if (currentDesktop() != desk_before)
{ {
offset = r.width() / 5; movingClient->setActiveBorderMode( ActiveRightMode );
TQCursor::setPos(offset, pos.y()); activate = true;
} }
break; else if (border == ActiveTop)
case 3:
slotSwitchDesktopUp();
if (currentDesktop() != desk_before)
{ {
offset = r.height() / 5; movingClient->setActiveBorderMode( ActiveTopMode );
TQCursor::setPos(pos.x(), r.height() - offset); activate = true;
}
else if (border == ActiveBottom)
{
movingClient->setActiveBorderMode( ActiveBottomMode );
activate = true;
} }
break;
case 4: if (activate)
slotSwitchDesktopDown();
if (currentDesktop() != desk_before)
{ {
offset = r.height() / 5; movingClient->setActiveBorderMaximizing(enable);
TQCursor::setPos(pos.x(), offset);
} }
break;
} }
return;
else
{
return; // Don't reset cursor position
}
}
else
{
// Desktop switching
if (options->activeBorders() == Options::ActiveSwitchAlways && isSide)
{
activeBorderSwitchDesktop(border, pos);
return; // Don't reset cursor position
}
} }
} }
else }
{ else
electric_current_border = border; {
electric_time_first = now; active_current_border = border;
electric_time_last = now; active_time_first = now;
electric_push_point = pos; active_time_last = now;
} active_push_point = pos;
}
int mouse_warp = 1; // 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]);
// reset the pointer to find out wether the user is really pushing
switch( border)
{
case 1: TQCursor::setPos(pos.x()+mouse_warp, pos.y()); break;
case 2: TQCursor::setPos(pos.x()-mouse_warp, pos.y()); break;
case 3: TQCursor::setPos(pos.x(), pos.y()+mouse_warp); break;
case 4: TQCursor::setPos(pos.x(), pos.y()-mouse_warp); break;
}
} }
// this function is called when the user entered an electric border void Workspace::activeBorderSwitchDesktop(ActiveBorder border, const TQPoint& _pos)
{
TQPoint pos = _pos;
TQRect r = TQApplication::desktop()->geometry();
const int offset = 5;
int desk_before = currentDesktop();
if (border == ActiveLeft || border == ActiveTopLeft || border == ActiveBottomLeft)
{
slotSwitchDesktopLeft();
pos.setX(r.width() - offset);
}
if (border == ActiveRight || border == ActiveTopRight || border == ActiveBottomRight)
{
slotSwitchDesktopRight();
pos.setX(offset);
}
if (border == ActiveTop || border == ActiveTopLeft || border == ActiveTopRight)
{
slotSwitchDesktopUp();
pos.setY(r.height() - offset);
}
if (border == ActiveBottom || border == ActiveBottomLeft || border == ActiveBottomRight)
{
slotSwitchDesktopDown();
pos.setY(offset);
}
if (currentDesktop() != desk_before)
{
TQCursor::setPos(pos);
}
}
// this function is called when the user entered an active border
// with the mouse. It may switch to another virtual desktop // with the mouse. It may switch to another virtual desktop
bool Workspace::electricBorder(XEvent *e) bool Workspace::activeBorderEvent(XEvent *e)
{
if (e->type == EnterNotify)
{ {
if( !electric_have_borders ) for (int i = 0; i < ACTIVE_BORDER_COUNT; ++i)
return false;
if( e->type == EnterNotify )
{ {
if( e->xcrossing.window == electric_top_border || if (active_windows[i] != None && e->xcrossing.window == active_windows[i])
e->xcrossing.window == electric_left_border || { // the user entered an active border
e->xcrossing.window == electric_bottom_border || checkActiveBorder(TQPoint(e->xcrossing.x_root, e->xcrossing.y_root), e->xcrossing.time);
e->xcrossing.window == electric_right_border) return true;
// the user entered an electric border
{
clientMoved( TQPoint( e->xcrossing.x_root, e->xcrossing.y_root ), e->xcrossing.time );
return true;
} }
} }
if( e->type == ClientMessage )
{
if( e->xclient.message_type == atoms->xdnd_position
&& ( e->xclient.window == electric_top_border
|| e->xclient.window == electric_bottom_border
|| e->xclient.window == electric_left_border
|| e->xclient.window == electric_right_border ))
{
updateXTime();
clientMoved( TQPoint( e->xclient.data.l[2]>>16, e->xclient.data.l[2]&0xffff), GET_QT_X_TIME() );
return true;
}
}
return false;
} }
if (e->type == ClientMessage)
// electric borders (input only windows) have to be always on the
// top. For that reason kwm calls this function always after some
// windows have been raised.
void Workspace::raiseElectricBorders()
{ {
if (e->xclient.message_type == atoms->xdnd_position)
if(electric_have_borders)
{ {
XRaiseWindow(tqt_xdisplay(), electric_top_border); for (int i = 0; i < ACTIVE_BORDER_COUNT; ++i)
XRaiseWindow(tqt_xdisplay(), electric_left_border); {
XRaiseWindow(tqt_xdisplay(), electric_bottom_border); if (active_windows[i] != None && e->xclient.window == active_windows[i])
XRaiseWindow(tqt_xdisplay(), electric_right_border); {
updateXTime();
checkActiveBorder(TQPoint(e->xclient.data.l[2]>>16, e->xclient.data.l[2]&0xffff), GET_QT_X_TIME());
return true;
}
}
} }
} }
return false;
}
void Workspace::addTopMenu( Client* c ) void Workspace::addTopMenu( Client* c )
{ {

@ -156,7 +156,10 @@ class Workspace : public TQObject, public KWinInterface, public KDecorationDefin
void clientHidden( Client* ); void clientHidden( Client* );
void clientAttentionChanged( Client* c, bool set ); void clientAttentionChanged( Client* c, bool set );
void clientMoved(const TQPoint &pos, Time time); void checkActiveBorder(const TQPoint &pos, Time time);
void reserveActiveBorder(ActiveBorder border);
void unreserveActiveBorder(ActiveBorder border);
void reserveActiveBorderSwitching(bool reserve);
/** /**
* Returns the current virtual desktop of this workspace * Returns the current virtual desktop of this workspace
@ -302,7 +305,7 @@ class Workspace : public TQObject, public KWinInterface, public KDecorationDefin
void requestDelayFocus( Client* ); void requestDelayFocus( Client* );
void updateFocusMousePosition( const TQPoint& pos ); void updateFocusMousePosition( const TQPoint& pos );
TQPoint focusMousePosition() const; TQPoint focusMousePosition() const;
void toggleTopDockShadows(bool on); void toggleTopDockShadows(bool on);
public slots: public slots:
@ -406,6 +409,7 @@ class Workspace : public TQObject, public KWinInterface, public KDecorationDefin
void cleanupTemporaryRules(); void cleanupTemporaryRules();
void writeWindowRules(); void writeWindowRules();
void kipcMessage( int id, int data ); void kipcMessage( int id, int data );
void updateActiveBorders();
// kompmgr // kompmgr
void setPopupClientOpacity(int v); void setPopupClientOpacity(int v);
void resetClientOpacity(); void resetClientOpacity();
@ -486,12 +490,10 @@ class Workspace : public TQObject, public KWinInterface, public KDecorationDefin
void tabBoxKeyPress( const KKeyNative& keyX ); void tabBoxKeyPress( const KKeyNative& keyX );
void tabBoxKeyRelease( const XKeyEvent& ev ); void tabBoxKeyRelease( const XKeyEvent& ev );
// electric borders // active borders
void checkElectricBorders( bool force = false ); void destroyActiveBorders();
void createBorderWindows(); bool activeBorderEvent(XEvent *e);
void destroyBorderWindows(); void activeBorderSwitchDesktop(ActiveBorder border, const TQPoint& pos);
bool electricBorder(XEvent * e);
void raiseElectricBorders();
// ------------------ // ------------------
@ -617,19 +619,17 @@ class Workspace : public TQObject, public KWinInterface, public KDecorationDefin
TDEStartupInfo* startup; TDEStartupInfo* startup;
bool electric_have_borders; ActiveBorder active_current_border;
int electric_current_border; Window active_windows[ ACTIVE_BORDER_COUNT ];
WId electric_top_border; int activeLeft;
WId electric_bottom_border; int activeRight;
WId electric_left_border; int activeTop;
WId electric_right_border; int activeBottom;
int electricLeft; Time active_time_first;
int electricRight; Time active_time_last;
int electricTop; Time active_time_last_trigger;
int electricBottom; TQPoint active_push_point;
Time electric_time_first; int active_reserved[ ACTIVE_BORDER_COUNT ]; // corners/edges used by something
Time electric_time_last;
TQPoint electric_push_point;
Qt::Orientation layoutOrientation; Qt::Orientation layoutOrientation;
int layoutX; int layoutX;
@ -663,7 +663,11 @@ class Workspace : public TQObject, public KWinInterface, public KDecorationDefin
int maximizedWindowCounter; int maximizedWindowCounter;
int topDockShadowSize;*/ int topDockShadowSize;*/
//end //end
Window outline_left;
Window outline_right;
Window outline_top;
Window outline_bottom;
signals: signals:
void kompmgrStarted(); void kompmgrStarted();
void kompmgrStopped(); void kompmgrStopped();

Loading…
Cancel
Save