[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kwin
Subject:    [Review Request] Maximizing windows on screen edge
From:       Martin =?utf-8?q?Gr=C3=A4=C3=9Flin?= <kde () martin-graesslin ! com>
Date:       2009-08-30 20:23:51
Message-ID: 200908302224.09581.kde () martin-graesslin ! com
[Download RAW message or body]

[Attachment #2 (multipart/signed)]

[Attachment #4 (multipart/mixed)]


Attached is a patch which implements "Aero snap" for kwin. I'm still totally 
unsure if we should have such a feature or not. Personally I think it's 
completely useless, but it could help people switching from Win7 to KDE. So 
that could be a pro.

For those who don't know the feature, when moving a window to an edge it will:
 * take half of the left screen at left screen edge
 * take half of the right screen at right screen edge
 * maximize the window at the top screen edge

The good thing is, that this is a kind of quick tiling. You can easily set two 
windows next to each other so that they don't overlap.

["screen-edge-maximizing.diff" (text/x-patch)]

diff --git a/client.cpp b/client.cpp
index ce6cb8c..20f22f9 100644
--- a/client.cpp
+++ b/client.cpp
@@ -121,6 +121,7 @@ Client::Client( Workspace* ws )
     , padding_right( 0 )
     , padding_top( 0 )
     , padding_bottom( 0 )
+    , electricMaximizing( false )
     { // TODO: Do all as initialization
 
     // Set the initial mapping state
diff --git a/client.h b/client.h
index fa5dc47..5ae24aa 100644
--- a/client.h
+++ b/client.h
@@ -218,6 +218,11 @@ class Client
         void resizeWithChecks( int w, int h, ForceGeometry_t force = \
                NormalGeometrySet );
         void resizeWithChecks( const QSize& s, ForceGeometry_t force = \
NormalGeometrySet );  void keepInArea( QRect area, bool partial = false );
+        void setElectricBorderMode( ElectricMaximizingMode mode );
+        ElectricMaximizingMode electricBorderMode() const;
+        void setElectricBorderMaximizing( bool maximizing );
+        bool isElectricBorderMaximizing() const;
+        QRect electricBorderMaximizeGeometry();
 
         void growHorizontal();
         void shrinkHorizontal();
@@ -582,6 +587,9 @@ class Client
         QPixmap decorationPixmapLeft, decorationPixmapRight, decorationPixmapTop, \
decorationPixmapBottom;  PaintRedirector* paintRedirector;
 
+        bool electricMaximizing;
+        ElectricMaximizingMode electricMode;
+
         friend bool performTransiencyCheck();
     };
 
diff --git a/geometry.cpp b/geometry.cpp
index c4cc4f2..cfe383d 100644
--- a/geometry.cpp
+++ b/geometry.cpp
@@ -2709,7 +2709,7 @@ bool Client::startMoveResize()
     Notify::raise( isResize() ? Notify::ResizeStart : Notify::MoveStart );
     if( effects )
         static_cast<EffectsHandlerImpl*>(effects)->windowUserMovedResized( \
                effectWindow(), true, false );
-    if( options->electricBorders() == Options::ElectricMoveOnly )
+    if( options->electricBorders() == Options::ElectricMoveOnly || \
options->electricBorderMaximize() )  workspace()->reserveElectricBorderSwitching( \
true );  return true;
     }
@@ -2717,10 +2717,37 @@ bool Client::startMoveResize()
 void Client::finishMoveResize( bool cancel )
     {
     leaveMoveResize();
+    if( isElectricBorderMaximizing() )
+        {
+        cancel = true;
+        }
     if( cancel )
         setGeometry( initialMoveResizeGeom );
     else
         setGeometry( moveResizeGeom );
+    if( isElectricBorderMaximizing() )
+        {
+        electricMaximizing = false;
+        switch( electricMode )
+            {
+            case ElectricMaximizeMode:
+                setMaximize( true, true );
+                break;
+            case ElectricLeftMode:
+                {
+                QRect max = workspace()->clientArea( MaximizeArea, cursorPos() \
,workspace()->currentDesktop() ); +                setGeometry( QRect( max.x(), \
max.y(), max.width()/2, max.height() ) ); +                break;
+                }
+            case ElectricRightMode:
+                {
+                QRect max = workspace()->clientArea( MaximizeArea, cursorPos() \
,workspace()->currentDesktop() ); +                setGeometry( QRect( max.x() + \
max.width()/2, max.y(), max.width()/2, max.height() ) ); +                break;
+                }
+            }
+        workspace()->hideElectricBorderWindowOutline();
+        }
     checkMaximizeGeometry();
 // FRAME    update();
     Notify::raise( isResize() ? Notify::ResizeEnd : Notify::MoveEnd );
@@ -2755,7 +2782,7 @@ void Client::leaveMoveResize()
     eater = 0;
     delete sync_timeout;
     sync_timeout = NULL;
-    if( options->electricBorders() == Options::ElectricMoveOnly )
+    if( options->electricBorders() == Options::ElectricMoveOnly || \
options->electricBorderMaximize() )  workspace()->reserveElectricBorderSwitching( \
false );  }
 
@@ -3094,6 +3121,8 @@ void Client::handleMoveResize( int x, int y, int x_root, int \
y_root )  
 void Client::performMoveResize()
     {
+    if( isElectricBorderMaximizing() )
+        return;
 #ifdef HAVE_XSYNC
     if( isResize() && sync_counter != None )
         {
@@ -3130,4 +3159,52 @@ void Client::syncTimeout()
         performMoveResize();
     }
 
+void Client::setElectricBorderMode( ElectricMaximizingMode mode )
+    {
+    electricMode = mode;
+    }
+
+ElectricMaximizingMode Client::electricBorderMode() const
+    {
+    return electricMode;
+    }
+
+bool Client::isElectricBorderMaximizing() const
+    {
+    return electricMaximizing;
+    }
+
+void Client::setElectricBorderMaximizing( bool maximizing )
+    {
+    electricMaximizing = maximizing;
+    if( maximizing )
+        workspace()->showElectricBorderWindowOutline();
+    else
+        workspace()->hideElectricBorderWindowOutline();
+    }
+
+QRect Client::electricBorderMaximizeGeometry()
+    {
+    QRect ret;
+    switch( electricMode )
+        {
+        case ElectricMaximizeMode:
+            ret = workspace()->clientArea( MaximizeArea, cursorPos() \
,workspace()->currentDesktop() ); +            break;
+        case ElectricLeftMode:
+            {
+            QRect max = workspace()->clientArea( MaximizeArea, cursorPos() \
,workspace()->currentDesktop() ); +            ret = QRect( max.x(), max.y(), \
max.width()/2, max.height() ); +            break;
+            }
+        case ElectricRightMode:
+            {
+            QRect max = workspace()->clientArea( MaximizeArea, cursorPos() \
,workspace()->currentDesktop() ); +            ret = QRect( max.x() + max.width()/2, \
max.y(), max.width()/2, max.height() ); +            break;
+            }
+        }
+    return ret;
+    }
+
 } // namespace
diff --git a/kcmkwin/kwinscreenedges/main.cpp b/kcmkwin/kwinscreenedges/main.cpp
index d7c0c67..c3099ed 100644
--- a/kcmkwin/kwinscreenedges/main.cpp
+++ b/kcmkwin/kwinscreenedges/main.cpp
@@ -56,6 +56,7 @@ KWinScreenEdgesConfig::KWinScreenEdgesConfig( QWidget* parent, \
                const QVariantLis
     connect( m_ui->desktopSwitchCombo, SIGNAL( currentIndexChanged(int) ), this, \
                SLOT( changed() ));
     connect( m_ui->activationDelaySpin, SIGNAL( valueChanged(int) ), this, SLOT( \
                changed() ));
     connect( m_ui->triggerCooldownSpin, SIGNAL( valueChanged(int) ), this, SLOT( \
changed() )); +    connect( m_ui->maximizeWindowBox, SIGNAL( stateChanged(int) ), \
this, SLOT( changed() ));  
     // Visual feedback of action group conflicts
     connect( m_ui->desktopSwitchCombo, SIGNAL( currentIndexChanged(int) ), this, \
SLOT( groupChanged() )); @@ -84,6 +85,11 @@ void \
KWinScreenEdgesConfig::groupChanged()  // Desktop switch conflicts
     m_ui->desktopSwitchLabel->setEnabled( true );
     m_ui->desktopSwitchCombo->setEnabled( true );
+
+    bool enableMaximize = false;
+    if( m_ui->desktopSwitchCombo->currentIndex() == 0 )
+        enableMaximize = true;
+    m_ui->maximizeWindowBox->setEnabled( enableMaximize );
     }
 
 void KWinScreenEdgesConfig::load()
@@ -97,6 +103,7 @@ void KWinScreenEdgesConfig::load()
     m_ui->desktopSwitchCombo->setCurrentIndex( config.readEntry( "ElectricBorders", \
                0 ));
     m_ui->activationDelaySpin->setValue( config.readEntry( "ElectricBorderDelay", \
                150 ));
     m_ui->triggerCooldownSpin->setValue( config.readEntry( "ElectricBorderCooldown", \
350 )); +    m_ui->maximizeWindowBox->setChecked( config.readEntry( \
"ElectricBorderMaximize", false ));  
     emit changed( false );
     }
@@ -112,6 +119,7 @@ void KWinScreenEdgesConfig::save()
     config.writeEntry( "ElectricBorders", m_ui->desktopSwitchCombo->currentIndex() \
                );
     config.writeEntry( "ElectricBorderDelay", m_ui->activationDelaySpin->value() );
     config.writeEntry( "ElectricBorderCooldown", m_ui->triggerCooldownSpin->value() \
); +    config.writeEntry( "ElectricBorderMaximize", \
m_ui->maximizeWindowBox->isChecked() );  
     config.sync();
 
@@ -129,6 +137,7 @@ void KWinScreenEdgesConfig::defaults()
     m_ui->desktopSwitchCombo->setCurrentIndex( 0 );
     m_ui->activationDelaySpin->setValue( 150 );
     m_ui->triggerCooldownSpin->setValue( 350 );
+    m_ui->maximizeWindowBox->setChecked( false );
 
     emit changed( true );
     }
