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 wxWindows 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 if ( size
.x
== -1 || size
.y
== -1 )
332 wxSize sizeDpy
= wxGetDisplaySize();
334 size
.x
= sizeDpy
.x
/ 3;
336 size
.y
= sizeDpy
.y
/ 5;
339 wxTopLevelWindows
.Append( this );
341 m_needParent
= FALSE
;
343 if (!PreCreation( parent
, pos
, size
) ||
344 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
346 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
352 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInTopLevelWindow
;
354 GtkWindowType win_type
= GTK_WINDOW_TOPLEVEL
;
356 if (style
& wxFRAME_TOOL_WINDOW
)
357 win_type
= GTK_WINDOW_POPUP
;
359 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)
361 // there is no more GTK_WINDOW_DIALOG in 2.0
363 win_type
= GTK_WINDOW_TOPLEVEL
;
365 win_type
= GTK_WINDOW_DIALOG
;
369 m_widget
= gtk_window_new( win_type
);
371 if (m_parent
&& (((GTK_IS_WINDOW(m_parent
->m_widget
)) &&
372 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) ||
373 (style
& wxFRAME_FLOAT_ON_PARENT
)))
375 gtk_window_set_transient_for( GTK_WINDOW(m_widget
), GTK_WINDOW(m_parent
->m_widget
) );
379 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), wxGTK_CONV( name
), wxGTK_CONV( name
) );
381 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
382 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
384 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
385 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
387 // m_mainWidget holds the toolbar, the menubar and the client area
388 m_mainWidget
= gtk_pizza_new();
389 gtk_widget_show( m_mainWidget
);
390 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
391 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
393 if (m_miniEdge
== 0) // wxMiniFrame has its own version.
395 // For m_mainWidget themes
396 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
397 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
399 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
400 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
404 // m_wxwindow only represents the client area without toolbar and menubar
405 m_wxwindow
= gtk_pizza_new();
406 gtk_widget_show( m_wxwindow
);
407 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
409 // we donm't allow the frame to get the focus as otherwise
410 // the frame will grab it at arbitrary focus changes
411 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
413 if (m_parent
) m_parent
->AddChild( this );
415 // the user resized the frame by dragging etc.
416 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
417 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
421 if ((m_x
!= -1) || (m_y
!= -1))
422 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
424 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
426 // we cannot set MWM hints and icons before the widget has
427 // been realized, so we do this directly after realization
428 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
429 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
431 // the only way to get the window size is to connect to this event
432 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
433 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
435 // map and unmap for iconized state
436 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
437 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
438 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
439 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
441 // the only way to get the window size is to connect to this event
442 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
443 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
445 // disable native tab traversal
446 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
447 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
450 if ((m_miniEdge
> 0) || (style
& wxSIMPLE_BORDER
) || (style
& wxNO_BORDER
))
457 m_gdkDecor
= (long) GDK_DECOR_BORDER
;
458 m_gdkFunc
= (long) GDK_FUNC_MOVE
;
460 // All this is for Motif Window Manager "hints" and is supposed to be
461 // recognized by other WMs as well.
462 if ((style
& wxCAPTION
) != 0)
464 m_gdkDecor
|= GDK_DECOR_TITLE
;
466 if ((style
& wxCLOSE_BOX
) != 0)
468 m_gdkFunc
|= GDK_FUNC_CLOSE
;
470 if ((style
& wxSYSTEM_MENU
) != 0)
472 m_gdkDecor
|= GDK_DECOR_MENU
;
474 if ((style
& wxMINIMIZE_BOX
) != 0)
476 m_gdkFunc
|= GDK_FUNC_MINIMIZE
;
477 m_gdkDecor
|= GDK_DECOR_MINIMIZE
;
479 if ((style
& wxMAXIMIZE_BOX
) != 0)
481 m_gdkFunc
|= GDK_FUNC_MAXIMIZE
;
482 m_gdkDecor
|= GDK_DECOR_MAXIMIZE
;
484 if ((style
& wxRESIZE_BORDER
) != 0)
486 m_gdkFunc
|= GDK_FUNC_RESIZE
;
487 m_gdkDecor
|= GDK_DECOR_RESIZEH
;
494 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
498 wxASSERT_MSG( FALSE
, _T("Window still grabbed"));
502 m_isBeingDeleted
= TRUE
;
504 // it may also be GtkScrolledWindow in the case of an MDI child
505 if (GTK_IS_WINDOW(m_widget
))
507 gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL
);
513 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long style
)
515 if (show
== m_fsIsShowing
) return FALSE
; // return what?
517 m_fsIsShowing
= show
;
519 GdkWindow
*window
= m_widget
->window
;
520 wxX11FullScreenMethod method
=
521 wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(),
522 (WXWindow
)GDK_ROOT_WINDOW());
526 m_fsSaveFlag
= style
;
527 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
528 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
530 int screen_width
,screen_height
;
531 wxDisplaySize( &screen_width
, &screen_height
);
533 gint client_x
, client_y
, root_x
, root_y
;
536 if (method
!= wxX11_FS_WMSPEC
)
538 // don't do it always, Metacity hates it
539 m_fsSaveGdkFunc
= m_gdkFunc
;
540 m_fsSaveGdkDecor
= m_gdkDecor
;
541 m_gdkFunc
= m_gdkDecor
= 0;
542 gdk_window_set_decorations(window
, (GdkWMDecoration
)0);
543 gdk_window_set_functions(window
, (GdkWMFunction
)0);
546 gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
);
547 gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
,
548 &width
, &height
, NULL
);
550 gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
,
551 screen_width
+ 1, screen_height
+ 1);
553 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
554 (WXWindow
)GDK_ROOT_WINDOW(),
555 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
556 show
, &m_fsSaveFrame
, method
);
560 if (method
!= wxX11_FS_WMSPEC
)
562 // don't do it always, Metacity hates it
563 m_gdkFunc
= m_fsSaveGdkFunc
;
564 m_gdkDecor
= m_fsSaveGdkDecor
;
565 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
);
566 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
);
569 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
570 (WXWindow
)GDK_ROOT_WINDOW(),
571 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
572 show
, &m_fsSaveFrame
, method
);
574 SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
,
575 m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
582 // ----------------------------------------------------------------------------
583 // overridden wxWindow methods
584 // ----------------------------------------------------------------------------
586 bool wxTopLevelWindowGTK::Show( bool show
)
588 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
590 if (show
&& !m_sizeSet
)
592 /* by calling GtkOnSize here, we don't have to call
593 either after showing the frame, which would entail
594 much ugly flicker or from within the size_allocate
595 handler, because GTK 1.1.X forbids that. */
597 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
600 return wxWindow::Show( show
);
603 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
605 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
608 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
610 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
612 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
613 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
623 int old_width
= m_width
;
624 int old_height
= m_height
;
626 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
628 if (x
!= -1) m_x
= x
;
629 if (y
!= -1) m_y
= y
;
636 if (width
!= -1) m_width
= width
;
637 if (height
!= -1) m_height
= height
;
640 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
642 if (width == -1) m_width = 80;
645 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
647 if (height == -1) m_height = 26;
651 int minWidth
= GetMinWidth(),
652 minHeight
= GetMinHeight(),
653 maxWidth
= GetMaxWidth(),
654 maxHeight
= GetMaxHeight();
656 if (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA
)
658 // GPE's window manager doesn't like size hints
659 // at all, esp. when the user has to use the
667 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
668 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
669 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
670 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
672 if ((m_x
!= -1) || (m_y
!= -1))
674 if ((m_x
!= old_x
) || (m_y
!= old_y
))
676 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
680 if ((m_width
!= old_width
) || (m_height
!= old_height
))
682 if (m_widget
->window
)
683 gdk_window_resize( m_widget
->window
, m_width
, m_height
);
685 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
687 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
688 done either directly before the frame is shown or in idle time
689 so that different calls to SetSize() don't lead to flicker. */
696 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height
) const
698 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
700 wxWindow::DoGetClientSize( width
, height
);
704 *height
-= m_miniEdge
*2 + m_miniTitle
;
708 *width
-= m_miniEdge
*2;
712 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height
)
714 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
717 width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0);
720 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
721 int width
, int height
)
723 // due to a bug in gtk, x,y are always 0
728 if (m_resizing
) return;
731 if ( m_wxwindow
== NULL
) return;
736 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
737 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
738 set in wxFrame::Create so it is used to check what kind of frame we
739 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
740 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
741 importantly) m_mainWidget */
743 int minWidth
= GetMinWidth(),
744 minHeight
= GetMinHeight(),
745 maxWidth
= GetMaxWidth(),
746 maxHeight
= GetMaxHeight();
748 if (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA
)
750 // GPE's window manager doesn't like size hints
751 // at all, esp. when the user has to use the
759 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
760 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
761 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
762 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
767 gint flag
= 0; // GDK_HINT_POS;
770 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
771 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
773 geom
.min_width
= minWidth
;
774 geom
.min_height
= minHeight
;
776 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
777 // maxHeight or maxWidth is set, we must set them both, else the
778 // remaining -1 will be taken literally.
780 // I'm certain this also happens elsewhere, and is the probable
781 // cause of other such things as:
782 // Gtk-WARNING **: gtk_widget_size_allocate():
783 // attempt to allocate widget with width 65535 and height 600
784 // but I don't have time to track them all now..
786 // Really we need to encapulate all this height/width business and
787 // stop any old method from ripping at the members directly and
788 // scattering -1's without regard for who might resolve them later.
790 geom
.max_width
= ( maxHeight
== -1 ) ? maxWidth
791 : ( maxWidth
== -1 ) ? wxGetDisplaySize().GetWidth()
794 geom
.max_height
= ( maxWidth
== -1 ) ? maxHeight
// ( == -1 here )
795 : ( maxHeight
== -1 ) ? wxGetDisplaySize().GetHeight()
798 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
801 (GdkWindowHints
) flag
);
803 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
804 * menubar, the toolbar and the client area, which is represented by
806 * this hurts in the eye, but I don't want to call SetSize()
807 * because I don't want to call any non-native functions here. */
809 int client_x
= m_miniEdge
;
810 int client_y
= m_miniEdge
+ m_miniTitle
;
811 int client_w
= m_width
- 2*m_miniEdge
;
812 int client_h
= m_height
- 2*m_miniEdge
- m_miniTitle
;
814 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
816 client_x
, client_y
, client_w
, client_h
);
820 // If there is no m_mainWidget between m_widget and m_wxwindow there
821 // is no need to set the size or position of m_wxwindow.
826 // send size event to frame
827 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
828 event
.SetEventObject( this );
829 GetEventHandler()->ProcessEvent( event
);
834 void wxTopLevelWindowGTK::OnInternalIdle()
836 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
838 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
840 // we'll come back later
842 wxapp_install_idle_handler();
846 // set the focus if not done yet and if we can already do it
847 if ( GTK_WIDGET_REALIZED(m_wxwindow
) )
849 if ( g_delayedFocus
&&
850 wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this )
852 wxLogTrace(_T("focus"),
853 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
854 g_delayedFocus
->GetClassInfo()->GetClassName(),
855 g_delayedFocus
->GetLabel().c_str());
857 g_delayedFocus
->SetFocus();
858 g_delayedFocus
= NULL
;
862 wxWindow::OnInternalIdle();
865 // ----------------------------------------------------------------------------
867 // ----------------------------------------------------------------------------
869 void wxTopLevelWindowGTK::SetTitle( const wxString
&title
)
871 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
874 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
877 void wxTopLevelWindowGTK::DoSetIcon( const wxIcon
&icon
)
882 if (!m_widget
->window
)
885 wxMask
*mask
= icon
.GetMask();
886 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
887 if (mask
) bm
= mask
->GetBitmap();
889 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
892 void wxTopLevelWindowGTK::SetIcon( const wxIcon
&icon
)
894 SetIcons( wxIconBundle( icon
) );
897 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle
&icons
)
899 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
900 GdkWindow
* window
= m_widget
->window
;
902 wxTopLevelWindowBase::SetIcons( icons
);
904 DoSetIcon( icons
.GetIcon( -1 ) );
907 wxSetIconsX11( (WXDisplay
*)GDK_WINDOW_XDISPLAY( window
),
908 (WXWindow
)GDK_WINDOW_XWINDOW( window
), icons
);
912 // ----------------------------------------------------------------------------
913 // frame state: maximized/iconized/normal
914 // ----------------------------------------------------------------------------
916 void wxTopLevelWindowGTK::Maximize(bool maximize
)
920 gtk_window_maximize( GTK_WINDOW( m_widget
) );
922 gtk_window_unmaximize( GTK_WINDOW( m_widget
) );
924 wxFAIL_MSG( _T("not implemented") );
928 bool wxTopLevelWindowGTK::IsMaximized() const
930 // wxFAIL_MSG( _T("not implemented") );
932 // This is an approximation
936 void wxTopLevelWindowGTK::Restore()
939 // "Present" seems similar enough to "restore"
940 gtk_window_present( GTK_WINDOW( m_widget
) );
942 wxFAIL_MSG( _T("not implemented") );
946 void wxTopLevelWindowGTK::Iconize( bool iconize
)
950 gtk_window_iconify( GTK_WINDOW( m_widget
) );
952 gtk_window_deiconify( GTK_WINDOW( m_widget
) );
956 GdkWindow
*window
= m_widget
->window
;
958 // you should do it later, for example from OnCreate() handler
959 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
961 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
962 GDK_WINDOW_XWINDOW( window
),
963 DefaultScreen( GDK_DISPLAY() ) );
968 bool wxTopLevelWindowGTK::IsIconized() const
973 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
)
975 if ( iconize
!= m_isIconized
)
977 m_isIconized
= iconize
;
978 (void)SendIconizeEvent(iconize
);
982 void wxTopLevelWindowGTK::AddGrab()
987 gtk_grab_add( m_widget
);
989 gtk_grab_remove( m_widget
);
993 void wxTopLevelWindowGTK::RemoveGrab()
1004 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
)
1008 if (region
.IsEmpty())
1010 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
1015 gdk_window_shape_combine_region(window
, region
.GetRegion(), 0, 0);
1017 wxBitmap bmp
= region
.ConvertToBitmap();
1018 bmp
.SetMask(new wxMask(bmp
, *wxBLACK
));
1019 GdkBitmap
* mask
= bmp
.GetMask()->GetBitmap();
1020 gdk_window_shape_combine_mask(window
, mask
, 0, 0);
1029 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
)
1031 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), FALSE
,
1032 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1034 GdkWindow
*window
= NULL
;
1037 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
1038 do_shape_combine_region(window
, region
);
1040 window
= m_widget
->window
;
1041 return do_shape_combine_region(window
, region
);