1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // ============================================================================
12 // ============================================================================
14 // ----------------------------------------------------------------------------
16 // ----------------------------------------------------------------------------
18 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
19 #pragma implementation "toplevel.h"
22 // For compilers that support precompilation, includes "wx.h".
23 #include "wx/wxprec.h"
26 #define XIconifyWindow XICONIFYWINDOW
32 #include "wx/dialog.h"
33 #include "wx/control.h"
35 #include "wx/dcclient.h"
36 #include "wx/gtk/private.h"
38 #include "wx/settings.h"
43 #include <gdk/gdkkeysyms.h>
46 #include "wx/gtk/win_gtk.h"
48 #include "wx/unix/utilsx11.h"
51 #include <X11/Xatom.h>
53 // ----------------------------------------------------------------------------
55 // ----------------------------------------------------------------------------
57 extern void wxapp_install_idle_handler();
60 // ----------------------------------------------------------------------------
62 // ----------------------------------------------------------------------------
64 extern wxList wxPendingDelete
;
66 extern int g_openDialogs
;
67 extern wxWindowGTK
*g_delayedFocus
;
69 //-----------------------------------------------------------------------------
70 // "focus" from m_window
71 //-----------------------------------------------------------------------------
73 static gint
gtk_frame_focus_callback( GtkWidget
*widget
, GtkDirectionType
WXUNUSED(d
), wxWindow
*WXUNUSED(win
) )
76 wxapp_install_idle_handler();
78 // This disables GTK's tab traversal
79 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus" );
83 //-----------------------------------------------------------------------------
85 //-----------------------------------------------------------------------------
87 static void gtk_frame_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxTopLevelWindowGTK
*win
)
90 wxapp_install_idle_handler();
95 if ((win
->m_width
!= alloc
->width
) || (win
->m_height
!= alloc
->height
))
98 wxPrintf( "OnSize from " );
99 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
100 wxPrintf( win->GetClassInfo()->GetClassName() );
101 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
104 (int)alloc->height );
107 win
->m_width
= alloc
->width
;
108 win
->m_height
= alloc
->height
;
109 win
->m_queuedFullRedraw
= TRUE
;
110 win
->GtkUpdateSize();
114 //-----------------------------------------------------------------------------
116 //-----------------------------------------------------------------------------
118 static gint
gtk_frame_delete_callback( GtkWidget
*WXUNUSED(widget
), GdkEvent
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
121 wxapp_install_idle_handler();
123 if (win
->IsEnabled() &&
124 (g_openDialogs
== 0 || (win
->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) ||
132 //-----------------------------------------------------------------------------
134 //-----------------------------------------------------------------------------
137 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
140 wxapp_install_idle_handler();
142 if (!win
->m_hasVMT
|| !win
->IsShown())
147 gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y
);
151 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
152 mevent
.SetEventObject( win
);
153 win
->GetEventHandler()->ProcessEvent( mevent
);
158 //-----------------------------------------------------------------------------
159 // "realize" from m_widget
160 //-----------------------------------------------------------------------------
162 // we cannot MWM hints and icons before the widget has been realized,
163 // so we do this directly after realization
166 gtk_frame_realized_callback( GtkWidget
* WXUNUSED(widget
),
167 wxTopLevelWindowGTK
*win
)
170 wxapp_install_idle_handler();
172 // All this is for Motif Window Manager "hints" and is supposed to be
173 // recognized by other WM as well. Not tested.
174 gdk_window_set_decorations(win
->m_widget
->window
,
175 (GdkWMDecoration
)win
->m_gdkDecor
);
176 gdk_window_set_functions(win
->m_widget
->window
,
177 (GdkWMFunction
)win
->m_gdkFunc
);
179 // GTK's shrinking/growing policy
180 if ((win
->m_gdkFunc
& GDK_FUNC_RESIZE
) == 0)
181 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 0, 0, 1);
183 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
186 wxIconBundle iconsOld
= win
->GetIcons();
187 if ( iconsOld
.GetIcon(-1).Ok() )
189 win
->SetIcon( wxNullIcon
);
190 win
->SetIcons( iconsOld
);
194 //-----------------------------------------------------------------------------
195 // "map_event" from m_widget
196 //-----------------------------------------------------------------------------
199 gtk_frame_map_callback( GtkWidget
* WXUNUSED(widget
),
200 GdkEvent
* WXUNUSED(event
),
201 wxTopLevelWindow
*win
)
203 win
->SetIconizeState(FALSE
);
206 //-----------------------------------------------------------------------------
207 // "unmap_event" from m_widget
208 //-----------------------------------------------------------------------------
211 gtk_frame_unmap_callback( GtkWidget
* WXUNUSED(widget
),
212 GdkEvent
* WXUNUSED(event
),
213 wxTopLevelWindow
*win
)
215 win
->SetIconizeState(TRUE
);
218 //-----------------------------------------------------------------------------
219 // "expose_event" of m_client
220 //-----------------------------------------------------------------------------
222 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
224 GtkPizza
*pizza
= GTK_PIZZA(widget
);
226 gtk_paint_flat_box (win
->m_widget
->style
,
227 pizza
->bin_window
, GTK_STATE_NORMAL
,
237 //-----------------------------------------------------------------------------
238 // "draw" of m_client
239 //-----------------------------------------------------------------------------
243 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
245 GtkPizza
*pizza
= GTK_PIZZA(widget
);
247 gtk_paint_flat_box (win
->m_widget
->style
,
248 pizza
->bin_window
, GTK_STATE_NORMAL
,
258 // ----------------------------------------------------------------------------
259 // wxTopLevelWindowGTK itself
260 // ----------------------------------------------------------------------------
262 //-----------------------------------------------------------------------------
263 // InsertChild for wxTopLevelWindowGTK
264 //-----------------------------------------------------------------------------
266 /* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
267 * C++ has no virtual methods in a constructor. We have to emulate a
268 * virtual function here as wxWidgets requires different ways to insert
269 * a child in container classes. */
271 static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK
* parent
, wxWindow
* child
)
273 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
275 if (!parent
->m_insertInClientArea
)
277 // these are outside the client area
278 wxTopLevelWindowGTK
* frame
= (wxTopLevelWindowGTK
*) parent
;
279 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
280 GTK_WIDGET(child
->m_widget
),
288 // these are inside the client area
289 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
290 GTK_WIDGET(child
->m_widget
),
297 // resize on OnInternalIdle
298 parent
->GtkUpdateSize();
301 // ----------------------------------------------------------------------------
302 // wxTopLevelWindowGTK creation
303 // ----------------------------------------------------------------------------
305 void wxTopLevelWindowGTK::Init()
310 m_mainWidget
= (GtkWidget
*) NULL
;
311 m_insertInClientArea
= TRUE
;
312 m_isIconized
= FALSE
;
313 m_fsIsShowing
= FALSE
;
314 m_themeEnabled
= TRUE
;
315 m_gdkDecor
= m_gdkFunc
= 0;
319 bool wxTopLevelWindowGTK::Create( wxWindow
*parent
,
321 const wxString
& title
,
323 const wxSize
& sizeOrig
,
325 const wxString
&name
)
327 // always create a frame of some reasonable, even if arbitrary, size (at
328 // least for MSW compatibility)
329 wxSize size
= sizeOrig
;
330 size
.x
= WidthDefault(size
.x
);
331 size
.y
= HeightDefault(size
.y
);
333 wxTopLevelWindows
.Append( this );
335 m_needParent
= FALSE
;
337 if (!PreCreation( parent
, pos
, size
) ||
338 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
340 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
346 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInTopLevelWindow
;
348 // NB: m_widget may be !=NULL if it was created by derived class' Create,
349 // e.g. in wxTaskBarIconAreaGTK
350 if (m_widget
== NULL
)
352 GtkWindowType win_type
= GTK_WINDOW_TOPLEVEL
;
353 if (style
& wxFRAME_TOOL_WINDOW
)
354 win_type
= GTK_WINDOW_POPUP
;
356 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)
359 m_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
360 // Tell WM that this is a dialog window and make it center
361 // on parent by default (this is what GtkDialog ctor does):
362 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
363 GDK_WINDOW_TYPE_HINT_DIALOG
);
364 gtk_window_set_position(GTK_WINDOW(m_widget
),
365 GTK_WIN_POS_CENTER_ON_PARENT
);
367 m_widget
= gtk_window_new(GTK_WINDOW_DIALOG
);
372 m_widget
= gtk_window_new(win_type
);
376 if (m_parent
&& (((GTK_IS_WINDOW(m_parent
->m_widget
)) &&
377 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) ||
378 (style
& wxFRAME_FLOAT_ON_PARENT
)))
380 gtk_window_set_transient_for( GTK_WINDOW(m_widget
), GTK_WINDOW(m_parent
->m_widget
) );
383 #if GTK_CHECK_VERSION(2,2,0)
384 if (style
& wxFRAME_NO_TASKBAR
)
386 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), TRUE
);
391 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), wxGTK_CONV( name
), wxGTK_CONV( name
) );
393 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
394 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
396 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
397 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
399 // m_mainWidget holds the toolbar, the menubar and the client area
400 m_mainWidget
= gtk_pizza_new();
401 gtk_widget_show( m_mainWidget
);
402 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
403 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
405 if (m_miniEdge
== 0) // wxMiniFrame has its own version.
407 // For m_mainWidget themes
408 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
409 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
411 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
412 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
416 // m_wxwindow only represents the client area without toolbar and menubar
417 m_wxwindow
= gtk_pizza_new();
418 gtk_widget_show( m_wxwindow
);
419 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
421 // we donm't allow the frame to get the focus as otherwise
422 // the frame will grab it at arbitrary focus changes
423 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
425 if (m_parent
) m_parent
->AddChild( this );
427 // the user resized the frame by dragging etc.
428 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
429 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
433 if ((m_x
!= -1) || (m_y
!= -1))
434 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
436 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
438 // we cannot set MWM hints and icons before the widget has
439 // been realized, so we do this directly after realization
440 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
441 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
443 // the only way to get the window size is to connect to this event
444 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
445 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
447 // map and unmap for iconized state
448 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
449 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
450 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
451 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
453 // the only way to get the window size is to connect to this event
454 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
455 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
457 // disable native tab traversal
458 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
459 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
462 if ((m_miniEdge
> 0) || (style
& wxSIMPLE_BORDER
) || (style
& wxNO_BORDER
))
469 m_gdkDecor
= (long) GDK_DECOR_BORDER
;
470 m_gdkFunc
= (long) GDK_FUNC_MOVE
;
472 // All this is for Motif Window Manager "hints" and is supposed to be
473 // recognized by other WMs as well.
474 if ((style
& wxCAPTION
) != 0)
476 m_gdkDecor
|= GDK_DECOR_TITLE
;
478 if ((style
& wxCLOSE_BOX
) != 0)
480 m_gdkFunc
|= GDK_FUNC_CLOSE
;
482 if ((style
& wxSYSTEM_MENU
) != 0)
484 m_gdkDecor
|= GDK_DECOR_MENU
;
486 if ((style
& wxMINIMIZE_BOX
) != 0)
488 m_gdkFunc
|= GDK_FUNC_MINIMIZE
;
489 m_gdkDecor
|= GDK_DECOR_MINIMIZE
;
491 if ((style
& wxMAXIMIZE_BOX
) != 0)
493 m_gdkFunc
|= GDK_FUNC_MAXIMIZE
;
494 m_gdkDecor
|= GDK_DECOR_MAXIMIZE
;
496 if ((style
& wxRESIZE_BORDER
) != 0)
498 m_gdkFunc
|= GDK_FUNC_RESIZE
;
499 m_gdkDecor
|= GDK_DECOR_RESIZEH
;
506 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
510 wxASSERT_MSG( FALSE
, _T("Window still grabbed"));
514 m_isBeingDeleted
= TRUE
;
516 // it may also be GtkScrolledWindow in the case of an MDI child
517 if (GTK_IS_WINDOW(m_widget
))
519 gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL
);
525 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long style
)
527 if (show
== m_fsIsShowing
) return FALSE
; // return what?
529 m_fsIsShowing
= show
;
531 GdkWindow
*window
= m_widget
->window
;
532 wxX11FullScreenMethod method
=
533 wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(),
534 (WXWindow
)GDK_ROOT_WINDOW());
538 m_fsSaveFlag
= style
;
539 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
540 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
542 int screen_width
,screen_height
;
543 wxDisplaySize( &screen_width
, &screen_height
);
545 gint client_x
, client_y
, root_x
, root_y
;
548 if (method
!= wxX11_FS_WMSPEC
)
550 // don't do it always, Metacity hates it
551 m_fsSaveGdkFunc
= m_gdkFunc
;
552 m_fsSaveGdkDecor
= m_gdkDecor
;
553 m_gdkFunc
= m_gdkDecor
= 0;
554 gdk_window_set_decorations(window
, (GdkWMDecoration
)0);
555 gdk_window_set_functions(window
, (GdkWMFunction
)0);
558 gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
);
559 gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
,
560 &width
, &height
, NULL
);
562 gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
,
563 screen_width
+ 1, screen_height
+ 1);
565 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
566 (WXWindow
)GDK_ROOT_WINDOW(),
567 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
568 show
, &m_fsSaveFrame
, method
);
572 if (method
!= wxX11_FS_WMSPEC
)
574 // don't do it always, Metacity hates it
575 m_gdkFunc
= m_fsSaveGdkFunc
;
576 m_gdkDecor
= m_fsSaveGdkDecor
;
577 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
);
578 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
);
581 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
582 (WXWindow
)GDK_ROOT_WINDOW(),
583 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
584 show
, &m_fsSaveFrame
, method
);
586 SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
,
587 m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
594 // ----------------------------------------------------------------------------
595 // overridden wxWindow methods
596 // ----------------------------------------------------------------------------
598 bool wxTopLevelWindowGTK::Show( bool show
)
600 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
602 if (show
&& !m_sizeSet
)
604 /* by calling GtkOnSize here, we don't have to call
605 either after showing the frame, which would entail
606 much ugly flicker or from within the size_allocate
607 handler, because GTK 1.1.X forbids that. */
609 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
612 return wxWindow::Show( show
);
615 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
617 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
620 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
622 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
624 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
625 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
635 int old_width
= m_width
;
636 int old_height
= m_height
;
638 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
640 if (x
!= -1) m_x
= x
;
641 if (y
!= -1) m_y
= y
;
648 if (width
!= -1) m_width
= width
;
649 if (height
!= -1) m_height
= height
;
652 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
654 if (width == -1) m_width = 80;
657 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
659 if (height == -1) m_height = 26;
663 int minWidth
= GetMinWidth(),
664 minHeight
= GetMinHeight(),
665 maxWidth
= GetMaxWidth(),
666 maxHeight
= GetMaxHeight();
669 // GPE's window manager doesn't like size hints
670 // at all, esp. when the user has to use the
678 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
679 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
680 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
681 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
683 if ((m_x
!= -1) || (m_y
!= -1))
685 if ((m_x
!= old_x
) || (m_y
!= old_y
))
687 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
691 if ((m_width
!= old_width
) || (m_height
!= old_height
))
693 if (m_widget
->window
)
694 gdk_window_resize( m_widget
->window
, m_width
, m_height
);
696 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
698 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
699 done either directly before the frame is shown or in idle time
700 so that different calls to SetSize() don't lead to flicker. */
707 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height
) const
709 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
711 wxWindow::DoGetClientSize( width
, height
);
715 *height
-= m_miniEdge
*2 + m_miniTitle
;
719 *width
-= m_miniEdge
*2;
723 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height
)
725 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
728 width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0);
731 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
732 int width
, int height
)
734 // due to a bug in gtk, x,y are always 0
739 if (m_resizing
) return;
742 if ( m_wxwindow
== NULL
) return;
747 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
748 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
749 set in wxFrame::Create so it is used to check what kind of frame we
750 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
751 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
752 importantly) m_mainWidget */
754 int minWidth
= GetMinWidth(),
755 minHeight
= GetMinHeight(),
756 maxWidth
= GetMaxWidth(),
757 maxHeight
= GetMaxHeight();
760 // GPE's window manager doesn't like size hints
761 // at all, esp. when the user has to use the
769 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
770 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
771 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
772 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
777 gint flag
= 0; // GDK_HINT_POS;
780 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
781 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
783 geom
.min_width
= minWidth
;
784 geom
.min_height
= minHeight
;
786 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
787 // maxHeight or maxWidth is set, we must set them both, else the
788 // remaining -1 will be taken literally.
790 // I'm certain this also happens elsewhere, and is the probable
791 // cause of other such things as:
792 // Gtk-WARNING **: gtk_widget_size_allocate():
793 // attempt to allocate widget with width 65535 and height 600
794 // but I don't have time to track them all now..
796 // Really we need to encapulate all this height/width business and
797 // stop any old method from ripping at the members directly and
798 // scattering -1's without regard for who might resolve them later.
800 geom
.max_width
= ( maxHeight
== -1 ) ? maxWidth
801 : ( maxWidth
== -1 ) ? wxGetDisplaySize().GetWidth()
804 geom
.max_height
= ( maxWidth
== -1 ) ? maxHeight
// ( == -1 here )
805 : ( maxHeight
== -1 ) ? wxGetDisplaySize().GetHeight()
808 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
811 (GdkWindowHints
) flag
);
813 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
814 * menubar, the toolbar and the client area, which is represented by
816 * this hurts in the eye, but I don't want to call SetSize()
817 * because I don't want to call any non-native functions here. */
819 int client_x
= m_miniEdge
;
820 int client_y
= m_miniEdge
+ m_miniTitle
;
821 int client_w
= m_width
- 2*m_miniEdge
;
822 int client_h
= m_height
- 2*m_miniEdge
- m_miniTitle
;
824 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
826 client_x
, client_y
, client_w
, client_h
);
830 // If there is no m_mainWidget between m_widget and m_wxwindow there
831 // is no need to set the size or position of m_wxwindow.
836 // send size event to frame
837 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
838 event
.SetEventObject( this );
839 GetEventHandler()->ProcessEvent( event
);
844 void wxTopLevelWindowGTK::OnInternalIdle()
846 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
848 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
850 // we'll come back later
852 wxapp_install_idle_handler();
856 // set the focus if not done yet and if we can already do it
857 if ( GTK_WIDGET_REALIZED(m_wxwindow
) )
859 if ( g_delayedFocus
&&
860 wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this )
862 wxLogTrace(_T("focus"),
863 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
864 g_delayedFocus
->GetClassInfo()->GetClassName(),
865 g_delayedFocus
->GetLabel().c_str());
867 g_delayedFocus
->SetFocus();
868 g_delayedFocus
= NULL
;
872 wxWindow::OnInternalIdle();
875 // ----------------------------------------------------------------------------
877 // ----------------------------------------------------------------------------
879 void wxTopLevelWindowGTK::SetTitle( const wxString
&title
)
881 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
884 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
887 void wxTopLevelWindowGTK::DoSetIcon( const wxIcon
&icon
)
892 if (!m_widget
->window
)
895 wxMask
*mask
= icon
.GetMask();
896 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
897 if (mask
) bm
= mask
->GetBitmap();
899 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
902 void wxTopLevelWindowGTK::SetIcon( const wxIcon
&icon
)
904 SetIcons( wxIconBundle( icon
) );
907 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle
&icons
)
909 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
910 GdkWindow
* window
= m_widget
->window
;
912 wxTopLevelWindowBase::SetIcons( icons
);
914 DoSetIcon( icons
.GetIcon( -1 ) );
917 wxSetIconsX11( (WXDisplay
*)GDK_WINDOW_XDISPLAY( window
),
918 (WXWindow
)GDK_WINDOW_XWINDOW( window
), icons
);
922 // ----------------------------------------------------------------------------
923 // frame state: maximized/iconized/normal
924 // ----------------------------------------------------------------------------
926 void wxTopLevelWindowGTK::Maximize(bool maximize
)
930 gtk_window_maximize( GTK_WINDOW( m_widget
) );
932 gtk_window_unmaximize( GTK_WINDOW( m_widget
) );
934 wxFAIL_MSG( _T("not implemented") );
938 bool wxTopLevelWindowGTK::IsMaximized() const
940 // wxFAIL_MSG( _T("not implemented") );
942 // This is an approximation
946 void wxTopLevelWindowGTK::Restore()
949 // "Present" seems similar enough to "restore"
950 gtk_window_present( GTK_WINDOW( m_widget
) );
952 wxFAIL_MSG( _T("not implemented") );
956 void wxTopLevelWindowGTK::Iconize( bool iconize
)
960 gtk_window_iconify( GTK_WINDOW( m_widget
) );
962 gtk_window_deiconify( GTK_WINDOW( m_widget
) );
966 GdkWindow
*window
= m_widget
->window
;
968 // you should do it later, for example from OnCreate() handler
969 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
971 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
972 GDK_WINDOW_XWINDOW( window
),
973 DefaultScreen( GDK_DISPLAY() ) );
978 bool wxTopLevelWindowGTK::IsIconized() const
983 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
)
985 if ( iconize
!= m_isIconized
)
987 m_isIconized
= iconize
;
988 (void)SendIconizeEvent(iconize
);
992 void wxTopLevelWindowGTK::AddGrab()
997 gtk_grab_add( m_widget
);
999 gtk_grab_remove( m_widget
);
1003 void wxTopLevelWindowGTK::RemoveGrab()
1014 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
)
1018 if (region
.IsEmpty())
1020 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
1025 gdk_window_shape_combine_region(window
, region
.GetRegion(), 0, 0);
1027 wxBitmap bmp
= region
.ConvertToBitmap();
1028 bmp
.SetMask(new wxMask(bmp
, *wxBLACK
));
1029 GdkBitmap
* mask
= bmp
.GetMask()->GetBitmap();
1030 gdk_window_shape_combine_mask(window
, mask
, 0, 0);
1039 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
)
1041 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), FALSE
,
1042 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1044 GdkWindow
*window
= NULL
;
1047 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
1048 do_shape_combine_region(window
, region
);
1050 window
= m_widget
->window
;
1051 return do_shape_combine_region(window
, region
);