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
) );
697 #endif // GTK+ >= 2.2.0
699 GdkWindow
*window
= m_widget
->window
;
703 m_fsSaveFlag
= style
;
704 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
705 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
707 int screen_width
,screen_height
;
708 wxDisplaySize( &screen_width
, &screen_height
);
710 gint client_x
, client_y
, root_x
, root_y
;
713 if (method
!= wxX11_FS_WMSPEC
)
715 // don't do it always, Metacity hates it
716 m_fsSaveGdkFunc
= m_gdkFunc
;
717 m_fsSaveGdkDecor
= m_gdkDecor
;
718 m_gdkFunc
= m_gdkDecor
= 0;
719 gdk_window_set_decorations(window
, (GdkWMDecoration
)0);
720 gdk_window_set_functions(window
, (GdkWMFunction
)0);
723 gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
);
724 gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
,
725 &width
, &height
, NULL
);
727 gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
,
728 screen_width
+ 1, screen_height
+ 1);
730 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
731 (WXWindow
)GDK_ROOT_WINDOW(),
732 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
733 show
, &m_fsSaveFrame
, method
);
737 if (method
!= wxX11_FS_WMSPEC
)
739 // don't do it always, Metacity hates it
740 m_gdkFunc
= m_fsSaveGdkFunc
;
741 m_gdkDecor
= m_fsSaveGdkDecor
;
742 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
);
743 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
);
746 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
747 (WXWindow
)GDK_ROOT_WINDOW(),
748 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
749 show
, &m_fsSaveFrame
, method
);
751 SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
,
752 m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
759 // ----------------------------------------------------------------------------
760 // overridden wxWindow methods
761 // ----------------------------------------------------------------------------
763 bool wxTopLevelWindowGTK::Show( bool show
)
765 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
767 if (show
&& !m_sizeSet
)
769 /* by calling GtkOnSize here, we don't have to call
770 either after showing the frame, which would entail
771 much ugly flicker or from within the size_allocate
772 handler, because GTK 1.1.X forbids that. */
774 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
778 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
780 return wxWindow::Show( show
);
783 void wxTopLevelWindowGTK::Raise()
786 gtk_window_present( GTK_WINDOW( m_widget
) );
792 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
794 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
797 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
799 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
801 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
802 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
812 int old_width
= m_width
;
813 int old_height
= m_height
;
815 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
817 if (x
!= -1) m_x
= x
;
818 if (y
!= -1) m_y
= y
;
825 if (width
!= -1) m_width
= width
;
826 if (height
!= -1) m_height
= height
;
829 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
831 if (width == -1) m_width = 80;
834 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
836 if (height == -1) m_height = 26;
840 int minWidth
= GetMinWidth(),
841 minHeight
= GetMinHeight(),
842 maxWidth
= GetMaxWidth(),
843 maxHeight
= GetMaxHeight();
846 // GPE's window manager doesn't like size hints
847 // at all, esp. when the user has to use the
855 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
856 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
857 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
858 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
860 if ((m_x
!= -1) || (m_y
!= -1))
862 if ((m_x
!= old_x
) || (m_y
!= old_y
))
864 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
868 if ((m_width
!= old_width
) || (m_height
!= old_height
))
870 if (m_widget
->window
)
871 gdk_window_resize( m_widget
->window
, m_width
, m_height
);
873 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
875 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
876 done either directly before the frame is shown or in idle time
877 so that different calls to SetSize() don't lead to flicker. */
884 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height
) const
886 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
888 wxWindow::DoGetClientSize( width
, height
);
892 *height
-= m_miniEdge
*2 + m_miniTitle
;
896 *width
-= m_miniEdge
*2;
900 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height
)
902 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
905 width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0);
908 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
909 int width
, int height
)
911 // due to a bug in gtk, x,y are always 0
916 if (m_resizing
) return;
919 if ( m_wxwindow
== NULL
) return;
924 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
925 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
926 set in wxFrame::Create so it is used to check what kind of frame we
927 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
928 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
929 importantly) m_mainWidget */
931 int minWidth
= GetMinWidth(),
932 minHeight
= GetMinHeight(),
933 maxWidth
= GetMaxWidth(),
934 maxHeight
= GetMaxHeight();
937 // GPE's window manager doesn't like size hints
938 // at all, esp. when the user has to use the
946 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
947 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
948 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
949 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
954 gint flag
= 0; // GDK_HINT_POS;
957 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
958 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
960 geom
.min_width
= minWidth
;
961 geom
.min_height
= minHeight
;
963 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
964 // maxHeight or maxWidth is set, we must set them both, else the
965 // remaining -1 will be taken literally.
967 // I'm certain this also happens elsewhere, and is the probable
968 // cause of other such things as:
969 // Gtk-WARNING **: gtk_widget_size_allocate():
970 // attempt to allocate widget with width 65535 and height 600
971 // but I don't have time to track them all now..
973 // Really we need to encapulate all this height/width business and
974 // stop any old method from ripping at the members directly and
975 // scattering -1's without regard for who might resolve them later.
977 geom
.max_width
= ( maxHeight
== -1 ) ? maxWidth
978 : ( maxWidth
== -1 ) ? wxGetDisplaySize().GetWidth()
981 geom
.max_height
= ( maxWidth
== -1 ) ? maxHeight
// ( == -1 here )
982 : ( maxHeight
== -1 ) ? wxGetDisplaySize().GetHeight()
985 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
988 (GdkWindowHints
) flag
);
990 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
991 * menubar, the toolbar and the client area, which is represented by
993 * this hurts in the eye, but I don't want to call SetSize()
994 * because I don't want to call any non-native functions here. */
996 int client_x
= m_miniEdge
;
997 int client_y
= m_miniEdge
+ m_miniTitle
;
998 int client_w
= m_width
- 2*m_miniEdge
;
999 int client_h
= m_height
- 2*m_miniEdge
- m_miniTitle
;
1001 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
1003 client_x
, client_y
, client_w
, client_h
);
1007 // If there is no m_mainWidget between m_widget and m_wxwindow there
1008 // is no need to set the size or position of m_wxwindow.
1013 // send size event to frame
1014 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1015 event
.SetEventObject( this );
1016 GetEventHandler()->ProcessEvent( event
);
1021 void wxTopLevelWindowGTK::OnInternalIdle()
1023 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
1025 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
1027 // we'll come back later
1029 wxapp_install_idle_handler();
1033 // set the focus if not done yet and if we can already do it
1034 if ( GTK_WIDGET_REALIZED(m_wxwindow
) )
1036 if ( g_delayedFocus
&&
1037 wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this )
1039 wxLogTrace(_T("focus"),
1040 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
1041 g_delayedFocus
->GetClassInfo()->GetClassName(),
1042 g_delayedFocus
->GetLabel().c_str());
1044 g_delayedFocus
->SetFocus();
1045 g_delayedFocus
= NULL
;
1049 wxWindow::OnInternalIdle();
1051 // Synthetize activate events.
1052 if ( g_sendActivateEvent
!= -1 )
1054 bool activate
= g_sendActivateEvent
!= 0;
1056 // if (!activate) wxPrintf( wxT("de") );
1057 // wxPrintf( wxT("activate\n") );
1060 g_sendActivateEvent
= -1;
1062 wxTheApp
->SetActive(activate
, (wxWindow
*)g_lastActiveFrame
);
1066 // ----------------------------------------------------------------------------
1068 // ----------------------------------------------------------------------------
1070 void wxTopLevelWindowGTK::SetTitle( const wxString
&title
)
1072 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1075 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
1078 void wxTopLevelWindowGTK::SetIcon( const wxIcon
&icon
)
1080 SetIcons( wxIconBundle( icon
) );
1083 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle
&icons
)
1085 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1087 wxTopLevelWindowBase::SetIcons( icons
);
1091 size_t max
= icons
.m_icons
.GetCount();
1093 for (size_t i
= 0; i
< max
; i
++)
1095 if (icons
.m_icons
[i
].Ok())
1097 list
= g_list_prepend(list
, icons
.m_icons
[i
].GetPixbuf());
1100 gtk_window_set_icon_list(GTK_WINDOW(m_widget
), list
);
1103 #else // !__WXGTK20__
1104 GdkWindow
* window
= m_widget
->window
;
1108 wxIcon icon
= icons
.GetIcon(-1);
1111 wxMask
*mask
= icon
.GetMask();
1112 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1113 if (mask
) bm
= mask
->GetBitmap();
1115 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
1118 wxSetIconsX11( (WXDisplay
*)GDK_WINDOW_XDISPLAY( window
),
1119 (WXWindow
)GDK_WINDOW_XWINDOW( window
), icons
);
1120 #endif // !__WXGTK20__
1123 // ----------------------------------------------------------------------------
1124 // frame state: maximized/iconized/normal
1125 // ----------------------------------------------------------------------------
1127 void wxTopLevelWindowGTK::Maximize(bool maximize
)
1131 gtk_window_maximize( GTK_WINDOW( m_widget
) );
1133 gtk_window_unmaximize( GTK_WINDOW( m_widget
) );
1135 wxFAIL_MSG( _T("not implemented") );
1139 bool wxTopLevelWindowGTK::IsMaximized() const
1142 if(!m_widget
->window
)
1145 return gdk_window_get_state(m_widget
->window
) & GDK_WINDOW_STATE_MAXIMIZED
;
1147 // wxFAIL_MSG( _T("not implemented") );
1149 // This is an approximation
1154 void wxTopLevelWindowGTK::Restore()
1157 // "Present" seems similar enough to "restore"
1158 gtk_window_present( GTK_WINDOW( m_widget
) );
1160 wxFAIL_MSG( _T("not implemented") );
1164 void wxTopLevelWindowGTK::Iconize( bool iconize
)
1168 gtk_window_iconify( GTK_WINDOW( m_widget
) );
1170 gtk_window_deiconify( GTK_WINDOW( m_widget
) );
1174 GdkWindow
*window
= m_widget
->window
;
1176 // you should do it later, for example from OnCreate() handler
1177 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
1179 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
1180 GDK_WINDOW_XWINDOW( window
),
1181 DefaultScreen( GDK_DISPLAY() ) );
1186 bool wxTopLevelWindowGTK::IsIconized() const
1188 return m_isIconized
;
1191 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
)
1193 if ( iconize
!= m_isIconized
)
1195 m_isIconized
= iconize
;
1196 (void)SendIconizeEvent(iconize
);
1200 void wxTopLevelWindowGTK::AddGrab()
1205 gtk_grab_add( m_widget
);
1206 wxEventLoop().Run();
1207 gtk_grab_remove( m_widget
);
1211 void wxTopLevelWindowGTK::RemoveGrab()
1222 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
)
1226 if (region
.IsEmpty())
1228 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
1233 gdk_window_shape_combine_region(window
, region
.GetRegion(), 0, 0);
1235 wxBitmap bmp
= region
.ConvertToBitmap();
1236 bmp
.SetMask(new wxMask(bmp
, *wxBLACK
));
1237 GdkBitmap
* mask
= bmp
.GetMask()->GetBitmap();
1238 gdk_window_shape_combine_mask(window
, mask
, 0, 0);
1247 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
)
1249 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), FALSE
,
1250 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1252 GdkWindow
*window
= NULL
;
1255 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
1256 do_shape_combine_region(window
, region
);
1258 window
= m_widget
->window
;
1259 return do_shape_combine_region(window
, region
);
1262 bool wxTopLevelWindowGTK::IsActive()
1264 return (this == (wxTopLevelWindowGTK
*)g_activeFrame
);