diff --git a/kcmkwin/kwinscreenedges/main.ui b/kcmkwin/kwinscreenedges/main.ui
index c0615a4..25ab62b 100644
--- a/kcmkwin/kwinscreenedges/main.ui
+++ b/kcmkwin/kwinscreenedges/main.ui
@@ -58,7 +58,7 @@
         </item>
        </widget>
       </item>
-      <item row="1" column="0">
+      <item row="2" column="0">
        <widget class="QLabel" name="label">
         <property name="toolTip">
          <string>Amount of time required for the mouse cursor to be pushed against \
the edge of the screen before the action is triggered</string> @@ -71,7 +71,7 @@
         </property>
        </widget>
       </item>
-      <item row="1" column="1">
+      <item row="2" column="1">
        <widget class="KIntSpinBox" name="activationDelaySpin">
         <property name="suffix">
          <string> ms</string>
@@ -87,7 +87,7 @@
         </property>
        </widget>
       </item>
-      <item row="2" column="0">
+      <item row="3" column="0">
        <widget class="QLabel" name="label_2">
         <property name="enabled">
          <bool>true</bool>
@@ -103,7 +103,7 @@
         </property>
        </widget>
       </item>
-      <item row="2" column="1">
+      <item row="3" column="1">
        <widget class="KIntSpinBox" name="triggerCooldownSpin">
         <property name="enabled">
          <bool>true</bool>
