diff --git a/effects.cpp b/effects.cpp index ddabd90963..ca4125eaa4 100644 --- a/effects.cpp +++ b/effects.cpp @@ -32,7 +32,9 @@ namespace KWin { -EffectsHandlerImpl::EffectsHandlerImpl(CompositingType type) : EffectsHandler(type) +EffectsHandlerImpl::EffectsHandlerImpl(CompositingType type) + : EffectsHandler(type) + , keyboard_grab_effect( NULL ) { foreach( const QString& effect, options->defaultEffects ) loadEffect( effect ); @@ -40,11 +42,10 @@ EffectsHandlerImpl::EffectsHandlerImpl(CompositingType type) : EffectsHandler(ty EffectsHandlerImpl::~EffectsHandlerImpl() { - // Can't be done in EffectsHandler since it would result in pure virtuals - // being called + if( keyboard_grab_effect != NULL ) + ungrabKeyboard(); foreach( EffectPair ep, loaded_effects ) unloadEffect( ep.first ); - foreach( InputWindowPair pos, input_windows ) XDestroyWindow( display(), pos.second ); } @@ -237,6 +238,35 @@ void EffectsHandlerImpl::cursorMoved( const QPoint& pos, Qt::MouseButtons button ep.second->cursorMoved( pos, buttons ); } +bool EffectsHandlerImpl::grabKeyboard( Effect* effect ) + { + if( keyboard_grab_effect != NULL ) + return false; + bool ret = grabXKeyboard(); + if( !ret ) + return false; + keyboard_grab_effect = effect; + return true; + } + +void EffectsHandlerImpl::ungrabKeyboard() + { + assert( keyboard_grab_effect != NULL ); + ungrabXKeyboard(); + keyboard_grab_effect = NULL; + } + +void EffectsHandlerImpl::grabbedKeyboardEvent( QKeyEvent* e ) + { + if( keyboard_grab_effect != NULL ) + keyboard_grab_effect->grabbedKeyboardEvent( e ); + } + +bool EffectsHandlerImpl::hasKeyboardGrab() const + { + return keyboard_grab_effect != NULL; + } + void EffectsHandlerImpl::activateWindow( EffectWindow* c ) { if( Client* cl = dynamic_cast< Client* >( static_cast(c)->window())) diff --git a/effects.h b/effects.h index e88fe2754b..c96224f2c3 100644 --- a/effects.h +++ b/effects.h @@ -43,6 +43,8 @@ class EffectsHandlerImpl : public EffectsHandler virtual int displayWidth() const; virtual int displayHeight() const; virtual QPoint cursorPos() const; + virtual bool grabKeyboard( Effect* effect ); + virtual void ungrabKeyboard(); virtual EffectWindowList stackingOrder() const; virtual void setTabBoxWindow(EffectWindow*); @@ -92,12 +94,15 @@ class EffectsHandlerImpl : public EffectsHandler void tabBoxUpdated(); bool borderActivated( ElectricBorder border ); void cursorMoved( const QPoint& pos, Qt::MouseButtons buttons ); + void grabbedKeyboardEvent( QKeyEvent* e ); + bool hasKeyboardGrab() const; void loadEffect( const QString& name ); void unloadEffect( const QString& name ); protected: KLibrary* findEffectLibrary( const QString& effectname ); + Effect* keyboard_grab_effect; }; class EffectWindowImpl : public EffectWindow diff --git a/effects/presentwindows.cpp b/effects/presentwindows.cpp index d2bffdf022..eb2f2c04ba 100644 --- a/effects/presentwindows.cpp +++ b/effects/presentwindows.cpp @@ -31,6 +31,7 @@ PresentWindowsEffect::PresentWindowsEffect() , mActivated( false ) , mActiveness( 0.0 ) , mRearranging( 1.0 ) + , hasKeyboardGrab( false ) , mHoverWindow( NULL ) { @@ -257,13 +258,16 @@ void PresentWindowsEffect::effectActivated() { // Create temporary input window to catch mouse events mInput = effects->createFullScreenInputWindow( this, Qt::PointingHandCursor ); - // TODO: maybe also create a KAction so that ressing Esc would terminate the effect? + hasKeyboardGrab = effects->grabKeyboard( this ); } void PresentWindowsEffect::effectTerminated() { // Destroy the temporary input window effects->destroyInputWindow( mInput ); + if( hasKeyboardGrab ) + effects->ungrabKeyboard(); + hasKeyboardGrab = false; } void PresentWindowsEffect::rearrangeWindows() @@ -625,5 +629,14 @@ bool PresentWindowsEffect::borderActivated( ElectricBorder border ) return false; } +void PresentWindowsEffect::grabbedKeyboardEvent( QKeyEvent* e ) + { + if( e->key() == Qt::Key_Escape ) + { + setActive( false ); + return; + } + } + } // namespace #include "presentwindows.moc" diff --git a/effects/presentwindows.h b/effects/presentwindows.h index d3e9db3b40..efe6c1b7cd 100644 --- a/effects/presentwindows.h +++ b/effects/presentwindows.h @@ -38,6 +38,7 @@ class PresentWindowsEffect virtual void windowClosed( EffectWindow* c ); virtual void windowInputMouseEvent( Window w, QEvent* e ); virtual bool borderActivated( ElectricBorder border ); + virtual void grabbedKeyboardEvent( QKeyEvent* e ); public slots: void setActive(bool active); @@ -76,6 +77,7 @@ class PresentWindowsEffect float mRearranging; Window mInput; + bool hasKeyboardGrab; EffectWindowList mWindowsToPresent; struct WindowData diff --git a/events.cpp b/events.cpp index dff66e832a..fd1814f656 100644 --- a/events.cpp +++ b/events.cpp @@ -205,6 +205,9 @@ bool Workspace::workspaceEvent( XEvent * e ) mouse_emulation = false; ungrabXKeyboard(); } + if( effects && static_cast< EffectsHandlerImpl* >( effects )->hasKeyboardGrab() + && ( e->type == KeyPress || e->type == KeyRelease )) + return false; // let Qt process it, it'll be intercepted again in eventFilter() if ( e->type == PropertyNotify || e->type == ClientMessage ) { @@ -501,6 +504,20 @@ bool Workspace::workspaceEvent( XEvent * e ) return false; } +// Used only to filter events that need to be processed by Qt first +// (e.g. keyboard input to be composed), otherwise events are +// handle by the XEvent filter above +bool Workspace::workspaceEvent( QEvent* e ) + { + if(( e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease || e->type() == QEvent::ShortcutOverride ) + && effects && static_cast< EffectsHandlerImpl* >( effects )->hasKeyboardGrab()) + { + static_cast< EffectsHandlerImpl* >( effects )->grabbedKeyboardEvent( static_cast< QKeyEvent* >( e )); + return true; + } + return false; + } + // Some events don't have the actual window which caused the event // as e->xany.window (e.g. ConfigureRequest), but as some other // field in the XEvent structure. diff --git a/lib/kwineffects.cpp b/lib/kwineffects.cpp index 8f98d449ef..89b186821f 100644 --- a/lib/kwineffects.cpp +++ b/lib/kwineffects.cpp @@ -86,6 +86,10 @@ void Effect::windowInputMouseEvent( Window, QEvent* ) { } +void Effect::grabbedKeyboardEvent( QKeyEvent* ) + { + } + void Effect::desktopChanged( int ) { } diff --git a/lib/kwineffects.h b/lib/kwineffects.h index e8f6f96f46..dfcb3fe731 100644 --- a/lib/kwineffects.h +++ b/lib/kwineffects.h @@ -26,6 +26,7 @@ License. See the file "COPYING" for the exact licensing terms. #include class KLibrary; +class QKeyEvent; namespace KWin { @@ -99,6 +100,7 @@ class KWIN_EXPORT Effect virtual void windowDamaged( EffectWindow* w, const QRect& r ); virtual void windowGeometryShapeChanged( EffectWindow* w, const QRect& old ); virtual void cursorMoved( const QPoint& pos, Qt::MouseButtons buttons ); + virtual void grabbedKeyboardEvent( QKeyEvent* e ); virtual void tabBoxAdded( int mode ); virtual void tabBoxClosed(); @@ -172,6 +174,8 @@ class KWIN_EXPORT EffectsHandler virtual Window createFullScreenInputWindow( Effect* e, const QCursor& cursor ); virtual void destroyInputWindow( Window w ) = 0; virtual QPoint cursorPos() const = 0; + virtual bool grabKeyboard( Effect* effect ) = 0; + virtual void ungrabKeyboard() = 0; virtual void checkElectricBorder(const QPoint &pos, Time time) = 0; virtual void reserveElectricBorder( ElectricBorder border ) = 0; diff --git a/main.cpp b/main.cpp index 3e2a2cde8c..f645a1e053 100644 --- a/main.cpp +++ b/main.cpp @@ -14,7 +14,6 @@ License. See the file "COPYING" for the exact licensing terms. #include "main.h" -#include #include #include #include @@ -26,11 +25,13 @@ License. See the file "COPYING" for the exact licensing terms. #include #include #include +#include #include "atoms.h" #include "options.h" #include "sm.h" #include "utils.h" +#include "effects.h" #define INT8 _X11INT8 #define INT32 _X11INT32 @@ -120,6 +121,8 @@ Application::Application( ) options = new Options; atoms = new Atoms; + initting = false; // TODO + // create workspace. (void) new Workspace( isSessionRestored() ); @@ -127,13 +130,15 @@ Application::Application( ) initting = false; // startup done, we are up and running now. + QDBusInterface ksplash( "org.kde.ksplash", "/ksplash", "org.kde.KSplash" ); + ksplash.call( "upAndRunning", QString( "wm started" )); XEvent e; e.xclient.type = ClientMessage; e.xclient.message_type = XInternAtom( display(), "_KDE_SPLASH_PROGRESS", False ); e.xclient.display = display(); e.xclient.window = rootWindow(); e.xclient.format = 8; - strcpy( e.xclient.data.b, "wm" ); + strcpy( e.xclient.data.b, "wm started" ); XSendEvent( display(), rootWindow(), False, SubstructureNotifyMask, &e ); } @@ -143,6 +148,8 @@ Application::~Application() if( owner.ownerWindow() != None ) // if there was no --replace (no new WM) XSetInputFocus( display(), PointerRoot, RevertToPointerRoot, xTime() ); delete options; + delete effects; + delete atoms; } void Application::lostSelection() @@ -160,6 +167,13 @@ bool Application::x11EventFilter( XEvent *e ) return KApplication::x11EventFilter( e ); } +bool Application::notify( QObject* o, QEvent* e ) + { + if( Workspace::self()->workspaceEvent( e )) + return true; + return KApplication::notify( o, e ); + } + static void sighandler(int) { QApplication::exit(); @@ -277,9 +291,9 @@ KDE_EXPORT int kdemain( int argc, char * argv[] ) QString appname; if (KWin::screen_number == 0) - appname = "org.kde.kwin"; + appname = "kwin"; else - appname.sprintf("org.kde.kwin-screen-%d", KWin::screen_number); + appname.sprintf("kwin-screen-%d", KWin::screen_number); QDBusConnection::sessionBus().interface()->registerService( appname, QDBusConnectionInterface::DontQueueService ); diff --git a/main.h b/main.h index 551fa19616..043ef1778b 100644 --- a/main.h +++ b/main.h @@ -28,6 +28,7 @@ class Application : public KApplication protected: bool x11EventFilter( XEvent * ); + bool notify( QObject* o, QEvent* e ); private slots: void lostSelection(); diff --git a/workspace.h b/workspace.h index 7bb1e21c62..9047ce7a8c 100644 --- a/workspace.h +++ b/workspace.h @@ -80,6 +80,7 @@ class Workspace : public QObject, public KDecorationDefines static Workspace * self() { return _self; } bool workspaceEvent( XEvent * ); + bool workspaceEvent( QEvent * ); KDecoration* createDecoration( KDecorationBridge* bridge );