// keeps its previous value
static wxWindowGTK *g_focusWindowLast = (wxWindowGTK *)NULL;
+// the frame that is currently active (i.e. its child has focus). It is
+// used to generate wxActivateEvents
+static wxWindowGTK *g_activeFrame = (wxWindowGTK *)NULL;
+static bool g_activeFrameLostFocus = FALSE;
+
// if we detect that the app has got/lost the focus, we set this variable to
// either TRUE or FALSE and an activate event will be sent during the next
// OnIdle() call and it is reset to -1: this value means that we shouldn't
return (wxWindow *)NULL;
}
+// Returns toplevel grandparent of given window:
+static wxWindowGTK* wxGetTopLevelParent(wxWindowGTK *win)
+{
+ wxWindowGTK *p = win;
+ while (p && !p->IsTopLevel())
+ p = p->GetParent();
+ return p;
+}
+
+
static void draw_frame( GtkWidget *widget, wxWindowGTK *win )
{
// wxUniversal widgets draw the borders and scrollbars themselves
static long map_to_unmodified_wx_keysym( GdkEventKey *event )
{
KeySym keysym = event->keyval;
- guint key_code = 0;
+ long key_code;
switch (keysym)
{
case GDK_F11: key_code = WXK_F11; break;
case GDK_F12: key_code = WXK_F12; break;
default:
- {
- if (event->length == 1)
- {
- key_code = toupper( (unsigned char)*event->string );
- }
- else if ((keysym & 0xFF) == keysym)
+ if ( (keysym & 0xFF) == keysym )
{
guint upper = gdk_keyval_to_upper( (guint)keysym );
- keysym = (upper != 0 ? upper : keysym ); /* to be MSW compatible */
- key_code = (guint)keysym;
+ key_code = upper ? upper : keysym;
+ }
+ else
+ {
+ // unknown key code
+ key_code = 0;
}
- }
}
- return (key_code);
+ return key_code;
}
static long map_to_wx_keysym( GdkEventKey *event )
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;
- }
- else if ((keysym & 0xFF) == keysym)
+ if (event->length == 1)
+ {
+ key_code = (unsigned char)*event->string;
+ }
+ else if ((keysym & 0xFF) == keysym)
{
key_code = (guint)keysym;
}
- }
}
- return (key_code);
+ return key_code;
}
//-----------------------------------------------------------------------------
// "key_press_event" from any window
//-----------------------------------------------------------------------------
+// turn on to see the key event codes on the console
+#undef DEBUG_KEY_EVENTS
+
static gint gtk_window_key_press_callback( GtkWidget *widget,
GdkEventKey *gdk_event,
wxWindow *win )
if (g_blockEventsOnDrag) return FALSE;
-/*
- wxString tmp;
- tmp += (char)gdk_event->keyval;
- printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
- printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
-*/
-
int x = 0;
int y = 0;
GdkModifierType state;
- if (gdk_event->window) gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
+ if (gdk_event->window)
+ gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
bool ret = FALSE;
long key_code = map_to_unmodified_wx_keysym( gdk_event );
+
+#ifdef DEBUG_KEY_EVENTS
+ wxPrintf(_T("Key press event: %d => %ld\n"), gdk_event->keyval, key_code);
+#endif // DEBUG_KEY_EVENTS
+
/* sending unknown key events doesn't really make sense */
- if (key_code == 0) return FALSE;
+ if (key_code == 0)
+ return FALSE;
wxKeyEvent event( wxEVT_KEY_DOWN );
event.SetTimestamp( gdk_event->time );
}
#endif // wxUSE_ACCEL
- /* wxMSW doesn't send char events with Alt pressed */
/* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
will only be sent if it is not in an accelerator table. */
- key_code = map_to_wx_keysym( gdk_event );
+ if ( !ret )
+ {
+ key_code = map_to_wx_keysym( gdk_event );
- if ( (!ret) &&
- (key_code != 0))
- {
- wxKeyEvent event2( wxEVT_CHAR );
- event2.SetTimestamp( gdk_event->time );
- event2.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
- event2.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
- event2.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
- event2.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
- event2.m_keyCode = key_code;
- event2.m_scanCode = gdk_event->keyval;
- event2.m_x = x;
- event2.m_y = y;
- event2.SetEventObject( win );
- ret = win->GetEventHandler()->ProcessEvent( event2 );
+ if ( key_code )
+ {
+#ifdef DEBUG_KEY_EVENTS
+ wxPrintf(_T("Char event: %ld\n"), key_code);
+#endif // DEBUG_KEY_EVENTS
+
+ // reuse the ame event object, just change its type and use the
+ // translated keycode instead of the raw one
+ event.SetEventType(wxEVT_CHAR);
+ event.m_keyCode = key_code;
+
+ ret = win->GetEventHandler()->ProcessEvent( event );
+ }
}
/* win is a control: tab can be propagated up */
- if ( (!ret) &&
+ if ( !ret &&
((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
// VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
// have this style, yet choose not to process this particular TAB in which
// case TAB must still work as a navigational character
#if 0
- (!win->HasFlag(wxTE_PROCESS_TAB)) &&
+ !win->HasFlag(wxTE_PROCESS_TAB) &&
#endif // 0
- (win->GetParent()) &&
- (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
+ win->GetParent() && (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
{
wxNavigationKeyEvent new_event;
new_event.SetEventObject( win->GetParent() );
}
/* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
- if ( (!ret) &&
+ if ( !ret &&
(gdk_event->keyval == GDK_Escape) )
{
wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
ret = win->GetEventHandler()->ProcessEvent( new_event );
}
-#if (GTK_MINOR_VERSION > 0)
- /* Pressing F10 will activate the menu bar of the top frame. */
/* Doesn't work. */
-/*
+#if 0 // (GTK_MINOR_VERSION > 0)
+ /* Pressing F10 will activate the menu bar of the top frame. */
if ( (!ret) &&
(gdk_event->keyval == GDK_F10) )
{
ancestor = ancestor->GetParent();
}
}
-*/
-#endif
+#endif // 0
if (ret)
{
if (!win->m_hasVMT) return FALSE;
if (g_blockEventsOnDrag) return FALSE;
-/*
- printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
- if (gdk_event->state & GDK_SHIFT_MASK)
- printf( "ShiftDown.\n" );
- else
- printf( "ShiftUp.\n" );
- if (gdk_event->state & GDK_CONTROL_MASK)
- printf( "ControlDown.\n" );
- else
- printf( "ControlUp.\n" );
- printf( "\n" );
-*/
-
long key_code = map_to_unmodified_wx_keysym( gdk_event );
+#ifdef DEBUG_KEY_EVENTS
+ wxPrintf(_T("Key release event: %d => %ld\n"), gdk_event->keyval, key_code);
+#endif // DEBUG_KEY_EVENTS
+
/* sending unknown key events doesn't really make sense */
if (key_code == 0) return FALSE;
int x = 0;
int y = 0;
GdkModifierType state;
- if (gdk_event->window) gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
+ if (gdk_event->window)
+ gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
wxKeyEvent event( wxEVT_KEY_UP );
event.SetTimestamp( gdk_event->time );
}
#endif // wxUSE_CARET
- if (win->IsTopLevel())
+ wxWindowGTK *active = wxGetTopLevelParent(win);
+ if ( active != g_activeFrame )
{
- wxActivateEvent event( wxEVT_ACTIVATE, TRUE, win->GetId() );
- event.SetEventObject( win );
+ 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);
+ }
- // ignore return value
- win->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);
+ g_activeFrame->GetEventHandler()->ProcessEvent(event);
}
+ g_activeFrameLostFocus = FALSE;
+
wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
event.SetEventObject( win );
// "focus_out_event"
//-----------------------------------------------------------------------------
+static GtkWidget *gs_widgetLastFocus = NULL;
+
static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindowGTK *win )
{
DEBUG_MAIN_THREAD
if (!win->m_hasVMT) return FALSE;
if (g_blockEventsOnDrag) return FALSE;
+ // 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
+ // completely breaks wxUniv code so ignore this dummy event (we can't
+ // be losing focus if we're about to acquire it!)
+ if ( widget == gs_widgetLastFocus )
+ {
+ gs_widgetLastFocus = NULL;
+
+ return FALSE;
+ }
+
+ if ( !g_activeFrameLostFocus && g_activeFrame )
+ {
+ wxASSERT_MSG( wxGetTopLevelParent(win) == g_activeFrame, wxT("unfocusing window that haven't gained focus properly") )
+ 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
}
#endif // wxUSE_CARET
- if (win->IsTopLevel())
- {
- wxActivateEvent event( wxEVT_ACTIVATE, FALSE, win->GetId() );
- event.SetEventObject( win );
-
- // ignore return value
- win->GetEventHandler()->ProcessEvent( event );
- }
-
wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
event.SetEventObject( win );
if (g_focusWindow == this)
g_focusWindow = NULL;
+ if (g_activeFrame == this)
+ g_activeFrame = NULL;
+
m_isBeingDeleted = TRUE;
m_hasVMT = FALSE;
wxTheApp->SetActive(activate, (wxWindow *)g_focusWindowLast);
}
+ if ( g_activeFrameLostFocus )
+ {
+ 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);
+ g_activeFrame = NULL;
+ }
+ g_activeFrameLostFocus = FALSE;
+ }
+
wxCursor cursor = m_cursor;
if (g_globalCursor.Ok()) cursor = g_globalCursor;
dy = pizza->yoffset;
}
- int nx = m_x - dx;
- int ny = m_y - dy;
-
- if ( !IsTopLevel() && m_parent )
- {
- // We may be faking the client origin. So a window that's really at (0,
- // 30) may appear (to wxWin apps) to be at (0, 0).
- wxPoint pt(m_parent->GetClientAreaOrigin());
- nx -= pt.x;
- ny -= pt.y;
- }
-
- if (x) (*x) = nx;
- if (y) (*y) = ny;
+ if (x) (*x) = m_x - dx;
+ if (y) (*y) = m_y - dy;
}
void wxWindowGTK::DoClientToScreen( int *x, int *y ) const
if (m_wxwindow)
{
if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow))
+ {
+ // see comment in gtk_window_focus_out_callback()
+ gs_widgetLastFocus = m_wxwindow;
gtk_widget_grab_focus (m_wxwindow);
- return;
+ }
}
-
- if (m_widget)
+ else if (m_widget)
{
if (GTK_WIDGET_CAN_FOCUS(m_widget) && !GTK_WIDGET_HAS_FOCUS (m_widget) )
{