X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/fc9ab22a7692aa822bb3d8e6326dfb73d12a600b..abd474ea63667f727940a009cc3e0b23ba9f418f:/src/gtk/toplevel.cpp diff --git a/src/gtk/toplevel.cpp b/src/gtk/toplevel.cpp index fb3696031c..5062335525 100644 --- a/src/gtk/toplevel.cpp +++ b/src/gtk/toplevel.cpp @@ -72,6 +72,10 @@ static wxTopLevelWindowGTK *g_lastActiveFrame = NULL; // send any activate events at all static int g_sendActivateEvent = -1; +// Whether _NET_REQUEST_FRAME_EXTENTS support is working +// 0 == not tested yet, 1 == working, 2 == broken +static int gs_requestFrameExtentsStatus; + //----------------------------------------------------------------------------- // RequestUserAttention related functions //----------------------------------------------------------------------------- @@ -80,9 +84,8 @@ extern "C" { static void wxgtk_window_set_urgency_hint (GtkWindow *win, gboolean setting) { - wxASSERT_MSG( gtk_widget_get_realized(GTK_WIDGET(win)), - wxT("wxgtk_window_set_urgency_hint: GdkWindow not realized") ); - GdkWindow *window = GTK_WIDGET(win)->window; + GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(win)); + wxASSERT_MSG(window, "wxgtk_window_set_urgency_hint: GdkWindow not realized"); XWMHints *wm_hints; wm_hints = XGetWMHints(GDK_WINDOW_XDISPLAY(window), GDK_WINDOW_XWINDOW(window)); @@ -219,8 +222,9 @@ size_allocate(GtkWidget*, GtkAllocation* alloc, wxTopLevelWindowGTK* win) win->m_oldClientWidth = alloc->width; win->m_oldClientHeight = alloc->height; - wxSize size(win->m_widget->allocation.width, - win->m_widget->allocation.height); + GtkAllocation a; + gtk_widget_get_allocation(win->m_widget, &a); + wxSize size(a.width, a.height); size += win->m_decorSize; win->m_width = size.x; win->m_height = size.y; @@ -309,16 +313,18 @@ static void gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), wxTopLevelWindowGTK *win ) { - gdk_window_set_decorations(win->m_widget->window, + gdk_window_set_decorations(gtk_widget_get_window(win->m_widget), (GdkWMDecoration)win->m_gdkDecor); - gdk_window_set_functions(win->m_widget->window, + gdk_window_set_functions(gtk_widget_get_window(win->m_widget), (GdkWMFunction)win->m_gdkFunc); // GTK's shrinking/growing policy if ( !(win->m_gdkFunc & GDK_FUNC_RESIZE) ) gtk_window_set_resizable(GTK_WINDOW(win->m_widget), FALSE); +#if !GTK_CHECK_VERSION(3,0,0) && !defined(GTK_DISABLE_DEPRECATED) else gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1); +#endif const wxIconBundle& icons = win->GetIcons(); if (icons.GetIconCount()) @@ -439,6 +445,14 @@ static gboolean property_notify_event( static GdkAtom property = gdk_atom_intern("_NET_FRAME_EXTENTS", false); if (event->state == GDK_PROPERTY_NEW_VALUE && event->atom == property) { + if (win->m_netFrameExtentsTimerId) + { + // WM support for _NET_REQUEST_FRAME_EXTENTS is working + gs_requestFrameExtentsStatus = 1; + g_source_remove(win->m_netFrameExtentsTimerId); + win->m_netFrameExtentsTimerId = 0; + } + wxSize decorSize = win->m_decorSize; int left, right, top, bottom; if (wxGetFrameExtents(event->window, &left, &right, &top, &bottom)) @@ -450,6 +464,24 @@ static gboolean property_notify_event( } } +extern "C" { +static gboolean request_frame_extents_timeout(void* data) +{ + // WM support for _NET_REQUEST_FRAME_EXTENTS is broken + gs_requestFrameExtentsStatus = 2; + gdk_threads_enter(); + wxTopLevelWindowGTK* win = static_cast(data); + win->m_netFrameExtentsTimerId = 0; + wxSize decorSize = win->m_decorSize; + int left, right, top, bottom; + if (wxGetFrameExtents(gtk_widget_get_window(win->m_widget), &left, &right, &top, &bottom)) + decorSize.Set(left + right, top + bottom); + win->GTKUpdateDecorSize(decorSize); + gdk_threads_leave(); + return false; +} +} + // ---------------------------------------------------------------------------- // wxTopLevelWindowGTK creation // ---------------------------------------------------------------------------- @@ -466,6 +498,7 @@ void wxTopLevelWindowGTK::Init() m_deferShow = true; m_deferShowAllowed = true; m_updateDecorSize = true; + m_netFrameExtentsTimerId = 0; m_urgency_hint = -2; } @@ -565,7 +598,7 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, #endif gtk_window_set_title( GTK_WINDOW(m_widget), wxGTK_CONV( title ) ); - GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS ); + gtk_widget_set_can_focus(m_widget, false); g_signal_connect (m_widget, "delete_event", G_CALLBACK (gtk_frame_delete_callback), this); @@ -573,7 +606,7 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, // m_mainWidget is a GtkVBox, holding the bars and client area (m_wxwindow) m_mainWidget = gtk_vbox_new(false, 0); gtk_widget_show( m_mainWidget ); - GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS ); + gtk_widget_set_can_focus(m_mainWidget, false); gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget ); // m_wxwindow is the client area @@ -583,7 +616,7 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, // we donm't allow the frame to get the focus as otherwise // the frame will grab it at arbitrary focus changes - GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS ); + gtk_widget_set_can_focus(m_wxwindow, false); if (m_parent) m_parent->AddChild( this ); @@ -594,8 +627,10 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, G_CALLBACK (wxgtk_tlw_size_request_callback), this); PostCreation(); +#if !GTK_CHECK_VERSION(3,0,0) && !defined(GTK_DISABLE_DEPRECATED) if ((m_x != -1) || (m_y != -1)) gtk_widget_set_uposition( m_widget, m_x, m_y ); +#endif // we cannot set MWM hints and icons before the widget has // been realized, so we do this directly after realization @@ -678,6 +713,13 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, wxTopLevelWindowGTK::~wxTopLevelWindowGTK() { + if ( m_netFrameExtentsTimerId ) + { + // Don't let the timer callback fire as the window pointer passed to it + // will become invalid very soon. + g_source_remove(m_netFrameExtentsTimerId); + } + #if wxUSE_LIBHILDON || wxUSE_LIBHILDON2 // it can also be a (standard) dialog if ( HILDON_IS_WINDOW(m_widget) ) @@ -714,8 +756,9 @@ bool wxTopLevelWindowGTK::EnableCloseButton( bool enable ) else m_gdkFunc &= ~GDK_FUNC_CLOSE; - if (gtk_widget_get_realized(m_widget) && (m_widget->window)) - gdk_window_set_functions( m_widget->window, (GdkWMFunction)m_gdkFunc ); + GdkWindow* window = gtk_widget_get_window(m_widget); + if (window) + gdk_window_set_functions(window, (GdkWMFunction)m_gdkFunc); return true; } @@ -744,7 +787,7 @@ bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long) } else { - GdkWindow *window = m_widget->window; + GdkWindow* window = gtk_widget_get_window(m_widget); if (show) { @@ -763,12 +806,11 @@ bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long) gdk_window_set_decorations(window, (GdkWMDecoration)0); gdk_window_set_functions(window, (GdkWMFunction)0); - gdk_window_get_origin (m_widget->window, &root_x, &root_y); - gdk_window_get_geometry (m_widget->window, &client_x, &client_y, - &width, &height, NULL); + gdk_window_get_origin(window, &root_x, &root_y); + gdk_window_get_geometry(window, &client_x, &client_y, &width, &height, NULL); - gdk_window_move_resize (m_widget->window, -client_x, -client_y, - screen_width + 1, screen_height + 1); + gdk_window_move_resize( + window, -client_x, -client_y, screen_width + 1, screen_height + 1); wxSetFullScreenStateX11((WXDisplay*)GDK_DISPLAY(), (WXWindow)GDK_ROOT_WINDOW(), @@ -810,8 +852,11 @@ void wxTopLevelWindowGTK::Refresh( bool WXUNUSED(eraseBackground), const wxRect gtk_widget_queue_draw( m_widget ); - if (m_wxwindow && m_wxwindow->window) - gdk_window_invalidate_rect( m_wxwindow->window, NULL, TRUE ); + GdkWindow* window = NULL; + if (m_wxwindow) + window = gtk_widget_get_window(m_wxwindow); + if (window) + gdk_window_invalidate_rect(window, NULL, true); } bool wxTopLevelWindowGTK::Show( bool show ) @@ -821,7 +866,8 @@ bool wxTopLevelWindowGTK::Show( bool show ) bool deferShow = show && !m_isShown && m_deferShow; if (deferShow) { - deferShow = m_deferShowAllowed && !gtk_widget_get_realized(m_widget); + deferShow = gs_requestFrameExtentsStatus != 2 && + m_deferShowAllowed && !gtk_widget_get_realized(m_widget); if (deferShow) { deferShow = g_signal_handler_find(m_widget, @@ -841,13 +887,6 @@ bool wxTopLevelWindowGTK::Show( bool show ) // restore and save. m_updateDecorSize = deferShow; } - if (deferShow) - { - // Fluxbox support for _NET_REQUEST_FRAME_EXTENTS is broken - const char* name = gdk_x11_screen_get_window_manager_name(screen); - deferShow = strcmp(name, "Fluxbox") != 0; - m_updateDecorSize = deferShow; - } m_deferShow = deferShow; } @@ -864,27 +903,44 @@ bool wxTopLevelWindowGTK::Show( bool show ) // causes the widget tree to be size_allocated, which generates size // events in the wrong order. However, the size_allocates will not be // done if the allocation is not the default (1,1). - const int alloc_width = m_widget->allocation.width; + GtkAllocation alloc; + gtk_widget_get_allocation(m_widget, &alloc); + const int alloc_width = alloc.width; if (alloc_width == 1) - m_widget->allocation.width = 2; + { + alloc.width = 2; + gtk_widget_set_allocation(m_widget, &alloc); + } gtk_widget_realize(m_widget); if (alloc_width == 1) - m_widget->allocation.width = 1; + { + alloc.width = 1; + gtk_widget_set_allocation(m_widget, &alloc); + } // send _NET_REQUEST_FRAME_EXTENTS XClientMessageEvent xevent; memset(&xevent, 0, sizeof(xevent)); xevent.type = ClientMessage; - xevent.window = gdk_x11_drawable_get_xid(m_widget->window); + GdkWindow* window = gtk_widget_get_window(m_widget); + xevent.window = gdk_x11_drawable_get_xid(window); xevent.message_type = gdk_x11_atom_to_xatom_for_display( - gdk_drawable_get_display(m_widget->window), + gdk_drawable_get_display(window), gdk_atom_intern("_NET_REQUEST_FRAME_EXTENTS", false)); xevent.format = 32; - Display* display = gdk_x11_drawable_get_xdisplay(m_widget->window); + Display* display = gdk_x11_drawable_get_xdisplay(window); XSendEvent(display, DefaultRootWindow(display), false, SubstructureNotifyMask | SubstructureRedirectMask, (XEvent*)&xevent); + if (gs_requestFrameExtentsStatus == 0) + { + // if WM does not respond to request within 1 second, + // we assume support for _NET_REQUEST_FRAME_EXTENTS is not working + m_netFrameExtentsTimerId = + g_timeout_add(1000, request_frame_extents_timeout, this); + } + // defer calling gtk_widget_show() m_isShown = true; return true; @@ -1219,8 +1275,8 @@ void wxTopLevelWindowGTK::Maximize(bool maximize) bool wxTopLevelWindowGTK::IsMaximized() const { - return m_widget->window && - (gdk_window_get_state(m_widget->window) & GDK_WINDOW_STATE_MAXIMIZED); + GdkWindow* window = gtk_widget_get_window(m_widget); + return window && (gdk_window_get_state(window) & GDK_WINDOW_STATE_MAXIMIZED); } void wxTopLevelWindowGTK::Restore() @@ -1299,9 +1355,9 @@ bool wxTopLevelWindowGTK::SetShape(const wxRegion& region) if ( gtk_widget_get_realized(m_widget) ) { if ( m_wxwindow ) - do_shape_combine_region(m_wxwindow->window, region); + do_shape_combine_region(gtk_widget_get_window(m_wxwindow), region); - return do_shape_combine_region(m_widget->window, region); + return do_shape_combine_region(gtk_widget_get_window(m_widget), region); } else // not realized yet { @@ -1403,14 +1459,17 @@ static Window wxGetTopmostWindowX11(Display *dpy, Window child) bool wxTopLevelWindowGTK::SetTransparent(wxByte alpha) { - if (!m_widget || !m_widget->window) + GdkWindow* window = NULL; + if (m_widget) + window = gtk_widget_get_window(m_widget); + if (window == NULL) return false; - Display* dpy = GDK_WINDOW_XDISPLAY (m_widget->window); + Display* dpy = GDK_WINDOW_XDISPLAY(window); // We need to get the X Window that has the root window as the immediate parent // and m_widget->window as a child. This should be the X Window that the WM manages and // from which the opacity property is checked from. - Window win = wxGetTopmostWindowX11(dpy, GDK_WINDOW_XID (m_widget->window)); + Window win = wxGetTopmostWindowX11(dpy, GDK_WINDOW_XID(window)); // Using pure Xlib to not have a GTK version check mess due to gtk2.0 not having GdkDisplay