1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk1/toplevel.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // For compilers that support precompilation, includes "wx.h".
11 #include "wx/wxprec.h"
13 // ============================================================================
15 // ============================================================================
17 // ----------------------------------------------------------------------------
19 // ----------------------------------------------------------------------------
22 #define XIconifyWindow XICONIFYWINDOW
25 #include "wx/toplevel.h"
30 #include "wx/dcclient.h"
31 #include "wx/dialog.h"
35 #include "wx/control.h"
36 #include "wx/gtk1/private.h"
37 #include "wx/settings.h"
38 #include "wx/evtloop.h"
43 #include <gdk/gdkkeysyms.h>
46 #include "wx/gtk1/win_gtk.h"
48 #include "wx/unix/utilsx11.h"
51 #include <X11/Xatom.h>
53 // ----------------------------------------------------------------------------
55 // ----------------------------------------------------------------------------
57 extern void wxapp_install_idle_handler();
60 // ----------------------------------------------------------------------------
62 // ----------------------------------------------------------------------------
64 extern wxList wxPendingDelete
;
66 extern int g_openDialogs
;
67 extern wxWindowGTK
*g_delayedFocus
;
69 // the frame that is currently active (i.e. its child has focus). It is
70 // used to generate wxActivateEvents
71 static wxTopLevelWindowGTK
*g_activeFrame
= (wxTopLevelWindowGTK
*) NULL
;
72 static wxTopLevelWindowGTK
*g_lastActiveFrame
= (wxTopLevelWindowGTK
*) NULL
;
74 // if we detect that the app has got/lost the focus, we set this variable to
75 // either TRUE or FALSE and an activate event will be sent during the next
76 // OnIdle() call and it is reset to -1: this value means that we shouldn't
77 // send any activate events at all
78 static int g_sendActivateEvent
= -1;
80 //-----------------------------------------------------------------------------
81 // RequestUserAttention related functions
82 //-----------------------------------------------------------------------------
85 static void wxgtk_window_set_urgency_hint (GtkWindow
*win
,
88 wxASSERT_MSG( GTK_WIDGET_REALIZED(win
), wxT("wxgtk_window_set_urgency_hint: GdkWindow not realized") );
89 GdkWindow
*window
= GTK_WIDGET(win
)->window
;
92 wm_hints
= XGetWMHints(GDK_WINDOW_XDISPLAY(window
), GDK_WINDOW_XWINDOW(window
));
95 wm_hints
= XAllocWMHints();
98 wm_hints
->flags
|= XUrgencyHint
;
100 wm_hints
->flags
&= ~XUrgencyHint
;
102 XSetWMHints(GDK_WINDOW_XDISPLAY(window
), GDK_WINDOW_XWINDOW(window
), wm_hints
);
106 static gint
gtk_frame_urgency_timer_callback( wxTopLevelWindowGTK
*win
)
108 wxgtk_window_set_urgency_hint(GTK_WINDOW( win
->m_widget
), FALSE
);
110 win
->m_urgency_hint
= -2;
115 //-----------------------------------------------------------------------------
117 //-----------------------------------------------------------------------------
120 static gint
gtk_frame_focus_in_callback( GtkWidget
*widget
,
121 GdkEvent
*WXUNUSED(event
),
122 wxTopLevelWindowGTK
*win
)
125 wxapp_install_idle_handler();
127 switch ( g_sendActivateEvent
)
130 // we've got focus from outside, synthetize wxActivateEvent
131 g_sendActivateEvent
= 1;
135 // another our window just lost focus, it was already ours before
136 // - don't send any wxActivateEvent
137 g_sendActivateEvent
= -1;
142 g_lastActiveFrame
= g_activeFrame
;
144 // wxPrintf( wxT("active: %s\n"), win->GetTitle().c_str() );
146 // MR: wxRequestUserAttention related block
147 switch( win
->m_urgency_hint
)
150 gtk_timeout_remove( win
->m_urgency_hint
);
151 // no break, fallthrough to remove hint too
153 wxgtk_window_set_urgency_hint(GTK_WINDOW( widget
), FALSE
);
155 win
->m_urgency_hint
= -2;
161 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
);
162 wxActivateEvent
event(wxEVT_ACTIVATE
, true, g_activeFrame
->GetId());
163 event
.SetEventObject(g_activeFrame
);
164 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
170 //-----------------------------------------------------------------------------
172 //-----------------------------------------------------------------------------
175 static gint
gtk_frame_focus_out_callback( GtkWidget
*widget
,
176 GdkEventFocus
*WXUNUSED(gdk_event
),
177 wxTopLevelWindowGTK
*win
)
180 wxapp_install_idle_handler();
182 // if the focus goes out of our app alltogether, OnIdle() will send
183 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
184 // g_sendActivateEvent to -1
185 g_sendActivateEvent
= 0;
187 // wxASSERT_MSG( (g_activeFrame == win), wxT("TLW deactivatd although it wasn't active") );
189 // wxPrintf( wxT("inactive: %s\n"), win->GetTitle().c_str() );
193 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
);
194 wxActivateEvent
event(wxEVT_ACTIVATE
, false, g_activeFrame
->GetId());
195 event
.SetEventObject(g_activeFrame
);
196 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
198 g_activeFrame
= NULL
;
205 //-----------------------------------------------------------------------------
206 // "focus" from m_window
207 //-----------------------------------------------------------------------------
210 static gint
gtk_frame_focus_callback( GtkWidget
*widget
, GtkDirectionType
WXUNUSED(d
), wxWindow
*WXUNUSED(win
) )
213 wxapp_install_idle_handler();
215 // This disables GTK's tab traversal
216 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus" );
221 //-----------------------------------------------------------------------------
223 //-----------------------------------------------------------------------------
226 static void gtk_frame_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxTopLevelWindowGTK
*win
)
229 wxapp_install_idle_handler();
234 if ((win
->m_width
!= alloc
->width
) || (win
->m_height
!= alloc
->height
))
237 wxPrintf( "OnSize from " );
238 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
239 wxPrintf( win->GetClassInfo()->GetClassName() );
240 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
243 (int)alloc->height );
246 win
->m_width
= alloc
->width
;
247 win
->m_height
= alloc
->height
;
248 win
->GtkUpdateSize();
253 //-----------------------------------------------------------------------------
255 //-----------------------------------------------------------------------------
258 static gint
gtk_frame_delete_callback( GtkWidget
*WXUNUSED(widget
), GdkEvent
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
261 wxapp_install_idle_handler();
263 if (win
->IsEnabled() &&
264 (g_openDialogs
== 0 || (win
->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) ||
273 //-----------------------------------------------------------------------------
275 //-----------------------------------------------------------------------------
279 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
282 wxapp_install_idle_handler();
284 if (!win
->m_hasVMT
|| !win
->IsShown())
290 gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y
);
294 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
295 mevent
.SetEventObject( win
);
296 win
->GetEventHandler()->ProcessEvent( mevent
);
302 //-----------------------------------------------------------------------------
303 // "realize" from m_widget
304 //-----------------------------------------------------------------------------
306 // we cannot MWM hints and icons before the widget has been realized,
307 // so we do this directly after realization
311 gtk_frame_realized_callback( GtkWidget
* WXUNUSED(widget
),
312 wxTopLevelWindowGTK
*win
)
315 wxapp_install_idle_handler();
317 // All this is for Motif Window Manager "hints" and is supposed to be
318 // recognized by other WM as well. Not tested.
319 gdk_window_set_decorations(win
->m_widget
->window
,
320 (GdkWMDecoration
)win
->m_gdkDecor
);
321 gdk_window_set_functions(win
->m_widget
->window
,
322 (GdkWMFunction
)win
->m_gdkFunc
);
324 // GTK's shrinking/growing policy
325 if ((win
->m_gdkFunc
& GDK_FUNC_RESIZE
) == 0)
326 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 0, 0, 1);
328 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
331 wxIconBundle iconsOld
= win
->GetIcons();
332 if ( iconsOld
.GetIcon(-1).Ok() )
334 win
->SetIcon( wxNullIcon
);
335 win
->SetIcons( iconsOld
);
340 //-----------------------------------------------------------------------------
341 // "map_event" from m_widget
342 //-----------------------------------------------------------------------------
346 gtk_frame_map_callback( GtkWidget
* WXUNUSED(widget
),
347 GdkEvent
* WXUNUSED(event
),
348 wxTopLevelWindow
*win
)
350 win
->SetIconizeState(false);
354 //-----------------------------------------------------------------------------
355 // "unmap_event" from m_widget
356 //-----------------------------------------------------------------------------
360 gtk_frame_unmap_callback( GtkWidget
* WXUNUSED(widget
),
361 GdkEvent
* WXUNUSED(event
),
362 wxTopLevelWindow
*win
)
364 win
->SetIconizeState(true);
368 //-----------------------------------------------------------------------------
369 // "expose_event" of m_client
370 //-----------------------------------------------------------------------------
373 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
375 GtkPizza
*pizza
= GTK_PIZZA(widget
);
377 gtk_paint_flat_box (win
->m_widget
->style
,
378 pizza
->bin_window
, GTK_STATE_NORMAL
,
389 //-----------------------------------------------------------------------------
390 // "draw" of m_client
391 //-----------------------------------------------------------------------------
394 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
396 GtkPizza
*pizza
= GTK_PIZZA(widget
);
398 gtk_paint_flat_box (win
->m_widget
->style
,
399 pizza
->bin_window
, GTK_STATE_NORMAL
,
408 // ----------------------------------------------------------------------------
409 // wxTopLevelWindowGTK itself
410 // ----------------------------------------------------------------------------
412 //-----------------------------------------------------------------------------
413 // InsertChild for wxTopLevelWindowGTK
414 //-----------------------------------------------------------------------------
416 /* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
417 * C++ has no virtual methods in a constructor. We have to emulate a
418 * virtual function here as wxWidgets requires different ways to insert
419 * a child in container classes. */
421 static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK
* parent
, wxWindow
* child
)
423 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
425 if (!parent
->m_insertInClientArea
)
427 // these are outside the client area
428 wxTopLevelWindowGTK
* frame
= (wxTopLevelWindowGTK
*) parent
;
429 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
430 GTK_WIDGET(child
->m_widget
),
438 // these are inside the client area
439 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
440 GTK_WIDGET(child
->m_widget
),
447 // resize on OnInternalIdle
448 parent
->GtkUpdateSize();
451 // ----------------------------------------------------------------------------
452 // wxTopLevelWindowGTK creation
453 // ----------------------------------------------------------------------------
455 void wxTopLevelWindowGTK::Init()
460 m_mainWidget
= (GtkWidget
*) NULL
;
461 m_insertInClientArea
= true;
462 m_isIconized
= false;
463 m_fsIsShowing
= false;
464 m_themeEnabled
= true;
465 m_gdkDecor
= m_gdkFunc
= 0;
471 bool wxTopLevelWindowGTK::Create( wxWindow
*parent
,
473 const wxString
& title
,
475 const wxSize
& sizeOrig
,
477 const wxString
&name
)
479 // always create a frame of some reasonable, even if arbitrary, size (at
480 // least for MSW compatibility)
481 wxSize size
= sizeOrig
;
482 size
.x
= WidthDefault(size
.x
);
483 size
.y
= HeightDefault(size
.y
);
485 wxTopLevelWindows
.Append( this );
487 m_needParent
= false;
489 if (!PreCreation( parent
, pos
, size
) ||
490 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
492 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
498 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInTopLevelWindow
;
500 // NB: m_widget may be !=NULL if it was created by derived class' Create,
501 // e.g. in wxTaskBarIconAreaGTK
502 if (m_widget
== NULL
)
504 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)
506 m_widget
= gtk_window_new(GTK_WINDOW_DIALOG
);
510 m_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
511 #if GTK_CHECK_VERSION(2,1,0)
512 if (!gtk_check_version(2,1,0))
514 if (style
& wxFRAME_TOOL_WINDOW
)
516 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
517 GDK_WINDOW_TYPE_HINT_UTILITY
);
519 // On some WMs, like KDE, a TOOL_WINDOW will still show
520 // on the taskbar, but on Gnome a TOOL_WINDOW will not.
521 // For consistency between WMs and with Windows, we
522 // should set the NO_TASKBAR flag which will apply
523 // the set_skip_taskbar_hint if it is available,
524 // ensuring no taskbar entry will appear.
525 style
|= wxFRAME_NO_TASKBAR
;
532 wxWindow
*topParent
= wxGetTopLevelParent(m_parent
);
533 if (topParent
&& (((GTK_IS_WINDOW(topParent
->m_widget
)) &&
534 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) ||
535 (style
& wxFRAME_FLOAT_ON_PARENT
)))
537 gtk_window_set_transient_for( GTK_WINDOW(m_widget
),
538 GTK_WINDOW(topParent
->m_widget
) );
542 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), wxGTK_CONV( name
), wxGTK_CONV( name
) );
544 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
545 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
547 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
548 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
550 // m_mainWidget holds the toolbar, the menubar and the client area
551 m_mainWidget
= gtk_pizza_new();
552 gtk_widget_show( m_mainWidget
);
553 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
554 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
556 if (m_miniEdge
== 0) // wxMiniFrame has its own version.
558 // For m_mainWidget themes
559 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
560 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
561 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
562 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
565 // m_wxwindow only represents the client area without toolbar and menubar
566 m_wxwindow
= gtk_pizza_new();
567 gtk_widget_show( m_wxwindow
);
568 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
570 // we donm't allow the frame to get the focus as otherwise
571 // the frame will grab it at arbitrary focus changes
572 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
574 if (m_parent
) m_parent
->AddChild( this );
576 // the user resized the frame by dragging etc.
577 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
578 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
582 if ((m_x
!= -1) || (m_y
!= -1))
583 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
585 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
587 // we cannot set MWM hints and icons before the widget has
588 // been realized, so we do this directly after realization
589 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
590 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
592 // map and unmap for iconized state
593 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
594 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
595 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
596 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
598 // the only way to get the window size is to connect to this event
599 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
600 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
602 // disable native tab traversal
603 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
604 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
607 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
608 GTK_SIGNAL_FUNC(gtk_frame_focus_in_callback
), (gpointer
)this );
609 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
610 GTK_SIGNAL_FUNC(gtk_frame_focus_out_callback
), (gpointer
)this );
613 if ((m_miniEdge
> 0) || (style
& wxSIMPLE_BORDER
) || (style
& wxNO_BORDER
))
620 m_gdkDecor
= (long) GDK_DECOR_BORDER
;
621 m_gdkFunc
= (long) GDK_FUNC_MOVE
;
623 // All this is for Motif Window Manager "hints" and is supposed to be
624 // recognized by other WMs as well.
625 if ((style
& wxCAPTION
) != 0)
627 m_gdkDecor
|= GDK_DECOR_TITLE
;
629 if ((style
& wxCLOSE_BOX
) != 0)
631 m_gdkFunc
|= GDK_FUNC_CLOSE
;
633 if ((style
& wxSYSTEM_MENU
) != 0)
635 m_gdkDecor
|= GDK_DECOR_MENU
;
637 if ((style
& wxMINIMIZE_BOX
) != 0)
639 m_gdkFunc
|= GDK_FUNC_MINIMIZE
;
640 m_gdkDecor
|= GDK_DECOR_MINIMIZE
;
642 if ((style
& wxMAXIMIZE_BOX
) != 0)
644 m_gdkFunc
|= GDK_FUNC_MAXIMIZE
;
645 m_gdkDecor
|= GDK_DECOR_MAXIMIZE
;
647 if ((style
& wxRESIZE_BORDER
) != 0)
649 m_gdkFunc
|= GDK_FUNC_RESIZE
;
650 m_gdkDecor
|= GDK_DECOR_RESIZEH
;
657 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
661 wxASSERT_MSG( false, _T("Window still grabbed"));
665 m_isBeingDeleted
= true;
667 // it may also be GtkScrolledWindow in the case of an MDI child
668 if (GTK_IS_WINDOW(m_widget
))
670 gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL
);
673 if (g_activeFrame
== this)
674 g_activeFrame
= NULL
;
675 if (g_lastActiveFrame
== this)
676 g_lastActiveFrame
= NULL
;
681 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long style
)
683 if (show
== m_fsIsShowing
)
684 return false; // return what?
686 m_fsIsShowing
= show
;
688 wxX11FullScreenMethod method
=
689 wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(),
690 (WXWindow
)GDK_ROOT_WINDOW());
692 #if GTK_CHECK_VERSION(2,2,0)
693 // NB: gtk_window_fullscreen() uses freedesktop.org's WMspec extensions
694 // to switch to fullscreen, which is not always available. We must
695 // check if WM supports the spec and use legacy methods if it
697 if ( (method
== wxX11_FS_WMSPEC
) && !gtk_check_version(2,2,0) )
700 gtk_window_fullscreen( GTK_WINDOW( m_widget
) );
702 gtk_window_unfullscreen( GTK_WINDOW( m_widget
) );
705 #endif // GTK+ >= 2.2.0
707 GdkWindow
*window
= m_widget
->window
;
711 m_fsSaveFlag
= style
;
712 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
713 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
715 int screen_width
,screen_height
;
716 wxDisplaySize( &screen_width
, &screen_height
);
718 gint client_x
, client_y
, root_x
, root_y
;
721 if (method
!= wxX11_FS_WMSPEC
)
723 // don't do it always, Metacity hates it
724 m_fsSaveGdkFunc
= m_gdkFunc
;
725 m_fsSaveGdkDecor
= m_gdkDecor
;
726 m_gdkFunc
= m_gdkDecor
= 0;
727 gdk_window_set_decorations(window
, (GdkWMDecoration
)0);
728 gdk_window_set_functions(window
, (GdkWMFunction
)0);
731 gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
);
732 gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
,
733 &width
, &height
, NULL
);
735 gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
,
736 screen_width
+ 1, screen_height
+ 1);
738 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
739 (WXWindow
)GDK_ROOT_WINDOW(),
740 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
741 show
, &m_fsSaveFrame
, method
);
745 if (method
!= wxX11_FS_WMSPEC
)
747 // don't do it always, Metacity hates it
748 m_gdkFunc
= m_fsSaveGdkFunc
;
749 m_gdkDecor
= m_fsSaveGdkDecor
;
750 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
);
751 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
);
754 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
755 (WXWindow
)GDK_ROOT_WINDOW(),
756 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
757 show
, &m_fsSaveFrame
, method
);
759 SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
,
760 m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
764 // documented behaviour is to show the window if it's still hidden when
765 // showing it full screen
766 if ( show
&& !IsShown() )
772 // ----------------------------------------------------------------------------
773 // overridden wxWindow methods
774 // ----------------------------------------------------------------------------
776 bool wxTopLevelWindowGTK::Show( bool show
)
778 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
780 if (show
&& !m_sizeSet
)
782 /* by calling GtkOnSize here, we don't have to call
783 either after showing the frame, which would entail
784 much ugly flicker or from within the size_allocate
785 handler, because GTK 1.1.X forbids that. */
787 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
791 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
793 return wxWindow::Show( show
);
796 void wxTopLevelWindowGTK::Raise()
801 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
803 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
806 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
808 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
810 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
811 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
821 int old_width
= m_width
;
822 int old_height
= m_height
;
824 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
826 if (x
!= -1) m_x
= x
;
827 if (y
!= -1) m_y
= y
;
834 if (width
!= -1) m_width
= width
;
835 if (height
!= -1) m_height
= height
;
838 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
840 if (width == -1) m_width = 80;
843 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
845 if (height == -1) m_height = 26;
849 int minWidth
= GetMinWidth(),
850 minHeight
= GetMinHeight(),
851 maxWidth
= GetMaxWidth(),
852 maxHeight
= GetMaxHeight();
855 // GPE's window manager doesn't like size hints
856 // at all, esp. when the user has to use the
864 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
865 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
866 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
867 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
869 if ((m_x
!= -1) || (m_y
!= -1))
871 if ((m_x
!= old_x
) || (m_y
!= old_y
))
873 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
877 if ((m_width
!= old_width
) || (m_height
!= old_height
))
879 if (m_widget
->window
)
880 gdk_window_resize( m_widget
->window
, m_width
, m_height
);
882 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
884 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
885 done either directly before the frame is shown or in idle time
886 so that different calls to SetSize() don't lead to flicker. */
893 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height
) const
895 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
897 wxWindow::DoGetClientSize( width
, height
);
901 *height
-= m_miniEdge
*2 + m_miniTitle
;
905 *width
-= m_miniEdge
*2;
909 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height
)
911 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
914 width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0);
917 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
918 int width
, int height
)
920 // due to a bug in gtk, x,y are always 0
925 if (m_resizing
) return;
928 if ( m_wxwindow
== NULL
) return;
933 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
934 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
935 set in wxFrame::Create so it is used to check what kind of frame we
936 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
937 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
938 importantly) m_mainWidget */
940 int minWidth
= GetMinWidth(),
941 minHeight
= GetMinHeight(),
942 maxWidth
= GetMaxWidth(),
943 maxHeight
= GetMaxHeight();
946 // GPE's window manager doesn't like size hints
947 // at all, esp. when the user has to use the
955 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
956 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
957 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
958 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
963 gint flag
= 0; // GDK_HINT_POS;
966 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
967 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
969 geom
.min_width
= minWidth
;
970 geom
.min_height
= minHeight
;
972 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
973 // maxHeight or maxWidth is set, we must set them both, else the
974 // remaining -1 will be taken literally.
976 // I'm certain this also happens elsewhere, and is the probable
977 // cause of other such things as:
978 // Gtk-WARNING **: gtk_widget_size_allocate():
979 // attempt to allocate widget with width 65535 and height 600
980 // but I don't have time to track them all now..
982 // Really we need to encapulate all this height/width business and
983 // stop any old method from ripping at the members directly and
984 // scattering -1's without regard for who might resolve them later.
986 geom
.max_width
= ( maxHeight
== -1 ) ? maxWidth
987 : ( maxWidth
== -1 ) ? wxGetDisplaySize().GetWidth()
990 geom
.max_height
= ( maxWidth
== -1 ) ? maxHeight
// ( == -1 here )
991 : ( maxHeight
== -1 ) ? wxGetDisplaySize().GetHeight()
994 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
997 (GdkWindowHints
) flag
);
999 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
1000 * menubar, the toolbar and the client area, which is represented by
1002 * this hurts in the eye, but I don't want to call SetSize()
1003 * because I don't want to call any non-native functions here. */
1005 int client_x
= m_miniEdge
;
1006 int client_y
= m_miniEdge
+ m_miniTitle
;
1007 int client_w
= m_width
- 2*m_miniEdge
;
1008 int client_h
= m_height
- 2*m_miniEdge
- m_miniTitle
;
1010 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
1012 client_x
, client_y
, client_w
, client_h
);
1016 // If there is no m_mainWidget between m_widget and m_wxwindow there
1017 // is no need to set the size or position of m_wxwindow.
1022 // send size event to frame
1023 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1024 event
.SetEventObject( this );
1025 GetEventHandler()->ProcessEvent( event
);
1030 void wxTopLevelWindowGTK::OnInternalIdle()
1032 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
1034 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
1036 // we'll come back later
1038 wxapp_install_idle_handler();
1042 // set the focus if not done yet and if we can already do it
1043 if ( GTK_WIDGET_REALIZED(m_wxwindow
) )
1045 if ( g_delayedFocus
&&
1046 wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this )
1048 wxLogTrace(_T("focus"),
1049 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
1050 g_delayedFocus
->GetClassInfo()->GetClassName(),
1051 g_delayedFocus
->GetLabel().c_str());
1053 g_delayedFocus
->SetFocus();
1054 g_delayedFocus
= NULL
;
1058 wxWindow::OnInternalIdle();
1060 // Synthetize activate events.
1061 if ( g_sendActivateEvent
!= -1 )
1063 bool activate
= g_sendActivateEvent
!= 0;
1065 // if (!activate) wxPrintf( wxT("de") );
1066 // wxPrintf( wxT("activate\n") );
1069 g_sendActivateEvent
= -1;
1071 wxTheApp
->SetActive(activate
, (wxWindow
*)g_lastActiveFrame
);
1075 // ----------------------------------------------------------------------------
1077 // ----------------------------------------------------------------------------
1079 void wxTopLevelWindowGTK::SetTitle( const wxString
&title
)
1081 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1083 if ( title
== m_title
)
1088 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
1091 void wxTopLevelWindowGTK::SetIcon( const wxIcon
&icon
)
1093 SetIcons( wxIconBundle( icon
) );
1096 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle
&icons
)
1098 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1100 wxTopLevelWindowBase::SetIcons( icons
);
1102 GdkWindow
* window
= m_widget
->window
;
1106 wxIcon icon
= icons
.GetIcon(-1);
1109 wxMask
*mask
= icon
.GetMask();
1110 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1111 if (mask
) bm
= mask
->GetBitmap();
1113 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
1116 wxSetIconsX11( (WXDisplay
*)GDK_WINDOW_XDISPLAY( window
),
1117 (WXWindow
)GDK_WINDOW_XWINDOW( window
), icons
);
1120 // ----------------------------------------------------------------------------
1121 // frame state: maximized/iconized/normal
1122 // ----------------------------------------------------------------------------
1124 void wxTopLevelWindowGTK::Maximize(bool maximize
)
1126 wxFAIL_MSG( _T("not implemented") );
1129 bool wxTopLevelWindowGTK::IsMaximized() const
1131 // wxFAIL_MSG( _T("not implemented") );
1133 // This is an approximation
1137 void wxTopLevelWindowGTK::Restore()
1139 wxFAIL_MSG( _T("not implemented") );
1142 void wxTopLevelWindowGTK::Iconize( bool iconize
)
1146 GdkWindow
*window
= m_widget
->window
;
1148 // you should do it later, for example from OnCreate() handler
1149 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
1151 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
1152 GDK_WINDOW_XWINDOW( window
),
1153 DefaultScreen( GDK_DISPLAY() ) );
1157 bool wxTopLevelWindowGTK::IsIconized() const
1159 return m_isIconized
;
1162 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
)
1164 if ( iconize
!= m_isIconized
)
1166 m_isIconized
= iconize
;
1167 (void)SendIconizeEvent(iconize
);
1171 void wxTopLevelWindowGTK::AddGrab()
1176 gtk_grab_add( m_widget
);
1177 wxEventLoop().Run();
1178 gtk_grab_remove( m_widget
);
1182 void wxTopLevelWindowGTK::RemoveGrab()
1193 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
)
1197 if (region
.IsEmpty())
1199 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
1203 wxBitmap bmp
= region
.ConvertToBitmap();
1204 bmp
.SetMask(new wxMask(bmp
, *wxBLACK
));
1205 GdkBitmap
* mask
= bmp
.GetMask()->GetBitmap();
1206 gdk_window_shape_combine_mask(window
, mask
, 0, 0);
1214 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
)
1216 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), false,
1217 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1219 GdkWindow
*window
= NULL
;
1222 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
1223 do_shape_combine_region(window
, region
);
1225 window
= m_widget
->window
;
1226 return do_shape_combine_region(window
, region
);
1229 bool wxTopLevelWindowGTK::IsActive()
1231 return (this == (wxTopLevelWindowGTK
*)g_activeFrame
);
1234 void wxTopLevelWindowGTK::RequestUserAttention(int flags
)
1236 bool new_hint_value
= false;
1238 // FIXME: This is a workaround to focus handling problem
1239 // If RequestUserAttention is called for example right after a wxSleep, OnInternalIdle hasn't
1240 // yet been processed, and the internal focus system is not up to date yet.
1241 // wxYieldIfNeeded ensures the processing of it, but can have unwanted side effects - MR
1242 ::wxYieldIfNeeded();
1244 if(m_urgency_hint
>= 0)
1245 gtk_timeout_remove(m_urgency_hint
);
1247 m_urgency_hint
= -2;
1249 if( GTK_WIDGET_REALIZED(m_widget
) && !IsActive() )
1251 new_hint_value
= true;
1253 if (flags
& wxUSER_ATTENTION_INFO
)
1255 m_urgency_hint
= gtk_timeout_add(5000, (GtkFunction
)gtk_frame_urgency_timer_callback
, this);
1257 m_urgency_hint
= -1;
1261 wxgtk_window_set_urgency_hint(GTK_WINDOW( m_widget
), new_hint_value
);
1264 void wxTopLevelWindowGTK::SetWindowStyleFlag( long style
)
1266 // Process wxWindow styles. This also updates the internal variable
1267 // Therefore m_windowStyle bits carry now the _new_ style values
1268 wxWindow::SetWindowStyleFlag(style
);