@@ -122,7 +122,7 @@
         </property>
        </widget>
       </item>
-      <item row="3" column="0">
+      <item row="4" column="0">
        <spacer name="verticalSpacer_2">
         <property name="orientation">
          <enum>Qt::Vertical</enum>
@@ -135,6 +135,13 @@
         </property>
        </spacer>
       </item>
+      <item row="1" column="0" colspan="2">
+       <widget class="QCheckBox" name="maximizeWindowBox">
+        <property name="text">
+         <string>Maximize window on edge while moving</string>
+        </property>
+       </widget>
+      </item>
      </layout>
     </widget>
    </item>
diff --git a/lib/kwinglobals.h b/lib/kwinglobals.h
index f5113dd..b6f2161 100644
--- a/lib/kwinglobals.h
+++ b/lib/kwinglobals.h
@@ -72,6 +72,13 @@ enum ElectricBorder
     ElectricNone
 };
 
+enum ElectricMaximizingMode
+{
+    ElectricMaximizeMode,
+    ElectricLeftMode,
+    ElectricRightMode
+};
+
 // TODO: Hardcoding is bad, need to add some way of registering global actions to \
these.  // When designing the new system we must keep in mind that we have \
conditional actions  // such as "only when moving windows" desktop switching that the \
                current global action
