get more accurate TLW sizing by using a window decorations cache

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@48646 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Paul Cornett
2007-09-13 04:36:06 +00:00
parent 7742ea6a6f
commit 290cd3016c
6 changed files with 216 additions and 147 deletions

View File

@@ -14,7 +14,6 @@
#include "wx/toplevel.h" #include "wx/toplevel.h"
#ifdef __WXGTK20__
#include <gtk/gtkversion.h> #include <gtk/gtkversion.h>
#if GTK_CHECK_VERSION(2, 1, 0) #if GTK_CHECK_VERSION(2, 1, 0)
@@ -26,6 +25,8 @@ public:
// Returns true if SYSTRAY protocol is supported by the desktop // Returns true if SYSTRAY protocol is supported by the desktop
bool IsProtocolSupported(); bool IsProtocolSupported();
virtual bool IsDecorCacheable() const;
wxEvtHandler *m_invokingWindow; wxEvtHandler *m_invokingWindow;
protected: protected:
@@ -34,6 +35,5 @@ protected:
#endif // wxUSE_MENUS_NATIVE #endif // wxUSE_MENUS_NATIVE
}; };
#endif // __WXGTK20__
#endif // GTK_CHECK_VERSION(2, 1, 0) #endif // GTK_CHECK_VERSION(2, 1, 0)
#endif // _WX_GTK_TASKBARPRIV_H_ #endif // _WX_GTK_TASKBARPRIV_H_

View File

@@ -94,11 +94,11 @@ public:
GtkWidget *m_mainWidget; GtkWidget *m_mainWidget;
bool m_fsIsShowing; /* full screen */ bool m_fsIsShowing; /* full screen */
long m_fsSaveGdkFunc, m_fsSaveGdkDecor; int m_fsSaveGdkFunc, m_fsSaveGdkDecor;
wxRect m_fsSaveFrame; wxRect m_fsSaveFrame;
// m_windowStyle translated to GDK's terms // m_windowStyle translated to GDK's terms
long m_gdkFunc, int m_gdkFunc,
m_gdkDecor; m_gdkDecor;
bool m_sizeSet; bool m_sizeSet;
@@ -113,11 +113,14 @@ public:
int maxW = wxDefaultCoord, int maxH = wxDefaultCoord, int maxW = wxDefaultCoord, int maxH = wxDefaultCoord,
int incW = wxDefaultCoord, int incH = wxDefaultCoord ); int incW = wxDefaultCoord, int incH = wxDefaultCoord );
// return the full size of the window without WM decorations // return the size of the window without WM decorations
void GTKDoGetSize(int *width, int *height) const; void GTKDoGetSize(int *width, int *height) const;
void GtkUpdateSize() { m_sizeSet = false; } void GtkUpdateSize() { m_sizeSet = false; }
// whether frame extents are accurate
virtual bool IsDecorCacheable() const;
protected: protected:
// common part of all ctors // common part of all ctors
void Init(); void Init();
@@ -126,7 +129,6 @@ protected:
virtual void DoMoveWindow(int x, int y, int width, int height); virtual void DoMoveWindow(int x, int y, int width, int height);
// take into account WM decorations here // take into account WM decorations here
virtual void DoGetSize(int *width, int *height) const;
virtual void DoSetSize(int x, int y, virtual void DoSetSize(int x, int y,
int width, int height, int width, int height,
int sizeFlags = wxSIZE_AUTO); int sizeFlags = wxSIZE_AUTO);
@@ -134,11 +136,6 @@ protected:
// override these methods to take into account tool/menu/statusbars // override these methods to take into account tool/menu/statusbars
virtual void DoGetClientSize(int *width, int *height) const; virtual void DoGetClientSize(int *width, int *height) const;
// this method takes the size of the window not taking account of
// decorations
void GTKDoSetSize(int width, int height);
// string shown in the title bar // string shown in the title bar
wxString m_title; wxString m_title;

View File

