X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9c61c5b04b0b023eb9592bde5633c2111f1940fb..f27d62bf2f27f3b0b6e5cd608c8308c8bd81a93c:/src/gtk/window.cpp diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index b72018c1df..e1b0b87036 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -228,7 +228,7 @@ int g_lastButtonNumber = 0; //----------------------------------------------------------------------------- // the trace mask used for the focus debugging messages -#define TRACE_FOCUS _T("focus") +#define TRACE_FOCUS wxT("focus") //----------------------------------------------------------------------------- // missing gdk functions @@ -281,11 +281,11 @@ wxgtk_window_size_request_callback(GtkWidget * WXUNUSED(widget), extern "C" { static gboolean -gtk_window_expose_callback( GtkWidget* widget, +gtk_window_expose_callback( GtkWidget*, GdkEventExpose *gdk_event, wxWindow *win ) { - if (gdk_event->window == widget->window) + if (gdk_event->window == win->GTKGetDrawingWindow()) { win->GetUpdateRegion() = wxRegion( gdk_event->region ); win->GtkSendPaintEvents(); @@ -304,7 +304,7 @@ extern "C" { static gboolean expose_event_border(GtkWidget* widget, GdkEventExpose* gdk_event, wxWindow* win) { - if (gdk_event->window != widget->window) + if (gdk_event->window != gtk_widget_get_parent_window(win->m_wxwindow)) return false; const GtkAllocation& alloc = win->m_wxwindow->allocation; @@ -383,7 +383,7 @@ inline bool wxIsUpperChar(int code) // set WXTRACE to this to see the key event codes on the console -#define TRACE_KEYS _T("keyevent") +#define TRACE_KEYS wxT("keyevent") // translates an X key symbol to WXK_XXX value // @@ -714,9 +714,9 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event, KeySym keysym = gdk_event->keyval; - wxLogTrace(TRACE_KEYS, _T("Key %s event: keysym = %ld"), - event.GetEventType() == wxEVT_KEY_UP ? _T("release") - : _T("press"), + wxLogTrace(TRACE_KEYS, wxT("Key %s event: keysym = %ld"), + event.GetEventType() == wxEVT_KEY_UP ? wxT("release") + : wxT("press"), keysym); long key_code = wxTranslateKeySymToWXKey(keysym, false /* !isChar */); @@ -745,7 +745,7 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event, Display *dpy = (Display *)wxGetDisplay(); KeyCode keycode = XKeysymToKeycode(dpy, keysym); - wxLogTrace(TRACE_KEYS, _T("\t-> keycode %d"), keycode); + wxLogTrace(TRACE_KEYS, wxT("\t-> keycode %d"), keycode); KeySym keysymNormalized = XKeycodeToKeysym(dpy, keycode, 0); @@ -784,7 +784,7 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event, } } - wxLogTrace(TRACE_KEYS, _T("\t-> wxKeyCode %ld"), key_code); + wxLogTrace(TRACE_KEYS, wxT("\t-> wxKeyCode %ld"), key_code); // sending unknown key events doesn't really make sense if ( !key_code ) @@ -857,7 +857,7 @@ gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget), win->m_imData->lastKeyEvent = NULL; if (intercepted_by_IM) { - wxLogTrace(TRACE_KEYS, _T("Key event intercepted by IM")); + wxLogTrace(TRACE_KEYS, wxT("Key event intercepted by IM")); return TRUE; } } @@ -919,7 +919,7 @@ gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget), if ( key_code ) { - wxLogTrace(TRACE_KEYS, _T("Char event: %ld"), key_code); + wxLogTrace(TRACE_KEYS, wxT("Char event: %ld"), key_code); event.m_keyCode = key_code; @@ -996,7 +996,7 @@ gtk_wxwindow_commit_cb (GtkIMContext * WXUNUSED(context), event.m_uniChar = *pstr; // Backward compatible for ISO-8859-1 event.m_keyCode = *pstr < 256 ? event.m_uniChar : 0; - wxLogTrace(TRACE_KEYS, _T("IM sent character '%c'"), event.m_uniChar); + wxLogTrace(TRACE_KEYS, wxT("IM sent character '%c'"), event.m_uniChar); #else event.m_keyCode = (char)*pstr; #endif // wxUSE_UNICODE @@ -1831,9 +1831,9 @@ gtk_window_realized_callback(GtkWidget* widget, wxWindow* win) if (win->m_imData) { gtk_im_context_set_client_window( win->m_imData->context, - widget->window); + win->m_wxwindow ? win->GTKGetDrawingWindow() : widget->window); } - + // We cannot set colours and fonts before the widget // been realized, so we do this directly after realization // or otherwise in idle time @@ -1925,30 +1925,6 @@ void gtk_window_style_set_callback( GtkWidget *WXUNUSED(widget), } // extern "C" -// Helper to suspend colour change event event processing while we change a widget's style -class wxSuspendStyleEvents -{ -public: - wxSuspendStyleEvents(wxWindow* win) - { - m_win = NULL; - if (win->m_wxwindow && win->IsTopLevel()) - { - m_win = win; - g_signal_handlers_block_by_func( - m_win->m_wxwindow, (void*)gtk_window_style_set_callback, m_win); - } - } - ~wxSuspendStyleEvents() - { - if (m_win) - g_signal_handlers_unblock_by_func( - m_win->m_wxwindow, (void*)gtk_window_style_set_callback, m_win); - } - - wxWindow* m_win; -}; - // ---------------------------------------------------------------------------- // this wxWindowBase function is implemented here (in platform-specific file) // because it is static and so couldn't be made virtual @@ -1964,7 +1940,7 @@ wxWindow *wxWindowBase::DoFindFocus() void wxWindowGTK::AddChildGTK(wxWindowGTK* child) { wxASSERT_MSG(m_wxwindow, "Cannot add a child to a window without a client area"); - + // the window might have been scrolled already, we // have to adapt the position wxPizza* pizza = WX_PIZZA(m_wxwindow); @@ -1973,8 +1949,7 @@ void wxWindowGTK::AddChildGTK(wxWindowGTK* child) gtk_widget_set_size_request( child->m_widget, child->m_width, child->m_height); - gtk_fixed_put( - GTK_FIXED(m_wxwindow), child->m_widget, child->m_x, child->m_y); + pizza->put(child->m_widget, child->m_x, child->m_y); } //----------------------------------------------------------------------------- @@ -2112,7 +2087,7 @@ bool wxWindowGTK::Create( wxWindow *parent, #endif - m_wxwindow = wxPizza::New(m_windowStyle,this); + m_wxwindow = wxPizza::New(m_windowStyle); #ifndef __WXUNIVERSAL__ if (HasFlag(wxPizza::BORDER_STYLES)) { @@ -2235,6 +2210,12 @@ wxWindowGTK::~wxWindowGTK() // delete before the widgets to avoid a crash on solaris delete m_imData; + // avoid problem with GTK+ 2.18 where a frozen window causes the whole + // TLW to be frozen, and if the window is then destroyed, nothing ever + // gets painted again + if (IsFrozen()) + DoThaw(); + if (m_widget) { // Note that gtk_widget_destroy() does not destroy the widget, it just @@ -2341,40 +2322,25 @@ void wxWindowGTK::PostCreation() G_CALLBACK(size_allocate), this); } - if (m_wxwindow) - { #if GTK_CHECK_VERSION(2, 8, 0) - if (!gtk_check_version(2,8,0)) + if ( gtk_check_version(2,8,0) == NULL ) + { + // Make sure we can notify the app when mouse capture is lost + if ( m_wxwindow ) { - // Make sure we can notify the app when mouse capture is lost g_signal_connect (m_wxwindow, "grab_broken_event", G_CALLBACK (gtk_window_grab_broken), this); } -#endif - } - if ( connect_widget != m_wxwindow ) - { -#if GTK_CHECK_VERSION(2, 8, 0) - if (!gtk_check_version(2,8,0)) + if ( connect_widget != m_wxwindow ) { - // Make sure we can notify app code when mouse capture is lost g_signal_connect (connect_widget, "grab_broken_event", G_CALLBACK (gtk_window_grab_broken), this); } -#endif } +#endif // GTK+ >= 2.8 -#ifdef GTK_IS_FILE_CHOOSER_BUTTON - if (!gtk_check_version(2,6,0) && GTK_IS_FILE_CHOOSER_BUTTON(m_widget)) - { - // If we connect to the "size_request" signal of a GtkFileChooserButton - // then that control won't be sized properly when placed inside sizers - // (this can be tested removing this elseif and running XRC or WIDGETS samples) - // FIXME: what should be done here ? - } else -#endif - if ( !IsTopLevel() ) // top level windows use their own callback + if ( GTKShouldConnectSizeRequest() ) { // This is needed if we want to add our windows into native // GTK controls, such as the toolbar. With this callback, the @@ -2397,6 +2363,11 @@ void wxWindowGTK::PostCreation() gtk_widget_show( m_widget ); } +gulong wxWindowGTK::GTKConnectWidget(const char *signal, void (*callback)()) +{ + return g_signal_connect(m_widget, signal, callback, this); +} + void wxWindowGTK::ConnectWidget( GtkWidget *widget ) { g_signal_connect (widget, "key_press_event", @@ -2443,9 +2414,9 @@ bool wxWindowGTK::Destroy() void wxWindowGTK::DoMoveWindow(int x, int y, int width, int height) { gtk_widget_set_size_request(m_widget, width, height); - + // inform the parent to perform the move - wxASSERT_MSG(m_parent && m_parent->m_wxwindow, + wxASSERT_MSG(m_parent && m_parent->m_wxwindow, "the parent window has no client area?"); WX_PIZZA(m_parent->m_wxwindow)->move(m_widget, x, y); } @@ -2542,7 +2513,7 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags event.SetEventObject( this ); HandleWindowEvent( event ); } - } else + } else if (sizeFlags & wxSIZE_FORCE_EVENT) { wxSizeEvent event( wxSize(m_width,m_height), GetId() ); @@ -2606,7 +2577,7 @@ void wxWindowGTK::OnInternalIdle() if (m_wxwindow && (m_wxwindow != m_widget)) { - GdkWindow *window = m_wxwindow->window; + GdkWindow* window = GTKGetDrawingWindow(); if (window) gdk_window_set_cursor( window, cursor.GetCursor() ); @@ -3170,14 +3141,14 @@ void wxWindowGTK::SetFocus() !GTK_WIDGET_CAN_FOCUS(widget) ) { wxLogTrace(TRACE_FOCUS, - _T("Setting focus to a child of %s(%p, %s)"), + wxT("Setting focus to a child of %s(%p, %s)"), GetClassInfo()->GetClassName(), this, GetLabel().c_str()); gtk_widget_child_focus(widget, GTK_DIR_TAB_FORWARD); } else { wxLogTrace(TRACE_FOCUS, - _T("Setting focus to %s(%p, %s)"), + wxT("Setting focus to %s(%p, %s)"), GetClassInfo()->GetClassName(), this, GetLabel().c_str()); gtk_widget_grab_focus(widget); } @@ -3271,7 +3242,7 @@ wxLayoutDirection wxWindowGTK::GTKGetLayout(GtkWidget *widget) /* static */ void wxWindowGTK::GTKSetLayout(GtkWidget *widget, wxLayoutDirection dir) { - wxASSERT_MSG( dir != wxLayout_Default, _T("invalid layout direction") ); + wxASSERT_MSG( dir != wxLayout_Default, wxT("invalid layout direction") ); gtk_widget_set_direction(widget, dir == wxLayout_RightToLeft ? GTK_TEXT_DIR_RTL @@ -3328,14 +3299,14 @@ bool wxWindowGTK::DoNavigateIn(int flags) { if ( flags & wxNavigationKeyEvent::WinChange ) { - wxFAIL_MSG( _T("not implemented") ); + wxFAIL_MSG( wxT("not implemented") ); return false; } else // navigate inside the container { wxWindow *parent = wxGetTopLevelParent((wxWindow *)this); - wxCHECK_MSG( parent, false, _T("every window must have a TLW parent") ); + wxCHECK_MSG( parent, false, wxT("every window must have a TLW parent") ); GtkDirectionType dir; dir = flags & wxNavigationKeyEvent::IsForward ? GTK_DIR_TAB_FORWARD @@ -3477,7 +3448,7 @@ void wxWindowGTK::GTKUpdateCursor() GdkWindow *win = windowsThis[n]; if ( !win ) { - wxFAIL_MSG(_T("NULL window returned by GTKGetWindow()?")); + wxFAIL_MSG(wxT("NULL window returned by GTKGetWindow()?")); continue; } @@ -3513,7 +3484,7 @@ wxWindowGTK::ScrollDir wxWindowGTK::ScrollDirFromRange(GtkRange *range) const return (ScrollDir)dir; } - wxFAIL_MSG( _T("event from unknown scrollbar received") ); + wxFAIL_MSG( wxT("event from unknown scrollbar received") ); return ScrollDir_Max; } @@ -3572,6 +3543,7 @@ void wxWindowGTK::Refresh(bool WXUNUSED(eraseBackground), if (!GTK_WIDGET_MAPPED (w)) return; + GdkWindow* window = GTKGetDrawingWindow(); if (rect) { int x = rect->x; @@ -3582,24 +3554,27 @@ void wxWindowGTK::Refresh(bool WXUNUSED(eraseBackground), r.y = rect->y; r.width = rect->width; r.height = rect->height; - gdk_window_invalidate_rect( m_wxwindow->window, &r, TRUE ); + gdk_window_invalidate_rect(window, &r, true); } else - gdk_window_invalidate_rect( m_wxwindow->window, NULL, TRUE ); + gdk_window_invalidate_rect(window, NULL, true); } } void wxWindowGTK::Update() { - if (m_widget && m_widget->window) + if (m_widget && GTK_WIDGET_MAPPED(m_widget)) { GdkDisplay* display = gtk_widget_get_display(m_widget); // Flush everything out to the server, and wait for it to finish. // This ensures nothing will overwrite the drawing we are about to do. gdk_display_sync(display); - gdk_window_process_updates(m_widget->window, TRUE); - + GdkWindow* window = GTKGetDrawingWindow(); + if (window == NULL) + window = m_widget->window; + gdk_window_process_updates(window, true); + // Flush again, but no need to wait for it to finish gdk_display_flush(display); } @@ -3703,7 +3678,7 @@ void wxWindowGTK::GtkSendPaintEvents() rect.height = upd.GetHeight(); gtk_paint_flat_box( parent->m_widget->style, - m_wxwindow->window, + GTKGetDrawingWindow(), (GtkStateType)GTK_WIDGET_STATE(m_wxwindow), GTK_SHADOW_NONE, &rect, @@ -3763,7 +3738,21 @@ void wxWindowGTK::DoSetToolTip( wxToolTip *tip ) wxWindowBase::DoSetToolTip(tip); if (m_tooltip) + { m_tooltip->GTKApply( (wxWindow *)this ); + } + else + { + GtkWidget *w = GetConnectWidget(); + wxToolTip::GTKApply(w, NULL); +#if GTK_CHECK_VERSION(2, 12, 0) + // Just applying NULL doesn't work on 2.12.0, so also use + // gtk_widget_set_has_tooltip. It is part of the new GtkTooltip API + // but seems also to work with the old GtkTooltips. + if (gtk_check_version(2, 12, 0) == NULL) + gtk_widget_set_has_tooltip(w, FALSE); +#endif + } } void wxWindowGTK::GTKApplyToolTip( GtkTooltips *tips, const gchar *tip ) @@ -3903,12 +3892,30 @@ void wxWindowGTK::GTKApplyWidgetStyle(bool forceStyle) void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle *style) { - wxSuspendStyleEvents s(static_cast(this)); + if ( m_wxwindow ) + { + // block the signal temporarily to avoid sending + // wxSysColourChangedEvents when we change the colours ourselves + bool unblock = false; + if ( IsTopLevel() ) + { + unblock = true; + g_signal_handlers_block_by_func( + m_wxwindow, (void *)gtk_window_style_set_callback, this); + } - if (m_wxwindow) gtk_widget_modify_style(m_wxwindow, style); + + if ( unblock ) + { + g_signal_handlers_unblock_by_func( + m_wxwindow, (void *)gtk_window_style_set_callback, this); + } + } else + { gtk_widget_modify_style(m_widget, style); + } } bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style) @@ -3920,7 +3927,7 @@ bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style) GdkWindow *window; if ( m_wxwindow ) { - window = m_wxwindow->window; + window = GTKGetDrawingWindow(); } else { @@ -3963,23 +3970,6 @@ bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style) #if wxUSE_MENUS_NATIVE -static void SetInvokingWindow( wxMenu *menu, wxWindow* win ) -{ - menu->SetInvokingWindow( win ); - - wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst(); - while (node) - { - wxMenuItem *menuitem = node->GetData(); - if (menuitem->IsSubMenu()) - { - SetInvokingWindow( menuitem->GetSubMenu(), win ); - } - - node = node->GetNext(); - } -} - extern "C" { static void wxPopupMenuPositionCallback( GtkMenu *menu, @@ -4006,10 +3996,6 @@ bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y ) { wxCHECK_MSG( m_widget != NULL, false, wxT("invalid window") ); - wxCHECK_MSG( menu != NULL, false, wxT("invalid popup-menu") ); - - SetInvokingWindow( menu, this ); - menu->UpdateUI(); wxPoint pos; @@ -4086,7 +4072,7 @@ bool wxWindowGTK::GTKIsOwnWindow(GdkWindow *window) const GdkWindow *wxWindowGTK::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const { - return m_wxwindow ? m_wxwindow->window : m_widget->window; + return m_wxwindow ? GTKGetDrawingWindow() : m_widget->window; } bool wxWindowGTK::SetFont( const wxFont &font ) @@ -4109,11 +4095,11 @@ void wxWindowGTK::DoCaptureMouse() GdkWindow *window = NULL; if (m_wxwindow) - window = m_wxwindow->window; + window = GTKGetDrawingWindow(); else window = GetConnectWidget()->window; - wxCHECK_RET( window, _T("CaptureMouse() failed") ); + wxCHECK_RET( window, wxT("CaptureMouse() failed") ); const wxCursor* cursor = &m_cursor; if (!cursor->Ok()) @@ -4142,7 +4128,7 @@ void wxWindowGTK::DoReleaseMouse() GdkWindow *window = NULL; if (m_wxwindow) - window = m_wxwindow->window; + window = GTKGetDrawingWindow(); else window = GetConnectWidget()->window; @@ -4179,7 +4165,7 @@ void wxWindowGTK::SetScrollbar(int orient, { const int dir = ScrollDirFromOrient(orient); GtkRange* const sb = m_scrollBar[dir]; - wxCHECK_RET( sb, _T("this window is not scrollable") ); + wxCHECK_RET( sb, wxT("this window is not scrollable") ); if (range <= 0) { @@ -4208,7 +4194,7 @@ void wxWindowGTK::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh)) { const int dir = ScrollDirFromOrient(orient); GtkRange * const sb = m_scrollBar[dir]; - wxCHECK_RET( sb, _T("this window is not scrollable") ); + wxCHECK_RET( sb, wxT("this window is not scrollable") ); // This check is more than an optimization. Without it, the slider // will not move smoothly while tracking when using wxScrollHelper. @@ -4228,7 +4214,7 @@ void wxWindowGTK::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh)) int wxWindowGTK::GetScrollThumb(int orient) const { GtkRange * const sb = m_scrollBar[ScrollDirFromOrient(orient)]; - wxCHECK_MSG( sb, 0, _T("this window is not scrollable") ); + wxCHECK_MSG( sb, 0, wxT("this window is not scrollable") ); return wxRound(sb->adjustment->page_size); } @@ -4236,7 +4222,7 @@ int wxWindowGTK::GetScrollThumb(int orient) const int wxWindowGTK::GetScrollPos( int orient ) const { GtkRange * const sb = m_scrollBar[ScrollDirFromOrient(orient)]; - wxCHECK_MSG( sb, 0, _T("this window is not scrollable") ); + wxCHECK_MSG( sb, 0, wxT("this window is not scrollable") ); return wxRound(sb->adjustment->value); } @@ -4244,7 +4230,7 @@ int wxWindowGTK::GetScrollPos( int orient ) const int wxWindowGTK::GetScrollRange( int orient ) const { GtkRange * const sb = m_scrollBar[ScrollDirFromOrient(orient)]; - wxCHECK_MSG( sb, 0, _T("this window is not scrollable") ); + wxCHECK_MSG( sb, 0, wxT("this window is not scrollable") ); return wxRound(sb->adjustment->upper); } @@ -4350,7 +4336,7 @@ void wxWindowGTK::GTKScrolledWindowSetBorder(GtkWidget* w, int wxstyle) if(wxstyle & wxBORDER_RAISED) gtkstyle = GTK_SHADOW_OUT; - else if (wxstyle & wxBORDER_SUNKEN) + else if ((wxstyle & wxBORDER_SUNKEN) || (wxstyle & wxBORDER_THEME)) gtkstyle = GTK_SHADOW_IN; #if 0 // Now obsolete @@ -4414,7 +4400,7 @@ GdkWindow* wxWindowGTK::GTKGetDrawingWindow() const { GdkWindow* window = NULL; if (m_wxwindow) - window = m_wxwindow->window; + window = WX_PIZZA(m_wxwindow)->m_draw_window; return window; } @@ -4427,7 +4413,7 @@ extern "C" // this is called if we attempted to freeze unrealized widget when it finally // is realized (and so can be frozen): -static void wx_frozen_widget_realize(GtkWidget* w, void* WXUNUSED(data)) +static void wx_frozen_widget_realize(GtkWidget* w, wxWindowGTK* win) { wxASSERT( w && !GTK_WIDGET_NO_WINDOW(w) ); wxASSERT( GTK_WIDGET_REALIZED(w) ); @@ -4436,10 +4422,13 @@ static void wx_frozen_widget_realize(GtkWidget* w, void* WXUNUSED(data)) ( w, (void*)wx_frozen_widget_realize, - NULL + win ); - gdk_window_freeze_updates(w->window); + GdkWindow* window = w->window; + if (w == win->m_wxwindow) + window = win->GTKGetDrawingWindow(); + gdk_window_freeze_updates(window); } } // extern "C" @@ -4458,12 +4447,15 @@ void wxWindowGTK::GTKFreezeWidget(GtkWidget *w) w, "realize", G_CALLBACK(wx_frozen_widget_realize), - NULL + this ); return; } - gdk_window_freeze_updates(w->window); + GdkWindow* window = w->window; + if (w == m_wxwindow) + window = GTKGetDrawingWindow(); + gdk_window_freeze_updates(window); } void wxWindowGTK::GTKThawWidget(GtkWidget *w) @@ -4478,12 +4470,15 @@ void wxWindowGTK::GTKThawWidget(GtkWidget *w) ( w, (void*)wx_frozen_widget_realize, - NULL + this ); return; } - gdk_window_thaw_updates(w->window); + GdkWindow* window = w->window; + if (w == m_wxwindow) + window = GTKGetDrawingWindow(); + gdk_window_thaw_updates(window); } void wxWindowGTK::DoFreeze()