diff options
author | Michael Meeks <michael.meeks@suse.com> | 2011-10-06 22:22:39 +0100 |
---|---|---|
committer | Michael Meeks <michael.meeks@suse.com> | 2011-10-25 13:41:52 +0100 |
commit | 28b1f4ca5af84048a003a5dcf68c1f27296c0d0c (patch) | |
tree | 090e263f8183e092c2d1fb144890944044023c96 | |
parent | 2e48ed930d61e02da82c71790994204d3aefaa29 (diff) |
gtk3: make AnyInput to behave itself properly
-rw-r--r-- | vcl/inc/generic/gendata.hxx | 2 | ||||
-rw-r--r-- | vcl/inc/unx/gtk/gtkinst.hxx | 19 | ||||
-rw-r--r-- | vcl/unx/generic/app/salinst.cxx | 1 | ||||
-rw-r--r-- | vcl/unx/gtk/app/gtkinst.cxx | 143 |
4 files changed, 145 insertions, 20 deletions
diff --git a/vcl/inc/generic/gendata.hxx b/vcl/inc/generic/gendata.hxx index ef7725f6a559..10b0a09fc66d 100644 --- a/vcl/inc/generic/gendata.hxx +++ b/vcl/inc/generic/gendata.hxx @@ -51,7 +51,7 @@ class VCL_DLLPUBLIC SalGenericData : public SalData // for transient storage of unicode strings eg. 'u123' by input methods rtl::OUString m_aUnicodeEntry; public: - SalGenericData( SalGenericDataType t ) : SalData(), m_eType( t ) {} + SalGenericData( SalGenericDataType t ) : SalData(), m_eType( t ), m_pDisplay( NULL ) {} virtual ~SalGenericData() {} virtual void Dispose() {} diff --git a/vcl/inc/unx/gtk/gtkinst.hxx b/vcl/inc/unx/gtk/gtkinst.hxx index 3df521822877..80497dd8a572 100644 --- a/vcl/inc/unx/gtk/gtkinst.hxx +++ b/vcl/inc/unx/gtk/gtkinst.hxx @@ -82,19 +82,14 @@ public: class GtkSalTimer; #if GTK_CHECK_VERSION(3,0,0) class GtkInstance : public SvpSalInstance -{ -public: - GtkInstance( SalYieldMutex* pMutex ) - : SvpSalInstance( pMutex ) #else class GtkInstance : public X11SalInstance +#endif { public: - GtkInstance( SalYieldMutex* pMutex ) - : X11SalInstance( pMutex ) -#endif - {} + GtkInstance( SalYieldMutex* pMutex ); virtual ~GtkInstance(); + void Init(); virtual SalFrame* CreateFrame( SalFrame* pParent, sal_uLong nStyle ); virtual SalFrame* CreateChildFrame( SystemParentData* pParent, sal_uLong nStyle ); @@ -112,9 +107,17 @@ public: virtual bool AnyInput( sal_uInt16 nType ); void RemoveTimer (SalTimer *pTimer); + + // for managing a mirror of the in-flight un-dispatched gdk event queue + void addEvent( sal_uInt16 nMask ); + void subtractEvent( sal_uInt16 nMask ); private: std::vector<GtkSalTimer *> m_aTimers; bool IsTimerExpired(); + + // count of in-flight un-dispatched gdk events of a given input type + sal_uInt32 m_nAnyInput[16]; + void resetEvents(); }; #endif // _VCL_GTKINST_HXX diff --git a/vcl/unx/generic/app/salinst.cxx b/vcl/unx/generic/app/salinst.cxx index caac06931ba3..c6425baef1a8 100644 --- a/vcl/unx/generic/app/salinst.cxx +++ b/vcl/unx/generic/app/salinst.cxx @@ -167,6 +167,7 @@ bool X11SalInstance::AnyInput(sal_uInt16 nType) bRet = aInput.bRet; } + fprintf( stderr, "AnyInput 0x%x = %s\n", nType, bRet ? "true" : "false" ); return bRet; } diff --git a/vcl/unx/gtk/app/gtkinst.cxx b/vcl/unx/gtk/app/gtkinst.cxx index fbc96fca0c7e..db2d9dedb7da 100644 --- a/vcl/unx/gtk/app/gtkinst.cxx +++ b/vcl/unx/gtk/app/gtkinst.cxx @@ -29,6 +29,7 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_vcl.hxx" +#include <string.h> #include <osl/module.h> #include <unx/gtk/gtkdata.hxx> #include <unx/gtk/gtkinst.hxx> @@ -193,14 +194,130 @@ extern "C" pSalData->Init(); pSalData->initNWF(); + pInstance->Init(); + InitAtkBridge(); return pInstance; } } +// Handling the event queue + +void GtkInstance::resetEvents() +{ + memset( m_nAnyInput, 0, sizeof( m_nAnyInput ) ); +} + +void GtkInstance::addEvent( sal_uInt16 nMask ) +{ + sal_uInt16 nShift = 1; + for (int i = 0; i < 16; i++) { + if( nMask & nShift ) + m_nAnyInput[i]++; + nShift <<= 1; + } +} + +void GtkInstance::subtractEvent( sal_uInt16 nMask ) +{ + sal_uInt16 nShift = 1; + for (int i = 0; i < 16; i++) { + if( nMask & nShift && m_nAnyInput[i] > 0 ) + m_nAnyInput[i]--; + nShift <<= 1; + } +} + +extern "C" { + // We catch events as they pop out of X and into gdk + static GdkFilterReturn _sal_gtk_instance_filter_fn (GdkXEvent *_xevent, + GdkEvent *event, + gpointer data) + { + // FIXME: in theory this could be for non-X events but in reality it never is. + XEvent *pXEvent = (XEvent *)_xevent; + sal_uInt16 nType; + switch( pXEvent->type ) { + case ButtonPress: + case ButtonRelease: + case MotionNotify: + case EnterNotify: + case LeaveNotify: + nType = INPUT_MOUSE; + break; + case XLIB_KeyPress: + nType = INPUT_KEYBOARD; + break; + case Expose: + case GraphicsExpose: + case NoExpose: + nType = INPUT_PAINT; + break; + default: + nType = INPUT_OTHER; + break; + } + ((GtkInstance *)data)->addEvent( nType ); + + return GDK_FILTER_CONTINUE; + } + + // And then again as they pop out of gdk and into gtk+ + + static void _sal_gtk_event_handler_fn (GdkEvent *pEvent, gpointer data) + { + sal_uInt16 nType = 0; + switch( pEvent->type ) { + case GDK_MOTION_NOTIFY: + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + case GDK_BUTTON_RELEASE: + case GDK_ENTER_NOTIFY: + case GDK_LEAVE_NOTIFY: + case GDK_SCROLL: + nType = INPUT_MOUSE; + break; + case GDK_KEY_PRESS: + case GDK_KEY_RELEASE: + nType = INPUT_KEYBOARD; + break; + case GDK_EXPOSE: + nType = INPUT_PAINT; + break; + default: + nType = INPUT_OTHER; + break; + } + ((GtkInstance *)data)->subtractEvent( nType ); + + gtk_main_do_event( pEvent ); + } +} + +GtkInstance::GtkInstance( SalYieldMutex* pMutex ) +#if GTK_CHECK_VERSION(3,0,0) + : SvpSalInstance( pMutex ) +#else + : X11SalInstance( pMutex ) +#endif +{ + resetEvents(); +} + +// This has to happen after gtk_init has been called by saldata.cxx's +// Init or our handlers just get clobbered. +void GtkInstance::Init() +{ + gdk_window_add_filter( NULL, _sal_gtk_instance_filter_fn, this ); + gdk_event_handler_set( _sal_gtk_event_handler_fn, this, NULL ); +} + GtkInstance::~GtkInstance() { + gdk_event_handler_set( (GdkEventFunc)gtk_main_do_event, NULL, NULL ); + gdk_window_remove_filter( NULL, _sal_gtk_instance_filter_fn, this ); while( !m_aTimers.empty() ) delete *m_aTimers.begin(); DeInitAtkBridge(); @@ -213,9 +330,7 @@ SalFrame* GtkInstance::CreateFrame( SalFrame* pParent, sal_uLong nStyle ) SalFrame* GtkInstance::CreateChildFrame( SystemParentData* pParentData, sal_uLong ) { - SalFrame* pFrame = new GtkSalFrame( pParentData ); - - return pFrame; + return new GtkSalFrame( pParentData ); } SalObject* GtkInstance::CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, sal_Bool bShow ) @@ -273,7 +388,6 @@ void GtkInstance::AddToRecentDocumentList(const rtl::OUString& rFileUrl, const r #endif } - /* * Obsolete, non-working, and crufty code from the * beginning of time. When we update our base platform @@ -462,6 +576,9 @@ void GtkInstance::RemoveTimer (SalTimer *pTimer) void GtkInstance::Yield( bool bWait, bool bHandleAllCurrentEvents ) { GetGtkSalData()->Yield( bWait, bHandleAllCurrentEvents ); + + if( !gdk_events_pending() ) + resetEvents(); } bool GtkInstance::IsTimerExpired() @@ -485,13 +602,17 @@ bool GtkInstance::AnyInput( sal_uInt16 nType ) if( (nType & INPUT_TIMER) && IsTimerExpired() ) return true; else -#warning FIXME: this is really not ideal - we should snoop for misc. types - /* FIXME: AnyInput is also extremely fragile ... if we just return - !!gtk_events_pending(); we hang on start [!] ... amazing ...*/ - return false; -#if 0 - return X11SalInstance::AnyInput( nType ); -#endif + { + bool bRet = false; + sal_uInt16 nShift = 1; + for (int i = 0; i < 16; i++) { + bRet |= (nType & nShift) && m_nAnyInput[i] > 0; + nShift <<= 1; + } +// fprintf( stderr, "AnyInput 0x%x => %s\n", +// nType, bRet ? "true" : "false" ); + return bRet; + } } #if GTK_CHECK_VERSION(3,0,0) |