X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/67b73b9aab15be55949b2e0a97270c552cc0af9f..5b008dd712dc781933629f19039587076094ed8a:/src/gtk/window.cpp diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index fe8da3d23a..d98386fe20 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -47,6 +47,7 @@ #include "wx/settings.h" #include "wx/log.h" #include "wx/fontutil.h" +#include "wx/stattext.h" #ifdef __WXDEBUG__ #include "wx/thread.h" @@ -55,6 +56,12 @@ #include "wx/math.h" #include +// FIXME: Due to a hack we use GtkCombo in here, which is deprecated since gtk2.3.0 +#include +#if defined(GTK_DISABLE_DEPRECATED) && GTK_CHECK_VERSION(2,3,0) +#undef GTK_DISABLE_DEPRECATED +#endif + #include "wx/gtk/private.h" #include #include @@ -830,6 +837,10 @@ static void wxFillOtherKeyEventFields(wxKeyEvent& event, event.m_rawFlags = 0; #if wxUSE_UNICODE event.m_uniChar = gdk_keyval_to_unicode(gdk_event->keyval); + if ( gdk_event->type == GDK_KEY_PRESS || gdk_event->type == GDK_KEY_RELEASE ) + { + event.m_uniChar = toupper(event.m_uniChar); + } #endif wxGetMousePosition( &x, &y ); win->ScreenToClient( &x, &y ); @@ -1066,6 +1077,16 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, event.m_keyCode = key_code; + // To conform to the docs we need to translate Ctrl-alpha + // characters to values in the range 1-26. + if (event.ControlDown() && key_code >= 'a' && key_code <= 'z' ) + { + event.m_keyCode = key_code - 'a' + 1; +#if wxUSE_UNICODE + event.m_uniChar = event.m_keyCode; +#endif + } + // Implement OnCharHook by checking ancestor top level windows wxWindow *parent = win; while (parent && !parent->IsTopLevel()) @@ -1200,6 +1221,17 @@ static void gtk_wxwindow_commit_cb (GtkIMContext *context, #else event.m_keyCode = *pstr; #endif // wxUSE_UNICODE + + // To conform to the docs we need to translate Ctrl-alpha + // characters to values in the range 1-26. + if (event.ControlDown() && *pstr >= 'a' && *pstr <= 'z' ) + { + event.m_keyCode = *pstr - 'a' + 1; +#if wxUSE_UNICODE + event.m_uniChar = event.m_keyCode; +#endif + } + if (parent) { event.SetEventType( wxEVT_CHAR_HOOK ); @@ -1809,9 +1841,9 @@ static bool DoSendFocusEvents(wxWindow *win) } extern "C" { -static gint gtk_window_focus_in_callback( GtkWidget *widget, - GdkEvent *WXUNUSED(event), - wxWindow *win ) +static gboolean gtk_window_focus_in_callback( GtkWidget *widget, + GdkEvent *WXUNUSED(event), + wxWindow *win ) { DEBUG_MAIN_THREAD @@ -1841,20 +1873,25 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, } #endif // wxUSE_CARET + gboolean ret = FALSE; + // does the window itself think that it has the focus? if ( !win->m_hasFocus ) { // not yet, notify it win->m_hasFocus = true; - if ( DoSendFocusEvents(win) ) - { - g_signal_stop_emission_by_name (widget, "focus_in_event"); - return TRUE; - } + (void)DoSendFocusEvents(win); + + ret = true; } - return FALSE; + // Disable default focus handling for custom windows + // since the default GTK+ handler issues a repaint + if (win->m_wxwindow) + return ret; + + return false; } } @@ -1863,7 +1900,9 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, //----------------------------------------------------------------------------- extern "C" { -static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk_event, wxWindowGTK *win ) +static gboolean gtk_window_focus_out_callback( GtkWidget *widget, + GdkEventFocus *gdk_event, + wxWindowGTK *win ) { DEBUG_MAIN_THREAD @@ -1897,6 +1936,8 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk } #endif // wxUSE_CARET + gboolean ret = FALSE; + // don't send the window a kill focus event if it thinks that it doesn't // have focus already if ( win->m_hasFocus ) @@ -1906,14 +1947,17 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() ); event.SetEventObject( win ); - // even if we did process the event in wx code, still let GTK itself - // process it too as otherwise bad things happen, especially in GTK2 - // where the text control simply aborts the program if it doesn't get - // the matching focus out event (void)win->GetEventHandler()->ProcessEvent( event ); + + ret = true; } - - return FALSE; + + // Disable default focus handling for custom windows + // since the default GTK+ handler issues a repaint + if (win->m_wxwindow) + return ret; + + return false; } } @@ -1922,10 +1966,10 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk //----------------------------------------------------------------------------- extern "C" { -static -gint gtk_window_enter_callback( GtkWidget *widget, - GdkEventCrossing *gdk_event, - wxWindowGTK *win ) +static gboolean +gtk_window_enter_callback( GtkWidget *widget, + GdkEventCrossing *gdk_event, + wxWindowGTK *win ) { DEBUG_MAIN_THREAD @@ -1967,7 +2011,10 @@ gint gtk_window_enter_callback( GtkWidget *widget, //----------------------------------------------------------------------------- extern "C" { -static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindowGTK *win ) +static gboolean +gtk_window_leave_callback( GtkWidget *widget, + GdkEventCrossing *gdk_event, + wxWindowGTK *win ) { DEBUG_MAIN_THREAD @@ -2683,7 +2730,7 @@ void wxWindowGTK::PostCreation() g_signal_connect (m_wxwindow, "expose_event", G_CALLBACK (gtk_window_expose_callback), this); - // gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), !HasFlag( wxFULL_REPAINT_ON_RESIZE ) ); + gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), HasFlag( wxFULL_REPAINT_ON_RESIZE ) ); } // Create input method handler @@ -2707,10 +2754,20 @@ void wxWindowGTK::PostCreation() if (m_focusWidget == NULL) m_focusWidget = m_widget; - g_signal_connect (m_focusWidget, "focus_in_event", + if (m_wxwindow) + { + g_signal_connect (m_focusWidget, "focus_in_event", + G_CALLBACK (gtk_window_focus_in_callback), this); + g_signal_connect (m_focusWidget, "focus_out_event", + G_CALLBACK (gtk_window_focus_out_callback), this); + } + else + { + g_signal_connect_after (m_focusWidget, "focus_in_event", G_CALLBACK (gtk_window_focus_in_callback), this); - g_signal_connect_after (m_focusWidget, "focus_out_event", + g_signal_connect_after (m_focusWidget, "focus_out_event", G_CALLBACK (gtk_window_focus_out_callback), this); + } } // connect to the various key and mouse handlers @@ -2929,7 +2986,10 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags void wxWindowGTK::OnInternalIdle() { if ( m_dirtyTabOrder ) + { + m_dirtyTabOrder = false; RealizeTabOrder(); + } // Update style if the window was not yet realized // and SetBackgroundStyle(wxBG_STYLE_CUSTOM) was called @@ -3512,14 +3572,42 @@ void wxWindowGTK::RealizeTabOrder() { if (m_wxwindow) { - if (m_children.size() > 0) + if ( !m_children.empty() ) { +#if wxUSE_STATTEXT + // we don't only construct the correct focus chain but also use + // this opportunity to update the mnemonic widgets for all labels + // + // it would be nice to extract this code from here and put it in + // stattext.cpp to reduce dependencies but there is no really easy + // way to do it unfortunately + wxStaticText *lastLabel = NULL; +#endif // wxUSE_STATTEXT + GList *chain = NULL; - for (wxWindowList::const_iterator i = m_children.begin(); - i != m_children.end(); ++i) + for ( wxWindowList::const_iterator i = m_children.begin(); + i != m_children.end(); + ++i ) { - chain = g_list_prepend(chain, (*i)->m_widget); + wxWindowGTK *win = *i; +#if wxUSE_STATTEXT + if ( lastLabel ) + { + if ( win->AcceptsFocusFromKeyboard() ) + { + GtkLabel *l = GTK_LABEL(lastLabel->m_widget); + gtk_label_set_mnemonic_widget(l, win->m_widget); + lastLabel = NULL; + } + } + else // check if this one is a label + { + lastLabel = wxDynamicCast(win, wxStaticText); + } +#endif // wxUSE_STATTEXT + + chain = g_list_prepend(chain, win->m_widget); } chain = g_list_reverse(chain); @@ -3527,13 +3615,11 @@ void wxWindowGTK::RealizeTabOrder() gtk_container_set_focus_chain(GTK_CONTAINER(m_wxwindow), chain); g_list_free(chain); } - else + else // no children { gtk_container_unset_focus_chain(GTK_CONTAINER(m_wxwindow)); } } - - m_dirtyTabOrder = false; } void wxWindowGTK::Raise() @@ -3597,6 +3683,39 @@ void wxWindowGTK::WarpPointer( int x, int y ) gdk_window_warp_pointer( window, x, y ); } +static bool wxScrollAdjust(GtkAdjustment* adj, double change) +{ + double value_start = adj->value; + double value = value_start + change; + double upper = adj->upper - adj->page_size; + if (value > upper) + { + value = upper; + } + // Lower bound will be checked by gtk_adjustment_set_value + gtk_adjustment_set_value(adj, value); + return adj->value != value_start; +} + +bool wxWindowGTK::ScrollLines(int lines) +{ + return + m_vAdjust != NULL && + wxScrollAdjust(m_vAdjust, lines * m_vAdjust->step_increment); +} + +bool wxWindowGTK::ScrollPages(int pages) +{ + return + m_vAdjust != NULL && + wxScrollAdjust(m_vAdjust, pages * m_vAdjust->page_increment); +} + +void wxWindowGTK::SetVScrollAdjustment(GtkAdjustment* adj) +{ + wxASSERT(m_vAdjust == NULL); + m_vAdjust = adj; +} void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect ) {