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"
33 #include "wx/settings.h"
34 #include "wx/control.h"
37 #include "wx/gtk1/private.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 int g_openDialogs
;
65 extern wxWindowGTK
*g_delayedFocus
;
67 // the frame that is currently active (i.e. its child has focus). It is
68 // used to generate wxActivateEvents
69 static wxTopLevelWindowGTK
*g_activeFrame
= (wxTopLevelWindowGTK
*) NULL
;
70 static wxTopLevelWindowGTK
*g_lastActiveFrame
= (wxTopLevelWindowGTK
*) NULL
;
72 // if we detect that the app has got/lost the focus, we set this variable to
73 // either TRUE or FALSE and an activate event will be sent during the next
74 // OnIdle() call and it is reset to -1: this value means that we shouldn't
75 // send any activate events at all
76 static int g_sendActivateEvent
= -1;
78 //-----------------------------------------------------------------------------
79 // RequestUserAttention related functions
80 //-----------------------------------------------------------------------------
83 static void wxgtk_window_set_urgency_hint (GtkWindow
*win
,
86 wxASSERT_MSG( GTK_WIDGET_REALIZED(win
), wxT("wxgtk_window_set_urgency_hint: GdkWindow not realized") );
87 GdkWindow
*window
= GTK_WIDGET(win
)->window
;
90 wm_hints
= XGetWMHints(GDK_WINDOW_XDISPLAY(window
), GDK_WINDOW_XWINDOW(window
));
93 wm_hints
= XAllocWMHints();
96 wm_hints
->flags
|= XUrgencyHint
;
98 wm_hints
->flags
&= ~XUrgencyHint
;
100 XSetWMHints(GDK_WINDOW_XDISPLAY(window
), GDK_WINDOW_XWINDOW(window
), wm_hints
);
104 static gint
gtk_frame_urgency_timer_callback( wxTopLevelWindowGTK
*win
)
106 wxgtk_window_set_urgency_hint(GTK_WINDOW( win
->m_widget
), FALSE
);
108 win
->m_urgency_hint
= -2;
113 //-----------------------------------------------------------------------------
115 //-----------------------------------------------------------------------------
118 static gint
gtk_frame_focus_in_callback( GtkWidget
*widget
,
119 GdkEvent
*WXUNUSED(event
),
120 wxTopLevelWindowGTK
*win
)
123 wxapp_install_idle_handler();
125 switch ( g_sendActivateEvent
)
128 // we've got focus from outside, synthetize wxActivateEvent
129 g_sendActivateEvent
= 1;
133 // another our window just lost focus, it was already ours before
134 // - don't send any wxActivateEvent
135 g_sendActivateEvent
= -1;
140 g_lastActiveFrame
= g_activeFrame
;
142 // wxPrintf( wxT("active: %s\n"), win->GetTitle().c_str() );
144 // MR: wxRequestUserAttention related block
145 switch( win
->m_urgency_hint
)
148 gtk_timeout_remove( win
->m_urgency_hint
);
149 // no break, fallthrough to remove hint too
151 wxgtk_window_set_urgency_hint(GTK_WINDOW( widget
), FALSE
);
153 win
->m_urgency_hint
= -2;
159 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
);
160 wxActivateEvent
event(wxEVT_ACTIVATE
, true, g_activeFrame
->GetId());
161 event
.SetEventObject(g_activeFrame
);
162 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
168 //-----------------------------------------------------------------------------
170 //-----------------------------------------------------------------------------
173 static gint
gtk_frame_focus_out_callback( GtkWidget
*widget
,
174 GdkEventFocus
*WXUNUSED(gdk_event
),
175 wxTopLevelWindowGTK
*win
)
178 wxapp_install_idle_handler();
180 // if the focus goes out of our app alltogether, OnIdle() will send
181 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
182 // g_sendActivateEvent to -1
183 g_sendActivateEvent
= 0;
185 // wxASSERT_MSG( (g_activeFrame == win), wxT("TLW deactivatd although it wasn't active") );
187 // wxPrintf( wxT("inactive: %s\n"), win->GetTitle().c_str() );
191 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
);
192 wxActivateEvent
event(wxEVT_ACTIVATE
, false, g_activeFrame
->GetId());
193 event
.SetEventObject(g_activeFrame
);
194 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
196 g_activeFrame
= NULL
;
203 //-----------------------------------------------------------------------------
204 // "focus" from m_window
205 //-----------------------------------------------------------------------------
208 static gint
gtk_frame_focus_callback( GtkWidget
*widget
, GtkDirectionType
WXUNUSED(d
), wxWindow
*WXUNUSED(win
) )
211 wxapp_install_idle_handler();
213 // This disables GTK's tab traversal
214 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus" );
219 //-----------------------------------------------------------------------------
221 //-----------------------------------------------------------------------------
224 static void gtk_frame_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxTopLevelWindowGTK
*win
)
227 wxapp_install_idle_handler();
232 if ((win
->m_width
!= alloc
->width
) || (win
->m_height
!= alloc
->height
))
235 wxPrintf( "OnSize from " );
236 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
237 wxPrintf( win->GetClassInfo()->GetClassName() );
238 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
241 (int)alloc->height );
244 win
->m_width
= alloc
->width
;
245 win
->m_height
= alloc
->height
;
246 win
->GtkUpdateSize();
251 //-----------------------------------------------------------------------------
253 //-----------------------------------------------------------------------------
256 static gint
gtk_frame_delete_callback( GtkWidget
*WXUNUSED(widget
), GdkEvent
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
259 wxapp_install_idle_handler();
261 if (win
->IsEnabled() &&
262 (g_openDialogs
== 0 || (win
->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) ||
271 //-----------------------------------------------------------------------------
273 //-----------------------------------------------------------------------------
277 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
280 wxapp_install_idle_handler();
282 if (!win
->m_hasVMT
|| !win
->IsShown())
288 gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y
);
292 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
293 mevent
.SetEventObject( win
);
294 win
->GetEventHandler()->ProcessEvent( mevent
);
300 //-----------------------------------------------------------------------------
301 // "realize" from m_widget
302 //-----------------------------------------------------------------------------
304 // we cannot MWM hints and icons before the widget has been realized,
305 // so we do this directly after realization
309 gtk_frame_realized_callback( GtkWidget
* WXUNUSED(widget
),
310 wxTopLevelWindowGTK
*win
)
313 wxapp_install_idle_handler();
315 // All this is for Motif Window Manager "hints" and is supposed to be
316 // recognized by other WM as well. Not tested.
317 gdk_window_set_decorations(win
->m_widget
->window
,
318 (GdkWMDecoration
)win
->m_gdkDecor
);
319 gdk_window_set_functions(win
->m_widget
->window
,
320 (GdkWMFunction
)win
->m_gdkFunc
);
322 // GTK's shrinking/growing policy
323 if ((win
->m_gdkFunc
& GDK_FUNC_RESIZE
) == 0)
324 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 0, 0, 1);
326 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
329 wxIconBundle iconsOld
= win
->GetIcons();
330 if ( iconsOld
.GetIcon(-1).Ok() )
332 win
->SetIcon( wxNullIcon
);
333 win
->SetIcons( iconsOld
);
338 //-----------------------------------------------------------------------------
339 // "map_event" from m_widget
340 //-----------------------------------------------------------------------------
344 gtk_frame_map_callback( GtkWidget
* WXUNUSED(widget
),
345 GdkEvent
* WXUNUSED(event
),
346 wxTopLevelWindow
*win
)
348 win
->SetIconizeState(false);
352 //-----------------------------------------------------------------------------
353 // "unmap_event" from m_widget
354 //-----------------------------------------------------------------------------
358 gtk_frame_unmap_callback( GtkWidget
* WXUNUSED(widget
),
359 GdkEvent
* WXUNUSED(event
),
360 wxTopLevelWindow
*win
)
362 win
->SetIconizeState(true);
366 //-----------------------------------------------------------------------------
367 // "expose_event" of m_client
368 //-----------------------------------------------------------------------------
371 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
373 GtkPizza
*pizza
= GTK_PIZZA(widget
);
375 gtk_paint_flat_box (win
->m_widget
->style
,
376 pizza
->bin_window
, GTK_STATE_NORMAL
,
387 //-----------------------------------------------------------------------------
388 // "draw" of m_client
389 //-----------------------------------------------------------------------------
392 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
394 GtkPizza
*pizza
= GTK_PIZZA(widget
);
396 gtk_paint_flat_box (win
->m_widget
->style
,
397 pizza
->bin_window
, GTK_STATE_NORMAL
,
406 // ----------------------------------------------------------------------------
407 // wxTopLevelWindowGTK itself
408 // ----------------------------------------------------------------------------
410 //-----------------------------------------------------------------------------
411 // InsertChild for wxTopLevelWindowGTK
412 //-----------------------------------------------------------------------------
414 /* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
415 * C++ has no virtual methods in a constructor. We have to emulate a
416 * virtual function here as wxWidgets requires different ways to insert
417 * a child in container classes. */
419 static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK
* parent
, wxWindow
* child
)
421 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
423 if (!parent
->m_insertInClientArea
)
425 // these are outside the client area
426 wxTopLevelWindowGTK
* frame
= (wxTopLevelWindowGTK
*) parent
;
427 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
428 GTK_WIDGET(child
->m_widget
),
436 // these are inside the client area
437 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
438 GTK_WIDGET(child
->m_widget
),
445 // resize on OnInternalIdle
446 parent
->GtkUpdateSize();
449 // ----------------------------------------------------------------------------
450 // wxTopLevelWindowGTK creation
451 // ----------------------------------------------------------------------------
453 void wxTopLevelWindowGTK::Init()
458 m_mainWidget
= (GtkWidget
*) NULL
;
459 m_insertInClientArea
= true;
460 m_isIconized
= false;
461 m_fsIsShowing
= false;
462 m_themeEnabled
= true;
463 m_gdkDecor
= m_gdkFunc
= 0;
469 bool wxTopLevelWindowGTK::Create( wxWindow
*parent
,
471 const wxString
& title
,
473 const wxSize
& sizeOrig
,
475 const wxString
&name
)
477 // always create a frame of some reasonable, even if arbitrary, size (at
478 // least for MSW compatibility)
479 wxSize size
= sizeOrig
;
480 size
.x
= WidthDefault(size
.x
);
481 size
.y
= HeightDefault(size
.y
);
483 wxTopLevelWindows
.Append( this );
485 m_needParent
= false;
487 if (!PreCreation( parent
, pos
, size
) ||
488 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
490 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
496 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInTopLevelWindow
;
498 // NB: m_widget may be !=NULL if it was created by derived class' Create,
499 // e.g. in wxTaskBarIconAreaGTK
500 if (m_widget
== NULL
)
502 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)
504 m_widget
= gtk_window_new(GTK_WINDOW_DIALOG
);
508 m_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
509 #if GTK_CHECK_VERSION(2,1,0)
510 if (!gtk_check_version(2,1,0))
512 if (style
& wxFRAME_TOOL_WINDOW
)
514 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
515 GDK_WINDOW_TYPE_HINT_UTILITY
);
517 // On some WMs, like KDE, a TOOL_WINDOW will still show
518 // on the taskbar, but on Gnome a TOOL_WINDOW will not.
519 // For consistency between WMs and with Windows, we
520 // should set the NO_TASKBAR flag which will apply
521 // the set_skip_taskbar_hint if it is available,
522 // ensuring no taskbar entry will appear.
523 style
|= wxFRAME_NO_TASKBAR
;
530 wxWindow
*topParent
= wxGetTopLevelParent(m_parent
);
531 if (topParent
&& (((GTK_IS_WINDOW(topParent
->m_widget
)) &&
532 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) ||
533 (style
& wxFRAME_FLOAT_ON_PARENT
)))
535 gtk_window_set_transient_for( GTK_WINDOW(m_widget
),
536 GTK_WINDOW(topParent
->m_widget
) );
540 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), wxGTK_CONV( name
), wxGTK_CONV( name
) );
542 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
543 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
545 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
546 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
548 // m_mainWidget holds the toolbar, the menubar and the client area
549 m_mainWidget
= gtk_pizza_new();
550 gtk_widget_show( m_mainWidget
);
551 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
552 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
554 if (m_miniEdge
== 0) // wxMiniFrame has its own version.
556 // For m_mainWidget themes
557 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
558 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
559 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
560 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
563 // m_wxwindow only represents the client area without toolbar and menubar
564 m_wxwindow
= gtk_pizza_new();
565 gtk_widget_show( m_wxwindow
);
566 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
568 // we donm't allow the frame to get the focus as otherwise
569 // the frame will grab it at arbitrary focus changes
570 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
572 if (m_parent
) m_parent
->AddChild( this );
574 // the user resized the frame by dragging etc.
575 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
576 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
580 if ((m_x
!= -1) || (m_y
!= -1))
581 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
583 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
585 // we cannot set MWM hints and icons before the widget has
586 // been realized, so we do this directly after realization
587 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
588 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
590 // map and unmap for iconized state
591 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
592 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
593 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
594 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
596 // the only way to get the window size is to connect to this event
597 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
598 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
600 // disable native tab traversal
601 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
602 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
605 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
606 GTK_SIGNAL_FUNC(gtk_frame_focus_in_callback
), (gpointer
)this );
607 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
608 GTK_SIGNAL_FUNC(gtk_frame_focus_out_callback
), (gpointer
)this );
611 if ((m_miniEdge
> 0) || (style
& wxSIMPLE_BORDER
) || (style
& wxNO_BORDER
))
618 m_gdkDecor
= (long) GDK_DECOR_BORDER
;
619 m_gdkFunc
= (long) GDK_FUNC_MOVE
;
621 // All this is for Motif Window Manager "hints" and is supposed to be
622 // recognized by other WMs as well.
623 if ((style
& wxCAPTION
) != 0)
625 m_gdkDecor
|= GDK_DECOR_TITLE
;
627 if ((style
& wxCLOSE_BOX
) != 0)
629 m_gdkFunc
|= GDK_FUNC_CLOSE
;
631 if ((style
& wxSYSTEM_MENU
) != 0)
633 m_gdkDecor
|= GDK_DECOR_MENU
;
635 if ((style
& wxMINIMIZE_BOX
) != 0)
637 m_gdkFunc
|= GDK_FUNC_MINIMIZE
;
638 m_gdkDecor
|= GDK_DECOR_MINIMIZE
;
640 if ((style
& wxMAXIMIZE_BOX
) != 0)
642 m_gdkFunc
|= GDK_FUNC_MAXIMIZE
;
643 m_gdkDecor
|= GDK_DECOR_MAXIMIZE
;
645 if ((style
& wxRESIZE_BORDER
) != 0)
647 m_gdkFunc
|= GDK_FUNC_RESIZE
;
648 m_gdkDecor
|= GDK_DECOR_RESIZEH
;
655 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
659 wxASSERT_MSG( false, _T("Window still grabbed"));
663 m_isBeingDeleted
= true;
665 // it may also be GtkScrolledWindow in the case of an MDI child
666 if (GTK_IS_WINDOW(m_widget
))
668 gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL
);
671 if (g_activeFrame
== this)
672 g_activeFrame
= NULL
;
673 if (g_lastActiveFrame
== this)
674 g_lastActiveFrame
= NULL
;
679 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long style
)
681 if (show
== m_fsIsShowing
)
682 return false; // return what?
684 m_fsIsShowing
= show
;
686 wxX11FullScreenMethod method
=
687 wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(),
688 (WXWindow
)GDK_ROOT_WINDOW());
690 #if GTK_CHECK_VERSION(2,2,0)
691 // NB: gtk_window_fullscreen() uses freedesktop.org's WMspec extensions
692 // to switch to fullscreen, which is not always available. We must
693 // check if WM supports the spec and use legacy methods if it
695 if ( (method
== wxX11_FS_WMSPEC
) && !gtk_check_version(2,2,0) )
698 gtk_window_fullscreen( GTK_WINDOW( m_widget
) );
700 gtk_window_unfullscreen( GTK_WINDOW( m_widget
) );
703 #endif // GTK+ >= 2.2.0
705 GdkWindow
*window
= m_widget
->window
;
709 m_fsSaveFlag
= style
;
710 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
711 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
713 int screen_width
,screen_height
;
714 wxDisplaySize( &screen_width
, &screen_height
);
716 gint client_x
, client_y
, root_x
, root_y
;
719 if (method
!= wxX11_FS_WMSPEC
)
721 // don't do it always, Metacity hates it
722 m_fsSaveGdkFunc
= m_gdkFunc
;
723 m_fsSaveGdkDecor
= m_gdkDecor
;
724 m_gdkFunc
= m_gdkDecor
= 0;
725 gdk_window_set_decorations(window
, (GdkWMDecoration
)0);
726 gdk_window_set_functions(window
, (GdkWMFunction
)0);
729 gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
);
730 gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
,
731 &width
, &height
, NULL
);
733 gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
,
734 screen_width
+ 1, screen_height
+ 1);
736 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
737 (WXWindow
)GDK_ROOT_WINDOW(),
738 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
739 show
, &m_fsSaveFrame
, method
);
743 if (method
!= wxX11_FS_WMSPEC
)
745 // don't do it always, Metacity hates it
746 m_gdkFunc
= m_fsSaveGdkFunc
;
747 m_gdkDecor
= m_fsSaveGdkDecor
;
748 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
);
749 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
);
752 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
753 (WXWindow
)GDK_ROOT_WINDOW(),
754 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
755 show
, &m_fsSaveFrame
, method
);
757 SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
,
758 m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
762 // documented behaviour is to show the window if it's still hidden when
763 // showing it full screen
764 if ( show
&& !IsShown() )
770 // ----------------------------------------------------------------------------
771 // overridden wxWindow methods
772 // ----------------------------------------------------------------------------
774 bool wxTopLevelWindowGTK::Show( bool show
)
776 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
778 if (show
&& !m_sizeSet
)
780 /* by calling GtkOnSize here, we don't have to call
781 either after showing the frame, which would entail
782 much ugly flicker or from within the size_allocate
783 handler, because GTK 1.1.X forbids that. */
785 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
789 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
791 return wxWindow::Show( show
);
794 void wxTopLevelWindowGTK::Raise()
799 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
801 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
804 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
806 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
808 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
809 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
819 int old_width
= m_width
;
820 int old_height
= m_height
;
822 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
824 if (x
!= -1) m_x
= x
;
825 if (y
!= -1) m_y
= y
;
832 if (width
!= -1) m_width
= width
;
833 if (height
!= -1) m_height
= height
;
836 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
838 if (width == -1) m_width = 80;
841 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
843 if (height == -1) m_height = 26;
847 int minWidth
= GetMinWidth(),
848 minHeight
= GetMinHeight(),
849 maxWidth
= GetMaxWidth(),
850 maxHeight
= GetMaxHeight();
853 // GPE's window manager doesn't like size hints
854 // at all, esp. when the user has to use the
862 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
863 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
864 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
865 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
867 if ((m_x
!= -1) || (m_y
!= -1))
869 if ((m_x
!= old_x
) || (m_y
!= old_y
))
871 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
875 if ((m_width
!= old_width
) || (m_height
!= old_height
))
877 if (m_widget
->window
)
878 gdk_window_resize( m_widget
->window
, m_width
, m_height
);
880 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
882 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
883 done either directly before the frame is shown or in idle time
884 so that different calls to SetSize() don't lead to flicker. */
891 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height
) const
893 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
895 wxWindow::DoGetClientSize( width
, height
);
899 *height
-= m_miniEdge
*2 + m_miniTitle
;
903 *width
-= m_miniEdge
*2;
907 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height
)
909 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
912 width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0);
915 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
916 int width
, int height
)
918 // due to a bug in gtk, x,y are always 0
923 if (m_resizing
) return;
926 if ( m_wxwindow
== NULL
) return;
931 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
932 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
933 set in wxFrame::Create so it is used to check what kind of frame we
934 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
935 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
936 importantly) m_mainWidget */
938 int minWidth
= GetMinWidth(),
939 minHeight
= GetMinHeight(),
940 maxWidth
= GetMaxWidth(),
941 maxHeight
= GetMaxHeight();
944 // GPE's window manager doesn't like size hints
945 // at all, esp. when the user has to use the
953 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
954 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
955 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
956 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
961 gint flag
= 0; // GDK_HINT_POS;
964 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
965 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
967 geom
.min_width
= minWidth
;
968 geom
.min_height
= minHeight
;
970 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
971 // maxHeight or maxWidth is set, we must set them both, else the
972 // remaining -1 will be taken literally.
974 // I'm certain this also happens elsewhere, and is the probable
975 // cause of other such things as:
976 // Gtk-WARNING **: gtk_widget_size_allocate():
977 // attempt to allocate widget with width 65535 and height 600
978 // but I don't have time to track them all now..
980 // Really we need to encapulate all this height/width business and
981 // stop any old method from ripping at the members directly and
982 // scattering -1's without regard for who might resolve them later.
984 geom
.max_width
= ( maxHeight
== -1 ) ? maxWidth
985 : ( maxWidth
== -1 ) ? wxGetDisplaySize().GetWidth()
988 geom
.max_height
= ( maxWidth
== -1 ) ? maxHeight
// ( == -1 here )
989 : ( maxHeight
== -1 ) ? wxGetDisplaySize().GetHeight()
992 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
995 (GdkWindowHints
) flag
);
997 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
998 * menubar, the toolbar and the client area, which is represented by
1000 * this hurts in the eye, but I don't want to call SetSize()
1001 * because I don't want to call any non-native functions here. */
1003 int client_x
= m_miniEdge
;
1004 int client_y
= m_miniEdge
+ m_miniTitle
;
1005 int client_w
= m_width
- 2*m_miniEdge
;
1006 int client_h
= m_height
- 2*m_miniEdge
- m_miniTitle
;
1008 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
1010 client_x
, client_y
, client_w
, client_h
);
1014 // If there is no m_mainWidget between m_widget and m_wxwindow there
1015 // is no need to set the size or position of m_wxwindow.
1020 // send size event to frame
1021 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1022 event
.SetEventObject( this );
1023 GetEventHandler()->ProcessEvent( event
);
1028 void wxTopLevelWindowGTK::OnInternalIdle()
1030 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
1032 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
1034 // we'll come back later
1036 wxapp_install_idle_handler();
1040 // set the focus if not done yet and if we can already do it
1041 if ( GTK_WIDGET_REALIZED(m_wxwindow
) )
1043 if ( g_delayedFocus
&&
1044 wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this )
1046 wxLogTrace(_T("focus"),
1047 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
1048 g_delayedFocus
->GetClassInfo()->GetClassName(),
1049 g_delayedFocus
->GetLabel().c_str());
1051 g_delayedFocus
->SetFocus();
1052 g_delayedFocus
= NULL
;
1056 wxWindow::OnInternalIdle();
1058 // Synthetize activate events.
1059 if ( g_sendActivateEvent
!= -1 )
1061 bool activate
= g_sendActivateEvent
!= 0;
1063 // if (!activate) wxPrintf( wxT("de") );
1064 // wxPrintf( wxT("activate\n") );
1067 g_sendActivateEvent
= -1;
1069 wxTheApp
->SetActive(activate
, (wxWindow
*)g_lastActiveFrame
);
1073 // ----------------------------------------------------------------------------
1075 // ----------------------------------------------------------------------------
1077 void wxTopLevelWindowGTK::SetTitle( const wxString
&title
)
1079 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1081 if ( title
== m_title
)
1086 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
1089 void wxTopLevelWindowGTK::SetIcon( const wxIcon
&icon
)
1091 SetIcons( wxIconBundle( icon
) );
1094 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle
&icons
)
1096 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1098 wxTopLevelWindowBase::SetIcons( icons
);
1100 GdkWindow
* window
= m_widget
->window
;
1104 wxIcon icon
= icons
.GetIcon(-1);
1107 wxMask
*mask
= icon
.GetMask();
1108 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1109 if (mask
) bm
= mask
->GetBitmap();
1111 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
1114 wxSetIconsX11( (WXDisplay
*)GDK_WINDOW_XDISPLAY( window
),
1115 (WXWindow
)GDK_WINDOW_XWINDOW( window
), icons
);
1118 // ----------------------------------------------------------------------------
1119 // frame state: maximized/iconized/normal
1120 // ----------------------------------------------------------------------------
1122 void wxTopLevelWindowGTK::Maximize(bool maximize
)
1124 wxFAIL_MSG( _T("not implemented") );
1127 bool wxTopLevelWindowGTK::IsMaximized() const
1129 // wxFAIL_MSG( _T("not implemented") );
1131 // This is an approximation
1135 void wxTopLevelWindowGTK::Restore()
1137 wxFAIL_MSG( _T("not implemented") );
1140 void wxTopLevelWindowGTK::Iconize( bool iconize
)
1144 GdkWindow
*window
= m_widget
->window
;
1146 // you should do it later, for example from OnCreate() handler
1147 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
1149 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
1150 GDK_WINDOW_XWINDOW( window
),
1151 DefaultScreen( GDK_DISPLAY() ) );
1155 bool wxTopLevelWindowGTK::IsIconized() const
1157 return m_isIconized
;
1160 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
)
1162 if ( iconize
!= m_isIconized
)
1164 m_isIconized
= iconize
;
1165 (void)SendIconizeEvent(iconize
);
1169 void wxTopLevelWindowGTK::AddGrab()
1174 gtk_grab_add( m_widget
);
1175 wxEventLoop().Run();
1176 gtk_grab_remove( m_widget
);
1180 void wxTopLevelWindowGTK::RemoveGrab()
1191 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
)
1195 if (region
.IsEmpty())
1197 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
1201 wxBitmap bmp
= region
.ConvertToBitmap();
1202 bmp
.SetMask(new wxMask(bmp
, *wxBLACK
));
1203 GdkBitmap
* mask
= bmp
.GetMask()->GetBitmap();
1204 gdk_window_shape_combine_mask(window
, mask
, 0, 0);
1212 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
)
1214 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), false,
1215 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1217 GdkWindow
*window
= NULL
;
1220 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
1221 do_shape_combine_region(window
, region
);
1223 window
= m_widget
->window
;
1224 return do_shape_combine_region(window
, region
);
1227 bool wxTopLevelWindowGTK::IsActive()
1229 return (this == (wxTopLevelWindowGTK
*)g_activeFrame
);
1232 void wxTopLevelWindowGTK::RequestUserAttention(int flags
)
1234 bool new_hint_value
= false;
1236 // FIXME: This is a workaround to focus handling problem
1237 // If RequestUserAttention is called for example right after a wxSleep, OnInternalIdle hasn't
1238 // yet been processed, and the internal focus system is not up to date yet.
1239 // wxYieldIfNeeded ensures the processing of it, but can have unwanted side effects - MR
1240 ::wxYieldIfNeeded();
1242 if(m_urgency_hint
>= 0)
1243 gtk_timeout_remove(m_urgency_hint
);
1245 m_urgency_hint
= -2;
1247 if( GTK_WIDGET_REALIZED(m_widget
) && !IsActive() )
1249 new_hint_value
= true;
1251 if (flags
& wxUSER_ATTENTION_INFO
)
1253 m_urgency_hint
= gtk_timeout_add(5000, (GtkFunction
)gtk_frame_urgency_timer_callback
, this);
1255 m_urgency_hint
= -1;
1259 wxgtk_window_set_urgency_hint(GTK_WINDOW( m_widget
), new_hint_value
);
1262 void wxTopLevelWindowGTK::SetWindowStyleFlag( long style
)
1264 // Process wxWindow styles. This also updates the internal variable
1265 // Therefore m_windowStyle bits carry now the _new_ style values
1266 wxWindow::SetWindowStyleFlag(style
);