+#ifndef __WXGTK20__
+static gint gtk_window_key_press_callback( GtkWidget *widget,
+ GdkEventKey *gdk_event,
+ wxWindow *win )
+{
+ DEBUG_MAIN_THREAD
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (!win->m_hasVMT)
+ return FALSE;
+ if (g_blockEventsOnDrag)
+ return FALSE;
+
+
+ wxKeyEvent event( wxEVT_KEY_DOWN );
+ if ( !wxTranslateGTKKeyEventToWx(event, win, gdk_event) )
+ {
+ // unknown key pressed, ignore (the event would be useless anyhow)
+ return FALSE;
+ }
+
+ // Emit KEY_DOWN event
+ bool ret = win->GetEventHandler()->ProcessEvent( event );
+
+#if wxUSE_ACCEL
+ if (!ret)
+ {
+ wxWindowGTK *ancestor = win;
+ while (ancestor)
+ {
+ int command = ancestor->GetAcceleratorTable()->GetCommand( event );
+ if (command != -1)
+ {
+ wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
+ ret = ancestor->GetEventHandler()->ProcessEvent( command_event );
+ break;
+ }
+ if (ancestor->IsTopLevel())
+ break;
+ ancestor = ancestor->GetParent();
+ }
+ }
+#endif // wxUSE_ACCEL
+
+ // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
+ // will only be sent if it is not in an accelerator table.
+ if (!ret)
+ {
+ // Find key code for EVT_CHAR and EVT_CHAR_HOOK events
+ KeySym keysym = gdk_event->keyval;
+ long key_code = wxTranslateKeySymToWXKey(keysym, TRUE /* isChar */);
+ if ( !key_code )
+ {
+ if ( gdk_event->length == 1 )
+ {
+ key_code = (unsigned char)gdk_event->string[0];
+ }
+ else if ( wxIsAsciiKeysym(keysym) )
+ {
+ // ASCII key
+ key_code = (unsigned char)keysym;
+ }
+ }
+
+ if ( key_code )
+ {
+ wxLogTrace(TRACE_KEYS, _T("Char event: %ld"), key_code);
+
+ event.m_keyCode = key_code;
+
+ // Implement OnCharHook by checking ancesteror top level windows
+ wxWindow *parent = win;
+ while (parent && !parent->IsTopLevel())
+ parent = parent->GetParent();
+ if (parent)
+ {
+ event.SetEventType( wxEVT_CHAR_HOOK );
+ ret = parent->GetEventHandler()->ProcessEvent( event );
+ }
+
+ if (!ret)
+ {
+ event.SetEventType(wxEVT_CHAR);
+ ret = win->GetEventHandler()->ProcessEvent( event );
+ }
+ }
+ }
+
+ // win is a control: tab can be propagated up
+ 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) &&
+#endif // 0
+ win->GetParent() && (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
+ {
+ wxNavigationKeyEvent new_event;
+ new_event.SetEventObject( win->GetParent() );
+ // GDK reports GDK_ISO_Left_Tab for SHIFT-TAB
+ new_event.SetDirection( (gdk_event->keyval == GDK_Tab) );
+ // CTRL-TAB changes the (parent) window, i.e. switch notebook page
+ new_event.SetWindowChange( (gdk_event->state & GDK_CONTROL_MASK) );
+ new_event.SetCurrentFocus( win );
+ ret = win->GetParent()->GetEventHandler()->ProcessEvent( new_event );
+ }
+
+ // generate wxID_CANCEL if <esc> has been pressed (typically in dialogs)
+ if ( !ret &&
+ (gdk_event->keyval == GDK_Escape) )
+ {
+ // however only do it if we have a Cancel button in the dialog,
+ // otherwise the user code may get confused by the events from a
+ // non-existing button and, worse, a wxButton might get button event
+ // from another button which is not really expected
+ wxWindow *winForCancel = win,
+ *btnCancel = NULL;
+ while ( winForCancel )
+ {
+ btnCancel = winForCancel->FindWindow(wxID_CANCEL);
+ if ( btnCancel )
+ {
+ // found a cancel button
+ break;
+ }
+
+ if ( winForCancel->IsTopLevel() )
+ {
+ // no need to look further
+ break;
+ }
+
+ // maybe our parent has a cancel button?
+ winForCancel = winForCancel->GetParent();
+ }
+
+ if ( btnCancel )
+ {
+ wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
+ event.SetEventObject(btnCancel);
+ ret = btnCancel->GetEventHandler()->ProcessEvent(event);
+ }
+ }
+
+ if (ret)
+ {
+ gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
+ return TRUE;
+ }
+
+ return FALSE;
+}
+#endif
+
+#ifdef __WXGTK20__
+static gint gtk_window_key_press_callback( GtkWidget *widget,
+ GdkEventKey *gdk_event,
+ wxWindow *win )
+{
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (!win->m_hasVMT)
+ return FALSE;
+ if (g_blockEventsOnDrag)
+ return FALSE;
+
+ bool ret = FALSE;
+ bool dont_use_IM = FALSE;
+
+ wxKeyEvent event( wxEVT_KEY_DOWN );
+ long keycode = wxTranslateKeySymToWXKey( gdk_event->keyval, FALSE );
+ if (keycode)
+ {
+ // We were able to decode the key press without
+ // any input method, so don't use it.
+ dont_use_IM = TRUE;
+
+ // now fill all the other fields
+ int x = 0;
+ int y = 0;
+ GdkModifierType state;
+ if (gdk_event->window)
+ gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
+
+ event.SetTimestamp( gdk_event->time );
+ event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK) != 0;
+ event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK) != 0;
+ event.m_altDown = (gdk_event->state & GDK_MOD1_MASK) != 0;
+ event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK) != 0;
+ event.m_keyCode = keycode;
+ event.m_scanCode = gdk_event->keyval;
+ event.m_rawCode = (wxUint32) gdk_event->keyval;
+ event.m_rawFlags = 0;
+ event.m_x = x;
+ event.m_y = y;
+ event.SetEventObject( win );
+
+ // send key down event
+ ret = win->GetEventHandler()->ProcessEvent( event );
+
+ if (!ret)
+ {
+ // Implement OnCharHook by checking ancesteror top level windows
+ wxWindow *parent = win;
+ while (parent && !parent->IsTopLevel())
+ parent = parent->GetParent();
+ if (parent)
+ {
+ event.SetEventType( wxEVT_CHAR_HOOK );
+ ret = parent->GetEventHandler()->ProcessEvent( event );
+ }
+
+ if (!ret)
+ {
+ event.SetEventType(wxEVT_CHAR);
+ ret = win->GetEventHandler()->ProcessEvent( event );
+ }
+ }
+
+ // win is a control: tab can be propagated up
+ if ( !ret &&
+ ((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
+ win->GetParent() && (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
+ {
+ wxNavigationKeyEvent new_event;
+ new_event.SetEventObject( win->GetParent() );
+ // GDK reports GDK_ISO_Left_Tab for SHIFT-TAB
+ new_event.SetDirection( (gdk_event->keyval == GDK_Tab) );
+ // CTRL-TAB changes the (parent) window, i.e. switch notebook page
+ new_event.SetWindowChange( (gdk_event->state & GDK_CONTROL_MASK) );
+ new_event.SetCurrentFocus( win );
+ ret = win->GetParent()->GetEventHandler()->ProcessEvent( new_event );
+ }
+
+ if ( !ret &&
+ (gdk_event->keyval == GDK_Escape) )
+ {
+ wxWindow *winForCancel = win, *btnCancel = NULL;
+ while ( winForCancel )
+ {
+ btnCancel = winForCancel->FindWindow(wxID_CANCEL);
+ if ( btnCancel ) break;
+
+ if ( winForCancel->IsTopLevel() ) break;
+
+ winForCancel = winForCancel->GetParent();
+ }
+
+ if ( btnCancel )
+ {
+ wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
+ event.SetEventObject(btnCancel);
+ ret = btnCancel->GetEventHandler()->ProcessEvent(event);
+ }
+ }
+ }
+
+ if (ret)
+ {
+ gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
+ return TRUE;
+ }
+
+ if (!dont_use_IM && win->m_imContext)
+ {
+ // In GTK 2.0, we need to hand over the key
+ // event to an input method and the IM will
+ // emit a "commit" event containing the
+ // actual utf8 character.
+ gtk_im_context_filter_keypress ( (GtkIMContext*) win->m_imContext, gdk_event );
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void gtk_wxwindow_commit_cb (GtkIMContext *context,
+ const gchar *str,
+ wxWindow *window)
+{
+ bool ret = FALSE;
+
+ wxKeyEvent event( wxEVT_KEY_DOWN );
+
+#if wxUSE_UNICODE
+ event.m_uniChar = g_utf8_get_char( str );
+
+ // Backward compatible for ISO-8859
+ if (event.m_uniChar < 256)
+ event.m_keyCode = event.m_uniChar;
+#else
+ gunichar uniChar = g_utf8_get_char( str );
+ // We cannot handle Unicode in non-Unicode mode
+ if (uniChar > 255) return;
+
+ event.m_keyCode = uniChar;
+#endif
+
+ if (!ret)
+ {
+ // Implement OnCharHook by checking ancesteror top level windows
+ wxWindow *parent = window;
+ while (parent && !parent->IsTopLevel())
+ parent = parent->GetParent();
+ if (parent)
+ {
+ event.SetEventType( wxEVT_CHAR_HOOK );
+ ret = parent->GetEventHandler()->ProcessEvent( event );
+ }
+
+ if (!ret)
+ {
+ event.SetEventType(wxEVT_CHAR);
+ ret = window->GetEventHandler()->ProcessEvent( event );
+ }
+ }
+}
+#endif
+
+