Add support for activating features using window borders/corners.
Enabled it for PresentWindowsEffect for now. svn path=/branches/work/kwin_composite/; revision=650532
This commit is contained in:
parent
faadbf6920
commit
35bbf89aed
11 changed files with 294 additions and 235 deletions
14
effects.cpp
14
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;
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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<Toplevel*, WindowData> mWindowData;
|
||||
|
||||
ElectricBorder borderActivate;
|
||||
ElectricBorder borderActivateAll;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ License. See the file "COPYING" for the exact licensing terms.
|
|||
|
||||
#include "glutils.h"
|
||||
|
||||
#include <kdebug.h>
|
||||
#include <QPixmap>
|
||||
#include <QImage>
|
||||
#include <QHash>
|
||||
|
|
12
layers.cpp
12
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;
|
||||
|
||||
|
|
14
utils.h
14
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:
|
||||
|
|
415
workspace.cpp
415
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());
|
||||
|
|
23
workspace.h
23
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;
|
||||
|
|
Loading…
Reference in a new issue