diff --git a/options.cpp b/options.cpp
index 946b91e..b88cf97 100644
--- a/options.cpp
+++ b/options.cpp
@@ -143,6 +143,7 @@ unsigned long Options::updateSettings()
     electric_borders = config.readEntry("ElectricBorders", 0);
     electric_border_delay = config.readEntry("ElectricBorderDelay", 150);
     electric_border_cooldown = config.readEntry("ElectricBorderCooldown", 350);
+    electric_border_maximize = config.readEntry("ElectricBorderMaximize", false);
 
     OpTitlebarDblClick = windowOperation( \
                config.readEntry("TitlebarDoubleClickCommand", "Maximize"), true );
     setOpMaxButtonLeftClick( windowOperation( \
                config.readEntry("MaximizeButtonLeftClickCommand", "Maximize"), true \
                ));
diff --git a/options.h b/options.h
index 6f72785..0771299 100644
--- a/options.h
+++ b/options.h
@@ -289,6 +289,11 @@ class Options : public KDecorationOptions
         * @returns the trigger cooldown for electric borders in milliseconds.
         */
         int electricBorderCooldown();
+        /**
+        * @returns true if a window gets maximized when it reaches an electric
+        * border while being moved.
+        */
+        bool electricBorderMaximize() const { return electric_border_maximize; }
 
         bool topMenuEnabled() const { return topmenus; }
         bool desktopTopMenu() const { return desktop_topmenu; }
@@ -353,6 +358,7 @@ class Options : public KDecorationOptions
         int electric_borders;
         int electric_border_delay;
         int electric_border_cooldown;
+        bool electric_border_maximize;
         bool show_geometry_tip;
         bool topmenus;
         bool desktop_topmenu;
diff --git a/workspace.cpp b/workspace.cpp
index 3888727..b3f9505 100644
--- a/workspace.cpp
+++ b/workspace.cpp
@@ -453,6 +453,17 @@ void Workspace::init()
         }
     if( new_active_client != NULL )
         activateClient( new_active_client );
+
+    // outline windows for electric border maximize window mode
+    outline_left = XCreateWindow( QX11Info::display(), QX11Info::appRootWindow(), 0, \
0, 1, 1, 0, +        CopyFromParent, CopyFromParent, CopyFromParent, \
CWOverrideRedirect, &attr ); +    outline_right = XCreateWindow( QX11Info::display(), \
QX11Info::appRootWindow(), 0, 0, 1, 1, 0, +        CopyFromParent, CopyFromParent, \
CopyFromParent, CWOverrideRedirect, &attr ); +    outline_top = XCreateWindow( \
QX11Info::display(), QX11Info::appRootWindow(), 0, 0, 1, 1, 0, +        \
CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attr ); +    \
outline_bottom = XCreateWindow( QX11Info::display(), QX11Info::appRootWindow(), 0, 0, \
1, 1, 0, +        CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, \
&attr ); +
     // SELI TODO: This won't work with unreasonable focus policies,
     // and maybe in rare cases also if the selected client doesn't
     // want focus
@@ -493,6 +504,12 @@ Workspace::~Workspace()
     writeWindowRules();
     KGlobal::config()->sync();
 
+    // destroy outline windows for electric border maximize window mode
+    XDestroyWindow( QX11Info::display(), outline_left );
+    XDestroyWindow( QX11Info::display(), outline_right );
+    XDestroyWindow( QX11Info::display(), outline_top );
+    XDestroyWindow( QX11Info::display(), outline_bottom );
+
     delete rootInfo;
     delete supportWindow;
     delete mgr;
