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
31 #include "wx/toplevel.h"
33 #include "wx/dialog.h"
34 #include "wx/control.h"
36 #include "wx/dcclient.h"
37 #include "wx/gtk/private.h"
39 #include "wx/settings.h"
44 #include <gdk/gdkkeysyms.h>
47 #include "wx/gtk/win_gtk.h"
49 #include "wx/unix/utilsx11.h"
52 #include <X11/Xatom.h>
54 // ----------------------------------------------------------------------------
56 // ----------------------------------------------------------------------------
58 extern void wxapp_install_idle_handler();
61 // ----------------------------------------------------------------------------
63 // ----------------------------------------------------------------------------
65 extern wxList wxPendingDelete
;
67 extern int g_openDialogs
;
68 extern wxWindowGTK
*g_delayedFocus
;
70 // the frame that is currently active (i.e. its child has focus). It is
71 // used to generate wxActivateEvents
72 static wxTopLevelWindowGTK
*g_activeFrame
= (wxTopLevelWindowGTK
*) NULL
;
73 static wxTopLevelWindowGTK
*g_lastActiveFrame
= (wxTopLevelWindowGTK
*) NULL
;
75 // if we detect that the app has got/lost the focus, we set this variable to
76 // either TRUE or FALSE and an activate event will be sent during the next
77 // OnIdle() call and it is reset to -1: this value means that we shouldn't
78 // send any activate events at all
79 static int g_sendActivateEvent
= -1;
81 //-----------------------------------------------------------------------------
83 //-----------------------------------------------------------------------------
86 static gint
gtk_frame_focus_in_callback( GtkWidget
*widget
,
87 GdkEvent
*WXUNUSED(event
),
88 wxTopLevelWindowGTK
*win
)
91 wxapp_install_idle_handler();
93 switch ( g_sendActivateEvent
)
96 // we've got focus from outside, synthetize wxActivateEvent
97 g_sendActivateEvent
= 1;
101 // another our window just lost focus, it was already ours before
102 // - don't send any wxActivateEvent
103 g_sendActivateEvent
= -1;
108 g_lastActiveFrame
= g_activeFrame
;
110 // wxPrintf( wxT("active: %s\n"), win->GetTitle().c_str() );
112 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
);
113 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
114 event
.SetEventObject(g_activeFrame
);
115 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
121 //-----------------------------------------------------------------------------
123 //-----------------------------------------------------------------------------
126 static gint
gtk_frame_focus_out_callback( GtkWidget
*widget
,
127 GdkEventFocus
*WXUNUSED(gdk_event
),
128 wxTopLevelWindowGTK
*win
)
131 wxapp_install_idle_handler();
133 // if the focus goes out of our app alltogether, OnIdle() will send
134 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
135 // g_sendActivateEvent to -1
136 g_sendActivateEvent
= 0;
138 // wxASSERT_MSG( (g_activeFrame == win), wxT("TLW deactivatd although it wasn't active") );
140 // wxPrintf( wxT("inactive: %s\n"), win->GetTitle().c_str() );
144 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
);
145 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
146 event
.SetEventObject(g_activeFrame
);
147 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
149 g_activeFrame
= NULL
;
156 //-----------------------------------------------------------------------------
157 // "focus" from m_window
158 //-----------------------------------------------------------------------------
161 static gint
gtk_frame_focus_callback( GtkWidget
*widget
, GtkDirectionType
WXUNUSED(d
), wxWindow
*WXUNUSED(win
) )
164 wxapp_install_idle_handler();
166 // This disables GTK's tab traversal
167 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus" );
172 //-----------------------------------------------------------------------------
174 //-----------------------------------------------------------------------------
177 static void gtk_frame_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxTopLevelWindowGTK
*win
)
180 wxapp_install_idle_handler();
185 if ((win
->m_width
!= alloc
->width
) || (win
->m_height
!= alloc
->height
))
188 wxPrintf( "OnSize from " );
189 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
190 wxPrintf( win->GetClassInfo()->GetClassName() );
191 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
194 (int)alloc->height );
197 win
->m_width
= alloc
->width
;
198 win
->m_height
= alloc
->height
;
199 win
->GtkUpdateSize();
204 //-----------------------------------------------------------------------------
206 //-----------------------------------------------------------------------------
209 static gint
gtk_frame_delete_callback( GtkWidget
*WXUNUSED(widget
), GdkEvent
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
212 wxapp_install_idle_handler();
214 if (win
->IsEnabled() &&
215 (g_openDialogs
== 0 || (win
->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) ||
224 //-----------------------------------------------------------------------------
226 //-----------------------------------------------------------------------------
230 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
233 wxapp_install_idle_handler();
235 if (!win
->m_hasVMT
|| !win
->IsShown())
241 gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y
);
245 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
246 mevent
.SetEventObject( win
);
247 win
->GetEventHandler()->ProcessEvent( mevent
);
253 //-----------------------------------------------------------------------------
254 // "realize" from m_widget
255 //-----------------------------------------------------------------------------
257 // we cannot MWM hints and icons before the widget has been realized,
258 // so we do this directly after realization
262 gtk_frame_realized_callback( GtkWidget
* WXUNUSED(widget
),
263 wxTopLevelWindowGTK
*win
)
266 wxapp_install_idle_handler();
268 // All this is for Motif Window Manager "hints" and is supposed to be
269 // recognized by other WM as well. Not tested.
270 gdk_window_set_decorations(win
->m_widget
->window
,
271 (GdkWMDecoration
)win
->m_gdkDecor
);
272 gdk_window_set_functions(win
->m_widget
->window
,
273 (GdkWMFunction
)win
->m_gdkFunc
);
275 // GTK's shrinking/growing policy
276 if ((win
->m_gdkFunc
& GDK_FUNC_RESIZE
) == 0)
277 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 0, 0, 1);
279 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
282 wxIconBundle iconsOld
= win
->GetIcons();
283 if ( iconsOld
.GetIcon(-1).Ok() )
285 win
->SetIcon( wxNullIcon
);
286 win
->SetIcons( iconsOld
);
291 //-----------------------------------------------------------------------------
292 // "map_event" from m_widget
293 //-----------------------------------------------------------------------------
297 gtk_frame_map_callback( GtkWidget
* WXUNUSED(widget
),
298 GdkEvent
* WXUNUSED(event
),
299 wxTopLevelWindow
*win
)
301 win
->SetIconizeState(FALSE
);
305 //-----------------------------------------------------------------------------
306 // "unmap_event" from m_widget
307 //-----------------------------------------------------------------------------
311 gtk_frame_unmap_callback( GtkWidget
* WXUNUSED(widget
),
312 GdkEvent
* WXUNUSED(event
),
313 wxTopLevelWindow
*win
)
315 win
->SetIconizeState(TRUE
);
319 //-----------------------------------------------------------------------------
320 // "expose_event" of m_client
321 //-----------------------------------------------------------------------------
324 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
326 GtkPizza
*pizza
= GTK_PIZZA(widget
);
328 gtk_paint_flat_box (win
->m_widget
->style
,
329 pizza
->bin_window
, GTK_STATE_NORMAL
,
340 //-----------------------------------------------------------------------------
341 // "draw" of m_client
342 //-----------------------------------------------------------------------------
347 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
349 GtkPizza
*pizza
= GTK_PIZZA(widget
);
351 gtk_paint_flat_box (win
->m_widget
->style
,
352 pizza
->bin_window
, GTK_STATE_NORMAL
,
363 // ----------------------------------------------------------------------------
364 // wxTopLevelWindowGTK itself
365 // ----------------------------------------------------------------------------
367 //-----------------------------------------------------------------------------
368 // InsertChild for wxTopLevelWindowGTK
369 //-----------------------------------------------------------------------------
371 /* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
372 * C++ has no virtual methods in a constructor. We have to emulate a
373 * virtual function here as wxWidgets requires different ways to insert
374 * a child in container classes. */
376 static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK
* parent
, wxWindow
* child
)
378 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
380 if (!parent
->m_insertInClientArea
)
382 // these are outside the client area
383 wxTopLevelWindowGTK
* frame
= (wxTopLevelWindowGTK
*) parent
;
384 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
385 GTK_WIDGET(child
->m_widget
),
393 // these are inside the client area
394 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
395 GTK_WIDGET(child
->m_widget
),
402 // resize on OnInternalIdle
403 parent
->GtkUpdateSize();
406 // ----------------------------------------------------------------------------
407 // wxTopLevelWindowGTK creation
408 // ----------------------------------------------------------------------------
410 void wxTopLevelWindowGTK::Init()
415 m_mainWidget
= (GtkWidget
*) NULL
;
416 m_insertInClientArea
= TRUE
;
417 m_isIconized
= FALSE
;
418 m_fsIsShowing
= FALSE
;
419 m_themeEnabled
= TRUE
;
420 m_gdkDecor
= m_gdkFunc
= 0;
424 bool wxTopLevelWindowGTK::Create( wxWindow
*parent
,
426 const wxString
& title
,
428 const wxSize
& sizeOrig
,
430 const wxString
&name
)
432 // always create a frame of some reasonable, even if arbitrary, size (at
433 // least for MSW compatibility)
434 wxSize size
= sizeOrig
;
435 size
.x
= WidthDefault(size
.x
);
436 size
.y
= HeightDefault(size
.y
);
438 wxTopLevelWindows
.Append( this );
440 m_needParent
= FALSE
;
442 if (!PreCreation( parent
, pos
, size
) ||
443 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
445 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
451 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInTopLevelWindow
;
453 // NB: m_widget may be !=NULL if it was created by derived class' Create,
454 // e.g. in wxTaskBarIconAreaGTK
455 if (m_widget
== NULL
)
457 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)
460 m_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
461 // Tell WM that this is a dialog window and make it center
462 // on parent by default (this is what GtkDialog ctor does):
463 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
464 GDK_WINDOW_TYPE_HINT_DIALOG
);
465 gtk_window_set_position(GTK_WINDOW(m_widget
),
466 GTK_WIN_POS_CENTER_ON_PARENT
);
468 m_widget
= gtk_window_new(GTK_WINDOW_DIALOG
);
473 m_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
474 #if GTK_CHECK_VERSION(2,1,0)
475 if (!gtk_check_version(2,1,0))
477 if (style
& wxFRAME_TOOL_WINDOW
)
479 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
480 GDK_WINDOW_TYPE_HINT_UTILITY
);
482 // On some WMs, like KDE, a TOOL_WINDOW will still show
483 // on the taskbar, but on Gnome a TOOL_WINDOW will not.
484 // For consistency between WMs and with Windows, we
485 // should set the NO_TASKBAR flag which will apply
486 // the set_skip_taskbar_hint if it is available,
487 // ensuring no taskbar entry will appear.
488 style
|= wxFRAME_NO_TASKBAR
;
495 wxWindow
*topParent
= wxGetTopLevelParent(m_parent
);
496 if (topParent
&& (((GTK_IS_WINDOW(topParent
->m_widget
)) &&
497 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) ||
498 (style
& wxFRAME_FLOAT_ON_PARENT
)))
500 gtk_window_set_transient_for( GTK_WINDOW(m_widget
),
501 GTK_WINDOW(topParent
->m_widget
) );
504 #if GTK_CHECK_VERSION(2,2,0)
505 if (!gtk_check_version(2,2,0))
507 if (style
& wxFRAME_NO_TASKBAR
)
509 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), TRUE
);
514 #if GTK_CHECK_VERSION(2,4,0)
515 if (!gtk_check_version(2,4,0))
517 if (style
& wxSTAY_ON_TOP
)
519 gtk_window_set_keep_above(GTK_WINDOW(m_widget
), TRUE
);
525 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), wxGTK_CONV( name
), wxGTK_CONV( name
) );
527 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
528 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
530 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
531 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
533 // m_mainWidget holds the toolbar, the menubar and the client area
534 m_mainWidget
= gtk_pizza_new();
535 gtk_widget_show( m_mainWidget
);
536 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
537 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
539 if (m_miniEdge
== 0) // wxMiniFrame has its own version.
541 // For m_mainWidget themes
542 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
543 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
545 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
546 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
550 // m_wxwindow only represents the client area without toolbar and menubar
551 m_wxwindow
= gtk_pizza_new();
552 gtk_widget_show( m_wxwindow
);
553 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
555 // we donm't allow the frame to get the focus as otherwise
556 // the frame will grab it at arbitrary focus changes
557 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
559 if (m_parent
) m_parent
->AddChild( this );
561 // the user resized the frame by dragging etc.
562 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
563 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
567 if ((m_x
!= -1) || (m_y
!= -1))
568 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
570 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
572 // we cannot set MWM hints and icons before the widget has
573 // been realized, so we do this directly after realization
574 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
575 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
577 // the only way to get the window size is to connect to this event
578 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
579 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
581 // map and unmap for iconized state
582 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
583 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
584 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
585 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
587 // the only way to get the window size is to connect to this event
588 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
589 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
591 // disable native tab traversal
592 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
593 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
596 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
597 GTK_SIGNAL_FUNC(gtk_frame_focus_in_callback
), (gpointer
)this );
598 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
599 GTK_SIGNAL_FUNC(gtk_frame_focus_out_callback
), (gpointer
)this );
602 if ((m_miniEdge
> 0) || (style
& wxSIMPLE_BORDER
) || (style
& wxNO_BORDER
))
609 m_gdkDecor
= (long) GDK_DECOR_BORDER
;
610 m_gdkFunc
= (long) GDK_FUNC_MOVE
;
612 // All this is for Motif Window Manager "hints" and is supposed to be
613 // recognized by other WMs as well.
614 if ((style
& wxCAPTION
) != 0)
616 m_gdkDecor
|= GDK_DECOR_TITLE
;
618 if ((style
& wxCLOSE_BOX
) != 0)
620 m_gdkFunc
|= GDK_FUNC_CLOSE
;
622 if ((style
& wxSYSTEM_MENU
) != 0)
624 m_gdkDecor
|= GDK_DECOR_MENU
;
626 if ((style
& wxMINIMIZE_BOX
) != 0)
628 m_gdkFunc
|= GDK_FUNC_MINIMIZE
;
629 m_gdkDecor
|= GDK_DECOR_MINIMIZE
;
631 if ((style
& wxMAXIMIZE_BOX
) != 0)
633 m_gdkFunc
|= GDK_FUNC_MAXIMIZE
;
634 m_gdkDecor
|= GDK_DECOR_MAXIMIZE
;
636 if ((style
& wxRESIZE_BORDER
) != 0)
638 m_gdkFunc
|= GDK_FUNC_RESIZE
;
639 m_gdkDecor
|= GDK_DECOR_RESIZEH
;
646 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
650 wxASSERT_MSG( FALSE
, _T("Window still grabbed"));
654 m_isBeingDeleted
= TRUE
;
656 // it may also be GtkScrolledWindow in the case of an MDI child
657 if (GTK_IS_WINDOW(m_widget
))
659 gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL
);
662 if (g_activeFrame
== this)
663 g_activeFrame
= NULL
;
664 if (g_lastActiveFrame
== this)
665 g_lastActiveFrame
= NULL
;
670 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long style
)
672 if (show
== m_fsIsShowing
)
673 return FALSE
; // return what?
675 m_fsIsShowing
= show
;
677 wxX11FullScreenMethod method
=
678 wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(),
679 (WXWindow
)GDK_ROOT_WINDOW());
681 #if GTK_CHECK_VERSION(2,2,0)
682 // NB: gtk_window_fullscreen() uses freedesktop.org's WMspec extensions
683 // to switch to fullscreen, which is not always available. We must
684 // check if WM supports the spec and use legacy methods if it
686 if (method
== wxX11_FS_WMSPEC
)
689 gtk_window_fullscreen( GTK_WINDOW( m_widget
) );
691 gtk_window_unfullscreen( GTK_WINDOW( m_widget
) );
696 #endif // GTK+ >= 2.2.0
698 GdkWindow
*window
= m_widget
->window
;
702 m_fsSaveFlag
= style
;
703 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
704 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
706 int screen_width
,screen_height
;
707 wxDisplaySize( &screen_width
, &screen_height
);
709 gint client_x
, client_y
, root_x
, root_y
;
712 if (method
!= wxX11_FS_WMSPEC
)
714 // don't do it always, Metacity hates it
715 m_fsSaveGdkFunc
= m_gdkFunc
;
716 m_fsSaveGdkDecor
= m_gdkDecor
;
717 m_gdkFunc
= m_gdkDecor
= 0;
718 gdk_window_set_decorations(window
, (GdkWMDecoration
)0);
719 gdk_window_set_functions(window
, (GdkWMFunction
)0);
722 gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
);
723 gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
,
724 &width
, &height
, NULL
);
726 gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
,
727 screen_width
+ 1, screen_height
+ 1);
729 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
730 (WXWindow
)GDK_ROOT_WINDOW(),
731 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
732 show
, &m_fsSaveFrame
, method
);
736 if (method
!= wxX11_FS_WMSPEC
)
738 // don't do it always, Metacity hates it
739 m_gdkFunc
= m_fsSaveGdkFunc
;
740 m_gdkDecor
= m_fsSaveGdkDecor
;
741 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
);
742 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
);
745 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
746 (WXWindow
)GDK_ROOT_WINDOW(),
747 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
748 show
, &m_fsSaveFrame
, method
);
750 SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
,
751 m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
758 // ----------------------------------------------------------------------------
759 // overridden wxWindow methods
760 // ----------------------------------------------------------------------------
762 bool wxTopLevelWindowGTK::Show( bool show
)
764 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
766 if (show
&& !m_sizeSet
)
768 /* by calling GtkOnSize here, we don't have to call
769 either after showing the frame, which would entail
770 much ugly flicker or from within the size_allocate
771 handler, because GTK 1.1.X forbids that. */
773 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
777 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
779 return wxWindow::Show( show
);
782 void wxTopLevelWindowGTK::Raise()
785 gtk_window_present( GTK_WINDOW( m_widget
) );
791 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
793 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
796 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
798 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
800 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
801 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
811 int old_width
= m_width
;
812 int old_height
= m_height
;
814 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
816 if (x
!= -1) m_x
= x
;
817 if (y
!= -1) m_y
= y
;
824 if (width
!= -1) m_width
= width
;
825 if (height
!= -1) m_height
= height
;
828 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
830 if (width == -1) m_width = 80;
833 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
835 if (height == -1) m_height = 26;
839 int minWidth
= GetMinWidth(),
840 minHeight
= GetMinHeight(),
841 maxWidth
= GetMaxWidth(),
842 maxHeight
= GetMaxHeight();
845 // GPE's window manager doesn't like size hints
846 // at all, esp. when the user has to use the
854 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
855 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
856 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
857 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
859 if ((m_x
!= -1) || (m_y
!= -1))
861 if ((m_x
!= old_x
) || (m_y
!= old_y
))
863 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
867 if ((m_width
!= old_width
) || (m_height
!= old_height
))
869 if (m_widget
->window
)
870 gdk_window_resize( m_widget
->window
, m_width
, m_height
);
872 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
874 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
875 done either directly before the frame is shown or in idle time
876 so that different calls to SetSize() don't lead to flicker. */
883 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height
) const
885 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
887 wxWindow::DoGetClientSize( width
, height
);
891 *height
-= m_miniEdge
*2 + m_miniTitle
;
895 *width
-= m_miniEdge
*2;
899 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height
)
901 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
904 width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0);
907 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
908 int width
, int height
)
910 // due to a bug in gtk, x,y are always 0
915 if (m_resizing
) return;
918 if ( m_wxwindow
== NULL
) return;
923 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
924 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
925 set in wxFrame::Create so it is used to check what kind of frame we
926 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
927 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
928 importantly) m_mainWidget */
930 int minWidth
= GetMinWidth(),
931 minHeight
= GetMinHeight(),
932 maxWidth
= GetMaxWidth(),
933 maxHeight
= GetMaxHeight();
936 // GPE's window manager doesn't like size hints
937 // at all, esp. when the user has to use the
945 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
946 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
947 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
948 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
953 gint flag
= 0; // GDK_HINT_POS;
956 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
957 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
959 geom
.min_width
= minWidth
;
960 geom
.min_height
= minHeight
;
962 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
963 // maxHeight or maxWidth is set, we must set them both, else the
964 // remaining -1 will be taken literally.
966 // I'm certain this also happens elsewhere, and is the probable
967 // cause of other such things as:
968 // Gtk-WARNING **: gtk_widget_size_allocate():
969 // attempt to allocate widget with width 65535 and height 600
970 // but I don't have time to track them all now..
972 // Really we need to encapulate all this height/width business and
973 // stop any old method from ripping at the members directly and
974 // scattering -1's without regard for who might resolve them later.
976 geom
.max_width
= ( maxHeight
== -1 ) ? maxWidth
977 : ( maxWidth
== -1 ) ? wxGetDisplaySize().GetWidth()
980 geom
.max_height
= ( maxWidth
== -1 ) ? maxHeight
// ( == -1 here )
981 : ( maxHeight
== -1 ) ? wxGetDisplaySize().GetHeight()
984 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
987 (GdkWindowHints
) flag
);
989 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
990 * menubar, the toolbar and the client area, which is represented by
992 * this hurts in the eye, but I don't want to call SetSize()
993 * because I don't want to call any non-native functions here. */
995 int client_x
= m_miniEdge
;
996 int client_y
= m_miniEdge
+ m_miniTitle
;
997 int client_w
= m_width
- 2*m_miniEdge
;
998 int client_h
= m_height
- 2*m_miniEdge
- m_miniTitle
;
1000 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
1002 client_x
, client_y
, client_w
, client_h
);
1006 // If there is no m_mainWidget between m_widget and m_wxwindow there
1007 // is no need to set the size or position of m_wxwindow.
1012 // send size event to frame
1013 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1014 event
.SetEventObject( this );
1015 GetEventHandler()->ProcessEvent( event
);
1020 void wxTopLevelWindowGTK::OnInternalIdle()
1022 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
1024 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
1026 // we'll come back later
1028 wxapp_install_idle_handler();
1032 // set the focus if not done yet and if we can already do it
1033 if ( GTK_WIDGET_REALIZED(m_wxwindow
) )
1035 if ( g_delayedFocus
&&
1036 wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this )
1038 wxLogTrace(_T("focus"),
1039 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
1040 g_delayedFocus
->GetClassInfo()->GetClassName(),
1041 g_delayedFocus
->GetLabel().c_str());
1043 g_delayedFocus
->SetFocus();
1044 g_delayedFocus
= NULL
;
1048 wxWindow::OnInternalIdle();
1050 // Synthetize activate events.
1051 if ( g_sendActivateEvent
!= -1 )
1053 bool activate
= g_sendActivateEvent
!= 0;
1055 // if (!activate) wxPrintf( wxT("de") );
1056 // wxPrintf( wxT("activate\n") );
1059 g_sendActivateEvent
= -1;
1061 wxTheApp
->SetActive(activate
, (wxWindow
*)g_lastActiveFrame
);
1065 // ----------------------------------------------------------------------------
1067 // ----------------------------------------------------------------------------
1069 void wxTopLevelWindowGTK::SetTitle( const wxString
&title
)
1071 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1074 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
1077 void wxTopLevelWindowGTK::SetIcon( const wxIcon
&icon
)
1079 SetIcons( wxIconBundle( icon
) );
1082 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle
&icons
)
1084 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1086 wxTopLevelWindowBase::SetIcons( icons
);
1090 size_t max
= icons
.m_icons
.GetCount();
1092 for (size_t i
= 0; i
< max
; i
++)
1094 if (icons
.m_icons
[i
].Ok())
1096 list
= g_list_prepend(list
, icons
.m_icons
[i
].GetPixbuf());
1099 gtk_window_set_icon_list(GTK_WINDOW(m_widget
), list
);
1102 #else // !__WXGTK20__
1103 GdkWindow
* window
= m_widget
->window
;
1107 wxIcon icon
= icons
.GetIcon(-1);
1110 wxMask
*mask
= icon
.GetMask();
1111 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1112 if (mask
) bm
= mask
->GetBitmap();
1114 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
1117 wxSetIconsX11( (WXDisplay
*)GDK_WINDOW_XDISPLAY( window
),
1118 (WXWindow
)GDK_WINDOW_XWINDOW( window
), icons
);
1119 #endif // !__WXGTK20__
1122 // ----------------------------------------------------------------------------
1123 // frame state: maximized/iconized/normal
1124 // ----------------------------------------------------------------------------
1126 void wxTopLevelWindowGTK::Maximize(bool maximize
)
1130 gtk_window_maximize( GTK_WINDOW( m_widget
) );
1132 gtk_window_unmaximize( GTK_WINDOW( m_widget
) );
1134 wxFAIL_MSG( _T("not implemented") );
1138 bool wxTopLevelWindowGTK::IsMaximized() const
1141 if(!m_widget
->window
)
1144 return gdk_window_get_state(m_widget
->window
) & GDK_WINDOW_STATE_MAXIMIZED
;
1146 // wxFAIL_MSG( _T("not implemented") );
1148 // This is an approximation
1153 void wxTopLevelWindowGTK::Restore()
1156 // "Present" seems similar enough to "restore"
1157 gtk_window_present( GTK_WINDOW( m_widget
) );
1159 wxFAIL_MSG( _T("not implemented") );
1163 void wxTopLevelWindowGTK::Iconize( bool iconize
)
1167 gtk_window_iconify( GTK_WINDOW( m_widget
) );
1169 gtk_window_deiconify( GTK_WINDOW( m_widget
) );
1173 GdkWindow
*window
= m_widget
->window
;
1175 // you should do it later, for example from OnCreate() handler
1176 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
1178 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
1179 GDK_WINDOW_XWINDOW( window
),
1180 DefaultScreen( GDK_DISPLAY() ) );
1185 bool wxTopLevelWindowGTK::IsIconized() const
1187 return m_isIconized
;
1190 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
)
1192 if ( iconize
!= m_isIconized
)
1194 m_isIconized
= iconize
;
1195 (void)SendIconizeEvent(iconize
);
1199 void wxTopLevelWindowGTK::AddGrab()
1204 gtk_grab_add( m_widget
);
1206 gtk_grab_remove( m_widget
);
1210 void wxTopLevelWindowGTK::RemoveGrab()
1221 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
)
1225 if (region
.IsEmpty())
1227 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
1232 gdk_window_shape_combine_region(window
, region
.GetRegion(), 0, 0);
1234 wxBitmap bmp
= region
.ConvertToBitmap();
1235 bmp
.SetMask(new wxMask(bmp
, *wxBLACK
));
1236 GdkBitmap
* mask
= bmp
.GetMask()->GetBitmap();
1237 gdk_window_shape_combine_mask(window
, mask
, 0, 0);
1246 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
)
1248 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), FALSE
,
1249 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1251 GdkWindow
*window
= NULL
;
1254 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
1255 do_shape_combine_region(window
, region
);
1257 window
= m_widget
->window
;
1258 return do_shape_combine_region(window
, region
);
1261 bool wxTopLevelWindowGTK::IsActive()
1263 return (this == (wxTopLevelWindowGTK
*)g_activeFrame
);