@@ -310,6 +310,9 @@ void wxFrame::GtkOnSize()
ConstrainSize(); ConstrainSize();
int width, height;
GTKDoGetSize(&width, &height);
if (m_mainWidget) if (m_mainWidget)
{ {
// TODO // TODO
@@ -327,7 +330,7 @@ void wxFrame::GtkOnSize()
{ {
int xx = m_miniEdge; int xx = m_miniEdge;
int yy = m_miniEdge + m_miniTitle; int yy = m_miniEdge + m_miniTitle;
int ww = m_width - 2*m_miniEdge; int ww = width - 2*m_miniEdge;
if (ww < 0) if (ww < 0)
ww = 0; ww = 0;
menubarHeight = m_menuBarHeight; menubarHeight = m_menuBarHeight;
@@ -363,7 +366,7 @@ void wxFrame::GtkOnSize()
{ {
ww = m_toolBarDetached ? wxPLACE_HOLDER ww = m_toolBarDetached ? wxPLACE_HOLDER
: m_frameToolBar->m_width; : m_frameToolBar->m_width;
hh = m_height - 2*m_miniEdge; hh = height - 2*m_miniEdge;
client_area_x_offset += ww; client_area_x_offset += ww;
} }
@@ -373,7 +376,7 @@ void wxFrame::GtkOnSize()
ww = m_toolBarDetached ? wxPLACE_HOLDER ww = m_toolBarDetached ? wxPLACE_HOLDER
: m_frameToolBar->m_width; : m_frameToolBar->m_width;
xx = GetClientSize().x - 1; xx = GetClientSize().x - 1;
hh = m_height - 2*m_miniEdge; hh = height - 2*m_miniEdge;
if( hh < 0 ) if( hh < 0 )
hh = 0; hh = 0;
@@ -387,13 +390,13 @@ void wxFrame::GtkOnSize()
#endif // wxUSE_MENUS_NATIVE #endif // wxUSE_MENUS_NATIVE
m_frameToolBar->m_x = xx; m_frameToolBar->m_x = xx;
m_frameToolBar->m_y = yy; m_frameToolBar->m_y = yy;
ww = m_width - 2*m_miniEdge; ww = width - 2*m_miniEdge;
hh = m_toolBarDetached ? wxPLACE_HOLDER hh = m_toolBarDetached ? wxPLACE_HOLDER
: m_frameToolBar->m_height; : m_frameToolBar->m_height;
} }
else else
{ {
ww = m_width - 2*m_miniEdge; ww = width - 2*m_miniEdge;
hh = m_toolBarDetached ? wxPLACE_HOLDER hh = m_toolBarDetached ? wxPLACE_HOLDER
: m_frameToolBar->m_height; : m_frameToolBar->m_height;
@@ -412,8 +415,8 @@ void wxFrame::GtkOnSize()
int client_x = client_area_x_offset + m_miniEdge; int client_x = client_area_x_offset + m_miniEdge;
int client_y = client_area_y_offset + m_miniEdge + m_miniTitle; int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
int client_w = m_width - client_area_x_offset - 2*m_miniEdge; int client_w = width - client_area_x_offset - 2*m_miniEdge;
int client_h = m_height - client_area_y_offset- 2*m_miniEdge - m_miniTitle; int client_h = height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
if (client_w < 0) if (client_w < 0)
client_w = 0; client_w = 0;
if (client_h < 0) if (client_h < 0)
@@ -432,8 +435,8 @@ void wxFrame::GtkOnSize()
if (m_frameStatusBar && m_frameStatusBar->IsShown()) if (m_frameStatusBar && m_frameStatusBar->IsShown())
{ {
int xx = 0 + m_miniEdge; int xx = 0 + m_miniEdge;
int yy = m_height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset; int yy = height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset;
int ww = m_width - 2*m_miniEdge; int ww = width - 2*m_miniEdge;
if (ww < 0) if (ww < 0)
ww = 0; ww = 0;
int hh = wxSTATUS_HEIGHT; int hh = wxSTATUS_HEIGHT;

View File

@@ -134,11 +134,11 @@ void wxMDIParentFrame::GtkOnSize()
menu_bar->m_x = 0; menu_bar->m_x = 0;
menu_bar->m_y = 0; menu_bar->m_y = 0;
menu_bar->m_width = m_width; GTKDoGetSize(&menu_bar->m_width, NULL);
menu_bar->m_height = wxMENU_HEIGHT; menu_bar->m_height = wxMENU_HEIGHT;
gtk_pizza_set_size( GTK_PIZZA(m_mainWidget), gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
menu_bar->m_widget, menu_bar->m_widget,
0, 0, m_width, wxMENU_HEIGHT ); 0, 0, menu_bar->m_width, menu_bar->m_height);
} }
void wxMDIParentFrame::OnInternalIdle() void wxMDIParentFrame::OnInternalIdle()
@@ -160,11 +160,11 @@ void wxMDIParentFrame::OnInternalIdle()
wxMenuBar *menu_bar = active_child_frame->m_menuBar; wxMenuBar *menu_bar = active_child_frame->m_menuBar;
if (menu_bar) if (menu_bar)
{ {
menu_bar->m_width = m_width; GTKDoGetSize(&menu_bar->m_width, NULL);
menu_bar->m_height = wxMENU_HEIGHT; menu_bar->m_height = wxMENU_HEIGHT;
gtk_pizza_set_size( GTK_PIZZA(m_mainWidget), gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
menu_bar->m_widget, menu_bar->m_widget,
0, 0, m_width, wxMENU_HEIGHT ); 0, 0, menu_bar->m_width, menu_bar->m_height);
menu_bar->SetInvokingWindow(active_child_frame); menu_bar->SetInvokingWindow(active_child_frame);
} }
} }
@@ -191,11 +191,11 @@ void wxMDIParentFrame::OnInternalIdle()
{ {
if (menu_bar->Show(true)) if (menu_bar->Show(true))
{ {
menu_bar->m_width = m_width; GTKDoGetSize(&menu_bar->m_width, NULL);
menu_bar->m_height = wxMENU_HEIGHT; menu_bar->m_height = wxMENU_HEIGHT;
gtk_pizza_set_size( GTK_PIZZA(m_mainWidget), gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
menu_bar->m_widget, menu_bar->m_widget,
0, 0, m_width, wxMENU_HEIGHT ); 0, 0, menu_bar->m_width, menu_bar->m_height);
menu_bar->SetInvokingWindow( child_frame ); menu_bar->SetInvokingWindow( child_frame );
} }
visible_child_menu = true; visible_child_menu = true;
@@ -227,11 +227,11 @@ void wxMDIParentFrame::OnInternalIdle()
m_frameMenuBar->Show( true ); m_frameMenuBar->Show( true );
m_frameMenuBar->SetInvokingWindow( this ); m_frameMenuBar->SetInvokingWindow( this );
m_frameMenuBar->m_width = m_width; GTKDoGetSize(&m_frameMenuBar->m_width, NULL);
m_frameMenuBar->m_height = wxMENU_HEIGHT; m_frameMenuBar->m_height = wxMENU_HEIGHT;
gtk_pizza_set_size( GTK_PIZZA(m_mainWidget), gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
m_frameMenuBar->m_widget, m_frameMenuBar->m_widget,
0, 0, m_width, wxMENU_HEIGHT ); 0, 0, m_frameMenuBar->m_width, m_frameMenuBar->m_height);
} }
} }
} }
@@ -383,9 +383,11 @@ void wxMDIChildFrame::SetMenuBar( wxMenuBar *menu_bar )
m_menuBar->SetParent( mdi_frame ); m_menuBar->SetParent( mdi_frame );
/* insert the invisible menu bar into the _parent_ mdi frame */ /* insert the invisible menu bar into the _parent_ mdi frame */
int w;
mdi_frame->GTKDoGetSize(&w, NULL);
gtk_pizza_put( GTK_PIZZA(mdi_frame->m_mainWidget), gtk_pizza_put( GTK_PIZZA(mdi_frame->m_mainWidget),
m_menuBar->m_widget, m_menuBar->m_widget,
0, 0, mdi_frame->m_width, wxMENU_HEIGHT ); 0, 0, w, wxMENU_HEIGHT);
} }
} }

View File

@@ -14,6 +14,9 @@
#if wxUSE_TASKBARICON #if wxUSE_TASKBARICON
#include <gtk/gtkversion.h>
#if GTK_CHECK_VERSION(2, 1, 0)
#include "wx/gtk/taskbarpriv.h" #include "wx/gtk/taskbarpriv.h"
#ifndef WX_PRECOMP #ifndef WX_PRECOMP
@@ -22,14 +25,9 @@
#include "wx/menu.h" #include "wx/menu.h"
#endif #endif
#include <gtk/gtk.h>
#include <gdk/gdkx.h> #include <gdk/gdkx.h>
#ifdef __WXGTK20__
#include <gtk/gtkversion.h>
#if GTK_CHECK_VERSION(2, 1, 0)
#include "gtk/gtk.h"
#include "eggtrayicon.h" #include "eggtrayicon.h"
wxTaskBarIconAreaBase::wxTaskBarIconAreaBase() wxTaskBarIconAreaBase::wxTaskBarIconAreaBase()
@@ -73,6 +71,13 @@ bool wxTaskBarIconAreaBase::IsProtocolSupported()
return (bool)s_supported; 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 // Pop-up menu stuff
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -143,9 +148,7 @@ bool wxTaskBarIconAreaBase::DoPopupMenu( wxMenu *menu, int x, int y )
return true; return true;
} }
#endif // wxUSE_MENUS_NATIVE #endif // wxUSE_MENUS_NATIVE
#endif // __WXGTK20__
#endif // GTK_CHECK_VERSION(2, 1, 0) #endif // GTK_CHECK_VERSION(2, 1, 0)
#endif // wxUSE_TASKBARICON #endif // wxUSE_TASKBARICON

View File

@@ -194,6 +194,25 @@ static gboolean gtk_frame_focus_out_callback( GtkWidget *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" // "size_allocate"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -204,21 +223,16 @@ static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation*
if (!win->m_hasVMT) if (!win->m_hasVMT)
return; return;
if ((win->m_width != alloc->width) || (win->m_height != alloc->height)) wxSize sizeDecor;
{ if (!win->IsFullScreen())
/* sizeDecor = GetDecorSize(win->m_gdkDecor);
wxPrintf( wxT("gtk_frame_size_callback from ") ); const int w = alloc->width + sizeDecor.x;
if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) const int h = alloc->height + sizeDecor.y;
wxPrintf( win->GetClassInfo()->GetClassName() );
wxPrintf( wxT(" %d %d %d %d\n"), (int)alloc->x,
(int)alloc->y,
(int)alloc->width,
(int)alloc->height );
*/
// Tell the wxWindow class about the new size if (win->m_width != w || win->m_height != h)
win->m_width = alloc->width; {
win->m_height = alloc->height; win->m_width = w;
win->m_height = h;
win->GtkUpdateSize(); win->GtkUpdateSize();
} }
@@ -230,19 +244,17 @@ static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation*
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
extern "C" { extern "C" {
static
void wxgtk_tlw_size_request_callback(GtkWidget * WXUNUSED(widget), void wxgtk_tlw_size_request_callback(GtkWidget * WXUNUSED(widget),
GtkRequisition *requisition, GtkRequisition *requisition,
wxTopLevelWindowGTK *win) wxTopLevelWindowGTK *win)
{ {
// we must return the size of the window without WM decorations, otherwise // we must return the size of the window without WM decorations, otherwise
// GTK+ gets confused, so don't call just GetSize() here // GTK+ gets confused, so don't call just GetSize() here
int w, h; win->GTKDoGetSize(&requisition->width, &requisition->height);
win->GTKDoGetSize(&w, &h); }
}
requisition->height = h;
requisition->width = w;
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// "delete_event" // "delete_event"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -330,10 +342,30 @@ gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget),
extern "C" { extern "C" {
static gboolean static gboolean
gtk_frame_map_callback( GtkWidget * WXUNUSED(widget), gtk_frame_map_callback( GtkWidget* widget,
GdkEvent * WXUNUSED(event), GdkEvent * WXUNUSED(event),
wxTopLevelWindow *win ) 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);
wxSize& decorSize = GetDecorSize(win->m_gdkDecor);
const wxSize size = wxSize(rect.width - w, rect.height - h);
if (decorSize.x != size.x || decorSize.y != size.y)
{
// Update window size and frame extents cache
win->m_width = rect.width;
win->m_height = rect.height;
win->GtkUpdateSize();
decorSize = size;
}
}
win->SetIconizeState(false); win->SetIconizeState(false);
return false; return false;
} }
@@ -354,6 +386,64 @@ gtk_frame_unmap_callback( GtkWidget * WXUNUSED(widget),
} }
} }
//-----------------------------------------------------------------------------
// "property_notify_event" from m_widget
//-----------------------------------------------------------------------------
extern "C" {
static gboolean property_notify_event(
GtkWidget*, GdkEventProperty* event, wxTopLevelWindowGTK* win)
{
// 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())
{
Atom xproperty;
#if GTK_CHECK_VERSION(2, 2, 0)
if (gtk_check_version(2, 2, 0) == NULL)
{
xproperty = gdk_x11_atom_to_xatom_for_display(
gdk_drawable_get_display(event->window), property);
}
else
#endif
{
xproperty = gdk_x11_atom_to_xatom(property);
}
Atom type;
int format;
gulong nitems, bytes_after;
long* data = NULL;
Status status = XGetWindowProperty(
gdk_x11_drawable_get_xdisplay(event->window),
gdk_x11_drawable_get_xid(event->window),
xproperty,
0, 4, false, XA_CARDINAL,
&type, &format, &nitems, &bytes_after, (guchar**)&data);
if (status == Success && data && nitems == 4)
{
wxSize& decorSize = GetDecorSize(win->m_gdkDecor);
const wxSize size =
wxSize(int(data[0] + data[1]), int(data[2] + data[3]));
if (decorSize.x != size.x || decorSize.y != size.y)
{
// Update window size and frame extents cache
win->m_width += size.x - decorSize.x;
win->m_height += size.y - decorSize.y;
if (win->m_width < 0) win->m_width = 0;
if (win->m_height < 0) win->m_height = 0;
win->GtkUpdateSize();
decorSize = size;
}
}
if (data)
XFree(data);
}
return false;
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// "expose_event" of m_client // "expose_event" of m_client
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -535,8 +625,6 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent,
if ((m_x != -1) || (m_y != -1)) if ((m_x != -1) || (m_y != -1))
gtk_widget_set_uposition( m_widget, m_x, m_y ); gtk_widget_set_uposition( m_widget, m_x, m_y );
gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
// we cannot set MWM hints and icons before the widget has // we cannot set MWM hints and icons before the widget has
// been realized, so we do this directly after realization // been realized, so we do this directly after realization
g_signal_connect (m_widget, "realize", g_signal_connect (m_widget, "realize",
@@ -558,6 +646,10 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent,
g_signal_connect_after (m_widget, "focus_out_event", g_signal_connect_after (m_widget, "focus_out_event",
G_CALLBACK (gtk_frame_focus_out_callback), this); G_CALLBACK (gtk_frame_focus_out_callback), this);
gtk_widget_add_events(m_widget, GDK_PROPERTY_CHANGE_MASK);
g_signal_connect(m_widget, "property_notify_event",
G_CALLBACK(property_notify_event), this);
// decorations // decorations
if ((style & wxSIMPLE_BORDER) || (style & wxNO_BORDER)) if ((style & wxSIMPLE_BORDER) || (style & wxNO_BORDER))
{ {
@@ -575,8 +667,8 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent,
} }
else else
{ {
m_gdkDecor = (long) GDK_DECOR_BORDER; m_gdkDecor = GDK_DECOR_BORDER;
m_gdkFunc = (long) GDK_FUNC_MOVE; m_gdkFunc = GDK_FUNC_MOVE;
// All this is for Motif Window Manager "hints" and is supposed to be // All this is for Motif Window Manager "hints" and is supposed to be
// recognized by other WMs as well. // recognized by other WMs as well.
@@ -609,6 +701,11 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent,
} }
} }
// m_gdkDecor needs to be set before calling GTKDoGetSize
int w, h;
GTKDoGetSize(&w, &h);
gtk_window_set_default_size(GTK_WINDOW(m_widget), w, h);
return true; return true;
} }
@@ -787,37 +884,15 @@ void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXU
void wxTopLevelWindowGTK::GTKDoGetSize(int *width, int *height) const void wxTopLevelWindowGTK::GTKDoGetSize(int *width, int *height) const
{ {
return wxTopLevelWindowBase::DoGetSize(width, height); wxSize size(m_width, m_height);
} if (!IsFullScreen())
void wxTopLevelWindowGTK::GTKDoSetSize(int width, int height)
{ {
// avoid recursions size -= GetDecorSize(m_gdkDecor);
if (m_resizing) if (size.x < 0) size.x = 0;
return; if (size.y < 0) size.y = 0;
m_resizing = true;
int old_width = m_width;
int old_height = m_height;
if ( width != -1 )
m_width = width;
if ( height != -1 )
m_height = height;
ConstrainSize();
if ( m_width != old_width || m_height != old_height )
{
gtk_window_resize( GTK_WINDOW(m_widget), m_width, m_height );
/* we set the size in GtkOnSize, i.e. mostly the actual resizing is
done either directly before the frame is shown or in idle time
so that different calls to SetSize() don't lead to flicker. */
m_sizeSet = false;
} }
if (width) *width = size.x;
m_resizing = false; if (height) *height = size.y;
} }
void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags ) void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
@@ -851,48 +926,22 @@ void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int si
gtk_window_move( GTK_WINDOW(m_widget), m_x, m_y ); gtk_window_move( GTK_WINDOW(m_widget), m_x, m_y );
} }
m_resizing = true;
// and now change the size: as we want to set the size of the entire const wxSize oldSize(m_width, m_height);
// window, including decorations, we must adjust the size passed to if (width >= 0)
// GTKDoSetSize() which takes with the size of undecorated frame only m_width = width;
if ( width != -1 || height != -1 ) if (height >= 0)
m_height = height;
ConstrainSize();
if (m_width != oldSize.x || m_height != oldSize.y)
{ {
int wTotal, int w, h;
hTotal; GTKDoGetSize(&w, &h);
DoGetSize(&wTotal, &hTotal); gtk_window_resize(GTK_WINDOW(m_widget), w, h);
GtkUpdateSize();
int wUndec,
hUndec;
GTKDoGetSize(&wUndec, &hUndec);
if ( width != -1 )
width -= wTotal - wUndec;
if ( height != -1 )
height -= hTotal - hUndec;
} }
m_resizing = false;
GTKDoSetSize(width, height);
}
void wxTopLevelWindowGTK::DoGetSize(int *width, int *height) const
{
wxCHECK_RET( m_widget, wxT("invalid frame") );
if ( !m_widget->window )
{
// this can happen if we're called before the window is realized, so
// don't assert but just return the stored values
GTKDoGetSize(width, height);
return;
}
GdkRectangle rect;
gdk_window_get_frame_extents(m_widget->window, &rect);
if ( width )
*width = rect.width;
if ( height )
*height = rect.height;
} }
void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const
@@ -911,18 +960,20 @@ void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const
wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") ); wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
if (height) int w, h;
{ GTKDoGetSize(&w, &h);
*height = m_height - 2 * m_miniEdge - m_miniTitle;
if (*height < 0)
*height = 0;
}
if (width) if (width)
{ {
*width = m_width - 2 * m_miniEdge; *width = w - 2 * m_miniEdge;
if (*width < 0) if (*width < 0)
*width = 0; *width = 0;
} }
if (height)
{
*height = h - 2 * m_miniEdge - m_miniTitle;
if (*height < 0)
*height = 0;
}
} }
void wxTopLevelWindowGTK::DoSetSizeHints( int minW, int minH, void wxTopLevelWindowGTK::DoSetSizeHints( int minW, int minH,
@@ -935,17 +986,26 @@ void wxTopLevelWindowGTK::DoSetSizeHints( int minW, int minH,
const wxSize maxSize = GetMaxSize(); const wxSize maxSize = GetMaxSize();
GdkGeometry hints; GdkGeometry hints;
int hints_mask = 0; int hints_mask = 0;
const wxSize sizeDecor = GetDecorSize(m_gdkDecor);
if (minSize.x > 0 || minSize.y > 0) if (minSize.x > 0 || minSize.y > 0)
{ {
hints_mask |= GDK_HINT_MIN_SIZE; hints_mask |= GDK_HINT_MIN_SIZE;
hints.min_width = minSize.x > 0 ? minSize.x : 0; hints.min_width = minSize.x - sizeDecor.x;
hints.min_height = minSize.y > 0 ? minSize.y : 0; if (hints.min_width < 0)
hints.min_width = 0;
hints.min_height = minSize.y - sizeDecor.y;
if (hints.min_height < 0)
hints.min_height = 0;
} }
if (maxSize.x > 0 || maxSize.y > 0) if (maxSize.x > 0 || maxSize.y > 0)
{ {
hints_mask |= GDK_HINT_MAX_SIZE; hints_mask |= GDK_HINT_MAX_SIZE;
hints.max_width = maxSize.x > 0 ? maxSize.x : INT_MAX; hints.max_width = maxSize.x - sizeDecor.x;
hints.max_height = maxSize.y > 0 ? maxSize.y : INT_MAX; if (hints.max_width < 0)
hints.max_width = INT_MAX;
hints.max_height = maxSize.y - sizeDecor.y;
if (hints.max_height < 0)
hints.max_height = INT_MAX;
} }
if (incW > 0 || incH > 0) if (incW > 0 || incH > 0)
{ {
@@ -957,7 +1017,6 @@ void wxTopLevelWindowGTK::DoSetSizeHints( int minW, int minH,
(GtkWindow*)m_widget, NULL, &hints, (GdkWindowHints)hints_mask); (GtkWindow*)m_widget, NULL, &hints, (GdkWindowHints)hints_mask);
} }
void wxTopLevelWindowGTK::GtkOnSize() void wxTopLevelWindowGTK::GtkOnSize()
{ {
// avoid recursions // avoid recursions
@@ -970,9 +1029,11 @@ void wxTopLevelWindowGTK::GtkOnSize()
if (m_mainWidget) if (m_mainWidget)
{ {
int w, h;
GTKDoGetSize(&w, &h);
gtk_pizza_set_size( GTK_PIZZA(m_mainWidget), gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
m_wxwindow, m_wxwindow,
0, 0, m_width, m_height); 0, 0, w, h);
} }
m_sizeSet = true; m_sizeSet = true;
@@ -985,6 +1046,11 @@ void wxTopLevelWindowGTK::GtkOnSize()
m_resizing = false; m_resizing = false;
} }
bool wxTopLevelWindowGTK::IsDecorCacheable() const
{
return true;
}
void wxTopLevelWindowGTK::OnInternalIdle() void wxTopLevelWindowGTK::OnInternalIdle()
{ {
if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow)) if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
@@ -1232,8 +1298,6 @@ void wxTopLevelWindowGTK::SetWindowStyleFlag( long style )
#endif // GTK+ 2.2 #endif // GTK+ 2.2
} }
#include <X11/Xlib.h>
/* Get the X Window between child and the root window. /* Get the X Window between child and the root window.
This should usually be the WM managed XID */ This should usually be the WM managed XID */
static Window wxGetTopmostWindowX11(Display *dpy, Window child) static Window wxGetTopmostWindowX11(Display *dpy, Window child)