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 GtkWindowType win_type
= GTK_WINDOW_TOPLEVEL
;
350 if (style
& wxFRAME_TOOL_WINDOW
)
351 win_type
= GTK_WINDOW_POPUP
;
353 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)
355 // there is no more GTK_WINDOW_DIALOG in 2.0
357 win_type
= GTK_WINDOW_TOPLEVEL
;
359 win_type
= GTK_WINDOW_DIALOG
;
363 m_widget
= gtk_window_new( win_type
);
365 if (m_parent
&& (((GTK_IS_WINDOW(m_parent
->m_widget
)) &&
366 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) ||
367 (style
& wxFRAME_FLOAT_ON_PARENT
)))
369 gtk_window_set_transient_for( GTK_WINDOW(m_widget
), GTK_WINDOW(m_parent
->m_widget
) );
373 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), wxGTK_CONV( name
), wxGTK_CONV( name
) );
375 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
376 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
378 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
379 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
381 // m_mainWidget holds the toolbar, the menubar and the client area
382 m_mainWidget
= gtk_pizza_new();
383 gtk_widget_show( m_mainWidget
);
384 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
385 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
387 if (m_miniEdge
== 0) // wxMiniFrame has its own version.
389 // For m_mainWidget themes
390 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
391 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
393 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
394 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
398 // m_wxwindow only represents the client area without toolbar and menubar
399 m_wxwindow
= gtk_pizza_new();
400 gtk_widget_show( m_wxwindow
);
401 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
403 // we donm't allow the frame to get the focus as otherwise
404 // the frame will grab it at arbitrary focus changes
405 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
407 if (m_parent
) m_parent
->AddChild( this );
409 // the user resized the frame by dragging etc.
410 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
411 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
415 if ((m_x
!= -1) || (m_y
!= -1))
416 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
418 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
420 // we cannot set MWM hints and icons before the widget has
421 // been realized, so we do this directly after realization
422 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
423 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
425 // the only way to get the window size is to connect to this event
426 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
427 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
429 // map and unmap for iconized state
430 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
431 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
432 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
433 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
435 // the only way to get the window size is to connect to this event
436 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
437 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
439 // disable native tab traversal
440 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
441 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
444 if ((m_miniEdge
> 0) || (style
& wxSIMPLE_BORDER
) || (style
& wxNO_BORDER
))
451 m_gdkDecor
= (long) GDK_DECOR_BORDER
;
452 m_gdkFunc
= (long) GDK_FUNC_MOVE
;
454 // All this is for Motif Window Manager "hints" and is supposed to be
455 // recognized by other WMs as well.
456 if ((style
& wxCAPTION
) != 0)
458 m_gdkDecor
|= GDK_DECOR_TITLE
;
460 if ((style
& wxCLOSE_BOX
) != 0)
462 m_gdkFunc
|= GDK_FUNC_CLOSE
;
464 if ((style
& wxSYSTEM_MENU
) != 0)
466 m_gdkDecor
|= GDK_DECOR_MENU
;
468 if ((style
& wxMINIMIZE_BOX
) != 0)
470 m_gdkFunc
|= GDK_FUNC_MINIMIZE
;
471 m_gdkDecor
|= GDK_DECOR_MINIMIZE
;
473 if ((style
& wxMAXIMIZE_BOX
) != 0)
475 m_gdkFunc
|= GDK_FUNC_MAXIMIZE
;
476 m_gdkDecor
|= GDK_DECOR_MAXIMIZE
;
478 if ((style
& wxRESIZE_BORDER
) != 0)
480 m_gdkFunc
|= GDK_FUNC_RESIZE
;
481 m_gdkDecor
|= GDK_DECOR_RESIZEH
;
488 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
492 wxASSERT_MSG( FALSE
, _T("Window still grabbed"));
496 m_isBeingDeleted
= TRUE
;
498 // it may also be GtkScrolledWindow in the case of an MDI child
499 if (GTK_IS_WINDOW(m_widget
))
501 gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL
);
507 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long style
)
509 if (show
== m_fsIsShowing
) return FALSE
; // return what?
511 m_fsIsShowing
= show
;
513 GdkWindow
*window
= m_widget
->window
;
514 wxX11FullScreenMethod method
=
515 wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(),
516 (WXWindow
)GDK_ROOT_WINDOW());
520 m_fsSaveFlag
= style
;
521 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
522 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
524 int screen_width
,screen_height
;
525 wxDisplaySize( &screen_width
, &screen_height
);
527 gint client_x
, client_y
, root_x
, root_y
;
530 if (method
!= wxX11_FS_WMSPEC
)
532 // don't do it always, Metacity hates it
533 m_fsSaveGdkFunc
= m_gdkFunc
;
534 m_fsSaveGdkDecor
= m_gdkDecor
;
535 m_gdkFunc
= m_gdkDecor
= 0;
536 gdk_window_set_decorations(window
, (GdkWMDecoration
)0);
537 gdk_window_set_functions(window
, (GdkWMFunction
)0);
540 gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
);
541 gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
,
542 &width
, &height
, NULL
);
544 gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
,
545 screen_width
+ 1, screen_height
+ 1);
547 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
548 (WXWindow
)GDK_ROOT_WINDOW(),
549 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
550 show
, &m_fsSaveFrame
, method
);
554 if (method
!= wxX11_FS_WMSPEC
)
556 // don't do it always, Metacity hates it
557 m_gdkFunc
= m_fsSaveGdkFunc
;
558 m_gdkDecor
= m_fsSaveGdkDecor
;
559 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
);
560 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
);
563 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
564 (WXWindow
)GDK_ROOT_WINDOW(),
565 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
566 show
, &m_fsSaveFrame
, method
);
568 SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
,
569 m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
576 // ----------------------------------------------------------------------------
577 // overridden wxWindow methods
578 // ----------------------------------------------------------------------------
580 bool wxTopLevelWindowGTK::Show( bool show
)
582 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
584 if (show
&& !m_sizeSet
)
586 /* by calling GtkOnSize here, we don't have to call
587 either after showing the frame, which would entail
588 much ugly flicker or from within the size_allocate
589 handler, because GTK 1.1.X forbids that. */
591 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
594 return wxWindow::Show( show
);
597 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
599 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
602 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
604 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
606 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
607 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
617 int old_width
= m_width
;
618 int old_height
= m_height
;
620 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
622 if (x
!= -1) m_x
= x
;
623 if (y
!= -1) m_y
= y
;
630 if (width
!= -1) m_width
= width
;
631 if (height
!= -1) m_height
= height
;
634 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
636 if (width == -1) m_width = 80;
639 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
641 if (height == -1) m_height = 26;
645 int minWidth
= GetMinWidth(),
646 minHeight
= GetMinHeight(),
647 maxWidth
= GetMaxWidth(),
648 maxHeight
= GetMaxHeight();
651 // GPE's window manager doesn't like size hints
652 // at all, esp. when the user has to use the
660 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
661 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
662 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
663 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
665 if ((m_x
!= -1) || (m_y
!= -1))
667 if ((m_x
!= old_x
) || (m_y
!= old_y
))
669 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
673 if ((m_width
!= old_width
) || (m_height
!= old_height
))
675 if (m_widget
->window
)
676 gdk_window_resize( m_widget
->window
, m_width
, m_height
);
678 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
680 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
681 done either directly before the frame is shown or in idle time
682 so that different calls to SetSize() don't lead to flicker. */
689 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height
) const
691 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
693 wxWindow::DoGetClientSize( width
, height
);
697 *height
-= m_miniEdge
*2 + m_miniTitle
;
701 *width
-= m_miniEdge
*2;
705 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height
)
707 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
710 width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0);
713 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
714 int width
, int height
)
716 // due to a bug in gtk, x,y are always 0
721 if (m_resizing
) return;
724 if ( m_wxwindow
== NULL
) return;
729 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
730 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
731 set in wxFrame::Create so it is used to check what kind of frame we
732 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
733 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
734 importantly) m_mainWidget */
736 int minWidth
= GetMinWidth(),
737 minHeight
= GetMinHeight(),
738 maxWidth
= GetMaxWidth(),
739 maxHeight
= GetMaxHeight();
742 // GPE's window manager doesn't like size hints
743 // at all, esp. when the user has to use the
751 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
752 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
753 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
754 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
759 gint flag
= 0; // GDK_HINT_POS;
762 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
763 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
765 geom
.min_width
= minWidth
;
766 geom
.min_height
= minHeight
;
768 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
769 // maxHeight or maxWidth is set, we must set them both, else the
770 // remaining -1 will be taken literally.
772 // I'm certain this also happens elsewhere, and is the probable
773 // cause of other such things as:
774 // Gtk-WARNING **: gtk_widget_size_allocate():
775 // attempt to allocate widget with width 65535 and height 600
776 // but I don't have time to track them all now..
778 // Really we need to encapulate all this height/width business and
779 // stop any old method from ripping at the members directly and
780 // scattering -1's without regard for who might resolve them later.
782 geom
.max_width
= ( maxHeight
== -1 ) ? maxWidth
783 : ( maxWidth
== -1 ) ? wxGetDisplaySize().GetWidth()
786 geom
.max_height
= ( maxWidth
== -1 ) ? maxHeight
// ( == -1 here )
787 : ( maxHeight
== -1 ) ? wxGetDisplaySize().GetHeight()
790 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
793 (GdkWindowHints
) flag
);
795 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
796 * menubar, the toolbar and the client area, which is represented by
798 * this hurts in the eye, but I don't want to call SetSize()
799 * because I don't want to call any non-native functions here. */
801 int client_x
= m_miniEdge
;
802 int client_y
= m_miniEdge
+ m_miniTitle
;
803 int client_w
= m_width
- 2*m_miniEdge
;
804 int client_h
= m_height
- 2*m_miniEdge
- m_miniTitle
;
806 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
808 client_x
, client_y
, client_w
, client_h
);
812 // If there is no m_mainWidget between m_widget and m_wxwindow there
813 // is no need to set the size or position of m_wxwindow.
818 // send size event to frame
819 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
820 event
.SetEventObject( this );
821 GetEventHandler()->ProcessEvent( event
);
826 void wxTopLevelWindowGTK::OnInternalIdle()
828 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
830 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
832 // we'll come back later
834 wxapp_install_idle_handler();
838 // set the focus if not done yet and if we can already do it
839 if ( GTK_WIDGET_REALIZED(m_wxwindow
) )
841 if ( g_delayedFocus
&&
842 wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this )
844 wxLogTrace(_T("focus"),
845 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
846 g_delayedFocus
->GetClassInfo()->GetClassName(),
847 g_delayedFocus
->GetLabel().c_str());
849 g_delayedFocus
->SetFocus();
850 g_delayedFocus
= NULL
;
854 wxWindow::OnInternalIdle();
857 // ----------------------------------------------------------------------------
859 // ----------------------------------------------------------------------------
861 void wxTopLevelWindowGTK::SetTitle( const wxString
&title
)
863 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
866 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
869 void wxTopLevelWindowGTK::DoSetIcon( const wxIcon
&icon
)
874 if (!m_widget
->window
)
877 wxMask
*mask
= icon
.GetMask();
878 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
879 if (mask
) bm
= mask
->GetBitmap();
881 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
884 void wxTopLevelWindowGTK::SetIcon( const wxIcon
&icon
)
886 SetIcons( wxIconBundle( icon
) );
889 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle
&icons
)
891 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
892 GdkWindow
* window
= m_widget
->window
;
894 wxTopLevelWindowBase::SetIcons( icons
);
896 DoSetIcon( icons
.GetIcon( -1 ) );
899 wxSetIconsX11( (WXDisplay
*)GDK_WINDOW_XDISPLAY( window
),
900 (WXWindow
)GDK_WINDOW_XWINDOW( window
), icons
);
904 // ----------------------------------------------------------------------------
905 // frame state: maximized/iconized/normal
906 // ----------------------------------------------------------------------------
908 void wxTopLevelWindowGTK::Maximize(bool maximize
)
912 gtk_window_maximize( GTK_WINDOW( m_widget
) );
914 gtk_window_unmaximize( GTK_WINDOW( m_widget
) );
916 wxFAIL_MSG( _T("not implemented") );
920 bool wxTopLevelWindowGTK::IsMaximized() const
922 // wxFAIL_MSG( _T("not implemented") );
924 // This is an approximation
928 void wxTopLevelWindowGTK::Restore()
931 // "Present" seems similar enough to "restore"
932 gtk_window_present( GTK_WINDOW( m_widget
) );
934 wxFAIL_MSG( _T("not implemented") );
938 void wxTopLevelWindowGTK::Iconize( bool iconize
)
942 gtk_window_iconify( GTK_WINDOW( m_widget
) );
944 gtk_window_deiconify( GTK_WINDOW( m_widget
) );
948 GdkWindow
*window
= m_widget
->window
;
950 // you should do it later, for example from OnCreate() handler
951 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
953 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
954 GDK_WINDOW_XWINDOW( window
),
955 DefaultScreen( GDK_DISPLAY() ) );
960 bool wxTopLevelWindowGTK::IsIconized() const
965 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
)
967 if ( iconize
!= m_isIconized
)
969 m_isIconized
= iconize
;
970 (void)SendIconizeEvent(iconize
);
974 void wxTopLevelWindowGTK::AddGrab()
979 gtk_grab_add( m_widget
);
981 gtk_grab_remove( m_widget
);
985 void wxTopLevelWindowGTK::RemoveGrab()
996 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
)
1000 if (region
.IsEmpty())
1002 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
1007 gdk_window_shape_combine_region(window
, region
.GetRegion(), 0, 0);
1009 wxBitmap bmp
= region
.ConvertToBitmap();
1010 bmp
.SetMask(new wxMask(bmp
, *wxBLACK
));
1011 GdkBitmap
* mask
= bmp
.GetMask()->GetBitmap();
1012 gdk_window_shape_combine_mask(window
, mask
, 0, 0);
1021 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
)
1023 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), FALSE
,
1024 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1026 GdkWindow
*window
= NULL
;
1029 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
1030 do_shape_combine_region(window
, region
);
1032 window
= m_widget
->window
;
1033 return do_shape_combine_region(window
, region
);