From 35bbf89aed92efafd3e3f3c1916a77fe8e6a65dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Wed, 4 Apr 2007 19:08:03 +0000 Subject: [PATCH] Add support for activating features using window borders/corners. Enabled it for PresentWindowsEffect for now. svn path=/branches/work/kwin_composite/; revision=650532 --- effects.cpp | 14 ++ effects.h | 4 + effects/presentwindows.cpp | 27 ++- effects/presentwindows.h | 6 +- events.cpp | 4 +- geometry.cpp | 9 +- glutils.cpp | 1 + layers.cpp | 12 +- utils.h | 14 ++ workspace.cpp | 415 ++++++++++++++++++------------------- workspace.h | 23 +- 11 files changed, 294 insertions(+), 235 deletions(-) diff --git a/effects.cpp b/effects.cpp index 890e9b61fb..5d8127166f 100644 --- a/effects.cpp +++ b/effects.cpp @@ -116,6 +116,11 @@ void Effect::tabBoxUpdated() { } +bool Effect::borderActivated( ElectricBorder ) + { + return false; + } + void Effect::prePaintScreen( int* mask, QRegion* region, int time ) { effects->prePaintScreen( mask, region, time ); @@ -419,6 +424,15 @@ QRect EffectsHandler::transformWindowDamage( EffectWindow* w, const QRect& r ) return r; } +bool EffectsHandler::borderActivated( ElectricBorder border ) + { + bool ret = false; + foreach( EffectPair ep, loaded_effects ) + if( ep.second->borderActivated( border )) + ret = true; // bail out or tell all? + return ret; + } + Window EffectsHandler::createInputWindow( Effect* e, int x, int y, int w, int h, const QCursor& cursor ) { XSetWindowAttributes attrs; diff --git a/effects.h b/effects.h index f0d36bd1f7..a5de86ef09 100644 --- a/effects.h +++ b/effects.h @@ -62,6 +62,7 @@ class ScreenPaintData }; class Effect + : public KDecorationDefines { public: virtual ~Effect(); @@ -96,6 +97,7 @@ class Effect virtual void tabBoxAdded( int mode ); virtual void tabBoxClosed(); virtual void tabBoxUpdated(); + virtual bool borderActivated( ElectricBorder border ); // Interpolates between x and y static float interpolate(float x, float y, float a) @@ -131,6 +133,7 @@ class GenericEffectFactory : public EffectFactory class EffectsHandler + : public KDecorationDefines { friend class Effect; public: @@ -173,6 +176,7 @@ class EffectsHandler void tabBoxAdded( int mode ); void tabBoxClosed(); void tabBoxUpdated(); + bool borderActivated( ElectricBorder border ); void registerEffect( const QString& name, EffectFactory* factory ); void loadEffect( const QString& name ); diff --git a/effects/presentwindows.cpp b/effects/presentwindows.cpp index caf42e89e2..1d857c1d1a 100644 --- a/effects/presentwindows.cpp +++ b/effects/presentwindows.cpp @@ -44,6 +44,18 @@ PresentWindowsEffect::PresentWindowsEffect() b->setText( i18n("Toggle Expose effect (incl other desktops)" )); b->setGlobalShortcut(KShortcut(Qt::CTRL + Qt::Key_F11)); connect(b, SIGNAL(triggered(bool)), this, SLOT(toggleActiveAllDesktops())); + + borderActivate = ElectricTopRight; + borderActivateAll = ElectricNone; + + Workspace::self()->reserveElectricBorder( borderActivate ); + Workspace::self()->reserveElectricBorder( borderActivateAll ); + } + +PresentWindowsEffect::~PresentWindowsEffect() + { + Workspace::self()->unreserveElectricBorder( borderActivate ); + Workspace::self()->unreserveElectricBorder( borderActivateAll ); } @@ -396,7 +408,20 @@ void PresentWindowsEffect::calculateWindowTransformationsKompose(ClientList clie } } +bool PresentWindowsEffect::borderActivated( ElectricBorder border ) + { + if( border == borderActivate && !mActivated ) + { + toggleActive(); + return true; + } + if( border == borderActivateAll && !mActivated ) + { + toggleActiveAllDesktops(); + return true; + } + return false; + } } // namespace #include "presentwindows.moc" - diff --git a/effects/presentwindows.h b/effects/presentwindows.h index 71c73ab450..ebd3e9f19c 100644 --- a/effects/presentwindows.h +++ b/effects/presentwindows.h @@ -28,7 +28,7 @@ class PresentWindowsEffect Q_OBJECT public: PresentWindowsEffect(); - + virtual ~PresentWindowsEffect(); virtual void prePaintScreen( int* mask, QRegion* region, int time ); virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time ); @@ -38,6 +38,7 @@ class PresentWindowsEffect virtual void windowClosed( EffectWindow* c ); virtual void windowActivated( EffectWindow* c ); virtual void windowInputMouseEvent( Window w, QEvent* e ); + virtual bool borderActivated( ElectricBorder border ); public slots: void setActive(bool active); @@ -77,6 +78,9 @@ class PresentWindowsEffect float hover; }; QHash mWindowData; + + ElectricBorder borderActivate; + ElectricBorder borderActivateAll; }; } // namespace diff --git a/events.cpp b/events.cpp index d81a841c8f..19f913bdb5 100644 --- a/events.cpp +++ b/events.cpp @@ -405,7 +405,7 @@ bool Workspace::workspaceEvent( XEvent * e ) if ( w ) QWhatsThis::leaveWhatsThisMode(); } - if( electricBorder(e)) + if( electricBorderEvent(e)) return true; break; } @@ -470,7 +470,7 @@ bool Workspace::workspaceEvent( XEvent * e ) case FocusOut: return true; // always eat these, they would tell Qt that KWin is the active app case ClientMessage: - if( electricBorder( e )) + if( electricBorderEvent( e )) return true; break; case MappingNotify: diff --git a/geometry.cpp b/geometry.cpp index 96bce38390..b06965120c 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -51,7 +51,8 @@ void Workspace::desktopResized() rootInfo->setDesktopGeometry( -1, desktop_geometry ); updateClientArea(); - checkElectricBorders( true ); + destroyElectricBorders(); + updateElectricBorders(); if( compositing() ) { finishCompositing(); @@ -2295,6 +2296,8 @@ bool Client::startMoveResize() Notify::raise( isResize() ? Notify::ResizeStart : Notify::MoveStart ); if( effects ) effects->windowUserMovedResized( effectWindow(), true, false ); + if( options->electricBorders() == Options::ElectricMoveOnly ) + workspace()->reserveElectricBorderSwitching( true ); return true; } @@ -2335,6 +2338,8 @@ void Client::leaveMoveResize() moveResizeMode = false; delete eater; eater = 0; + if( options->electricBorders() == Options::ElectricMoveOnly ) + workspace()->reserveElectricBorderSwitching( false ); } // This function checks if it actually makes sense to perform a restricted move/resize. @@ -2572,7 +2577,7 @@ void Client::handleMoveResize( int x, int y, int x_root, int y_root ) } // so the geometry tip will be painted above the outline } if ( isMove() ) - workspace()->clientMoved(globalPos, xTime()); + workspace()->checkElectricBorder(globalPos, xTime()); if( effects ) effects->windowUserMovedResized( effectWindow(), false, false ); } diff --git a/glutils.cpp b/glutils.cpp index 0b9a0b7d89..7d37aeef31 100644 --- a/glutils.cpp +++ b/glutils.cpp @@ -10,6 +10,7 @@ License. See the file "COPYING" for the exact licensing terms. #include "glutils.h" +#include #include #include #include diff --git a/layers.cpp b/layers.cpp index 21261fe0e8..7d134971da 100644 --- a/layers.cpp +++ b/layers.cpp @@ -133,7 +133,8 @@ void Workspace::propagateClients( bool propagate_new_clients ) // when passig pointers around. // restack the windows according to the stacking order - Window* new_stack = new Window[ stacking_order.count() + 2 ]; + // 1 - supportWindow, 1 - topmenu_space, 8 - electric borders + Window* new_stack = new Window[ stacking_order.count() + 1 + 1 + 8 ]; int pos = 0; // Stack all windows under the support window. The support window is // not used for anything (besides the NETWM property), and it's not shown, @@ -157,9 +158,14 @@ void Workspace::propagateClients( bool propagate_new_clients ) new_stack[ topmenu_space_pos ] = topmenu_space->winId(); ++pos; } - // TODO isn't it too inefficient to restart always all clients? + for( int i = 0; + i < ELECTRIC_COUNT; + ++i ) + if( electric_windows[ i ] != None ) + new_stack[ pos++ ] = electric_windows[ i ]; + // TODO isn't it too inefficient to restack always all clients? // TODO don't restack not visible windows? - assert( new_stack[ 0 ] = supportWindow->winId()); + assert( new_stack[ 0 ] == supportWindow->winId()); XRestackWindows(display(), new_stack, pos); delete [] new_stack; diff --git a/utils.h b/utils.h index 6e679355ab..b1645c9017 100644 --- a/utils.h +++ b/utils.h @@ -154,6 +154,20 @@ enum ShadeMode ShadeActivated // "shaded", but visible due to alt+tab to the window }; +enum ElectricBorder + { + ElectricTop, + ElectricTopRight, + ElectricRight, + ElectricBottomRight, + ElectricBottom, + ElectricBottomLeft, + ElectricLeft, + ElectricTopLeft, + ELECTRIC_COUNT, + ElectricNone + }; + class Extensions { public: diff --git a/workspace.cpp b/workspace.cpp index 1fcc55a0aa..c837f650d5 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -110,12 +110,7 @@ Workspace::Workspace( bool restore ) global_shortcuts_disabled_for_client( false ), root (0), workspaceInit (true), - startup(0), electric_have_borders(false), - electric_current_border(0), - electric_top_border(None), - electric_bottom_border(None), - electric_left_border(None), - electric_right_border(None), + startup(0), layoutOrientation(Qt::Vertical), layoutX(-1), layoutY(2), @@ -145,6 +140,14 @@ Workspace::Workspace( bool restore ) default_colormap = DefaultColormap(display(), info.screen() ); installed_colormap = default_colormap; + for( int i = 0; + i < ELECTRIC_COUNT; + ++i ) + { + electric_reserved[ i ] = 0; + electric_windows[ i ] = None; + } + connect( &temporaryRulesMessages, SIGNAL( gotMessage( const QString& )), this, SLOT( gotTemporaryRulesMessage( const QString& ))); connect( &rulesUpdatedTimer, SIGNAL( timeout()), this, SLOT( writeWindowRules())); @@ -153,9 +156,6 @@ Workspace::Workspace( bool restore ) delayFocusTimer = 0; - electric_time_first = xTime(); - electric_time_last = xTime(); - if ( restore ) loadSessionInfo(); @@ -211,7 +211,9 @@ Workspace::Workspace( bool restore ) void Workspace::init() { - checkElectricBorders(); + if( options->electricBorders() == Options::ElectricAlways ) + reserveElectricBorderSwitching( true ); + updateElectricBorders(); // not used yet // topDock = 0L; @@ -395,7 +397,6 @@ void Workspace::init() updateStackingOrder( true ); updateClientArea(); - raiseElectricBorders(); // NETWM spec says we have to set it to (0,0) if we don't support it NETPoint* viewports = new NETPoint[ number_of_desktops ]; @@ -950,6 +951,9 @@ void Workspace::slotReconfigure() kDebug(1212) << "Workspace::slotReconfigure()" << endl; reconfigureTimer.stop(); + if( options->electricBorders() == Options::ElectricAlways ) + reserveElectricBorderSwitching( false ); + KGlobal::config()->reparseConfiguration(); unsigned long changed = options->updateSettings(); tab_box->reconfigure(); @@ -980,7 +984,9 @@ void Workspace::slotReconfigure() forEachClient( CheckBorderSizesProcedure()); } - checkElectricBorders(); + if( options->electricBorders() == Options::ElectricAlways ) + reserveElectricBorderSwitching( true ); + updateElectricBorders(); if( options->topMenuEnabled() && !managingTopMenus()) { @@ -2022,150 +2028,146 @@ void Workspace::cancelDelayFocus() // Electric Borders //========================================================================// // 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::checkElectricBorders( bool force ) +// to change the virtual desktop or activate another features +// by moving the mouse pointer to the borders or corners. +// Technically this is done with input only windows. +void Workspace::updateElectricBorders() { - if( force ) - destroyBorderWindows(); - - electric_current_border = 0; - + electric_time_first = xTime(); + electric_time_last = xTime(); + electric_current_border = ElectricNone; QRect r = QApplication::desktop()->geometry(); electricTop = r.top(); electricBottom = r.bottom(); electricLeft = r.left(); electricRight = r.right(); - if (options->electricBorders() == Options::ElectricAlways) - createBorderWindows(); + for( int pos = 0; + pos < ELECTRIC_COUNT; + ++pos ) + { + if( electric_reserved[ pos ] == 0 ) + { + if( electric_windows[ pos ] != None ) + XDestroyWindow( display(), electric_windows[ pos ] ); + electric_windows[ pos ] = None; + continue; + } + if( electric_windows[ pos ] != None ) + continue; + XSetWindowAttributes attributes; + attributes.override_redirect = True; + attributes.event_mask = EnterWindowMask | LeaveWindowMask; + unsigned long valuemask = CWOverrideRedirect | CWEventMask; + int xywh[ ELECTRIC_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 } + }; + electric_windows[ pos ] = XCreateWindow( display(), rootWindow(), + xywh[ pos ][ 0 ], xywh[ pos ][ 1 ], xywh[ pos ][ 2 ], xywh[ pos ][ 3 ], + 0, CopyFromParent, InputOnly, CopyFromParent, valuemask, &attributes ); + XMapWindow( display(), electric_windows[ pos ]); + // Set XdndAware on the windows, so that DND enter events are received (#86998) + Atom version = 4; // XDND version + XChangeProperty( display(), electric_windows[ pos ], atoms->xdnd_aware, XA_ATOM, + 32, PropModeReplace, ( unsigned char* )&version, 1 ); + } + } + +void Workspace::destroyElectricBorders() + { + for( int pos = 0; + pos < ELECTRIC_COUNT; + ++pos ) + { + if( electric_windows[ pos ] != None ) + XDestroyWindow( display(), electric_windows[ pos ] ); + electric_windows[ pos ] = None; + } + } + +void Workspace::reserveElectricBorderSwitching( bool reserve ) + { + if( reserve ) + { + reserveElectricBorder( ElectricTop ); + reserveElectricBorder( ElectricBottom ); + reserveElectricBorder( ElectricLeft ); + reserveElectricBorder( ElectricRight ); + } else - destroyBorderWindows(); + { + unreserveElectricBorder( ElectricTop ); + unreserveElectricBorder( ElectricBottom ); + unreserveElectricBorder( ElectricLeft ); + unreserveElectricBorder( ElectricRight ); + } } -void Workspace::createBorderWindows() +void Workspace::reserveElectricBorder( ElectricBorder border ) { - if ( electric_have_borders ) + if( border == ElectricNone ) return; - - electric_have_borders = true; - - QRect r = QApplication::desktop()->geometry(); - XSetWindowAttributes attributes; - unsigned long valuemask; - attributes.override_redirect = True; - attributes.event_mask = (EnterWindowMask | LeaveWindowMask | - VisibilityChangeMask); - valuemask= (CWOverrideRedirect | CWEventMask | CWCursor ); - attributes.cursor = XCreateFontCursor(display(), - XC_sb_up_arrow); - electric_top_border = XCreateWindow (display(), rootWindow(), - 0,0, - r.width(),1, - 0, - CopyFromParent, InputOnly, - CopyFromParent, - valuemask, &attributes); - XMapWindow(display(), electric_top_border); - - attributes.cursor = XCreateFontCursor(display(), - XC_sb_down_arrow); - electric_bottom_border = XCreateWindow (display(), rootWindow(), - 0,r.height()-1, - r.width(),1, - 0, - CopyFromParent, InputOnly, - CopyFromParent, - valuemask, &attributes); - XMapWindow(display(), electric_bottom_border); - - attributes.cursor = XCreateFontCursor(display(), - XC_sb_left_arrow); - electric_left_border = XCreateWindow (display(), rootWindow(), - 0,0, - 1,r.height(), - 0, - CopyFromParent, InputOnly, - CopyFromParent, - valuemask, &attributes); - XMapWindow(display(), electric_left_border); - - attributes.cursor = XCreateFontCursor(display(), - XC_sb_right_arrow); - electric_right_border = XCreateWindow (display(), rootWindow(), - r.width()-1,0, - 1,r.height(), - 0, - CopyFromParent, InputOnly, - CopyFromParent, - valuemask, &attributes); - XMapWindow(display(), electric_right_border); - // Set XdndAware on the windows, so that DND enter events are received (#86998) - Atom version = 4; // XDND version - XChangeProperty( display(), electric_top_border, atoms->xdnd_aware, XA_ATOM, - 32, PropModeReplace, ( unsigned char* )&version, 1 ); - XChangeProperty( display(), electric_bottom_border, atoms->xdnd_aware, XA_ATOM, - 32, PropModeReplace, ( unsigned char* )&version, 1 ); - XChangeProperty( display(), electric_left_border, atoms->xdnd_aware, XA_ATOM, - 32, PropModeReplace, ( unsigned char* )&version, 1 ); - XChangeProperty( display(), electric_right_border, atoms->xdnd_aware, XA_ATOM, - 32, PropModeReplace, ( unsigned char* )&version, 1 ); + if( electric_reserved[ border ]++ == 0 ) + QTimer::singleShot( 0, this, SLOT( updateElectricBorders())); } - -// 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() +void Workspace::unreserveElectricBorder( ElectricBorder border ) { - if( !electric_have_borders) - return; - - electric_have_borders = false; - - if(electric_top_border) - XDestroyWindow(display(),electric_top_border); - if(electric_bottom_border) - XDestroyWindow(display(),electric_bottom_border); - if(electric_left_border) - XDestroyWindow(display(),electric_left_border); - if(electric_right_border) - XDestroyWindow(display(),electric_right_border); - - electric_top_border = None; - electric_bottom_border = None; - electric_left_border = None; - electric_right_border = None; + if( border == ElectricNone ) + return; + assert( electric_reserved[ border ] > 0 ); + if( --electric_reserved[ border ] == 0 ) + QTimer::singleShot( 0, this, SLOT( updateElectricBorders())); } -void Workspace::clientMoved(const QPoint &pos, Time now) +void Workspace::checkElectricBorder(const QPoint &pos, Time now) { - if (options->electricBorders() == Options::ElectricDisabled) - return; - if ((pos.x() != electricLeft) && (pos.x() != electricRight) && (pos.y() != electricTop) && (pos.y() != electricBottom)) return; + bool have_borders = false; + for( int i = 0; + i < ELECTRIC_COUNT; + ++i ) + if( electric_windows[ i ] != None ) + have_borders = true; + if( !have_borders ) + return; + Time treshold_set = options->electricBorderDelay(); // set timeout Time treshold_reset = 250; // reset timeout int distance_reset = 30; // Mouse should not move more than this many pixels - int border = 0; - if (pos.x() == electricLeft) - border = 1; - else if (pos.x() == electricRight) - border = 2; - else if (pos.y() == electricTop) - border = 3; - else if (pos.y() == electricBottom) - border = 4; + ElectricBorder border; + if( pos.x() == electricLeft && pos.y() == electricTop ) + border = ElectricTopLeft; + else if( pos.x() == electricRight && pos.y() == electricTop ) + border = ElectricTopRight; + else if( pos.x() == electricLeft && pos.y() == electricBottom ) + border = ElectricBottomLeft; + else if( pos.x() == electricRight && pos.y() == electricBottom ) + border = ElectricBottomRight; + else if( pos.x() == electricLeft ) + border = ElectricLeft; + else if( pos.x() == electricRight ) + border = ElectricRight; + else if( pos.y() == electricTop ) + border = ElectricTop; + else if( pos.y() == electricBottom ) + border = ElectricBottom; + else + abort(); if ((electric_current_border == border) && (timestampDiff(electric_time_last, now) < treshold_reset) && @@ -2175,50 +2177,11 @@ void Workspace::clientMoved(const QPoint &pos, Time now) if (timestampDiff(electric_time_first, now) > treshold_set) { - electric_current_border = 0; - - QRect r = QApplication::desktop()->geometry(); - int offset; - - int desk_before = currentDesktop(); - switch(border) - { - case 1: - slotSwitchDesktopLeft(); - if (currentDesktop() != desk_before) - { - offset = r.width() / 5; - QCursor::setPos(r.width() - offset, pos.y()); - } - break; - - case 2: - slotSwitchDesktopRight(); - if (currentDesktop() != desk_before) - { - offset = r.width() / 5; - QCursor::setPos(offset, pos.y()); - } - break; - - case 3: - slotSwitchDesktopUp(); - if (currentDesktop() != desk_before) - { - offset = r.height() / 5; - QCursor::setPos(pos.x(), r.height() - offset); - } - break; - - case 4: - slotSwitchDesktopDown(); - if (currentDesktop() != desk_before) - { - offset = r.height() / 5; - QCursor::setPos(pos.x(), offset); - } - break; - } + electric_current_border = ElectricNone; + if( effects && effects->borderActivated( border )) + {} // handled by effects + else + electricBorderSwitchDesktop( border, pos ); return; } } @@ -2230,67 +2193,91 @@ void Workspace::clientMoved(const QPoint &pos, Time now) electric_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) + static int xdiff[ ELECTRIC_COUNT ] = { 0, -1, -1, -1, 0, 1, 1, 1 }; + static int ydiff[ ELECTRIC_COUNT ] = { 1, 1, 0, -1, -1, -1, 0, 1 }; + QCursor::setPos( pos.x() + xdiff[ border ], pos.y() + ydiff[ border ] ); + } - // reset the pointer to find out wether the user is really pushing - switch( border) +void Workspace::electricBorderSwitchDesktop( ElectricBorder border, const QPoint& pos ) + { + QRect r = QApplication::desktop()->geometry(); + int offset; + + int desk_before = currentDesktop(); + switch(border) { - case 1: QCursor::setPos(pos.x()+mouse_warp, pos.y()); break; - case 2: QCursor::setPos(pos.x()-mouse_warp, pos.y()); break; - case 3: QCursor::setPos(pos.x(), pos.y()+mouse_warp); break; - case 4: QCursor::setPos(pos.x(), pos.y()-mouse_warp); break; + case ElectricLeft: + slotSwitchDesktopLeft(); + if (currentDesktop() != desk_before) + { + offset = r.width() / 5; + QCursor::setPos(r.width() - offset, pos.y()); + } + break; + case ElectricRight: + slotSwitchDesktopRight(); + if (currentDesktop() != desk_before) + { + offset = r.width() / 5; + QCursor::setPos(offset, pos.y()); + } + break; + case ElectricTop: + slotSwitchDesktopUp(); + if (currentDesktop() != desk_before) + { + offset = r.height() / 5; + QCursor::setPos(pos.x(), r.height() - offset); + } + break; + case ElectricBottom: + slotSwitchDesktopDown(); + if (currentDesktop() != desk_before) + { + offset = r.height() / 5; + QCursor::setPos(pos.x(), offset); + } + break; + default: + break; } } // this function is called when the user entered an electric border // with the mouse. It may switch to another virtual desktop -bool Workspace::electricBorder(XEvent *e) +bool Workspace::electricBorderEvent(XEvent *e) { - if( !electric_have_borders ) - return false; if( e->type == EnterNotify ) { - if( e->xcrossing.window == electric_top_border || - e->xcrossing.window == electric_left_border || - e->xcrossing.window == electric_bottom_border || - e->xcrossing.window == electric_right_border) - // the user entered an electric border - { - clientMoved( QPoint( e->xcrossing.x_root, e->xcrossing.y_root ), e->xcrossing.time ); - return true; - } + for( int i = 0; + i < ELECTRIC_COUNT; + ++i ) + if( electric_windows[ i ] != None && e->xcrossing.window == electric_windows[ i ] ) + { // the user entered an electric border + checkElectricBorder( QPoint( 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 )) + if( e->xclient.message_type == atoms->xdnd_position ) { - updateXTime(); - clientMoved( QPoint( e->xclient.data.l[2]>>16, e->xclient.data.l[2]&0xffff), xTime() ); - return true; + for( int i = 0; + i < ELECTRIC_COUNT; + ++i ) + if( electric_windows[ i ] != None && e->xclient.window == electric_windows[ i ] ) + { + updateXTime(); + checkElectricBorder( QPoint( e->xclient.data.l[2]>>16, e->xclient.data.l[2]&0xffff), xTime() ); + return true; + } } } return false; } -// 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(electric_have_borders) - { - XRaiseWindow(display(), electric_top_border); - XRaiseWindow(display(), electric_left_border); - XRaiseWindow(display(), electric_bottom_border); - XRaiseWindow(display(), electric_right_border); - } - } - void Workspace::addTopMenu( Client* c ) { assert( c->isTopMenu()); diff --git a/workspace.h b/workspace.h index 8636c48c58..dcfe4e7d3b 100644 --- a/workspace.h +++ b/workspace.h @@ -154,7 +154,10 @@ class Workspace : public QObject, public KDecorationDefines void clientHidden( Client* ); void clientAttentionChanged( Client* c, bool set ); - void clientMoved(const QPoint &pos, Time time); + void checkElectricBorder(const QPoint &pos, Time time); + void reserveElectricBorder( ElectricBorder border ); + void unreserveElectricBorder( ElectricBorder border ); + void reserveElectricBorderSwitching( bool reserve ); /** * Returns the current virtual desktop of this workspace @@ -444,6 +447,7 @@ class Workspace : public QObject, public KDecorationDefines void setupCompositing(); void performCompositing(); void lostCMSelection(); + void updateElectricBorders(); protected: bool keyPressMouseEmulation( XKeyEvent& ev ); @@ -518,11 +522,9 @@ class Workspace : public QObject, public KDecorationDefines void tabBoxKeyRelease( const XKeyEvent& ev ); // electric borders - void checkElectricBorders( bool force = false ); - void createBorderWindows(); - void destroyBorderWindows(); - bool electricBorder(XEvent * e); - void raiseElectricBorders(); + void destroyElectricBorders(); + bool electricBorderEvent(XEvent * e); + void electricBorderSwitchDesktop( ElectricBorder border, const QPoint& pos ); // ------------------ @@ -659,12 +661,8 @@ class Workspace : public QObject, public KDecorationDefines KStartupInfo* startup; - bool electric_have_borders; - int electric_current_border; - WId electric_top_border; - WId electric_bottom_border; - WId electric_left_border; - WId electric_right_border; + ElectricBorder electric_current_border; + Window electric_windows[ ELECTRIC_COUNT ]; int electricLeft; int electricRight; int electricTop; @@ -672,6 +670,7 @@ class Workspace : public QObject, public KDecorationDefines Time electric_time_first; Time electric_time_last; QPoint electric_push_point; + int electric_reserved[ ELECTRIC_COUNT ]; // corners/edges used by something Qt::Orientation layoutOrientation; int layoutX;