#include "wx/gtk/private/event.h"
using namespace wxGTKImpl;
+#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
+#else
+typedef guint KeySym;
+#endif
#include <gdk/gdkkeysyms.h>
#if GTK_CHECK_VERSION(3,0,0)
keysym = (KeySym)gdk_event->string[0];
}
+#ifdef GDK_WINDOWING_X11
// we want to always get the same key code when the same key is
// pressed regardless of the state of the modifiers, i.e. on a
// standard US keyboard pressing '5' or '%' ('5' key with
// use the normalized, i.e. lower register, keysym if we've
// got one
key_code = keysymNormalized ? keysymNormalized : keysym;
+#else
+ key_code = keysym;
+#endif
// as explained above, we want to have lower register key codes
// normally but for the letter keys we want to have the upper ones
} // anonymous namespace
+// If a widget does not handle a key or mouse event, GTK+ sends it up the
+// parent chain until it is handled. These events are not supposed to propagate
+// in wxWidgets, so this code avoids handling them in any parent wxWindow,
+// while still allowing the event to propagate so things like native keyboard
+// navigation will work.
+#define wxPROCESS_EVENT_ONCE(EventType, event) \
+ static EventType eventPrev; \
+ if (memcmp(&eventPrev, event, sizeof(EventType)) == 0) \
+ return false; \
+ eventPrev = *event
+
extern "C" {
static gboolean
gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget),
if (g_blockEventsOnDrag)
return FALSE;
+ wxPROCESS_EVENT_ONCE(GdkEventKey, gdk_event);
+
wxKeyEvent event( wxEVT_KEY_DOWN );
bool ret = false;
bool return_after_IM = false;
if (g_blockEventsOnDrag)
return FALSE;
+ wxPROCESS_EVENT_ONCE(GdkEventKey, gdk_event);
+
wxKeyEvent event( wxEVT_KEY_UP );
if ( !wxTranslateGTKKeyEventToWx(event, win, gdk_event) )
{
}
}
-//-----------------------------------------------------------------------------
-// key and mouse events, after, from m_widget
-//-----------------------------------------------------------------------------
-
-extern "C" {
-static gboolean key_and_mouse_event_after(GtkWidget* widget, GdkEventKey*, wxWindow*)
-{
- // If a widget does not handle a key or mouse event, GTK+ sends it up the
- // parent chain until it is handled. These events are not supposed to
- // propagate in wxWidgets, so prevent it unless widget is in a native
- // container.
- return WX_IS_PIZZA(gtk_widget_get_parent(widget));
-}
-}
-
// ============================================================================
// the mouse events
// ============================================================================
else
{
if ((child->m_wxwindow == NULL) &&
- !gtk_widget_get_has_window(child->m_widget) &&
win->IsClientAreaChild(child) &&
(child->m_x <= xx) &&
(child->m_y <= yy) &&
GdkEventButton *gdk_event,
wxWindowGTK *win )
{
+ wxPROCESS_EVENT_ONCE(GdkEventButton, gdk_event);
+
wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win);
g_lastButtonNumber = gdk_event->button;
GdkEventButton *gdk_event,
wxWindowGTK *win )
{
+ wxPROCESS_EVENT_ONCE(GdkEventButton, gdk_event);
+
wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win);
g_lastButtonNumber = 0;
GdkEventMotion *gdk_event,
wxWindowGTK *win )
{
+ wxPROCESS_EVENT_ONCE(GdkEventMotion, gdk_event);
+
wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win);
if (gdk_event->is_hint)
static gboolean
window_scroll_event(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* win)
{
- if (gdk_event->direction != GDK_SCROLL_UP &&
- gdk_event->direction != GDK_SCROLL_DOWN)
- {
- return false;
- }
-
wxMouseEvent event(wxEVT_MOUSEWHEEL);
InitMouseEvent(win, event, gdk_event);
// FIXME: Get these values from GTK or GDK
event.m_linesPerAction = 3;
event.m_wheelDelta = 120;
- if (gdk_event->direction == GDK_SCROLL_UP)
- event.m_wheelRotation = 120;
- else
- event.m_wheelRotation = -120;
+
+ // Determine the scroll direction.
+ switch (gdk_event->direction)
+ {
+ case GDK_SCROLL_UP:
+ case GDK_SCROLL_RIGHT:
+ event.m_wheelRotation = 120;
+ break;
+
+ case GDK_SCROLL_DOWN:
+ case GDK_SCROLL_LEFT:
+ event.m_wheelRotation = -120;
+ break;
+
+ default:
+ return false; // Unknown/unhandled direction
+ }
+
+ // And the scroll axis.
+ switch (gdk_event->direction)
+ {
+ case GDK_SCROLL_UP:
+ case GDK_SCROLL_DOWN:
+ event.m_wheelAxis = wxMOUSE_WHEEL_VERTICAL;
+ break;
+
+ case GDK_SCROLL_LEFT:
+ case GDK_SCROLL_RIGHT:
+ event.m_wheelAxis = wxMOUSE_WHEEL_HORIZONTAL;
+ break;
+ }
if (win->GTKProcessEvent(event))
return TRUE;
m_width = WidthDefault(size.x) ;
m_height = HeightDefault(size.y);
- m_x = (int)pos.x;
- m_y = (int)pos.y;
+ if (pos != wxDefaultPosition)
+ {
+ m_x = pos.x;
+ m_y = pos.y;
+ }
return true;
}
ConnectWidget( connect_widget );
- // connect handler to prevent events from propagating up parent chain
- g_signal_connect_after(m_widget,
- "key_press_event", G_CALLBACK(key_and_mouse_event_after), this);
- g_signal_connect_after(m_widget,
- "key_release_event", G_CALLBACK(key_and_mouse_event_after), this);
- g_signal_connect_after(m_widget,
- "button_press_event", G_CALLBACK(key_and_mouse_event_after), this);
- g_signal_connect_after(m_widget,
- "button_release_event", G_CALLBACK(key_and_mouse_event_after), this);
- g_signal_connect_after(m_widget,
- "motion_notify_event", G_CALLBACK(key_and_mouse_event_after), this);
-
// We cannot set colours, fonts and cursors before the widget has been
// realized, so we do this directly after realization -- unless the widget
// was in fact realized already.
void wxWindowGTK::DoGetSize( int *width, int *height ) const
{
- wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
-
if (width) (*width) = m_width;
if (height) (*height) = m_height;
}
void wxWindowGTK::DoGetPosition( int *x, int *y ) const
{
- wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
-
int dx = 0;
int dy = 0;
- if (!IsTopLevel() && m_parent && m_parent->m_wxwindow)
+ GtkWidget* parent = NULL;
+ if (m_widget)
+ parent = gtk_widget_get_parent(m_widget);
+ if (WX_IS_PIZZA(parent))
{
- wxPizza* pizza = WX_PIZZA(m_parent->m_wxwindow);
+ wxPizza* pizza = WX_PIZZA(parent);
dx = pizza->m_scroll_x;
dy = pizza->m_scroll_y;
}
-
- if (m_x == -1 && m_y == -1)
- {
- GdkWindow *source = NULL;
- if (m_wxwindow)
- source = gtk_widget_get_window(m_wxwindow);
- else
- source = gtk_widget_get_window(m_widget);
-
- if (source)
- {
- int org_x = 0;
- int org_y = 0;
- gdk_window_get_origin( source, &org_x, &org_y );
-
- if (m_parent)
- m_parent->ScreenToClient(&org_x, &org_y);
-
- const_cast<wxWindowGTK*>(this)->m_x = org_x;
- const_cast<wxWindowGTK*>(this)->m_y = org_y;
- }
- }
-
if (x) (*x) = m_x - dx;
if (y) (*y) = m_y - dy;
}
GdkDeviceManager* manager = gdk_display_get_device_manager(display);
gdk_device_warp(gdk_device_manager_get_client_pointer(manager), screen, x, y);
#else
+#ifdef GDK_WINDOWING_X11
XWarpPointer(GDK_DISPLAY_XDISPLAY(display),
None,
GDK_WINDOW_XID(gdk_screen_get_root_window(screen)),
0, 0, 0, 0, x, y);
#endif
+#endif
}
wxWindowGTK::ScrollDir wxWindowGTK::ScrollDirFromRange(GtkRange *range) const
{
// Make sure GDK/X11 doesn't refresh the window
// automatically.
- gdk_window_set_back_pixmap( window, None, False );
+ gdk_window_set_back_pixmap( window, NULL, FALSE );
m_needsStyleChange = false;
}
else // window not realized yet