@@ -2117,6 +2134,7 @@ void Workspace::checkElectricBorder(const QPoint& pos, Time \
now)  Time treshold_reset = 250; // Reset timeout
     Time treshold_trigger = options->electricBorderCooldown(); // Minimum time \
                between triggers
     int distance_reset = 30; // Mouse should not move more than this many pixels
+    int pushback_pixels = 1;
 
     ElectricBorder border;
     if( pos.x() == electricLeft && pos.y() == electricTop )
@@ -2153,41 +2171,79 @@ void Workspace::checkElectricBorder(const QPoint& pos, Time \
now)  electric_current_border = ElectricNone;
             electric_time_last_trigger = now;
             if( movingClient )
-                { // If moving a client or have force doing the desktop switch
-                if( options->electricBorders() != Options::ElectricDisabled )
-                    electricBorderSwitchDesktop( border, pos );
-                return; // Don't reset cursor position
-                }
-            if( options->electricBorders() == Options::ElectricAlways &&
-              ( border == ElectricTop || border == ElectricRight ||
-                border == ElectricBottom || border == ElectricLeft ))
-                { // If desktop switching is always enabled don't apply it to the \
                corners if
-                  // an effect is applied to it (We will check that later).
-                electricBorderSwitchDesktop( border, pos );
-                return; // Don't reset cursor position
-                }
-            switch( options->electricBorderAction( border ))
                 {
-                case ElectricActionDashboard: // Display Plasma dashboard
+                // If moving a client or have force doing the desktop switch
+                if( options->electricBorders() != Options::ElectricDisabled )
                     {
-                    QDBusInterface plasmaApp( "org.kde.plasma-desktop", "/App" );
-                    plasmaApp.call( "toggleDashboard" );
+                    electricBorderSwitchDesktop( border, pos );
+                    return; // Don't reset cursor position
                     }
-                    break;
-                case ElectricActionShowDesktop:
+                // maximize only when not using for switch
+                if( options->electricBorderMaximize() && \
movingClient->isMaximizable() )  {
-                    setShowingDesktop( !showingDesktop() );
-                    break;
+                    bool enable = !movingClient->isElectricBorderMaximizing();
+                    bool activate = true;
+                    if( enable )
+                        {
+                        switch( border )
+                            {
+                            case ElectricTop:
+                                movingClient->setElectricBorderMode( \
ElectricMaximizeMode ); +                                break;
+                            case ElectricLeft:
+                                movingClient->setElectricBorderMode( \
ElectricLeftMode ); +                                break;
+                            case ElectricRight:
+                                movingClient->setElectricBorderMode( \
ElectricRightMode ); +                                break;
+                            default:
+                                activate = false;
+                                break;
+                            }
+                        }
+                    if( activate )
+                        {
+                        movingClient->setElectricBorderMaximizing( enable );
+                        // stronger push back
+                        pushback_pixels = 10;
+                        }
+                    }
+                else
+                    return; // Don't reset cursor position
+                }
+            else
+                {
+                if( options->electricBorders() == Options::ElectricAlways &&
+                ( border == ElectricTop || border == ElectricRight ||
+                    border == ElectricBottom || border == ElectricLeft ))
+                    { // If desktop switching is always enabled don't apply it to \
the corners if +                    // an effect is applied to it (We will check that \
later). +                    electricBorderSwitchDesktop( border, pos );
+                    return; // Don't reset cursor position
                     }
