static long map_to_unmodified_wx_keysym( GdkEventKey *event )
{
+ // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string
+ // but only event->keyval which is quite useless to us, so remember
+ // the last character from GDK_KEY_PRESS and resue it as last resort
+ //
+ // NB: should be MT-neutral as always called from main thread only
+ static struct
+ {
+ KeySym keysym;
+ long keycode;
+ } s_lastKeyPress = { 0, 0 };
+
KeySym keysym = event->keyval;
long key_code;
- switch (keysym)
+ switch ( keysym )
{
case GDK_Shift_L:
case GDK_Shift_R: key_code = WXK_SHIFT; break;
case GDK_F11: key_code = WXK_F11; break;
case GDK_F12: key_code = WXK_F12; break;
default:
- if ( (keysym & 0xFF) == keysym )
+ {
+ // do we have the translation?
+ if ( event->length == 1 )
{
- guint upper = gdk_keyval_to_upper( (guint)keysym );
- key_code = upper ? upper : keysym;
+ keysym = (KeySym)event->string[0];
}
- else
+ else if ( (keysym & 0xFF) != keysym )
{
- // unknown key code
- key_code = 0;
+ // non ASCII key, what to do?
+
+ if ( event->type == GDK_KEY_RELEASE )
+ {
+ // reuse the one from the last keypress if any
+ if ( keysym == s_lastKeyPress.keysym )
+ {
+ key_code = s_lastKeyPress.keycode;
+
+ // skip "return 0"
+ break;
+ }
+ }
+
+ // ignore this one, we don't know it
+ return 0;
}
+ //else: ASCII key, ok
+
+ guint upper = gdk_keyval_to_upper( (guint)keysym );
+ key_code = upper ? upper : keysym;
+
+ if ( event->type == GDK_KEY_PRESS )
+ {
+ // remember it to be reused below later
+ s_lastKeyPress.keysym = keysym;
+ s_lastKeyPress.keycode = key_code;
+ }
+ }
}
return key_code;
case GDK_F11: key_code = WXK_F11; break;
case GDK_F12: key_code = WXK_F12; break;
default:
- {
if (event->length == 1)
{
key_code = (unsigned char)*event->string;
{
key_code = (guint)keysym;
}
- }
}
return key_code;
return FALSE;
}
+// ============================================================================
+// the mouse events
+// ============================================================================
+
+// init wxMouseEvent with the info from gdk_event
+#define InitMouseEvent(win, event, gdk_event) \
+ { \
+ event.SetTimestamp( gdk_event->time ); \
+ event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
+ event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
+ event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
+ event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
+ event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
+ event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
+ event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
+\
+ wxPoint pt = win->GetClientAreaOrigin(); \
+ event.m_x = (wxCoord)gdk_event->x - pt.x; \
+ event.m_y = (wxCoord)gdk_event->y - pt.y; \
+ }
+
// ----------------------------------------------------------------------------
// mouse event processing helper
// ----------------------------------------------------------------------------
}
wxMouseEvent event( event_type );
- event.SetTimestamp( gdk_event->time );
- event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
- event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
- event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
- event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
- event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
- event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
- event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
-
- event.m_x = (wxCoord)gdk_event->x;
- event.m_y = (wxCoord)gdk_event->y;
+ InitMouseEvent( win, event, gdk_event );
AdjustEventButtonState(event);
+
+ // wxListBox actually get mouse events from the item
+
+ if (win->m_isListBox)
+ {
+ event.m_x += widget->allocation.x;
+ event.m_y += widget->allocation.y;
+ }
// Some control don't have their own X window and thus cannot get
// any events.
}
wxMouseEvent event( event_type );
- event.SetTimestamp( gdk_event->time );
- event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
- event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
- event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
- event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
- event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
- event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
- event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
- event.m_x = (wxCoord)gdk_event->x;
- event.m_y = (wxCoord)gdk_event->y;
+ InitMouseEvent( win, event, gdk_event );
AdjustEventButtonState(event);
+ // wxListBox actually get mouse events from the item
+
+ if (win->m_isListBox)
+ {
+ event.m_x += widget->allocation.x;
+ event.m_y += widget->allocation.y;
+ }
+
// Some control don't have their own X window and thus cannot get
// any events.
return FALSE;
}
-// ============================================================================
-// the mouse events
-// ============================================================================
-
-// init wxMouseEvent with the info from gdk_event
-#define InitMouseEvent(event, gdk_event) \
- event.SetTimestamp( gdk_event->time ); \
- event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
- event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
- event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
- event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
- event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
- event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
- event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
-\
- event.m_x = (wxCoord)gdk_event->x; \
- event.m_y = (wxCoord)gdk_event->y \
-
//-----------------------------------------------------------------------------
// "motion_notify_event"
//-----------------------------------------------------------------------------
*/
wxMouseEvent event( wxEVT_MOTION );
- InitMouseEvent(event, gdk_event);
+ InitMouseEvent(win, event, gdk_event);
if ( g_captureWindow )
{
wxMouseEvent event(g_captureWindowHasMouse ? wxEVT_ENTER_WINDOW
: wxEVT_LEAVE_WINDOW);
- InitMouseEvent(event, gdk_event);
+ InitMouseEvent(win, event, gdk_event);
event.SetEventObject(win);
win->GetEventHandler()->ProcessEvent(event);
}
}
#endif // wxUSE_CARET
-
wxWindowGTK *active = wxGetTopLevelParent(win);
if ( active != g_activeFrame )
{
if ( g_activeFrame )
{
+ wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame);
wxActivateEvent event(wxEVT_ACTIVATE, FALSE, g_activeFrame->GetId());
event.SetEventObject(g_activeFrame);
g_activeFrame->GetEventHandler()->ProcessEvent(event);
}
+ wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active);
g_activeFrame = active;
wxActivateEvent event(wxEVT_ACTIVATE, TRUE, g_activeFrame->GetId());
event.SetEventObject(g_activeFrame);
if (!win->m_hasVMT) return FALSE;
if (g_blockEventsOnDrag) return FALSE;
- //wxASSERT_MSG( wxGetTopLevelParent(win) == g_activeFrame, wxT("unfocusing window that haven't gained focus properly") )
- g_activeFrameLostFocus = TRUE;
-
// VZ: this is really weird but GTK+ seems to call us from inside
// gtk_widget_grab_focus(), i.e. it first sends "focus_out" signal to
// this widget and then "focus_in". This is totally unexpected and
return FALSE;
}
+ if ( !g_activeFrameLostFocus && g_activeFrame )
+ {
+ // VZ: commenting this out because it does happen (although not easy
+ // to reproduce, I only see it when using wxMiniFrame and not
+ // always) and makes using Mahogany quite annoying
+#if 0
+ wxASSERT_MSG( wxGetTopLevelParent(win) == g_activeFrame,
+ wxT("unfocusing window that hasn't gained focus properly") )
+#endif // 0
+
+ g_activeFrameLostFocus = TRUE;
+ }
+
// if the focus goes out of our app alltogether, OnIdle() will send
// wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
// g_sendActivateEvent to -1
gdk_window_get_pointer( widget->window, &x, &y, &state );
- InitMouseEvent(event, gdk_event);
-
- event.m_x = x;
- event.m_y = y;
+ InitMouseEvent(win, event, gdk_event);
+ wxPoint pt = win->GetClientAreaOrigin();
+ event.m_x = x + pt.x;
+ event.m_y = y + pt.y;
if (win->GetEventHandler()->ProcessEvent( event ))
{
event.m_middleDown = (state & GDK_BUTTON2_MASK);
event.m_rightDown = (state & GDK_BUTTON3_MASK);
- event.m_x = x;
- event.m_y = y;
+ wxPoint pt = win->GetClientAreaOrigin();
+ event.m_x = x + pt.x;
+ event.m_y = y + pt.y;
if (win->GetEventHandler()->ProcessEvent( event ))
{
m_isStaticBox = FALSE;
m_isRadioButton = FALSE;
+ m_isListBox = FALSE;
m_isFrame = FALSE;
m_acceptsFocus = FALSE;
{
if ( g_activeFrame )
{
+ wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame);
wxActivateEvent event(wxEVT_ACTIVATE, FALSE, g_activeFrame->GetId());
event.SetEventObject(g_activeFrame);
g_activeFrame->GetEventHandler()->ProcessEvent(event);
{
wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
+#if 0
+ wxPrintf( "SetFocus from " );
+ if (GetClassInfo() && GetClassInfo()->GetClassName())
+ wxPrintf( GetClassInfo()->GetClassName() );
+ wxPrintf( ".\n" );
+#endif
+
if (m_wxwindow)
{
if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow))
// ?
}
}
+
+#if 0
+ wxPrintf( "SetFocus finished in " );
+ if (GetClassInfo() && GetClassInfo()->GetClassName())
+ wxPrintf( GetClassInfo()->GetClassName() );
+ wxPrintf( ".\n" );
+#endif
+
}
bool wxWindowGTK::AcceptsFocus() const
}
}
+// used to pass the coordinates from wxWindowGTK::DoPopupMenu() to
+// wxPopupMenuPositionCallback()
+//
+// should be safe even in the MT case as the user can hardly popup 2 menus
+// simultaneously, can he?
static gint gs_pop_x = 0;
static gint gs_pop_y = 0;
-static void pop_pos_callback( GtkMenu * WXUNUSED(menu),
- gint *x, gint *y,
- wxWindowGTK *win )
+static void wxPopupMenuPositionCallback( GtkMenu *menu,
+ gint *x, gint *y,
+ gpointer WXUNUSED(user_data) )
{
- win->ClientToScreen( &gs_pop_x, &gs_pop_y );
- *x = gs_pop_x;
- *y = gs_pop_y;
+ // ensure that the menu appears entirely on screen
+ GtkRequisition req;
+ gtk_widget_get_child_requisition(GTK_WIDGET(menu), &req);
+
+ wxSize sizeScreen = wxGetDisplaySize();
+
+ gint xmax = sizeScreen.x - req.width,
+ ymax = sizeScreen.y - req.height;
+
+ *x = gs_pop_x < xmax ? gs_pop_x : xmax;
+ *y = gs_pop_y < ymax ? gs_pop_y : ymax;
}
bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y )
gs_pop_x = x;
gs_pop_y = y;
+ ClientToScreen( &gs_pop_x, &gs_pop_y );
bool is_waiting = TRUE;
gtk_menu_popup(
GTK_MENU(menu->m_menu),
- (GtkWidget *) NULL, // parent menu shell
- (GtkWidget *) NULL, // parent menu item
- (GtkMenuPositionFunc) pop_pos_callback,
- (gpointer) this, // client data
- 0, // button used to activate it
- gs_timeLastClick // the time of activation
+ (GtkWidget *) NULL, // parent menu shell
+ (GtkWidget *) NULL, // parent menu item
+ wxPopupMenuPositionCallback, // function to position it
+ NULL, // client data
+ 0, // button used to activate it
+ gs_timeLastClick // the time of activation
);
while (is_waiting)