Only account for WM frame extents in tlw size if WM supports _NET_FRAME_EXTENTS. Extents cache no longer needed.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@50467 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Paul Cornett 2007-12-04 17:26:57 +00:00
parent 9dcff96ba9
commit 53e3cd047c
5 changed files with 52 additions and 112 deletions

View File

@ -14,9 +14,6 @@
#include "wx/toplevel.h"
#include <gtk/gtkversion.h>
#if GTK_CHECK_VERSION(2, 1, 0)
class WXDLLIMPEXP_ADV wxTaskBarIconAreaBase : public wxTopLevelWindow
{
public:
@ -25,8 +22,6 @@ public:
// Returns true if SYSTRAY protocol is supported by the desktop
bool IsProtocolSupported();
virtual bool IsDecorCacheable() const;
wxEvtHandler *m_invokingWindow;
protected:
@ -35,5 +30,4 @@ protected:
#endif // wxUSE_MENUS_NATIVE
};
#endif // GTK_CHECK_VERSION(2, 1, 0)
#endif // _WX_GTK_TASKBARPRIV_H_

View File

@ -94,6 +94,8 @@ public:
GtkWidget *m_mainWidget;
bool m_deferShow;
bool m_fsIsShowing; /* full screen */
int m_fsSaveGdkFunc, m_fsSaveGdkDecor;
wxRect m_fsSaveFrame;
@ -112,9 +114,6 @@ public:
// return the size of the window without WM decorations
void GTKDoGetSize(int *width, int *height) const;
// whether frame extents are accurate
virtual bool IsDecorCacheable() const;
protected:
// give hints to the Window Manager for how the size
// of the TLW can be changed by dragging

View File

@ -347,10 +347,6 @@ bool wxMiniFrame::Create( wxWindow *parent, wxWindowID id, const wxString &title
if (style & wxRESIZE_BORDER)
m_gdkFunc = GDK_FUNC_RESIZE;
// need to reset default size after changing m_gdkDecor
gtk_window_set_default_size(GTK_WINDOW(m_widget), m_width, m_height);
m_decorSize.Set(0, 0);
// don't allow sizing smaller than decorations
GdkGeometry geom;
geom.min_width = 2 * m_miniEdge;

View File

@ -14,9 +14,6 @@
#if wxUSE_TASKBARICON
#include <gtk/gtkversion.h>
#if GTK_CHECK_VERSION(2, 1, 0)
#include "wx/gtk/taskbarpriv.h"
#ifndef WX_PRECOMP
@ -47,6 +44,16 @@ wxTaskBarIconAreaBase::wxTaskBarIconAreaBase()
wxFRAME_SHAPED,
wxEmptyString /*eggtray doesn't like setting wmclass*/);
// WM frame extents are not useful for wxTaskBarIcon
m_deferShow = false;
gulong handler_id = g_signal_handler_find(
m_widget,
GSignalMatchType(G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA),
g_signal_lookup("property_notify_event", GTK_TYPE_WIDGET),
0, NULL, NULL, this);
if (handler_id != 0)
g_signal_handler_disconnect(m_widget, handler_id);
m_invokingWindow = NULL;
}
@ -71,13 +78,6 @@ bool wxTaskBarIconAreaBase::IsProtocolSupported()
return (bool)s_supported;
}
bool wxTaskBarIconAreaBase::IsDecorCacheable() const
{
// Apparently, WM frame extents extend to full width of screen when window
// is in the tray. Don't cache, it's not useful for other windows.
return false;
}
//-----------------------------------------------------------------------------
// Pop-up menu stuff
//-----------------------------------------------------------------------------
@ -150,5 +150,4 @@ bool wxTaskBarIconAreaBase::DoPopupMenu( wxMenu *menu, int x, int y )
}
#endif // wxUSE_MENUS_NATIVE
#endif // GTK_CHECK_VERSION(2, 1, 0)
#endif // wxUSE_TASKBARICON

View File