-                case ElectricActionNone: // Either desktop switching or an effect
-                default:
+                switch( options->electricBorderAction( border ))
                     {
-                    if( effects && static_cast<EffectsHandlerImpl*>( effects \
                )->borderActivated( border ))
-                        {} // Handled by effects
-                    else
+                    case ElectricActionDashboard: // Display Plasma dashboard
+                        {
+                        QDBusInterface plasmaApp( "org.kde.plasma-desktop", "/App" \
); +                        plasmaApp.call( "toggleDashboard" );
+                        }
+                        break;
+                    case ElectricActionShowDesktop:
+                        {
+                        setShowingDesktop( !showingDesktop() );
+                        break;
+                        }
+                    case ElectricActionNone: // Either desktop switching or an \
effect +                    default:
                         {
-                        electricBorderSwitchDesktop( border, pos );
-                        return; // Don't reset cursor position
+                        if( effects && static_cast<EffectsHandlerImpl*>( effects \
)->borderActivated( border )) +                            {} // Handled by effects
+                        else
+                            {
+                            electricBorderSwitchDesktop( border, pos );
+                            return; // Don't reset cursor position
+                            }
                         }
                     }
                 }
@@ -2203,8 +2259,22 @@ void Workspace::checkElectricBorder(const QPoint& pos, Time \
now)  
     // 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[ELECTRIC_COUNT] = { 0, -1, -1, -1, 0, 1, 1, 1 };
-    const int ydiff[ELECTRIC_COUNT] = { 1, 1, 0, -1, -1, -1, 0, 1 };
+    const int xdiff[ELECTRIC_COUNT] = { 0,
+                                        -pushback_pixels,
+                                        -pushback_pixels,
+                                        -pushback_pixels,
+                                        0,
+                                        pushback_pixels,
+                                        pushback_pixels,
+                                        pushback_pixels };
+    const int ydiff[ELECTRIC_COUNT] = { pushback_pixels,
+                                        pushback_pixels,
+                                        0,
+                                        -pushback_pixels,
+                                        -pushback_pixels,
+                                        -pushback_pixels,
+                                        0,
+                                        pushback_pixels };
     QCursor::setPos( pos.x() + xdiff[border], pos.y() + ydiff[border] );
     }
 
@@ -2271,6 +2341,94 @@ bool Workspace::electricBorderEvent( XEvent* e )
     return false;
     }
 
