summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@suse.com>2011-10-06 22:22:39 +0100
committerMichael Meeks <michael.meeks@suse.com>2011-10-25 13:41:52 +0100
commit28b1f4ca5af84048a003a5dcf68c1f27296c0d0c (patch)
tree090e263f8183e092c2d1fb144890944044023c96 /vcl
parent2e48ed930d61e02da82c71790994204d3aefaa29 (diff)
gtk3: make AnyInput to behave itself properly
Diffstat (limited to 'vcl')
-rw-r--r--vcl/inc/generic/gendata.hxx2
-rw-r--r--vcl/inc/unx/gtk/gtkinst.hxx19
-rw-r--r--vcl/unx/generic/app/salinst.cxx1
-rw-r--r--vcl/unx/gtk/app/gtkinst.cxx143
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)