Support for effects taking control of the keyboard. Needs recent kdeui change

to work properly.


svn path=/branches/work/kwin_composite/; revision=654259
This commit is contained in:
Luboš Luňák 2007-04-15 16:31:13 +00:00
parent 67f830d223
commit 76cb5de294
10 changed files with 100 additions and 9 deletions

View file

@ -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<EffectWindowImpl*>(c)->window()))

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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.

View file

@ -86,6 +86,10 @@ void Effect::windowInputMouseEvent( Window, QEvent* )
{
}
void Effect::grabbedKeyboardEvent( QKeyEvent* )
{
}
void Effect::desktopChanged( int )
{
}

View file

@ -26,6 +26,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include <stdio.h>
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;

View file

@ -14,7 +14,6 @@ License. See the file "COPYING" for the exact licensing terms.
#include "main.h"
#include <kglobal.h>
#include <klocale.h>
#include <stdlib.h>
#include <kcmdlineargs.h>
@ -26,11 +25,13 @@ License. See the file "COPYING" for the exact licensing terms.
#include <stdio.h>
#include <fixx11h.h>
#include <QtDBus/QtDBus>
#include <kglobal.h>
#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 );

1
main.h
View file

@ -28,6 +28,7 @@ class Application : public KApplication
protected:
bool x11EventFilter( XEvent * );
bool notify( QObject* o, QEvent* e );
private slots:
void lostSelection();

View file

@ -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 );