+void Workspace::showElectricBorderWindowOutline()
+    {
+    if( !movingClient )
+        return;
+    // code copied from TabBox::updateOutline() in tabbox.cpp
+    QRect c = movingClient->electricBorderMaximizeGeometry();
+    // left/right parts are between top/bottom, they don't reach as far as the \
corners +    XMoveResizeWindow( QX11Info::display(), outline_left, c.x(), c.y() + 5, \
5, c.height() - 10 ); +    XMoveResizeWindow( QX11Info::display(), outline_right, \
c.x() + c.width() - 5, c.y() + 5, 5, c.height() - 10 ); +    XMoveResizeWindow( \
QX11Info::display(), outline_top, c.x(), c.y(), c.width(), 5 ); +    \
XMoveResizeWindow( QX11Info::display(), outline_bottom, c.x(), c.y() + c.height() - \
5, c.width(), 5 ); +    {
+    QPixmap pix( 5, c.height() - 10 );
+    QPainter p( &pix );
+    p.setPen( Qt::white );
+    p.drawLine( 0, 0, 0, pix.height() - 1 );
+    p.drawLine( 4, 0, 4, pix.height() - 1 );
+    p.setPen( Qt::gray );
+    p.drawLine( 1, 0, 1, pix.height() - 1 );
+    p.drawLine( 3, 0, 3, pix.height() - 1 );
+    p.setPen( Qt::black );
+    p.drawLine( 2, 0, 2, pix.height() - 1 );
+    p.end();
+    XSetWindowBackgroundPixmap( QX11Info::display(), outline_left, pix.handle());
+    XSetWindowBackgroundPixmap( QX11Info::display(), outline_right, pix.handle());
+    }
+    {
+    QPixmap pix( c.width(), 5 );
+    QPainter p( &pix );
+    p.setPen( Qt::white );
+    p.drawLine( 0, 0, pix.width() - 1 - 0, 0 );
+    p.drawLine( 4, 4, pix.width() - 1 - 4, 4 );
+    p.drawLine( 0, 0, 0, 4 );
+    p.drawLine( pix.width() - 1 - 0, 0, pix.width() - 1 - 0, 4 );
+    p.setPen( Qt::gray );
+    p.drawLine( 1, 1, pix.width() - 1 - 1, 1 );
+    p.drawLine( 3, 3, pix.width() - 1 - 3, 3 );
+    p.drawLine( 1, 1, 1, 4 );
+    p.drawLine( 3, 3, 3, 4 );
+    p.drawLine( pix.width() - 1 - 1, 1, pix.width() - 1 - 1, 4 );
+    p.drawLine( pix.width() - 1 - 3, 3, pix.width() - 1 - 3, 4 );
+    p.setPen( Qt::black );
+    p.drawLine( 2, 2, pix.width() - 1 - 2, 2 );
+    p.drawLine( 2, 2, 2, 4 );
+    p.drawLine( pix.width() - 1 - 2, 2, pix.width() - 1 - 2, 4 );
+    p.end();
+    XSetWindowBackgroundPixmap( QX11Info::display(), outline_top, pix.handle());
+    }
+    {
+    QPixmap pix( c.width(), 5 );
+    QPainter p( &pix );
+    p.setPen( Qt::white );
+    p.drawLine( 4, 0, pix.width() - 1 - 4, 0 );
+    p.drawLine( 0, 4, pix.width() - 1 - 0, 4 );
+    p.drawLine( 0, 4, 0, 0 );
+    p.drawLine( pix.width() - 1 - 0, 4, pix.width() - 1 - 0, 0 );
+    p.setPen( Qt::gray );
+    p.drawLine( 3, 1, pix.width() - 1 - 3, 1 );
+    p.drawLine( 1, 3, pix.width() - 1 - 1, 3 );
+    p.drawLine( 3, 1, 3, 0 );
+    p.drawLine( 1, 3, 1, 0 );
+    p.drawLine( pix.width() - 1 - 3, 1, pix.width() - 1 - 3, 0 );
+    p.drawLine( pix.width() - 1 - 1, 3, pix.width() - 1 - 1, 0 );
+    p.setPen( Qt::black );
+    p.drawLine( 2, 2, pix.width() - 1 - 2, 2 );
+    p.drawLine( 2, 0, 2, 2 );
+    p.drawLine( pix.width() - 1 - 2, 0, pix.width() - 1 - 2, 2 );
+    p.end();
+    XSetWindowBackgroundPixmap( QX11Info::display(), outline_bottom, pix.handle());
+    }
+    XClearWindow( QX11Info::display(), outline_left );
+    XClearWindow( QX11Info::display(), outline_right );
+    XClearWindow( QX11Info::display(), outline_top );
+    XClearWindow( QX11Info::display(), outline_bottom );
+    XMapWindow( QX11Info::display(), outline_left );
+    XMapWindow( QX11Info::display(), outline_right );
+    XMapWindow( QX11Info::display(), outline_top );
+    XMapWindow( QX11Info::display(), outline_bottom );
+    }
+
+void Workspace::hideElectricBorderWindowOutline()
+    {
+        XUnmapWindow( QX11Info::display(), outline_left );
+        XUnmapWindow( QX11Info::display(), outline_right );
+        XUnmapWindow( QX11Info::display(), outline_top );
+        XUnmapWindow( QX11Info::display(), outline_bottom );
+    }
+
 //-----------------------------------------------------------------------------
 // Top menu
 
diff --git a/workspace.h b/workspace.h
index 483847c..dd922ae 100644
--- a/workspace.h
+++ b/workspace.h
@@ -467,6 +467,8 @@ class Workspace : public QObject, public KDecorationDefines
         void stopMousePolling();
 
         void raiseElectricBorderWindows();
+        void showElectricBorderWindowOutline();
+        void hideElectricBorderWindowOutline();
 
     public slots:
         void addRepaintFull();
@@ -903,6 +905,11 @@ class Workspace : public QObject, public KDecorationDefines
         QList< int > composite_paint_times;
         QTimer compositeResetTimer; // for compressing composite resets
 
+        Window outline_left;
+        Window outline_right;
+        Window outline_top;
+        Window outline_bottom;
+
     private:
         friend bool performTransiencyCheck();
     };


["signature.asc" (application/pgp-signature)]

_______________________________________________
kwin mailing list
kwin@kde.org
https://mail.kde.org/mailman/listinfo/kwin


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic