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"
40 #include "wx/evtloop.h"
45 #include <gdk/gdkkeysyms.h>
48 #include "wx/gtk/win_gtk.h"
50 #include "wx/unix/utilsx11.h"
53 #include <X11/Xatom.h>
55 // ----------------------------------------------------------------------------
57 // ----------------------------------------------------------------------------
59 extern void wxapp_install_idle_handler();
62 // ----------------------------------------------------------------------------
64 // ----------------------------------------------------------------------------
66 extern wxList wxPendingDelete
;
68 extern int g_openDialogs
;
69 extern wxWindowGTK
*g_delayedFocus
;
71 // the frame that is currently active (i.e. its child has focus). It is
72 // used to generate wxActivateEvents
73 static wxTopLevelWindowGTK
*g_activeFrame
= (wxTopLevelWindowGTK
*) NULL
;
74 static wxTopLevelWindowGTK
*g_lastActiveFrame
= (wxTopLevelWindowGTK
*) NULL
;
76 // if we detect that the app has got/lost the focus, we set this variable to
77 // either TRUE or FALSE and an activate event will be sent during the next
78 // OnIdle() call and it is reset to -1: this value means that we shouldn't
79 // send any activate events at all
80 static int g_sendActivateEvent
= -1;
82 //-----------------------------------------------------------------------------
84 //-----------------------------------------------------------------------------
87 static gint
gtk_frame_focus_in_callback( GtkWidget
*widget
,
88 GdkEvent
*WXUNUSED(event
),
89 wxTopLevelWindowGTK
*win
)
92 wxapp_install_idle_handler();
94 switch ( g_sendActivateEvent
)
97 // we've got focus from outside, synthetize wxActivateEvent
98 g_sendActivateEvent
= 1;
102 // another our window just lost focus, it was already ours before
103 // - don't send any wxActivateEvent
104 g_sendActivateEvent
= -1;
109 g_lastActiveFrame
= g_activeFrame
;
111 // wxPrintf( wxT("active: %s\n"), win->GetTitle().c_str() );
113 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
);
114 wxActivateEvent
event(wxEVT_ACTIVATE
, true, g_activeFrame
->GetId());
115 event
.SetEventObject(g_activeFrame
);
116 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
122 //-----------------------------------------------------------------------------
124 //-----------------------------------------------------------------------------
127 static gint
gtk_frame_focus_out_callback( GtkWidget
*widget
,
128 GdkEventFocus
*WXUNUSED(gdk_event
),
129 wxTopLevelWindowGTK
*win
)
132 wxapp_install_idle_handler();
134 // if the focus goes out of our app alltogether, OnIdle() will send
135 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
136 // g_sendActivateEvent to -1
137 g_sendActivateEvent
= 0;
139 // wxASSERT_MSG( (g_activeFrame == win), wxT("TLW deactivatd although it wasn't active") );
141 // wxPrintf( wxT("inactive: %s\n"), win->GetTitle().c_str() );
145 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
);
146 wxActivateEvent
event(wxEVT_ACTIVATE
, false, g_activeFrame
->GetId());
147 event
.SetEventObject(g_activeFrame
);
148 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
150 g_activeFrame
= NULL
;
157 //-----------------------------------------------------------------------------
158 // "focus" from m_window
159 //-----------------------------------------------------------------------------
162 static gint
gtk_frame_focus_callback( GtkWidget
*widget
, GtkDirectionType
WXUNUSED(d
), wxWindow
*WXUNUSED(win
) )
165 wxapp_install_idle_handler();
167 // This disables GTK's tab traversal
168 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus" );
173 //-----------------------------------------------------------------------------
175 //-----------------------------------------------------------------------------
178 static void gtk_frame_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxTopLevelWindowGTK
*win
)
181 wxapp_install_idle_handler();
186 if ((win
->m_width
!= alloc
->width
) || (win
->m_height
!= alloc
->height
))
189 wxPrintf( "OnSize from " );
190 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
191 wxPrintf( win->GetClassInfo()->GetClassName() );
192 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
195 (int)alloc->height );
198 win
->m_width
= alloc
->width
;
199 win
->m_height
= alloc
->height
;
200 win
->GtkUpdateSize();
205 //-----------------------------------------------------------------------------
207 //-----------------------------------------------------------------------------
210 static gint
gtk_frame_delete_callback( GtkWidget
*WXUNUSED(widget
), GdkEvent
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
213 wxapp_install_idle_handler();
215 if (win
->IsEnabled() &&
216 (g_openDialogs
== 0 || (win
->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) ||
225 //-----------------------------------------------------------------------------
227 //-----------------------------------------------------------------------------
231 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
234 wxapp_install_idle_handler();
236 if (!win
->m_hasVMT
|| !win
->IsShown())
242 gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y
);
246 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
247 mevent
.SetEventObject( win
);
248 win
->GetEventHandler()->ProcessEvent( mevent
);
254 //-----------------------------------------------------------------------------
255 // "realize" from m_widget
256 //-----------------------------------------------------------------------------
258 // we cannot MWM hints and icons before the widget has been realized,
259 // so we do this directly after realization
263 gtk_frame_realized_callback( GtkWidget
* WXUNUSED(widget
),
264 wxTopLevelWindowGTK
*win
)
267 wxapp_install_idle_handler();
269 // All this is for Motif Window Manager "hints" and is supposed to be
270 // recognized by other WM as well. Not tested.
271 gdk_window_set_decorations(win
->m_widget
->window
,
272 (GdkWMDecoration
)win
->m_gdkDecor
);
273 gdk_window_set_functions(win
->m_widget
->window
,
274 (GdkWMFunction
)win
->m_gdkFunc
);
276 // GTK's shrinking/growing policy
277 if ((win
->m_gdkFunc
& GDK_FUNC_RESIZE
) == 0)
278 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 0, 0, 1);
280 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
283 wxIconBundle iconsOld
= win
->GetIcons();
284 if ( iconsOld
.GetIcon(-1).Ok() )
286 win
->SetIcon( wxNullIcon
);
287 win
->SetIcons( iconsOld
);
292 //-----------------------------------------------------------------------------
293 // "map_event" from m_widget
294 //-----------------------------------------------------------------------------
298 gtk_frame_map_callback( GtkWidget
* WXUNUSED(widget
),
299 GdkEvent
* WXUNUSED(event
),
300 wxTopLevelWindow
*win
)
302 win
->SetIconizeState(false);
306 //-----------------------------------------------------------------------------
307 // "unmap_event" from m_widget
308 //-----------------------------------------------------------------------------
312 gtk_frame_unmap_callback( GtkWidget
* WXUNUSED(widget
),
313 GdkEvent
* WXUNUSED(event
),
314 wxTopLevelWindow
*win
)
316 win
->SetIconizeState(TRUE
);
320 //-----------------------------------------------------------------------------
321 // "expose_event" of m_client
322 //-----------------------------------------------------------------------------
325 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
327 GtkPizza
*pizza
= GTK_PIZZA(widget
);
329 gtk_paint_flat_box (win
->m_widget
->style
,
330 pizza
->bin_window
, GTK_STATE_NORMAL
,
341 //-----------------------------------------------------------------------------
342 // "draw" of m_client
343 //-----------------------------------------------------------------------------
348 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
350 GtkPizza
*pizza
= GTK_PIZZA(widget
);
352 gtk_paint_flat_box (win
->m_widget
->style
,
353 pizza
->bin_window
, GTK_STATE_NORMAL
,
364 // ----------------------------------------------------------------------------
365 // wxTopLevelWindowGTK itself
366 // ----------------------------------------------------------------------------
368 //-----------------------------------------------------------------------------
369 // InsertChild for wxTopLevelWindowGTK
370 //-----------------------------------------------------------------------------
372 /* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
373 * C++ has no virtual methods in a constructor. We have to emulate a
374 * virtual function here as wxWidgets requires different ways to insert
375 * a child in container classes. */
377 static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK
* parent
, wxWindow
* child
)
379 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
381 if (!parent
->m_insertInClientArea
)
383 // these are outside the client area
384 wxTopLevelWindowGTK
* frame
= (wxTopLevelWindowGTK
*) parent
;
385 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
386 GTK_WIDGET(child
->m_widget
),
394 // these are inside the client area
395 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
396 GTK_WIDGET(child
->m_widget
),
403 // resize on OnInternalIdle
404 parent
->GtkUpdateSize();
407 // ----------------------------------------------------------------------------
408 // wxTopLevelWindowGTK creation
409 // ----------------------------------------------------------------------------
411 void wxTopLevelWindowGTK::Init()
416 m_mainWidget
= (GtkWidget
*) NULL
;
417 m_insertInClientArea
= true;
418 m_isIconized
= false;
419 m_fsIsShowing
= false;
420 m_themeEnabled
= true;
421 m_gdkDecor
= m_gdkFunc
= 0;
425 bool wxTopLevelWindowGTK::Create( wxWindow
*parent
,
427 const wxString
& title
,
429 const wxSize
& sizeOrig
,
431 const wxString
&name
)
433 // always create a frame of some reasonable, even if arbitrary, size (at
434 // least for MSW compatibility)
435 wxSize size
= sizeOrig
;
436 size
.x
= WidthDefault(size
.x
);
437 size
.y
= HeightDefault(size
.y
);
439 wxTopLevelWindows
.Append( this );
441 m_needParent
= false;
443 if (!PreCreation( parent
, pos
, size
) ||
444 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
446 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
452 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInTopLevelWindow
;
454 // NB: m_widget may be !=NULL if it was created by derived class' Create,
455 // e.g. in wxTaskBarIconAreaGTK
456 if (m_widget
== NULL
)
458 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)
461 m_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
462 // Tell WM that this is a dialog window and make it center
463 // on parent by default (this is what GtkDialog ctor does):
464 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
465 GDK_WINDOW_TYPE_HINT_DIALOG
);
466 gtk_window_set_position(GTK_WINDOW(m_widget
),
467 GTK_WIN_POS_CENTER_ON_PARENT
);
469 m_widget
= gtk_window_new(GTK_WINDOW_DIALOG
);
474 m_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
475 #if GTK_CHECK_VERSION(2,1,0)
476 if (!gtk_check_version(2,1,0))
478 if (style
& wxFRAME_TOOL_WINDOW
)
480 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
481 GDK_WINDOW_TYPE_HINT_UTILITY
);
483 // On some WMs, like KDE, a TOOL_WINDOW will still show
484 // on the taskbar, but on Gnome a TOOL_WINDOW will not.
485 // For consistency between WMs and with Windows, we
486 // should set the NO_TASKBAR flag which will apply
487 // the set_skip_taskbar_hint if it is available,
488 // ensuring no taskbar entry will appear.
489 style
|= wxFRAME_NO_TASKBAR
;
496 wxWindow
*topParent
= wxGetTopLevelParent(m_parent
);
497 if (topParent
&& (((GTK_IS_WINDOW(topParent
->m_widget
)) &&
498 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) ||
499 (style
& wxFRAME_FLOAT_ON_PARENT
)))
501 gtk_window_set_transient_for( GTK_WINDOW(m_widget
),
502 GTK_WINDOW(topParent
->m_widget
) );
505 #if GTK_CHECK_VERSION(2,2,0)
506 if (!gtk_check_version(2,2,0))
508 if (style
& wxFRAME_NO_TASKBAR
)
510 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), TRUE
);
515 #if GTK_CHECK_VERSION(2,4,0)
516 if (!gtk_check_version(2,4,0))
518 if (style
& wxSTAY_ON_TOP
)
520 gtk_window_set_keep_above(GTK_WINDOW(m_widget
), TRUE
);
526 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), wxGTK_CONV( name
), wxGTK_CONV( name
) );
528 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
529 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
531 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
532 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
534 // m_mainWidget holds the toolbar, the menubar and the client area
535 m_mainWidget
= gtk_pizza_new();
536 gtk_widget_show( m_mainWidget
);
537 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
538 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
540 if (m_miniEdge
== 0) // wxMiniFrame has its own version.
542 // For m_mainWidget themes
543 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
544 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
546 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
547 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
551 // m_wxwindow only represents the client area without toolbar and menubar
552 m_wxwindow
= gtk_pizza_new();
553 gtk_widget_show( m_wxwindow
);
554 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
556 // we donm't allow the frame to get the focus as otherwise
557 // the frame will grab it at arbitrary focus changes
558 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
560 if (m_parent
) m_parent
->AddChild( this );
562 // the user resized the frame by dragging etc.
563 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
564 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
568 if ((m_x
!= -1) || (m_y
!= -1))
569 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
571 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
573 // we cannot set MWM hints and icons before the widget has
574 // been realized, so we do this directly after realization
575 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
576 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
578 // the only way to get the window size is to connect to this event
579 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
580 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
582 // map and unmap for iconized state
583 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
584 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
585 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
586 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
588 // the only way to get the window size is to connect to this event
589 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
590 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
592 // disable native tab traversal
593 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
594 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
597 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
598 GTK_SIGNAL_FUNC(gtk_frame_focus_in_callback
), (gpointer
)this );
599 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
600 GTK_SIGNAL_FUNC(gtk_frame_focus_out_callback
), (gpointer
)this );
603 if ((m_miniEdge
> 0) || (style
& wxSIMPLE_BORDER
) || (style
& wxNO_BORDER
))
610 m_gdkDecor
= (long) GDK_DECOR_BORDER
;
611 m_gdkFunc
= (long) GDK_FUNC_MOVE
;
613 // All this is for Motif Window Manager "hints" and is supposed to be
614 // recognized by other WMs as well.
615 if ((style
& wxCAPTION
) != 0)
617 m_gdkDecor
|= GDK_DECOR_TITLE
;
619 if ((style
& wxCLOSE_BOX
) != 0)
621 m_gdkFunc
|= GDK_FUNC_CLOSE
;
623 if ((style
& wxSYSTEM_MENU
) != 0)
625 m_gdkDecor
|= GDK_DECOR_MENU
;
627 if ((style
& wxMINIMIZE_BOX
) != 0)
629 m_gdkFunc
|= GDK_FUNC_MINIMIZE
;
630 m_gdkDecor
|= GDK_DECOR_MINIMIZE
;
632 if ((style
& wxMAXIMIZE_BOX
) != 0)
634 m_gdkFunc
|= GDK_FUNC_MAXIMIZE
;
635 m_gdkDecor
|= GDK_DECOR_MAXIMIZE
;
637 if ((style
& wxRESIZE_BORDER
) != 0)
639 m_gdkFunc
|= GDK_FUNC_RESIZE
;
640 m_gdkDecor
|= GDK_DECOR_RESIZEH
;
647 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
651 wxASSERT_MSG( FALSE
, _T("Window still grabbed"));
655 m_isBeingDeleted
= true;
657 // it may also be GtkScrolledWindow in the case of an MDI child
658 if (GTK_IS_WINDOW(m_widget
))
660 gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL
);
663 if (g_activeFrame
== this)
664 g_activeFrame
= NULL
;
665 if (g_lastActiveFrame
== this)
666 g_lastActiveFrame
= NULL
;
671 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long style
)
673 if (show
== m_fsIsShowing
)
674 return false; // return what?
676 m_fsIsShowing
= show
;
678 wxX11FullScreenMethod method
=
679 wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(),
680 (WXWindow
)GDK_ROOT_WINDOW());
682 #if GTK_CHECK_VERSION(2,2,0)
683 // NB: gtk_window_fullscreen() uses freedesktop.org's WMspec extensions
684 // to switch to fullscreen, which is not always available. We must
685 // check if WM supports the spec and use legacy methods if it
687 if ( (method
== wxX11_FS_WMSPEC
) && !gtk_check_version(2,2,0) )
690 gtk_window_fullscreen( GTK_WINDOW( m_widget
) );
692 gtk_window_unfullscreen( GTK_WINDOW( m_widget
) );
695 #endif // GTK+ >= 2.2.0
697 GdkWindow
*window
= m_widget
->window
;
701 m_fsSaveFlag
= style
;
702 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
703 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
705 int screen_width
,screen_height
;
706 wxDisplaySize( &screen_width
, &screen_height
);
708 gint client_x
, client_y
, root_x
, root_y
;
711 if (method
!= wxX11_FS_WMSPEC
)
713 // don't do it always, Metacity hates it
714 m_fsSaveGdkFunc
= m_gdkFunc
;
715 m_fsSaveGdkDecor
= m_gdkDecor
;
716 m_gdkFunc
= m_gdkDecor
= 0;
717 gdk_window_set_decorations(window
, (GdkWMDecoration
)0);
718 gdk_window_set_functions(window
, (GdkWMFunction
)0);
721 gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
);
722 gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
,
723 &width
, &height
, NULL
);
725 gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
,
726 screen_width
+ 1, screen_height
+ 1);
728 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
729 (WXWindow
)GDK_ROOT_WINDOW(),
730 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
731 show
, &m_fsSaveFrame
, method
);
735 if (method
!= wxX11_FS_WMSPEC
)
737 // don't do it always, Metacity hates it
738 m_gdkFunc
= m_fsSaveGdkFunc
;
739 m_gdkDecor
= m_fsSaveGdkDecor
;
740 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
);
741 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
);
744 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
745 (WXWindow
)GDK_ROOT_WINDOW(),
746 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
747 show
, &m_fsSaveFrame
, method
);
749 SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
,
750 m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
754 // documented behaviour is to show the window if it's still hidden when
755 // showing it full screen
756 if ( show
&& !IsShown() )
762 // ----------------------------------------------------------------------------
763 // overridden wxWindow methods
764 // ----------------------------------------------------------------------------
766 bool wxTopLevelWindowGTK::Show( bool show
)
768 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
770 if (show
&& !m_sizeSet
)
772 /* by calling GtkOnSize here, we don't have to call
773 either after showing the frame, which would entail
774 much ugly flicker or from within the size_allocate
775 handler, because GTK 1.1.X forbids that. */
777 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
781 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
783 return wxWindow::Show( show
);
786 void wxTopLevelWindowGTK::Raise()
789 gtk_window_present( GTK_WINDOW( m_widget
) );
795 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
797 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
800 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
802 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
804 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
805 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
815 int old_width
= m_width
;
816 int old_height
= m_height
;
818 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
820 if (x
!= -1) m_x
= x
;
821 if (y
!= -1) m_y
= y
;
828 if (width
!= -1) m_width
= width
;
829 if (height
!= -1) m_height
= height
;
832 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
834 if (width == -1) m_width = 80;
837 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
839 if (height == -1) m_height = 26;
843 int minWidth
= GetMinWidth(),
844 minHeight
= GetMinHeight(),
845 maxWidth
= GetMaxWidth(),
846 maxHeight
= GetMaxHeight();
849 // GPE's window manager doesn't like size hints
850 // at all, esp. when the user has to use the
858 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
859 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
860 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
861 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
863 if ((m_x
!= -1) || (m_y
!= -1))
865 if ((m_x
!= old_x
) || (m_y
!= old_y
))
867 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
871 if ((m_width
!= old_width
) || (m_height
!= old_height
))
873 if (m_widget
->window
)
874 gdk_window_resize( m_widget
->window
, m_width
, m_height
);
876 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
878 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
879 done either directly before the frame is shown or in idle time
880 so that different calls to SetSize() don't lead to flicker. */
887 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height
) const
889 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
891 wxWindow::DoGetClientSize( width
, height
);
895 *height
-= m_miniEdge
*2 + m_miniTitle
;
899 *width
-= m_miniEdge
*2;
903 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height
)
905 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
908 width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0);
911 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
912 int width
, int height
)
914 // due to a bug in gtk, x,y are always 0
919 if (m_resizing
) return;
922 if ( m_wxwindow
== NULL
) return;
927 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
928 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
929 set in wxFrame::Create so it is used to check what kind of frame we
930 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
931 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
932 importantly) m_mainWidget */
934 int minWidth
= GetMinWidth(),
935 minHeight
= GetMinHeight(),
936 maxWidth
= GetMaxWidth(),
937 maxHeight
= GetMaxHeight();
940 // GPE's window manager doesn't like size hints
941 // at all, esp. when the user has to use the
949 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
950 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
951 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
952 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
957 gint flag
= 0; // GDK_HINT_POS;
960 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
961 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
963 geom
.min_width
= minWidth
;
964 geom
.min_height
= minHeight
;
966 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
967 // maxHeight or maxWidth is set, we must set them both, else the
968 // remaining -1 will be taken literally.
970 // I'm certain this also happens elsewhere, and is the probable
971 // cause of other such things as:
972 // Gtk-WARNING **: gtk_widget_size_allocate():
973 // attempt to allocate widget with width 65535 and height 600
974 // but I don't have time to track them all now..
976 // Really we need to encapulate all this height/width business and
977 // stop any old method from ripping at the members directly and
978 // scattering -1's without regard for who might resolve them later.
980 geom
.max_width
= ( maxHeight
== -1 ) ? maxWidth
981 : ( maxWidth
== -1 ) ? wxGetDisplaySize().GetWidth()
984 geom
.max_height
= ( maxWidth
== -1 ) ? maxHeight
// ( == -1 here )
985 : ( maxHeight
== -1 ) ? wxGetDisplaySize().GetHeight()
988 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
991 (GdkWindowHints
) flag
);
993 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
994 * menubar, the toolbar and the client area, which is represented by
996 * this hurts in the eye, but I don't want to call SetSize()
997 * because I don't want to call any non-native functions here. */
999 int client_x
= m_miniEdge
;
1000 int client_y
= m_miniEdge
+ m_miniTitle
;
1001 int client_w
= m_width
- 2*m_miniEdge
;
1002 int client_h
= m_height
- 2*m_miniEdge
- m_miniTitle
;
1004 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
1006 client_x
, client_y
, client_w
, client_h
);
1010 // If there is no m_mainWidget between m_widget and m_wxwindow there
1011 // is no need to set the size or position of m_wxwindow.
1016 // send size event to frame
1017 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1018 event
.SetEventObject( this );
1019 GetEventHandler()->ProcessEvent( event
);
1024 void wxTopLevelWindowGTK::OnInternalIdle()
1026 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
1028 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
1030 // we'll come back later
1032 wxapp_install_idle_handler();
1036 // set the focus if not done yet and if we can already do it
1037 if ( GTK_WIDGET_REALIZED(m_wxwindow
) )
1039 if ( g_delayedFocus
&&
1040 wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this )
1042 wxLogTrace(_T("focus"),
1043 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
1044 g_delayedFocus
->GetClassInfo()->GetClassName(),
1045 g_delayedFocus
->GetLabel().c_str());
1047 g_delayedFocus
->SetFocus();
1048 g_delayedFocus
= NULL
;
1052 wxWindow::OnInternalIdle();
1054 // Synthetize activate events.
1055 if ( g_sendActivateEvent
!= -1 )
1057 bool activate
= g_sendActivateEvent
!= 0;
1059 // if (!activate) wxPrintf( wxT("de") );
1060 // wxPrintf( wxT("activate\n") );
1063 g_sendActivateEvent
= -1;
1065 wxTheApp
->SetActive(activate
, (wxWindow
*)g_lastActiveFrame
);
1069 // ----------------------------------------------------------------------------
1071 // ----------------------------------------------------------------------------
1073 void wxTopLevelWindowGTK::SetTitle( const wxString
&title
)
1075 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1078 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
1081 void wxTopLevelWindowGTK::SetIcon( const wxIcon
&icon
)
1083 SetIcons( wxIconBundle( icon
) );
1086 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle
&icons
)
1088 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1090 wxTopLevelWindowBase::SetIcons( icons
);
1094 size_t max
= icons
.m_icons
.GetCount();
1096 for (size_t i
= 0; i
< max
; i
++)
1098 if (icons
.m_icons
[i
].Ok())
1100 list
= g_list_prepend(list
, icons
.m_icons
[i
].GetPixbuf());
1103 gtk_window_set_icon_list(GTK_WINDOW(m_widget
), list
);
1106 #else // !__WXGTK20__
1107 GdkWindow
* window
= m_widget
->window
;
1111 wxIcon icon
= icons
.GetIcon(-1);
1114 wxMask
*mask
= icon
.GetMask();
1115 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1116 if (mask
) bm
= mask
->GetBitmap();
1118 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
1121 wxSetIconsX11( (WXDisplay
*)GDK_WINDOW_XDISPLAY( window
),
1122 (WXWindow
)GDK_WINDOW_XWINDOW( window
), icons
);
1123 #endif // !__WXGTK20__
1126 // ----------------------------------------------------------------------------
1127 // frame state: maximized/iconized/normal
1128 // ----------------------------------------------------------------------------
1130 void wxTopLevelWindowGTK::Maximize(bool maximize
)
1134 gtk_window_maximize( GTK_WINDOW( m_widget
) );
1136 gtk_window_unmaximize( GTK_WINDOW( m_widget
) );
1138 wxFAIL_MSG( _T("not implemented") );
1142 bool wxTopLevelWindowGTK::IsMaximized() const
1145 if(!m_widget
->window
)
1148 return gdk_window_get_state(m_widget
->window
) & GDK_WINDOW_STATE_MAXIMIZED
;
1150 // wxFAIL_MSG( _T("not implemented") );
1152 // This is an approximation
1157 void wxTopLevelWindowGTK::Restore()
1160 // "Present" seems similar enough to "restore"
1161 gtk_window_present( GTK_WINDOW( m_widget
) );
1163 wxFAIL_MSG( _T("not implemented") );
1167 void wxTopLevelWindowGTK::Iconize( bool iconize
)
1171 gtk_window_iconify( GTK_WINDOW( m_widget
) );
1173 gtk_window_deiconify( GTK_WINDOW( m_widget
) );
1177 GdkWindow
*window
= m_widget
->window
;
1179 // you should do it later, for example from OnCreate() handler
1180 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
1182 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
1183 GDK_WINDOW_XWINDOW( window
),
1184 DefaultScreen( GDK_DISPLAY() ) );
1189 bool wxTopLevelWindowGTK::IsIconized() const
1191 return m_isIconized
;
1194 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
)
1196 if ( iconize
!= m_isIconized
)
1198 m_isIconized
= iconize
;
1199 (void)SendIconizeEvent(iconize
);
1203 void wxTopLevelWindowGTK::AddGrab()
1208 gtk_grab_add( m_widget
);
1209 wxEventLoop().Run();
1210 gtk_grab_remove( m_widget
);
1214 void wxTopLevelWindowGTK::RemoveGrab()
1225 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
)
1229 if (region
.IsEmpty())
1231 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
1236 gdk_window_shape_combine_region(window
, region
.GetRegion(), 0, 0);
1238 wxBitmap bmp
= region
.ConvertToBitmap();
1239 bmp
.SetMask(new wxMask(bmp
, *wxBLACK
));
1240 GdkBitmap
* mask
= bmp
.GetMask()->GetBitmap();
1241 gdk_window_shape_combine_mask(window
, mask
, 0, 0);
1250 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
)
1252 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), false,
1253 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1255 GdkWindow
*window
= NULL
;
1258 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
1259 do_shape_combine_region(window
, region
);
1261 window
= m_widget
->window
;
1262 return do_shape_combine_region(window
, region
);
1265 bool wxTopLevelWindowGTK::IsActive()
1267 return (this == (wxTopLevelWindowGTK
*)g_activeFrame
);