@ -202,25 +202,6 @@ gboolean gtk_frame_focus_out_callback(GtkWidget * WXUNUSED(widget),
}
}
//-----------------------------------------------------------------------------
// Get cached size of WM decorations for given GdkWMDecoration.
static wxSize& GetDecorSize(int decor)
{
// In testing, only the title bar and GDK_DECOR_BORDER made a difference.
// 4 possible combinations of title bar and border
static wxSize size[4];
int index = 0;
// title bar
if (decor & (GDK_DECOR_MENU | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE | GDK_DECOR_TITLE))
index = 1;
// border
if (decor & GDK_DECOR_BORDER)
index |= 2;
return size[index];
}
//-----------------------------------------------------------------------------
// "size_allocate" from m_wxwindow
//-----------------------------------------------------------------------------
@ -237,8 +218,7 @@ size_allocate(GtkWidget*, GtkAllocation* alloc, wxTopLevelWindowGTK* win)
wxSize size(win->m_widget->allocation.width,
win->m_widget->allocation.height);
if (!win->IsFullScreen())
size += win->m_decorSize;
size += win->m_decorSize;
win->m_width = size.x;
win->m_height = size.y;
@ -356,29 +336,10 @@ gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget),
extern "C" {
static gboolean
gtk_frame_map_callback( GtkWidget* widget,
gtk_frame_map_callback( GtkWidget*,
GdkEvent * WXUNUSED(event),
wxTopLevelWindow *win )
{
// Calculate size of WM decorations.
// Done here in case WM does not support the _NET_FRAME_EXTENTS property.
if (win->IsDecorCacheable() && !win->IsFullScreen())
{
GdkRectangle rect;
gdk_window_get_frame_extents(widget->window, &rect);
int w, h;
gdk_drawable_get_size(widget->window, &w, &h);
const wxSize decorSize = wxSize(rect.width - w, rect.height - h);
if (win->m_decorSize != decorSize)
{
// Update window size and frame extents cache
win->m_width = rect.width;
win->m_height = rect.height;
win->m_decorSize = decorSize;
GetDecorSize(win->m_gdkDecor) = decorSize;
}
}
const bool wasIconized = win->IsIconized();
win->SetIconizeState(false);
@ -424,8 +385,7 @@ static gboolean property_notify_event(
{
// Watch for changes to _NET_FRAME_EXTENTS property
static GdkAtom property = gdk_atom_intern("_NET_FRAME_EXTENTS", false);
if (event->state == GDK_PROPERTY_NEW_VALUE && event->atom == property &&
win->IsDecorCacheable() && !win->IsFullScreen())
if (event->state == GDK_PROPERTY_NEW_VALUE && event->atom == property)
{
Atom xproperty = gdk_x11_atom_to_xatom_for_display(
gdk_drawable_get_display(event->window), property);
@ -447,8 +407,7 @@ static gboolean property_notify_event(
{
const wxSize diff = win->m_decorSize - decorSize;
win->m_decorSize = decorSize;
GetDecorSize(win->m_gdkDecor) = decorSize;
if (GTK_WIDGET_VISIBLE(win->m_widget))
if (!win->m_deferShow)
{
// adjust overall size to match change in frame extents
win->m_width -= diff.x;
@ -467,9 +426,10 @@ static gboolean property_notify_event(
gtk_window_resize(GTK_WINDOW(win->m_widget), w, h);
}
}
if (!GTK_WIDGET_VISIBLE(win->m_widget))
if (win->m_deferShow)
{
// gtk_widget_show() was deferred, do it now
win->m_deferShow = false;
wxSizeEvent sizeEvent(win->GetSize(), win->GetId());
sizeEvent.SetEventObject(win);
win->HandleWindowEvent(sizeEvent);
@ -503,6 +463,7 @@ void wxTopLevelWindowGTK::Init()
m_themeEnabled = true;
m_gdkDecor = m_gdkFunc = 0;
m_grabbed = false;
m_deferShow = true;
m_urgency_hint = -2;
}
@ -697,12 +658,7 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent,
}
}
m_decorSize = GetDecorSize(m_gdkDecor);
// m_sizeDecor needs to be set before calling GTKDoGetSize
int w, h;
GTKDoGetSize(&w, &h);
gtk_window_set_default_size(GTK_WINDOW(m_widget), w, h);
gtk_window_set_default_size(GTK_WINDOW(m_widget), m_width, m_height);
return true;
}
@ -839,7 +795,9 @@ bool wxTopLevelWindowGTK::Show( bool show )
{
wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
if (show && !GTK_WIDGET_REALIZED(m_widget))
const bool wasRealized = GTK_WIDGET_REALIZED(m_widget);
bool deferShow = show && m_deferShow && !wasRealized;
if (deferShow)
{
// Initial show. If WM supports _NET_REQUEST_FRAME_EXTENTS, defer
// calling gtk_widget_show() until _NET_FRAME_EXTENTS property
@ -865,32 +823,34 @@ bool wxTopLevelWindowGTK::Show( bool show )
g_object_unref(child);
}
// if WM supports _NET_REQUEST_FRAME_EXTENTS
GdkAtom request_extents =
gdk_atom_intern("_NET_REQUEST_FRAME_EXTENTS", false);
GdkScreen* screen = gdk_drawable_get_screen(m_widget->window);
if (gdk_x11_screen_supports_net_wm_hint(screen, request_extents))
{
// 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);
xevent.message_type = gdk_x11_atom_to_xatom_for_display(
gdk_drawable_get_display(m_widget->window), request_extents);
xevent.format = 32;
Display* display = gdk_x11_drawable_get_xdisplay(m_widget->window);
XSendEvent(display, DefaultRootWindow(display), false,
SubstructureNotifyMask | SubstructureRedirectMask,
(XEvent*)&xevent);
m_deferShow =
deferShow = gdk_x11_screen_supports_net_wm_hint(
gdk_drawable_get_screen(m_widget->window),
gdk_atom_intern("_NET_REQUEST_FRAME_EXTENTS", false)) != 0;
}
if (deferShow)
{
// 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);
xevent.message_type = gdk_x11_atom_to_xatom_for_display(
gdk_drawable_get_display(m_widget->window),
gdk_atom_intern("_NET_REQUEST_FRAME_EXTENTS", false));
xevent.format = 32;
Display* display = gdk_x11_drawable_get_xdisplay(m_widget->window);
XSendEvent(display, DefaultRootWindow(display), false,
SubstructureNotifyMask | SubstructureRedirectMask,
(XEvent*)&xevent);
// defer calling gtk_widget_show()
m_isShown = true;
return true;
}
// WM does not support _NET_REQUEST_FRAME_EXTENTS, overall size may
// change when correct frame extents become known.
// defer calling gtk_widget_show()
m_isShown = true;
return true;
}
if (show && !wasRealized)
{
// size_allocate signals occur in reverse order (bottom to top).
// Things work better if the initial wxSizeEvents are sent (from the
// top down), before the initial size_allocate signals occur.
@ -929,12 +889,9 @@ void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXU
void wxTopLevelWindowGTK::GTKDoGetSize(int *width, int *height) const
{
wxSize size(m_width, m_height);
if (!IsFullScreen())
{
size -= m_decorSize;
if (size.x < 0) size.x = 0;
if (size.y < 0) size.y = 0;
}
size -= m_decorSize;
if (size.x < 0) size.x = 0;
if (size.y < 0) size.y = 0;
if (width) *width = size.x;
if (height) *height = size.y;
}
@ -1044,11 +1001,6 @@ void wxTopLevelWindowGTK::DoSetSizeHints( int minW, int minH,
(GtkWindow*)m_widget, NULL, &hints, (GdkWindowHints)hints_mask);
}
bool wxTopLevelWindowGTK::IsDecorCacheable() const
{
return true;
}
void wxTopLevelWindowGTK::OnInternalIdle()
{
// set the focus if not done yet and if we can already do it