1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk1/toplevel.cpp
4 // Author: Robert Roebling
5 // Copyright: (c) 1998 Robert Roebling
6 // Licence: wxWindows licence
7 /////////////////////////////////////////////////////////////////////////////
9 // For compilers that support precompilation, includes "wx.h".
10 #include "wx/wxprec.h"
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #define XIconifyWindow XICONIFYWINDOW
24 #include "wx/toplevel.h"
29 #include "wx/dcclient.h"
30 #include "wx/dialog.h"
32 #include "wx/settings.h"
33 #include "wx/control.h"
36 #include "wx/gtk1/private.h"
37 #include "wx/evtloop.h"
42 #include <gdk/gdkkeysyms.h>
45 #include "wx/gtk1/win_gtk.h"
47 #include "wx/unix/utilsx11.h"
50 #include <X11/Xatom.h>
52 // ----------------------------------------------------------------------------
54 // ----------------------------------------------------------------------------
56 extern void wxapp_install_idle_handler();
59 // ----------------------------------------------------------------------------
61 // ----------------------------------------------------------------------------
63 extern int g_openDialogs
;
64 extern wxWindowGTK
*g_delayedFocus
;
66 // the frame that is currently active (i.e. its child has focus). It is
67 // used to generate wxActivateEvents
68 static wxTopLevelWindowGTK
*g_activeFrame
= NULL
;
69 static wxTopLevelWindowGTK
*g_lastActiveFrame
= NULL
;
71 // if we detect that the app has got/lost the focus, we set this variable to
72 // either TRUE or FALSE and an activate event will be sent during the next
73 // OnIdle() call and it is reset to -1: this value means that we shouldn't
74 // send any activate events at all
75 static int g_sendActivateEvent
= -1;
77 //-----------------------------------------------------------------------------
78 // RequestUserAttention related functions
79 //-----------------------------------------------------------------------------
82 static void wxgtk_window_set_urgency_hint (GtkWindow
*win
,
85 wxASSERT_MSG( GTK_WIDGET_REALIZED(win
), wxT("wxgtk_window_set_urgency_hint: GdkWindow not realized") );
86 GdkWindow
*window
= GTK_WIDGET(win
)->window
;
89 wm_hints
= XGetWMHints(GDK_WINDOW_XDISPLAY(window
), GDK_WINDOW_XWINDOW(window
));
92 wm_hints
= XAllocWMHints();
95 wm_hints
->flags
|= XUrgencyHint
;
97 wm_hints
->flags
&= ~XUrgencyHint
;
99 XSetWMHints(GDK_WINDOW_XDISPLAY(window
), GDK_WINDOW_XWINDOW(window
), wm_hints
);
103 static gint
gtk_frame_urgency_timer_callback( wxTopLevelWindowGTK
*win
)
105 wxgtk_window_set_urgency_hint(GTK_WINDOW( win
->m_widget
), FALSE
);
107 win
->m_urgency_hint
= -2;
112 //-----------------------------------------------------------------------------
114 //-----------------------------------------------------------------------------
117 static gint
gtk_frame_focus_in_callback( GtkWidget
*widget
,
118 GdkEvent
*WXUNUSED(event
),
119 wxTopLevelWindowGTK
*win
)
122 wxapp_install_idle_handler();
124 switch ( g_sendActivateEvent
)
127 // we've got focus from outside, synthetize wxActivateEvent
128 g_sendActivateEvent
= 1;
132 // another our window just lost focus, it was already ours before
133 // - don't send any wxActivateEvent
134 g_sendActivateEvent
= -1;
139 g_lastActiveFrame
= g_activeFrame
;
141 // wxPrintf( wxT("active: %s\n"), win->GetTitle().c_str() );
143 // MR: wxRequestUserAttention related block
144 switch( win
->m_urgency_hint
)
147 gtk_timeout_remove( win
->m_urgency_hint
);
148 // no break, fallthrough to remove hint too
150 wxgtk_window_set_urgency_hint(GTK_WINDOW( widget
), FALSE
);
152 win
->m_urgency_hint
= -2;
158 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
);
159 wxActivateEvent
event(wxEVT_ACTIVATE
, true, g_activeFrame
->GetId());
160 event
.SetEventObject(g_activeFrame
);
161 g_activeFrame
->HandleWindowEvent(event
);
167 //-----------------------------------------------------------------------------
169 //-----------------------------------------------------------------------------
172 static gint
gtk_frame_focus_out_callback( GtkWidget
*WXUNUSED(widget
),
173 GdkEventFocus
*WXUNUSED(gdk_event
),
174 wxTopLevelWindowGTK
*WXUNUSED(win
) )
177 wxapp_install_idle_handler();
179 // if the focus goes out of our app alltogether, OnIdle() will send
180 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
181 // g_sendActivateEvent to -1
182 g_sendActivateEvent
= 0;
184 // wxASSERT_MSG( (g_activeFrame == win), wxT("TLW deactivatd although it wasn't active") );
186 // wxPrintf( wxT("inactive: %s\n"), win->GetTitle().c_str() );
190 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
);
191 wxActivateEvent
event(wxEVT_ACTIVATE
, false, g_activeFrame
->GetId());
192 event
.SetEventObject(g_activeFrame
);
193 g_activeFrame
->HandleWindowEvent(event
);
195 g_activeFrame
= NULL
;
202 //-----------------------------------------------------------------------------
203 // "focus" from m_window
204 //-----------------------------------------------------------------------------
207 static gint
gtk_frame_focus_callback( GtkWidget
*widget
, GtkDirectionType
WXUNUSED(d
), wxWindow
*WXUNUSED(win
) )
210 wxapp_install_idle_handler();
212 // This disables GTK's tab traversal
213 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus" );
218 //-----------------------------------------------------------------------------
220 //-----------------------------------------------------------------------------
223 static void gtk_frame_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxTopLevelWindowGTK
*win
)
226 wxapp_install_idle_handler();
231 if ((win
->m_width
!= alloc
->width
) || (win
->m_height
!= alloc
->height
))
234 wxPrintf( "OnSize from " );
235 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
236 wxPrintf( win->GetClassInfo()->GetClassName() );
237 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
240 (int)alloc->height );
243 win
->m_width
= alloc
->width
;
244 win
->m_height
= alloc
->height
;
245 win
->GtkUpdateSize();
250 //-----------------------------------------------------------------------------
252 //-----------------------------------------------------------------------------
255 static gint
gtk_frame_delete_callback( GtkWidget
*WXUNUSED(widget
), GdkEvent
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
258 wxapp_install_idle_handler();
260 if (win
->IsEnabled() &&
261 (g_openDialogs
== 0 || (win
->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) ||
270 //-----------------------------------------------------------------------------
272 //-----------------------------------------------------------------------------
276 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
279 wxapp_install_idle_handler();
281 if (!win
->m_hasVMT
|| !win
->IsShown())
287 gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y
);
291 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
292 mevent
.SetEventObject( win
);
293 win
->HandleWindowEvent( mevent
);
299 //-----------------------------------------------------------------------------
300 // "realize" from m_widget
301 //-----------------------------------------------------------------------------
303 // we cannot MWM hints and icons before the widget has been realized,
304 // so we do this directly after realization
308 gtk_frame_realized_callback( GtkWidget
* WXUNUSED(widget
),
309 wxTopLevelWindowGTK
*win
)
312 wxapp_install_idle_handler();
314 // All this is for Motif Window Manager "hints" and is supposed to be
315 // recognized by other WM as well. Not tested.
316 gdk_window_set_decorations(win
->m_widget
->window
,
317 (GdkWMDecoration
)win
->m_gdkDecor
);
318 gdk_window_set_functions(win
->m_widget
->window
,
319 (GdkWMFunction
)win
->m_gdkFunc
);
321 // GTK's shrinking/growing policy
322 if ((win
->m_gdkFunc
& GDK_FUNC_RESIZE
) == 0)
323 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 0, 0, 1);
325 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
328 wxIconBundle iconsOld
= win
->GetIcons();
329 if ( !iconsOld
.IsEmpty() )
331 win
->SetIcon( wxNullIcon
);
332 win
->SetIcons( iconsOld
);
337 //-----------------------------------------------------------------------------
338 // "map_event" from m_widget
339 //-----------------------------------------------------------------------------
343 gtk_frame_map_callback( GtkWidget
* WXUNUSED(widget
),
344 GdkEvent
* WXUNUSED(event
),
345 wxTopLevelWindow
*win
)
347 win
->SetIconizeState(false);
351 //-----------------------------------------------------------------------------
352 // "unmap_event" from m_widget
353 //-----------------------------------------------------------------------------
357 gtk_frame_unmap_callback( GtkWidget
* WXUNUSED(widget
),
358 GdkEvent
* WXUNUSED(event
),
359 wxTopLevelWindow
*win
)
361 win
->SetIconizeState(true);
365 //-----------------------------------------------------------------------------
366 // "expose_event" of m_client
367 //-----------------------------------------------------------------------------
370 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
372 GtkPizza
*pizza
= GTK_PIZZA(widget
);
374 gtk_paint_flat_box (win
->m_widget
->style
,
375 pizza
->bin_window
, GTK_STATE_NORMAL
,
386 //-----------------------------------------------------------------------------
387 // "draw" of m_client
388 //-----------------------------------------------------------------------------
391 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
393 GtkPizza
*pizza
= GTK_PIZZA(widget
);
395 gtk_paint_flat_box (win
->m_widget
->style
,
396 pizza
->bin_window
, GTK_STATE_NORMAL
,
405 // ----------------------------------------------------------------------------
406 // wxTopLevelWindowGTK itself
407 // ----------------------------------------------------------------------------
409 //-----------------------------------------------------------------------------
410 // InsertChild for wxTopLevelWindowGTK
411 //-----------------------------------------------------------------------------
413 /* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
414 * C++ has no virtual methods in a constructor. We have to emulate a
415 * virtual function here as wxWidgets requires different ways to insert
416 * a child in container classes. */
418 static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK
* parent
, wxWindow
* child
)
420 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
422 if (!parent
->m_insertInClientArea
)
424 // these are outside the client area
425 wxTopLevelWindowGTK
* frame
= (wxTopLevelWindowGTK
*) parent
;
426 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
427 GTK_WIDGET(child
->m_widget
),
435 // these are inside the client area
436 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
437 GTK_WIDGET(child
->m_widget
),
444 // resize on OnInternalIdle
445 parent
->GtkUpdateSize();
448 // ----------------------------------------------------------------------------
449 // wxTopLevelWindowGTK creation
450 // ----------------------------------------------------------------------------
452 void wxTopLevelWindowGTK::Init()
458 m_insertInClientArea
= true;
459 m_isIconized
= false;
460 m_fsIsShowing
= false;
461 m_themeEnabled
= true;
462 m_gdkDecor
= m_gdkFunc
= 0;
468 bool wxTopLevelWindowGTK::Create( wxWindow
*parent
,
470 const wxString
& title
,
472 const wxSize
& sizeOrig
,
474 const wxString
&name
)
476 // always create a frame of some reasonable, even if arbitrary, size (at
477 // least for MSW compatibility)
478 wxSize size
= sizeOrig
;
479 size
.x
= WidthDefault(size
.x
);
480 size
.y
= HeightDefault(size
.y
);
482 wxTopLevelWindows
.Append( this );
484 m_needParent
= false;
486 if (!PreCreation( parent
, pos
, size
) ||
487 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
489 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
495 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInTopLevelWindow
;
497 // NB: m_widget may be !=NULL if it was created by derived class' Create,
498 // e.g. in wxTaskBarIconAreaGTK
499 if (m_widget
== NULL
)
501 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)
503 m_widget
= gtk_window_new(GTK_WINDOW_DIALOG
);
507 m_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
508 #if GTK_CHECK_VERSION(2,1,0)
509 if (!gtk_check_version(2,1,0))
511 if (style
& wxFRAME_TOOL_WINDOW
)
513 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
514 GDK_WINDOW_TYPE_HINT_UTILITY
);
516 // On some WMs, like KDE, a TOOL_WINDOW will still show
517 // on the taskbar, but on Gnome a TOOL_WINDOW will not.
518 // For consistency between WMs and with Windows, we
519 // should set the NO_TASKBAR flag which will apply
520 // the set_skip_taskbar_hint if it is available,
521 // ensuring no taskbar entry will appear.
522 style
|= wxFRAME_NO_TASKBAR
;
529 wxWindow
*topParent
= wxGetTopLevelParent(m_parent
);
530 if (topParent
&& (((GTK_IS_WINDOW(topParent
->m_widget
)) &&
531 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) ||
532 (style
& wxFRAME_FLOAT_ON_PARENT
)))
534 gtk_window_set_transient_for( GTK_WINDOW(m_widget
),
535 GTK_WINDOW(topParent
->m_widget
) );
539 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), wxGTK_CONV( name
), wxGTK_CONV( name
) );
541 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
542 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
544 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
545 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
547 // m_mainWidget holds the toolbar, the menubar and the client area
548 m_mainWidget
= gtk_pizza_new();
549 gtk_widget_show( m_mainWidget
);
550 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
551 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
553 if (m_miniEdge
== 0) // wxMiniFrame has its own version.
555 // For m_mainWidget themes
556 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
557 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
558 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
559 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
562 // m_wxwindow only represents the client area without toolbar and menubar
563 m_wxwindow
= gtk_pizza_new();
564 gtk_widget_show( m_wxwindow
);
565 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
567 // we donm't allow the frame to get the focus as otherwise
568 // the frame will grab it at arbitrary focus changes
569 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
571 if (m_parent
) m_parent
->AddChild( this );
573 // the user resized the frame by dragging etc.
574 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
575 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
579 if ((m_x
!= -1) || (m_y
!= -1))
580 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
582 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
584 // we cannot set MWM hints and icons before the widget has
585 // been realized, so we do this directly after realization
586 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
587 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
589 // map and unmap for iconized state
590 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
591 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
592 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
593 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
595 // the only way to get the window size is to connect to this event
596 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
597 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
599 // disable native tab traversal
600 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
601 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
604 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
605 GTK_SIGNAL_FUNC(gtk_frame_focus_in_callback
), (gpointer
)this );
606 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
607 GTK_SIGNAL_FUNC(gtk_frame_focus_out_callback
), (gpointer
)this );
610 if ((m_miniEdge
> 0) || (style
& wxSIMPLE_BORDER
) || (style
& wxNO_BORDER
))
617 m_gdkDecor
= (long) GDK_DECOR_BORDER
;
618 m_gdkFunc
= (long) GDK_FUNC_MOVE
;
620 // All this is for Motif Window Manager "hints" and is supposed to be
621 // recognized by other WMs as well.
622 if ((style
& wxCAPTION
) != 0)
624 m_gdkDecor
|= GDK_DECOR_TITLE
;
626 if ((style
& wxCLOSE_BOX
) != 0)
628 m_gdkFunc
|= GDK_FUNC_CLOSE
;
630 if ((style
& wxSYSTEM_MENU
) != 0)
632 m_gdkDecor
|= GDK_DECOR_MENU
;
634 if ((style
& wxMINIMIZE_BOX
) != 0)
636 m_gdkFunc
|= GDK_FUNC_MINIMIZE
;
637 m_gdkDecor
|= GDK_DECOR_MINIMIZE
;
639 if ((style
& wxMAXIMIZE_BOX
) != 0)
641 m_gdkFunc
|= GDK_FUNC_MAXIMIZE
;
642 m_gdkDecor
|= GDK_DECOR_MAXIMIZE
;
644 if ((style
& wxRESIZE_BORDER
) != 0)
646 m_gdkFunc
|= GDK_FUNC_RESIZE
;
647 m_gdkDecor
|= GDK_DECOR_RESIZEH
;
654 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
658 wxASSERT_MSG( false, wxT("Window still grabbed"));
664 // it may also be GtkScrolledWindow in the case of an MDI child
665 if (GTK_IS_WINDOW(m_widget
))
667 gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL
);
670 if (g_activeFrame
== this)
671 g_activeFrame
= NULL
;
672 if (g_lastActiveFrame
== this)
673 g_lastActiveFrame
= NULL
;
678 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long style
)
680 if (show
== m_fsIsShowing
)
681 return false; // return what?
683 m_fsIsShowing
= show
;
685 wxX11FullScreenMethod method
=
686 wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(),
687 (WXWindow
)GDK_ROOT_WINDOW());
689 #if GTK_CHECK_VERSION(2,2,0)
690 // NB: gtk_window_fullscreen() uses freedesktop.org's WMspec extensions
691 // to switch to fullscreen, which is not always available. We must
692 // check if WM supports the spec and use legacy methods if it
694 if ( (method
== wxX11_FS_WMSPEC
) && !gtk_check_version(2,2,0) )
697 gtk_window_fullscreen( GTK_WINDOW( m_widget
) );
699 gtk_window_unfullscreen( GTK_WINDOW( m_widget
) );
702 #endif // GTK+ >= 2.2.0
704 GdkWindow
*window
= m_widget
->window
;
708 m_fsSaveFlag
= style
;
709 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
710 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
712 int screen_width
,screen_height
;
713 wxDisplaySize( &screen_width
, &screen_height
);
715 gint client_x
, client_y
, root_x
, root_y
;
718 if (method
!= wxX11_FS_WMSPEC
)
720 // don't do it always, Metacity hates it
721 m_fsSaveGdkFunc
= m_gdkFunc
;
722 m_fsSaveGdkDecor
= m_gdkDecor
;
723 m_gdkFunc
= m_gdkDecor
= 0;
724 gdk_window_set_decorations(window
, (GdkWMDecoration
)0);
725 gdk_window_set_functions(window
, (GdkWMFunction
)0);
728 gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
);
729 gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
,
730 &width
, &height
, NULL
);
732 gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
,
733 screen_width
+ 1, screen_height
+ 1);
735 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
736 (WXWindow
)GDK_ROOT_WINDOW(),
737 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
738 show
, &m_fsSaveFrame
, method
);
742 if (method
!= wxX11_FS_WMSPEC
)
744 // don't do it always, Metacity hates it
745 m_gdkFunc
= m_fsSaveGdkFunc
;
746 m_gdkDecor
= m_fsSaveGdkDecor
;
747 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
);
748 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
);
751 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
752 (WXWindow
)GDK_ROOT_WINDOW(),
753 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
754 show
, &m_fsSaveFrame
, method
);
756 SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
,
757 m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
761 // documented behaviour is to show the window if it's still hidden when
762 // showing it full screen
763 if ( show
&& !IsShown() )
769 // ----------------------------------------------------------------------------
770 // overridden wxWindow methods
771 // ----------------------------------------------------------------------------
773 bool wxTopLevelWindowGTK::Show( bool show
)
775 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
777 if (show
&& !m_sizeSet
)
779 /* by calling GtkOnSize here, we don't have to call
780 either after showing the frame, which would entail
781 much ugly flicker or from within the size_allocate
782 handler, because GTK 1.1.X forbids that. */
784 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
788 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
790 return wxWindow::Show( show
);
793 void wxTopLevelWindowGTK::Raise()
798 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
800 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
803 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
805 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
807 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
808 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
818 int old_width
= m_width
;
819 int old_height
= m_height
;
821 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
823 if (x
!= -1) m_x
= x
;
824 if (y
!= -1) m_y
= y
;
831 if (width
!= -1) m_width
= width
;
832 if (height
!= -1) m_height
= height
;
835 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
837 if (width == -1) m_width = 80;
840 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
842 if (height == -1) m_height = 26;
846 int minWidth
= GetMinWidth(),
847 minHeight
= GetMinHeight(),
848 maxWidth
= GetMaxWidth(),
849 maxHeight
= GetMaxHeight();
852 // GPE's window manager doesn't like size hints
853 // at all, esp. when the user has to use the
861 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
862 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
863 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
864 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
866 if ((m_x
!= -1) || (m_y
!= -1))
868 if ((m_x
!= old_x
) || (m_y
!= old_y
))
870 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
874 if ((m_width
!= old_width
) || (m_height
!= old_height
))
876 if (m_widget
->window
)
877 gdk_window_resize( m_widget
->window
, m_width
, m_height
);
879 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
881 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
882 done either directly before the frame is shown or in idle time
883 so that different calls to SetSize() don't lead to flicker. */
890 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height
) const
892 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
894 wxWindow::DoGetClientSize( width
, height
);
898 *height
-= m_miniEdge
*2 + m_miniTitle
;
902 *width
-= m_miniEdge
*2;
906 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height
)
908 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
911 width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0);
914 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
915 int width
, int height
)
917 // due to a bug in gtk, x,y are always 0
922 if (m_resizing
) return;
925 if ( m_wxwindow
== NULL
) return;
930 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
931 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
932 set in wxFrame::Create so it is used to check what kind of frame we
933 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
934 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
935 importantly) m_mainWidget */
937 int minWidth
= GetMinWidth(),
938 minHeight
= GetMinHeight(),
939 maxWidth
= GetMaxWidth(),
940 maxHeight
= GetMaxHeight();
943 // GPE's window manager doesn't like size hints
944 // at all, esp. when the user has to use the
952 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
953 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
954 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
955 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
960 gint flag
= 0; // GDK_HINT_POS;
963 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
964 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
966 geom
.min_width
= minWidth
;
967 geom
.min_height
= minHeight
;
969 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
970 // maxHeight or maxWidth is set, we must set them both, else the
971 // remaining -1 will be taken literally.
973 // I'm certain this also happens elsewhere, and is the probable
974 // cause of other such things as:
975 // Gtk-WARNING **: gtk_widget_size_allocate():
976 // attempt to allocate widget with width 65535 and height 600
977 // but I don't have time to track them all now..
979 // Really we need to encapulate all this height/width business and
980 // stop any old method from ripping at the members directly and
981 // scattering -1's without regard for who might resolve them later.
983 geom
.max_width
= ( maxHeight
== -1 ) ? maxWidth
984 : ( maxWidth
== -1 ) ? wxGetDisplaySize().GetWidth()
987 geom
.max_height
= ( maxWidth
== -1 ) ? maxHeight
// ( == -1 here )
988 : ( maxHeight
== -1 ) ? wxGetDisplaySize().GetHeight()
991 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
994 (GdkWindowHints
) flag
);
996 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
997 * menubar, the toolbar and the client area, which is represented by
999 * this hurts in the eye, but I don't want to call SetSize()
1000 * because I don't want to call any non-native functions here. */
1002 int client_x
= m_miniEdge
;
1003 int client_y
= m_miniEdge
+ m_miniTitle
;
1004 int client_w
= m_width
- 2*m_miniEdge
;
1005 int client_h
= m_height
- 2*m_miniEdge
- m_miniTitle
;
1007 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
1009 client_x
, client_y
, client_w
, client_h
);
1013 // If there is no m_mainWidget between m_widget and m_wxwindow there
1014 // is no need to set the size or position of m_wxwindow.
1019 // send size event to frame
1020 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1021 event
.SetEventObject( this );
1022 HandleWindowEvent( event
);
1027 void wxTopLevelWindowGTK::OnInternalIdle()
1029 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
1031 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
1033 // we'll come back later
1035 wxapp_install_idle_handler();
1039 // set the focus if not done yet and if we can already do it
1040 if ( GTK_WIDGET_REALIZED(m_wxwindow
) )
1042 if ( g_delayedFocus
&&
1043 wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this )
1045 wxLogTrace(wxT("focus"),
1046 wxT("Setting focus from wxTLW::OnIdle() to %s(%s)"),
1047 g_delayedFocus
->GetClassInfo()->GetClassName(),
1048 g_delayedFocus
->GetLabel().c_str());
1050 g_delayedFocus
->SetFocus();
1051 g_delayedFocus
= NULL
;
1055 wxWindow::OnInternalIdle();
1057 // Synthetize activate events.
1058 if ( g_sendActivateEvent
!= -1 )
1060 bool activate
= g_sendActivateEvent
!= 0;
1062 // if (!activate) wxPrintf( wxT("de") );
1063 // wxPrintf( wxT("activate\n") );
1066 g_sendActivateEvent
= -1;
1068 wxTheApp
->SetActive(activate
, (wxWindow
*)g_lastActiveFrame
);
1072 // ----------------------------------------------------------------------------
1074 // ----------------------------------------------------------------------------
1076 void wxTopLevelWindowGTK::SetTitle( const wxString
&title
)
1078 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1080 if ( title
== m_title
)
1085 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
1088 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle
&icons
)
1090 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1092 wxTopLevelWindowBase::SetIcons( icons
);
1094 if ( icons
.IsEmpty() )
1097 GdkWindow
* window
= m_widget
->window
;
1101 wxIcon icon
= icons
.GetIcon(-1);
1104 wxMask
*mask
= icon
.GetMask();
1105 GdkBitmap
*bm
= NULL
;
1106 if (mask
) bm
= mask
->GetBitmap();
1108 gdk_window_set_icon( m_widget
->window
, NULL
, icon
.GetPixmap(), bm
);
1111 wxSetIconsX11( (WXDisplay
*)GDK_WINDOW_XDISPLAY( window
),
1112 (WXWindow
)GDK_WINDOW_XWINDOW( window
), icons
);
1115 // ----------------------------------------------------------------------------
1116 // frame state: maximized/iconized/normal
1117 // ----------------------------------------------------------------------------
1119 void wxTopLevelWindowGTK::Maximize(bool WXUNUSED(maximize
))
1121 wxFAIL_MSG( wxT("not implemented") );
1124 bool wxTopLevelWindowGTK::IsMaximized() const
1126 // wxFAIL_MSG( wxT("not implemented") );
1128 // This is an approximation
1132 void wxTopLevelWindowGTK::Restore()
1134 wxFAIL_MSG( wxT("not implemented") );
1137 void wxTopLevelWindowGTK::Iconize( bool iconize
)
1141 GdkWindow
*window
= m_widget
->window
;
1143 // you should do it later, for example from OnCreate() handler
1144 wxCHECK_RET( window
, wxT("frame not created yet - can't iconize") );
1146 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
1147 GDK_WINDOW_XWINDOW( window
),
1148 DefaultScreen( GDK_DISPLAY() ) );
1152 bool wxTopLevelWindowGTK::IsIconized() const
1154 return m_isIconized
;
1157 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
)
1159 if ( iconize
!= m_isIconized
)
1161 m_isIconized
= iconize
;
1162 (void)SendIconizeEvent(iconize
);
1166 void wxTopLevelWindowGTK::AddGrab()
1171 gtk_grab_add( m_widget
);
1172 wxEventLoop().Run();
1173 gtk_grab_remove( m_widget
);
1177 void wxTopLevelWindowGTK::RemoveGrab()
1188 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
)
1192 if (region
.IsEmpty())
1194 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
1198 wxBitmap bmp
= region
.ConvertToBitmap();
1199 bmp
.SetMask(new wxMask(bmp
, *wxBLACK
));
1200 GdkBitmap
* mask
= bmp
.GetMask()->GetBitmap();
1201 gdk_window_shape_combine_mask(window
, mask
, 0, 0);
1209 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
)
1211 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), false,
1212 wxT("Shaped windows must be created with the wxFRAME_SHAPED style."));
1214 GdkWindow
*window
= NULL
;
1217 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
1218 do_shape_combine_region(window
, region
);
1220 window
= m_widget
->window
;
1221 return do_shape_combine_region(window
, region
);
1224 bool wxTopLevelWindowGTK::IsActive()
1226 return (this == (wxTopLevelWindowGTK
*)g_activeFrame
);
1229 void wxTopLevelWindowGTK::RequestUserAttention(int flags
)
1231 bool new_hint_value
= false;
1233 // FIXME: This is a workaround to focus handling problem
1234 // If RequestUserAttention is called for example right after a wxSleep, OnInternalIdle hasn't
1235 // yet been processed, and the internal focus system is not up to date yet.
1236 // wxYieldIfNeeded ensures the processing of it, but can have unwanted side effects - MR
1237 ::wxYieldIfNeeded();
1239 if(m_urgency_hint
>= 0)
1240 gtk_timeout_remove(m_urgency_hint
);
1242 m_urgency_hint
= -2;
1244 if( GTK_WIDGET_REALIZED(m_widget
) && !IsActive() )
1246 new_hint_value
= true;
1248 if (flags
& wxUSER_ATTENTION_INFO
)
1250 m_urgency_hint
= gtk_timeout_add(5000, (GtkFunction
)gtk_frame_urgency_timer_callback
, this);
1252 m_urgency_hint
= -1;
1256 wxgtk_window_set_urgency_hint(GTK_WINDOW( m_widget
), new_hint_value
);
1259 void wxTopLevelWindowGTK::SetWindowStyleFlag( long style
)
1261 // Process wxWindow styles. This also updates the internal variable
1262 // Therefore m_windowStyle bits carry now the _new_ style values
1263 wxWindow::SetWindowStyleFlag(style
);