X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1c6896d71102174e20e8ea4367d3f2e80fbb7045..9f4de6b2cf06f53a98b28f53640f3b9ec8cf4182:/src/gtk/window.cpp diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index a148d6e60d..bad1ac7648 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -232,13 +232,17 @@ static bool g_captureWindowHasMouse = FALSE; // the last window which had the focus - this is normally never NULL (except // if we never had focus at all) as even when g_focusWindow is NULL it still // keeps its previous value -static wxWindowGTK *g_focusWindowLast = (wxWindowGTK *)NULL; +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 wxWindowGTK *g_activeFrame = (wxWindowGTK*) NULL; static bool g_activeFrameLostFocus = FALSE; +// If a window get the focus set but has not been realized +// yet, defer setting the focus to idle time. +wxWindowGTK *g_delayedFocus = (wxWindowGTK*) NULL; + // 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 @@ -266,43 +270,6 @@ extern bool g_mainThreadLocked; #else # define DEBUG_MAIN_THREAD #endif - -static gint gtk_debug_focus_in_callback( GtkWidget *WXUNUSED(widget), - GdkEvent *WXUNUSED(event), - const wxChar *WXUNUSED(name) ) -{ -/* - static bool s_done = FALSE; - if ( !s_done ) - { - wxLog::AddTraceMask("focus"); - s_done = TRUE; - } - wxLogTrace(wxT("FOCUS NOW AT: %s"), name); -*/ - - return FALSE; -} - -void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window ) -{ - // suppress warnings about gtk_debug_focus_in_callback being unused with - // this "if ( 0 )" - if ( 0 ) - { - wxString tmp = name; - tmp += wxT(" FROM "); - tmp += window; - - wxChar *s = new wxChar[tmp.Length()+1]; - - wxStrcpy( s, tmp ); - - gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event", - GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback), (gpointer)s ); - } -} - #else #define DEBUG_MAIN_THREAD #endif // Debug @@ -381,15 +348,6 @@ wxWindow *wxFindFocusedChild(wxWindowGTK *win) 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 @@ -534,8 +492,8 @@ static int gtk_window_expose_callback( GtkWidget *widget, if (g_isIdle) wxapp_install_idle_handler(); -/* - if (win->GetName() == wxT("panel")) +#if 0 + if (win->GetName()) { wxPrintf( wxT("OnExpose from ") ); if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) @@ -545,28 +503,6 @@ static int gtk_window_expose_callback( GtkWidget *widget, (int)gdk_event->area.width, (int)gdk_event->area.height ); } -*/ - -#ifndef __WXUNIVERSAL__ - GtkPizza *pizza = GTK_PIZZA (widget); - - if (win->GetThemeEnabled()) - { - wxWindow *parent = win->GetParent(); - while (parent && !parent->IsTopLevel()) - parent = parent->GetParent(); - if (!parent) - parent = win; - - gtk_paint_flat_box (parent->m_widget->style, - pizza->bin_window, - GTK_STATE_NORMAL, - GTK_SHADOW_NONE, - &gdk_event->area, - parent->m_widget, - (char *)"base", - 0, 0, -1, -1); - } #endif win->GetUpdateRegion().Union( gdk_event->area.x, @@ -575,7 +511,7 @@ static int gtk_window_expose_callback( GtkWidget *widget, gdk_event->area.height ); // Actual redrawing takes place in idle time. - win->Update(); + win->GtkUpdate(); #ifdef __WXGTK20__ @@ -635,8 +571,8 @@ static void gtk_window_draw_callback( GtkWidget *widget, return; } -/* - if (win->GetName() == wxT("panel")) +#if 0 + if (win->GetName()) { wxPrintf( wxT("OnDraw from ") ); if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) @@ -646,7 +582,7 @@ static void gtk_window_draw_callback( GtkWidget *widget, (int)rect->width, (int)rect->height ); } -*/ +#endif #ifndef __WXUNIVERSAL__ GtkPizza *pizza = GTK_PIZZA (widget); @@ -682,7 +618,7 @@ static void gtk_window_draw_callback( GtkWidget *widget, // Actual redrawing takes place in idle time. - win->Update(); + win->GtkUpdate(); #ifndef __WXUNIVERSAL__ // Redraw child widgets @@ -1009,6 +945,12 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event, } s_lastKeyPress = { 0, 0 }; KeySym keysym = gdk_event->keyval; + + wxLogTrace(TRACE_KEYS, _T("Key %s event: keysym = %d"), + event.GetEventType() == wxEVT_KEY_UP ? _T("release") + : _T("press"), + keysym); + long key_code = wxTranslateKeySymToWXKey(keysym, FALSE /* !isChar */); if ( !key_code ) @@ -1034,6 +976,9 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event, // and then back but always using the lower register Display *dpy = (Display *)wxGetDisplay(); KeyCode keycode = XKeysymToKeycode(dpy, keysym); + + wxLogTrace(TRACE_KEYS, _T("\t-> keycode %d"), keycode); + KeySym keysymNormalized = XKeycodeToKeysym(dpy, keycode, 0); // use the normalized, i.e. lower register, keysym if we've @@ -1071,10 +1016,7 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event, } } - wxLogTrace(TRACE_KEYS, _T("Key %s event: keysym = %d => keycode = %ld"), - event.GetEventType() == wxEVT_KEY_UP ? _T("release") - : _T("press"), - gdk_event->keyval, key_code); + wxLogTrace(TRACE_KEYS, _T("\t-> wxKeyCode %d"), key_code); // sending unknown key events doesn't really make sense if ( !key_code ) @@ -1156,12 +1098,12 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, { if ( gdk_event->length == 1 ) { - key_code = gdk_event->string[0]; + key_code = (unsigned char)gdk_event->string[0]; } - else if ((keysym & 0xFF) == keysym) + else if ( wxIsAsciiKeysym(keysym) ) { // ASCII key - key_code = (guint)keysym; + key_code = (unsigned char)keysym; } } @@ -1761,6 +1703,21 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget, // "focus_in_event" //----------------------------------------------------------------------------- +// send the wxChildFocusEvent and wxFocusEvent, common code of +// gtk_window_focus_in_callback() and SetFocus() +static bool DoSendFocusEvents(wxWindow *win) +{ + // Notify the parent keeping track of focus for the kbd navigation + // purposes that we got it. + wxChildFocusEvent eventChildFocus(win); + (void)win->GetEventHandler()->ProcessEvent(eventChildFocus); + + wxFocusEvent eventFocus(wxEVT_SET_FOCUS, win->GetId()); + eventFocus.SetEventObject(win); + + return win->GetEventHandler()->ProcessEvent(eventFocus); +} + static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win ) @@ -1791,14 +1748,9 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, g_focusWindow = win; #if 0 - wxLogDebug( wxT("OnSetFocus from %s\n"), win->GetName().c_str() ); + printf( "OnSetFocus 2 from %s\n", win->GetName().c_str() ); #endif - // notify the parent keeping track of focus for the kbd navigation - // purposes that we got it - wxChildFocusEvent eventFocus(win); - (void)win->GetEventHandler()->ProcessEvent(eventFocus); - #ifdef HAVE_XIM if (win->m_ic) gdk_im_begin(win->m_ic, win->m_wxwindow->window); @@ -1813,6 +1765,8 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, } #endif // wxUSE_CARET + g_activeFrameLostFocus = FALSE; + wxWindowGTK *active = wxGetTopLevelParent(win); if ( active != g_activeFrame ) { @@ -1829,20 +1783,18 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, wxActivateEvent event(wxEVT_ACTIVATE, TRUE, g_activeFrame->GetId()); event.SetEventObject(g_activeFrame); g_activeFrame->GetEventHandler()->ProcessEvent(event); + + // Don't send focus events in addition to activate + // if (win == g_activeFrame) + // return TRUE; } - g_activeFrameLostFocus = FALSE; - - - wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() ); - event.SetEventObject( win ); - if (win->GetEventHandler()->ProcessEvent( event )) + if ( DoSendFocusEvents(win) ) { gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" ); return TRUE; } - return FALSE; } @@ -2023,7 +1975,8 @@ static void gtk_window_vscroll_callback( GtkAdjustment *adjust, win->m_oldVerticalPos = adjust->value; - wxEventType command = GtkScrollWinTypeToWx(GET_SCROLL_TYPE(win->m_widget)); + GtkScrolledWindow *sw = GTK_SCROLLED_WINDOW(win->m_widget); + wxEventType command = GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw->vscrollbar)); int value = (int)(adjust->value+0.5); @@ -2051,7 +2004,8 @@ static void gtk_window_hscroll_callback( GtkAdjustment *adjust, float diff = adjust->value - win->m_oldHorizontalPos; if (fabs(diff) < 0.2) return; - wxEventType command = GtkScrollWinTypeToWx(GET_SCROLL_TYPE(win->m_widget)); + GtkScrolledWindow *sw = GTK_SCROLLED_WINDOW(win->m_widget); + wxEventType command = GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw->hscrollbar)); win->m_oldHorizontalPos = adjust->value; @@ -2158,10 +2112,10 @@ gtk_window_realized_callback( GtkWidget *WXUNUSED(m_widget), wxWindow *win ) wxapp_install_idle_handler(); if (win->m_delayedBackgroundColour) - win->SetBackgroundColour( win->GetBackgroundColour() ); + win->GtkSetBackgroundColour( win->GetBackgroundColour() ); if (win->m_delayedForegroundColour) - win->SetForegroundColour( win->GetForegroundColour() ); + win->GtkSetForegroundColour( win->GetForegroundColour() ); wxWindowCreateEvent event( win ); event.SetEventObject( win ); @@ -2572,6 +2526,9 @@ wxWindowGTK::~wxWindowGTK() if (g_activeFrame == this) g_activeFrame = NULL; + if ( g_delayedFocus == this ) + g_delayedFocus = NULL; + m_isBeingDeleted = TRUE; m_hasVMT = FALSE; @@ -2888,7 +2845,7 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags void wxWindowGTK::OnInternalIdle() { // Update invalidated regions. - Update(); + GtkUpdate(); // Synthetize activate events. if ( g_sendActivateEvent != -1 ) @@ -2913,7 +2870,7 @@ void wxWindowGTK::OnInternalIdle() } g_activeFrameLostFocus = FALSE; } - + wxCursor cursor = m_cursor; if (g_globalCursor.Ok()) cursor = g_globalCursor; @@ -3268,13 +3225,6 @@ void wxWindowGTK::SetFocus() { 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)) @@ -3286,7 +3236,22 @@ void wxWindowGTK::SetFocus() { if (GTK_WIDGET_CAN_FOCUS(m_widget) && !GTK_WIDGET_HAS_FOCUS (m_widget) ) { - gtk_widget_grab_focus (m_widget); + if (!GTK_WIDGET_REALIZED(m_widget)) + { + wxLogTrace(_T("focus"), + _T("Delaying setting focus to %s(%s)\n"), + GetClassInfo()->GetClassName(), GetLabel().c_str()); + + g_delayedFocus = this; + } + else + { + wxLogTrace(_T("focus"), + _T("Setting focus to %s(%s)\n"), + GetClassInfo()->GetClassName(), GetLabel().c_str()); + + gtk_widget_grab_focus (m_widget); + } } else if (GTK_IS_CONTAINER(m_widget)) { @@ -3297,6 +3262,8 @@ void wxWindowGTK::SetFocus() // ? } } + + (void)DoSendFocusEvents((wxWindow*)this); } bool wxWindowGTK::AcceptsFocus() const @@ -3412,6 +3379,9 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect ) if (!m_widget->window) return; #ifndef __WXGTK20__ + if (g_isIdle) + wxapp_install_idle_handler(); + if (eraseBackground && m_wxwindow && m_wxwindow->window) { if (rect) @@ -3478,6 +3448,11 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect ) } void wxWindowGTK::Update() +{ + GtkUpdate(); +} + +void wxWindowGTK::GtkUpdate() { #ifdef __WXGTK20__ if (m_wxwindow && GTK_PIZZA(m_wxwindow)->bin_window) @@ -3497,8 +3472,43 @@ void wxWindowGTK::GtkSendPaintEvents() return; } + // widget to draw on + GtkPizza *pizza = GTK_PIZZA (m_wxwindow); + + // Clip to paint region in wxClientDC m_clipPaintRegion = TRUE; - + + if (GetThemeEnabled()) + { + // find ancestor from which to steal background + wxWindow *parent = GetParent(); + while (parent && !parent->IsTopLevel()) + parent = parent->GetParent(); + if (!parent) + parent = (wxWindow*)this; + + wxRegionIterator upd( m_updateRegion ); + while (upd) + { + GdkRectangle rect; + rect.x = upd.GetX(); + rect.y = upd.GetY(); + rect.width = upd.GetWidth(); + rect.height = upd.GetHeight(); + + gtk_paint_flat_box( parent->m_widget->style, + pizza->bin_window, + GTK_STATE_NORMAL, + GTK_SHADOW_NONE, + &rect, + parent->m_widget, + (char *)"base", + 0, 0, -1, -1 ); + + upd ++; + } + } + else // if (!m_clearRegion.IsEmpty()) // always send an erase event { wxWindowDC dc( (wxWindow*)this ); @@ -3511,7 +3521,7 @@ void wxWindowGTK::GtkSendPaintEvents() { if (!g_eraseGC) { - g_eraseGC = gdk_gc_new( GTK_PIZZA(m_wxwindow)->bin_window ); + g_eraseGC = gdk_gc_new( pizza->bin_window ); gdk_gc_set_fill( g_eraseGC, GDK_SOLID ); } gdk_gc_set_foreground( g_eraseGC, m_backgroundColour.GetColor() ); @@ -3519,8 +3529,8 @@ void wxWindowGTK::GtkSendPaintEvents() wxRegionIterator upd( m_clearRegion ); while (upd) { - gdk_draw_rectangle( GTK_PIZZA(m_wxwindow)->bin_window, g_eraseGC, 1, - upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() ); + gdk_draw_rectangle( pizza->bin_window, g_eraseGC, 1, + upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() ); upd ++; } } @@ -3543,14 +3553,12 @@ void wxWindowGTK::GtkSendPaintEvents() // being redrawn because the wxWindows class is allowed to // paint over the window-less widgets. - GtkPizza *pizza = GTK_PIZZA(m_wxwindow); - GList *children = pizza->children; while (children) { GtkPizzaChild *child = (GtkPizzaChild*) children->data; children = children->next; - + if (GTK_WIDGET_NO_WINDOW (child->widget) && GTK_WIDGET_DRAWABLE (child->widget)) { @@ -3590,11 +3598,14 @@ void wxWindowGTK::Clear() { wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); - if (!m_widget->window) return; - if (m_wxwindow && m_wxwindow->window) { - gdk_window_clear( m_wxwindow->window ); + m_clearRegion.Clear(); + wxSize size( GetClientSize() ); + m_clearRegion.Union( 0,0,size.x,size.y ); + + // Better do this in idle? + GtkUpdate(); } } @@ -3613,16 +3624,34 @@ void wxWindowGTK::ApplyToolTip( GtkTooltips *tips, const wxChar *tip ) } #endif // wxUSE_TOOLTIPS +void wxWindowGTK::GtkSetBackgroundColour( const wxColour &colour ) +{ + GdkWindow *window = (GdkWindow*) NULL; + if (m_wxwindow) + window = GTK_PIZZA(m_wxwindow)->bin_window; + else + window = GetConnectWidget()->window; + + wxASSERT( window ); + + // We need the pixel value e.g. for background clearing. + m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) ); + + if (m_wxwindow) + { + // wxMSW doesn't clear the window here, either. + gdk_window_set_background( window, m_backgroundColour.GetColor() ); + } + + ApplyWidgetStyle(); +} + bool wxWindowGTK::SetBackgroundColour( const wxColour &colour ) { wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") ); if (!wxWindowBase::SetBackgroundColour(colour)) - { - // don't leave if the GTK widget has just - // been realized - if (!m_delayedBackgroundColour) return FALSE; - } + return FALSE; GdkWindow *window = (GdkWindow*) NULL; if (m_wxwindow) @@ -3636,27 +3665,27 @@ bool wxWindowGTK::SetBackgroundColour( const wxColour &colour ) // but it couldn't get applied as the // widget hasn't been realized yet. m_delayedBackgroundColour = TRUE; + return TRUE; } - - if (window) + else { - // We need the pixel value e.g. for background clearing. - m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) ); + GtkSetBackgroundColour( colour ); } - - if ((m_wxwindow) && - (m_wxwindow->window) && - (m_backgroundColour != wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE))) - { - /* wxMSW doesn't clear the window here. I don't do that either to - provide compatibility. call Clear() to do the job. */ - gdk_window_set_background( window, m_backgroundColour.GetColor() ); - } + return TRUE; +} - ApplyWidgetStyle(); +void wxWindowGTK::GtkSetForegroundColour( const wxColour &colour ) +{ + GdkWindow *window = (GdkWindow*) NULL; + if (m_wxwindow) + window = GTK_PIZZA(m_wxwindow)->bin_window; + else + window = GetConnectWidget()->window; - return TRUE; + wxASSERT( window ); + + ApplyWidgetStyle(); } bool wxWindowGTK::SetForegroundColour( const wxColour &colour ) @@ -3683,8 +3712,10 @@ bool wxWindowGTK::SetForegroundColour( const wxColour &colour ) // widget hasn't been realized yet. m_delayedForegroundColour = TRUE; } - - ApplyWidgetStyle(); + else + { + GtkSetForegroundColour( colour ); + } return TRUE; } @@ -4299,3 +4330,4 @@ void wxWinModule::OnExit() gdk_gc_unref( g_eraseGC ); } +// vi:sts=4:sw=4:et