From kde-devel Thu Jun 26 03:11:47 2008 From: Kelvie Wong Date: Thu, 26 Jun 2008 03:11:47 +0000 To: kde-devel Subject: [Proposal + WIP (but working) patches]: Present Windows feature - Message-Id: <200806252011.48047.kelvie () ieee ! org> X-MARC-Message: https://marc.info/?l=kde-devel&m=121444999828915 I sent this to the kwin mailing list, but I don't think many people subscribe to that, so I'll repost it here :) ---------- Forwarded Message ---------- Subject: [Proposal + WIP (but working) patches]: Present Windows feature - move window to current desktop. Date: Saturday, June 21, 2008 From: Kelvie Wong To: kwin@kde.org --- Attached is a couple of rough patches I've been using (on top of the KDE-svn) that enable me to do something that I do very often: move a window to the current desktop. I no longer use a taskbar (with too many tasks across too many desktops, it becomes much harder to find the window I want without a fullscreen solution), so I managed to find some time to quickly read some of the API and hack this up. Description =========== What this patch does is that when the user holds down Alt and left click on a window (such is the default for moving the window with the mouse) inside Present Windows, the window will be moved to the current desktop (the effect is then disabled, and the user returns back to the desktop they were at), and the window will be attached to the mouse as if the user had used Alt+Left Click on a normal window. This gives the user the illusion that the window is being dragged from the Present Windows effect into the current desktop. The mouse position inside the window thumbnail is also taken into account (e.g. if you drag the window by its top left corner, the top left corner of the window will be attached to the mouse when it is un-thumbnailed). Use Cases ========= Again, this was done to scratch my own itch (and match my workflow), but here are some use cases: 1. The user is working on something, and sees that he received an instant message; kopete is in another desktop. He also has about 20 other windows open, scattered around his desktops. He hits the shortcut key for Present Windows, and quickly finds kopete, uses Alt-click to quickly move kopete to the current desktop, and answers the message, and does not need to switch desktops to go back to work. 2. The user is quietly watching a streaming video, and notices that his CPU is doing something; rather than stopping the video, he can use Present Windows to find a terminal or KSysGuard quickly (either by looking or using the filter), and Alt-click to move the window to the current desktop with minimal interruption. 3. The user has 20-30 windows open (with multi-top level window applications like Gimp and Qt Designer, this isn't tough to do). He wants to find a specific window to move to this desktop. The task bar is a mess, and the windows stack over themselves too much in the Desktop Grid. The quickest way to move a window to the current desktop would be Present Windows, as the user gets an overall view of _all_ windows, and also the ability to filter them. API Additions ============= This change required a new function in kwineffects to expose the mouseCommand functionality that is available (currently) only in the internal client libraries. Improvements ============ As I've mentioned, this was a patch I quickly made to scratch my own 1. The global KWin settings should be queried to find out the right key combination for "move window". For me (and I would imagine, most other people), this is Alt+Left click, but this may change; it would probably be better to respect the user's choice in their "mouse move" shortcut. This was beyond my knowledge w.r.t. how to implement this correctly (e.g., do I check the settings every time on a mouseEvent? or should I store it during initialization? if so, how do I change it?). 2. Maybe the windowMouseMove handler should be more generic to allow for more mouse commands later, such as a windowMouseCommand function that takes an enum telling it what to do. 3. Actions for Left, Right, Middle (and perhaps scroll wheel, as well) + modifiers should probably be customizable in the Present Windows settings box; and this could be one of the actions (To Current Desktop + mouse move). Anyways, without further ado, the patches. -- Kelvie Wong --- workspace/kwin/effects.cpp | 7 +++++++ workspace/kwin/effects.h | 1 + workspace/kwin/effects/presentwindows.cpp | 20 ++++++++++++++++++-- workspace/kwin/lib/kwineffects.h | 1 + 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/workspace/kwin/effects.cpp b/workspace/kwin/effects.cpp index 4db4c6f..8edd998 100644 --- a/workspace/kwin/effects.cpp +++ b/workspace/kwin/effects.cpp @@ -369,6 +369,13 @@ void EffectsHandlerImpl::windowToDesktop( EffectWindow* w, int desktop ) Workspace::self()->sendClientToDesktop( cl, desktop, true ); } +void EffectsHandlerImpl::windowMouseMove( EffectWindow* w, const QPoint& pos ) + { + Client* cl = dynamic_cast< Client* >( static_cast(w)->window()); + if( cl && !cl->isDesktop() && !cl->isDock() && !cl->isTopMenu()) + cl->performMouseCommand( Options::MouseMove, pos ); + } + int EffectsHandlerImpl::currentDesktop() const { return Workspace::self()->currentDesktop(); diff --git a/workspace/kwin/effects.h b/workspace/kwin/effects.h index d14ee3e..d9cfaf7 100644 --- a/workspace/kwin/effects.h +++ b/workspace/kwin/effects.h @@ -53,6 +53,7 @@ class EffectsHandlerImpl : public EffectsHandler virtual EffectWindow* activeWindow() const; virtual void moveWindow( EffectWindow* w, const QPoint& pos ); virtual void windowToDesktop( EffectWindow* w, int desktop ); + virtual void windowMouseMove( EffectWindow* w, const QPoint& pos ); virtual int currentDesktop() const; virtual int numberOfDesktops() const; diff --git a/workspace/kwin/effects/presentwindows.cpp b/workspace/kwin/effects/presentwindows.cpp index 6e9134e..aed0be0 100644 --- a/workspace/kwin/effects/presentwindows.cpp +++ b/workspace/kwin/effects/presentwindows.cpp @@ -265,13 +265,29 @@ void PresentWindowsEffect::windowInputMouseEvent( Window w, QEvent* e ) } // Find out which window (if any) was clicked and activate it - QPoint pos = static_cast< QMouseEvent* >( e )->pos(); + QMouseEvent *me = static_cast< QMouseEvent* >( e ); + QPoint pos = me->pos(); for( DataHash::iterator it = mWindowData.begin(); it != mWindowData.end(); ++it ) { if( it.value().area.contains(pos) ) + { + if( me->modifiers() & Qt::AltModifier ) { - effects->activateWindow( it.key() ); + EffectWindow *ew = it.key(); + QRectF areaF(it.value().area); + QPointF posF(pos); + posF -= areaF.topLeft(); + qreal x_ratio = posF.x() / areaF.width(); + qreal y_ratio = posF.y() / areaF.height(); + + QPointF newPos(pos); + newPos -= QPointF( x_ratio * ew->width(), y_ratio * ew->height() ); + effects->windowToDesktop( it.key(), effects->currentDesktop() ); + effects->moveWindow( ew, newPos.toPoint() ); + effects->windowMouseMove( ew, cursorPos() ); + } + effects->activateWindow( it.key() ); // mWindowData gets cleared and rebuilt when a window is // activated, so it's dangerous (and unnecessary) to continue break; diff --git a/workspace/kwin/lib/kwineffects.h b/workspace/kwin/lib/kwineffects.h index 32397b7..b86b2a0 100644 --- a/workspace/kwin/lib/kwineffects.h +++ b/workspace/kwin/lib/kwineffects.h @@ -470,6 +470,7 @@ class KWIN_EXPORT EffectsHandler virtual EffectWindow* activeWindow() const = 0 ; virtual void moveWindow( EffectWindow* w, const QPoint& pos ) = 0; virtual void windowToDesktop( EffectWindow* w, int desktop ) = 0; + virtual void windowMouseMove( EffectWindow* w, const QPoint& pos) = 0; // virtual int currentDesktop() const = 0; virtual int numberOfDesktops() const = 0; -- 1.5.6.GIT ------------------------------------------------------- -- Kelvie Wong >> Visit http://mail.kde.org/mailman/listinfo/kde-devel#unsub to unsubscribe <<