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"
27 #include "wx/dialog.h"
28 #include "wx/control.h"
30 #include "wx/dcclient.h"
31 #include "wx/gtk1/private.h"
33 #include "wx/settings.h"
34 #include "wx/evtloop.h"
39 #include <gdk/gdkkeysyms.h>
42 #include "wx/gtk1/win_gtk.h"
44 #include "wx/unix/utilsx11.h"
47 #include <X11/Xatom.h>
49 // ----------------------------------------------------------------------------
51 // ----------------------------------------------------------------------------
53 extern void wxapp_install_idle_handler();
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
60 extern wxList wxPendingDelete
;
62 extern int g_openDialogs
;
63 extern wxWindowGTK
*g_delayedFocus
;
65 // the frame that is currently active (i.e. its child has focus). It is
66 // used to generate wxActivateEvents
67 static wxTopLevelWindowGTK
*g_activeFrame
= (wxTopLevelWindowGTK
*) NULL
;
68 static wxTopLevelWindowGTK
*g_lastActiveFrame
= (wxTopLevelWindowGTK
*) NULL
;
70 // if we detect that the app has got/lost the focus, we set this variable to
71 // either TRUE or FALSE and an activate event will be sent during the next
72 // OnIdle() call and it is reset to -1: this value means that we shouldn't
73 // send any activate events at all
74 static int g_sendActivateEvent
= -1;
76 //-----------------------------------------------------------------------------
77 // RequestUserAttention related functions
78 //-----------------------------------------------------------------------------
81 static void wxgtk_window_set_urgency_hint (GtkWindow
*win
,
84 wxASSERT_MSG( GTK_WIDGET_REALIZED(win
), wxT("wxgtk_window_set_urgency_hint: GdkWindow not realized") );
85 GdkWindow
*window
= GTK_WIDGET(win
)->window
;
88 wm_hints
= XGetWMHints(GDK_WINDOW_XDISPLAY(window
), GDK_WINDOW_XWINDOW(window
));
91 wm_hints
= XAllocWMHints();
94 wm_hints
->flags
|= XUrgencyHint
;
96 wm_hints
->flags
&= ~XUrgencyHint
;
98 XSetWMHints(GDK_WINDOW_XDISPLAY(window
), GDK_WINDOW_XWINDOW(window
), wm_hints
);
102 static gint
gtk_frame_urgency_timer_callback( wxTopLevelWindowGTK
*win
)
104 wxgtk_window_set_urgency_hint(GTK_WINDOW( win
->m_widget
), FALSE
);
106 win
->m_urgency_hint
= -2;
111 //-----------------------------------------------------------------------------
113 //-----------------------------------------------------------------------------
116 static gint
gtk_frame_focus_in_callback( GtkWidget
*widget
,
117 GdkEvent
*WXUNUSED(event
),
118 wxTopLevelWindowGTK
*win
)
121 wxapp_install_idle_handler();
123 switch ( g_sendActivateEvent
)
126 // we've got focus from outside, synthetize wxActivateEvent
127 g_sendActivateEvent
= 1;
131 // another our window just lost focus, it was already ours before
132 // - don't send any wxActivateEvent
133 g_sendActivateEvent
= -1;
138 g_lastActiveFrame
= g_activeFrame
;
140 // wxPrintf( wxT("active: %s\n"), win->GetTitle().c_str() );
142 // MR: wxRequestUserAttention related block
143 switch( win
->m_urgency_hint
)
146 gtk_timeout_remove( win
->m_urgency_hint
);
147 // no break, fallthrough to remove hint too
149 wxgtk_window_set_urgency_hint(GTK_WINDOW( widget
), FALSE
);
151 win
->m_urgency_hint
= -2;
157 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
);
158 wxActivateEvent
event(wxEVT_ACTIVATE
, true, g_activeFrame
->GetId());
159 event
.SetEventObject(g_activeFrame
);
160 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
166 //-----------------------------------------------------------------------------
168 //-----------------------------------------------------------------------------
171 static gint
gtk_frame_focus_out_callback( GtkWidget
*widget
,
172 GdkEventFocus
*WXUNUSED(gdk_event
),
173 wxTopLevelWindowGTK
*win
)
176 wxapp_install_idle_handler();
178 // if the focus goes out of our app alltogether, OnIdle() will send
179 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
180 // g_sendActivateEvent to -1
181 g_sendActivateEvent
= 0;
183 // wxASSERT_MSG( (g_activeFrame == win), wxT("TLW deactivatd although it wasn't active") );
185 // wxPrintf( wxT("inactive: %s\n"), win->GetTitle().c_str() );
189 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
);
190 wxActivateEvent
event(wxEVT_ACTIVATE
, false, g_activeFrame
->GetId());
191 event
.SetEventObject(g_activeFrame
);
192 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
194 g_activeFrame
= NULL
;
201 //-----------------------------------------------------------------------------
202 // "focus" from m_window
203 //-----------------------------------------------------------------------------
206 static gint
gtk_frame_focus_callback( GtkWidget
*widget
, GtkDirectionType
WXUNUSED(d
), wxWindow
*WXUNUSED(win
) )
209 wxapp_install_idle_handler();
211 // This disables GTK's tab traversal
212 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus" );
217 //-----------------------------------------------------------------------------
219 //-----------------------------------------------------------------------------
222 static void gtk_frame_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxTopLevelWindowGTK
*win
)
225 wxapp_install_idle_handler();
230 if ((win
->m_width
!= alloc
->width
) || (win
->m_height
!= alloc
->height
))
233 wxPrintf( "OnSize from " );
234 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
235 wxPrintf( win->GetClassInfo()->GetClassName() );
236 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
239 (int)alloc->height );
242 win
->m_width
= alloc
->width
;
243 win
->m_height
= alloc
->height
;
244 win
->GtkUpdateSize();
249 //-----------------------------------------------------------------------------
251 //-----------------------------------------------------------------------------
254 static gint
gtk_frame_delete_callback( GtkWidget
*WXUNUSED(widget
), GdkEvent
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
257 wxapp_install_idle_handler();
259 if (win
->IsEnabled() &&
260 (g_openDialogs
== 0 || (win
->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) ||
269 //-----------------------------------------------------------------------------
271 //-----------------------------------------------------------------------------
275 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
278 wxapp_install_idle_handler();
280 if (!win
->m_hasVMT
|| !win
->IsShown())
286 gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y
);
290 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
291 mevent
.SetEventObject( win
);
292 win
->GetEventHandler()->ProcessEvent( mevent
);
298 //-----------------------------------------------------------------------------
299 // "realize" from m_widget
300 //-----------------------------------------------------------------------------
302 // we cannot MWM hints and icons before the widget has been realized,
303 // so we do this directly after realization
307 gtk_frame_realized_callback( GtkWidget
* WXUNUSED(widget
),
308 wxTopLevelWindowGTK
*win
)
311 wxapp_install_idle_handler();
313 // All this is for Motif Window Manager "hints" and is supposed to be
314 // recognized by other WM as well. Not tested.
315 gdk_window_set_decorations(win
->m_widget
->window
,
316 (GdkWMDecoration
)win
->m_gdkDecor
);
317 gdk_window_set_functions(win
->m_widget
->window
,
318 (GdkWMFunction
)win
->m_gdkFunc
);
320 // GTK's shrinking/growing policy
321 if ((win
->m_gdkFunc
& GDK_FUNC_RESIZE
) == 0)
322 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 0, 0, 1);
324 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
327 wxIconBundle iconsOld
= win
->GetIcons();
328 if ( iconsOld
.GetIcon(-1).Ok() )
330 win
->SetIcon( wxNullIcon
);
331 win
->SetIcons( iconsOld
);
336 //-----------------------------------------------------------------------------
337 // "map_event" from m_widget
338 //-----------------------------------------------------------------------------
342 gtk_frame_map_callback( GtkWidget
* WXUNUSED(widget
),
343 GdkEvent
* WXUNUSED(event
),
344 wxTopLevelWindow
*win
)
346 win
->SetIconizeState(false);
350 //-----------------------------------------------------------------------------
351 // "unmap_event" from m_widget
352 //-----------------------------------------------------------------------------
356 gtk_frame_unmap_callback( GtkWidget
* WXUNUSED(widget
),
357 GdkEvent
* WXUNUSED(event
),
358 wxTopLevelWindow
*win
)
360 win
->SetIconizeState(true);
364 //-----------------------------------------------------------------------------
365 // "expose_event" of m_client
366 //-----------------------------------------------------------------------------
369 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
371 GtkPizza
*pizza
= GTK_PIZZA(widget
);
373 gtk_paint_flat_box (win
->m_widget
->style
,
374 pizza
->bin_window
, GTK_STATE_NORMAL
,
385 //-----------------------------------------------------------------------------
386 // "draw" of m_client
387 //-----------------------------------------------------------------------------
390 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
392 GtkPizza
*pizza
= GTK_PIZZA(widget
);
394 gtk_paint_flat_box (win
->m_widget
->style
,
395 pizza
->bin_window
, GTK_STATE_NORMAL
,
404 // ----------------------------------------------------------------------------
405 // wxTopLevelWindowGTK itself
406 // ----------------------------------------------------------------------------
408 //-----------------------------------------------------------------------------
409 // InsertChild for wxTopLevelWindowGTK
410 //-----------------------------------------------------------------------------
412 /* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
413 * C++ has no virtual methods in a constructor. We have to emulate a
414 * virtual function here as wxWidgets requires different ways to insert
415 * a child in container classes. */
417 static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK
* parent
, wxWindow
* child
)
419 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
421 if (!parent
->m_insertInClientArea
)
423 // these are outside the client area
424 wxTopLevelWindowGTK
* frame
= (wxTopLevelWindowGTK
*) parent
;
425 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
426 GTK_WIDGET(child
->m_widget
),
434 // these are inside the client area
435 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
436 GTK_WIDGET(child
->m_widget
),
443 // resize on OnInternalIdle
444 parent
->GtkUpdateSize();
447 // ----------------------------------------------------------------------------
448 // wxTopLevelWindowGTK creation
449 // ----------------------------------------------------------------------------
451 void wxTopLevelWindowGTK::Init()
456 m_mainWidget
= (GtkWidget
*) NULL
;
457 m_insertInClientArea
= true;
458 m_isIconized
= false;
459 m_fsIsShowing
= false;
460 m_themeEnabled
= true;
461 m_gdkDecor
= m_gdkFunc
= 0;
467 bool wxTopLevelWindowGTK::Create( wxWindow
*parent
,
469 const wxString
& title
,
471 const wxSize
& sizeOrig
,
473 const wxString
&name
)
475 // always create a frame of some reasonable, even if arbitrary, size (at
476 // least for MSW compatibility)
477 wxSize size
= sizeOrig
;
478 size
.x
= WidthDefault(size
.x
);
479 size
.y
= HeightDefault(size
.y
);
481 wxTopLevelWindows
.Append( this );
483 m_needParent
= false;
485 if (!PreCreation( parent
, pos
, size
) ||
486 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
488 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
494 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInTopLevelWindow
;
496 // NB: m_widget may be !=NULL if it was created by derived class' Create,
497 // e.g. in wxTaskBarIconAreaGTK
498 if (m_widget
== NULL
)
500 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)
502 m_widget
= gtk_window_new(GTK_WINDOW_DIALOG
);
506 m_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
507 #if GTK_CHECK_VERSION(2,1,0)
508 if (!gtk_check_version(2,1,0))
510 if (style
& wxFRAME_TOOL_WINDOW
)
512 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
513 GDK_WINDOW_TYPE_HINT_UTILITY
);
515 // On some WMs, like KDE, a TOOL_WINDOW will still show
516 // on the taskbar, but on Gnome a TOOL_WINDOW will not.
517 // For consistency between WMs and with Windows, we
518 // should set the NO_TASKBAR flag which will apply
519 // the set_skip_taskbar_hint if it is available,
520 // ensuring no taskbar entry will appear.
521 style
|= wxFRAME_NO_TASKBAR
;
528 wxWindow
*topParent
= wxGetTopLevelParent(m_parent
);
529 if (topParent
&& (((GTK_IS_WINDOW(topParent
->m_widget
)) &&
530 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) ||
531 (style
& wxFRAME_FLOAT_ON_PARENT
)))
533 gtk_window_set_transient_for( GTK_WINDOW(m_widget
),
534 GTK_WINDOW(topParent
->m_widget
) );
538 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), wxGTK_CONV( name
), wxGTK_CONV( name
) );
540 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
541 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
543 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
544 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
546 // m_mainWidget holds the toolbar, the menubar and the client area
547 m_mainWidget
= gtk_pizza_new();
548 gtk_widget_show( m_mainWidget
);
549 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
550 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
552 if (m_miniEdge
== 0) // wxMiniFrame has its own version.
554 // For m_mainWidget themes
555 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
556 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
557 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
558 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
561 // m_wxwindow only represents the client area without toolbar and menubar
562 m_wxwindow
= gtk_pizza_new();
563 gtk_widget_show( m_wxwindow
);
564 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
566 // we donm't allow the frame to get the focus as otherwise
567 // the frame will grab it at arbitrary focus changes
568 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
570 if (m_parent
) m_parent
->AddChild( this );
572 // the user resized the frame by dragging etc.
573 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
574 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
578 if ((m_x
!= -1) || (m_y
!= -1))
579 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
581 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
583 // we cannot set MWM hints and icons before the widget has
584 // been realized, so we do this directly after realization
585 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
586 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
588 // map and unmap for iconized state
589 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
590 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
591 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
592 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
594 // the only way to get the window size is to connect to this event
595 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
596 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
598 // disable native tab traversal
599 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
600 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
603 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
604 GTK_SIGNAL_FUNC(gtk_frame_focus_in_callback
), (gpointer
)this );
605 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
606 GTK_SIGNAL_FUNC(gtk_frame_focus_out_callback
), (gpointer
)this );
609 if ((m_miniEdge
> 0) || (style
& wxSIMPLE_BORDER
) || (style
& wxNO_BORDER
))
616 m_gdkDecor
= (long) GDK_DECOR_BORDER
;
617 m_gdkFunc
= (long) GDK_FUNC_MOVE
;
619 // All this is for Motif Window Manager "hints" and is supposed to be
620 // recognized by other WMs as well.
621 if ((style
& wxCAPTION
) != 0)
623 m_gdkDecor
|= GDK_DECOR_TITLE
;
625 if ((style
& wxCLOSE_BOX
) != 0)
627 m_gdkFunc
|= GDK_FUNC_CLOSE
;
629 if ((style
& wxSYSTEM_MENU
) != 0)
631 m_gdkDecor
|= GDK_DECOR_MENU
;
633 if ((style
& wxMINIMIZE_BOX
) != 0)
635 m_gdkFunc
|= GDK_FUNC_MINIMIZE
;
636 m_gdkDecor
|= GDK_DECOR_MINIMIZE
;
638 if ((style
& wxMAXIMIZE_BOX
) != 0)
640 m_gdkFunc
|= GDK_FUNC_MAXIMIZE
;
641 m_gdkDecor
|= GDK_DECOR_MAXIMIZE
;
643 if ((style
& wxRESIZE_BORDER
) != 0)
645 m_gdkFunc
|= GDK_FUNC_RESIZE
;
646 m_gdkDecor
|= GDK_DECOR_RESIZEH
;
653 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
657 wxASSERT_MSG( false, _T("Window still grabbed"));
661 m_isBeingDeleted
= true;
663 // it may also be GtkScrolledWindow in the case of an MDI child
664 if (GTK_IS_WINDOW(m_widget
))
666 gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL
);
669 if (g_activeFrame
== this)
670 g_activeFrame
= NULL
;
671 if (g_lastActiveFrame
== this)
672 g_lastActiveFrame
= NULL
;
677 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long style
)
679 if (show
== m_fsIsShowing
)
680 return false; // return what?
682 m_fsIsShowing
= show
;
684 wxX11FullScreenMethod method
=
685 wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(),
686 (WXWindow
)GDK_ROOT_WINDOW());
688 #if GTK_CHECK_VERSION(2,2,0)
689 // NB: gtk_window_fullscreen() uses freedesktop.org's WMspec extensions
690 // to switch to fullscreen, which is not always available. We must
691 // check if WM supports the spec and use legacy methods if it
693 if ( (method
== wxX11_FS_WMSPEC
) && !gtk_check_version(2,2,0) )
696 gtk_window_fullscreen( GTK_WINDOW( m_widget
) );
698 gtk_window_unfullscreen( GTK_WINDOW( m_widget
) );
701 #endif // GTK+ >= 2.2.0
703 GdkWindow
*window
= m_widget
->window
;
707 m_fsSaveFlag
= style
;
708 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
709 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
711 int screen_width
,screen_height
;
712 wxDisplaySize( &screen_width
, &screen_height
);
714 gint client_x
, client_y
, root_x
, root_y
;
717 if (method
!= wxX11_FS_WMSPEC
)
719 // don't do it always, Metacity hates it
720 m_fsSaveGdkFunc
= m_gdkFunc
;
721 m_fsSaveGdkDecor
= m_gdkDecor
;
722 m_gdkFunc
= m_gdkDecor
= 0;
723 gdk_window_set_decorations(window
, (GdkWMDecoration
)0);
724 gdk_window_set_functions(window
, (GdkWMFunction
)0);
727 gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
);
728 gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
,
729 &width
, &height
, NULL
);
731 gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
,
732 screen_width
+ 1, screen_height
+ 1);
734 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
735 (WXWindow
)GDK_ROOT_WINDOW(),
736 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
737 show
, &m_fsSaveFrame
, method
);
741 if (method
!= wxX11_FS_WMSPEC
)
743 // don't do it always, Metacity hates it
744 m_gdkFunc
= m_fsSaveGdkFunc
;
745 m_gdkDecor
= m_fsSaveGdkDecor
;
746 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
);
747 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
);
750 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
751 (WXWindow
)GDK_ROOT_WINDOW(),
752 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
753 show
, &m_fsSaveFrame
, method
);
755 SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
,
756 m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
760 // documented behaviour is to show the window if it's still hidden when
761 // showing it full screen
762 if ( show
&& !IsShown() )
768 // ----------------------------------------------------------------------------
769 // overridden wxWindow methods
770 // ----------------------------------------------------------------------------
772 bool wxTopLevelWindowGTK::Show( bool show
)
774 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
776 if (show
&& !m_sizeSet
)
778 /* by calling GtkOnSize here, we don't have to call
779 either after showing the frame, which would entail
780 much ugly flicker or from within the size_allocate
781 handler, because GTK 1.1.X forbids that. */
783 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
787 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
789 return wxWindow::Show( show
);
792 void wxTopLevelWindowGTK::Raise()
797 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
799 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
802 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
804 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
806 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
807 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
817 int old_width
= m_width
;
818 int old_height
= m_height
;
820 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
822 if (x
!= -1) m_x
= x
;
823 if (y
!= -1) m_y
= y
;
830 if (width
!= -1) m_width
= width
;
831 if (height
!= -1) m_height
= height
;
834 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
836 if (width == -1) m_width = 80;
839 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
841 if (height == -1) m_height = 26;
845 int minWidth
= GetMinWidth(),
846 minHeight
= GetMinHeight(),
847 maxWidth
= GetMaxWidth(),
848 maxHeight
= GetMaxHeight();
851 // GPE's window manager doesn't like size hints
852 // at all, esp. when the user has to use the
860 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
861 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
862 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
863 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
865 if ((m_x
!= -1) || (m_y
!= -1))
867 if ((m_x
!= old_x
) || (m_y
!= old_y
))
869 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
873 if ((m_width
!= old_width
) || (m_height
!= old_height
))
875 if (m_widget
->window
)
876 gdk_window_resize( m_widget
->window
, m_width
, m_height
);
878 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
880 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
881 done either directly before the frame is shown or in idle time
882 so that different calls to SetSize() don't lead to flicker. */
889 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height
) const
891 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
893 wxWindow::DoGetClientSize( width
, height
);
897 *height
-= m_miniEdge
*2 + m_miniTitle
;
901 *width
-= m_miniEdge
*2;
905 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height
)
907 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
910 width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0);
913 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
914 int width
, int height
)
916 // due to a bug in gtk, x,y are always 0
921 if (m_resizing
) return;
924 if ( m_wxwindow
== NULL
) return;
929 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
930 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
931 set in wxFrame::Create so it is used to check what kind of frame we
932 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
933 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
934 importantly) m_mainWidget */
936 int minWidth
= GetMinWidth(),
937 minHeight
= GetMinHeight(),
938 maxWidth
= GetMaxWidth(),
939 maxHeight
= GetMaxHeight();
942 // GPE's window manager doesn't like size hints
943 // at all, esp. when the user has to use the
951 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
952 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
953 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
954 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
959 gint flag
= 0; // GDK_HINT_POS;
962 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
963 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
965 geom
.min_width
= minWidth
;
966 geom
.min_height
= minHeight
;
968 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
969 // maxHeight or maxWidth is set, we must set them both, else the
970 // remaining -1 will be taken literally.
972 // I'm certain this also happens elsewhere, and is the probable
973 // cause of other such things as:
974 // Gtk-WARNING **: gtk_widget_size_allocate():
975 // attempt to allocate widget with width 65535 and height 600
976 // but I don't have time to track them all now..
978 // Really we need to encapulate all this height/width business and
979 // stop any old method from ripping at the members directly and
980 // scattering -1's without regard for who might resolve them later.
982 geom
.max_width
= ( maxHeight
== -1 ) ? maxWidth
983 : ( maxWidth
== -1 ) ? wxGetDisplaySize().GetWidth()
986 geom
.max_height
= ( maxWidth
== -1 ) ? maxHeight
// ( == -1 here )
987 : ( maxHeight
== -1 ) ? wxGetDisplaySize().GetHeight()
990 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
993 (GdkWindowHints
) flag
);
995 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
996 * menubar, the toolbar and the client area, which is represented by
998 * this hurts in the eye, but I don't want to call SetSize()
999 * because I don't want to call any non-native functions here. */
1001 int client_x
= m_miniEdge
;
1002 int client_y
= m_miniEdge
+ m_miniTitle
;
1003 int client_w
= m_width
- 2*m_miniEdge
;
1004 int client_h
= m_height
- 2*m_miniEdge
- m_miniTitle
;
1006 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
1008 client_x
, client_y
, client_w
, client_h
);
1012 // If there is no m_mainWidget between m_widget and m_wxwindow there
1013 // is no need to set the size or position of m_wxwindow.
1018 // send size event to frame
1019 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1020 event
.SetEventObject( this );
1021 GetEventHandler()->ProcessEvent( event
);
1026 void wxTopLevelWindowGTK::OnInternalIdle()
1028 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
1030 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
1032 // we'll come back later
1034 wxapp_install_idle_handler();
1038 // set the focus if not done yet and if we can already do it
1039 if ( GTK_WIDGET_REALIZED(m_wxwindow
) )
1041 if ( g_delayedFocus
&&
1042 wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this )
1044 wxLogTrace(_T("focus"),
1045 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
1046 g_delayedFocus
->GetClassInfo()->GetClassName(),
1047 g_delayedFocus
->GetLabel().c_str());
1049 g_delayedFocus
->SetFocus();
1050 g_delayedFocus
= NULL
;
1054 wxWindow::OnInternalIdle();
1056 // Synthetize activate events.
1057 if ( g_sendActivateEvent
!= -1 )
1059 bool activate
= g_sendActivateEvent
!= 0;
1061 // if (!activate) wxPrintf( wxT("de") );
1062 // wxPrintf( wxT("activate\n") );
1065 g_sendActivateEvent
= -1;
1067 wxTheApp
->SetActive(activate
, (wxWindow
*)g_lastActiveFrame
);
1071 // ----------------------------------------------------------------------------
1073 // ----------------------------------------------------------------------------
1075 void wxTopLevelWindowGTK::SetTitle( const wxString
&title
)
1077 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1079 if ( title
== m_title
)
1084 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
1087 void wxTopLevelWindowGTK::SetIcon( const wxIcon
&icon
)
1089 SetIcons( wxIconBundle( icon
) );
1092 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle
&icons
)
1094 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1096 wxTopLevelWindowBase::SetIcons( icons
);
1098 GdkWindow
* window
= m_widget
->window
;
1102 wxIcon icon
= icons
.GetIcon(-1);
1105 wxMask
*mask
= icon
.GetMask();
1106 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1107 if (mask
) bm
= mask
->GetBitmap();
1109 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
1112 wxSetIconsX11( (WXDisplay
*)GDK_WINDOW_XDISPLAY( window
),
1113 (WXWindow
)GDK_WINDOW_XWINDOW( window
), icons
);
1116 // ----------------------------------------------------------------------------
1117 // frame state: maximized/iconized/normal
1118 // ----------------------------------------------------------------------------
1120 void wxTopLevelWindowGTK::Maximize(bool maximize
)
1122 wxFAIL_MSG( _T("not implemented") );
1125 bool wxTopLevelWindowGTK::IsMaximized() const
1127 // wxFAIL_MSG( _T("not implemented") );
1129 // This is an approximation
1133 void wxTopLevelWindowGTK::Restore()
1135 wxFAIL_MSG( _T("not implemented") );
1138 void wxTopLevelWindowGTK::Iconize( bool iconize
)
1142 GdkWindow
*window
= m_widget
->window
;
1144 // you should do it later, for example from OnCreate() handler
1145 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
1147 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
1148 GDK_WINDOW_XWINDOW( window
),
1149 DefaultScreen( GDK_DISPLAY() ) );
1153 bool wxTopLevelWindowGTK::IsIconized() const
1155 return m_isIconized
;
1158 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
)
1160 if ( iconize
!= m_isIconized
)
1162 m_isIconized
= iconize
;
1163 (void)SendIconizeEvent(iconize
);
1167 void wxTopLevelWindowGTK::AddGrab()
1172 gtk_grab_add( m_widget
);
1173 wxEventLoop().Run();
1174 gtk_grab_remove( m_widget
);
1178 void wxTopLevelWindowGTK::RemoveGrab()
1189 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
)
1193 if (region
.IsEmpty())
1195 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
1199 wxBitmap bmp
= region
.ConvertToBitmap();
1200 bmp
.SetMask(new wxMask(bmp
, *wxBLACK
));
1201 GdkBitmap
* mask
= bmp
.GetMask()->GetBitmap();
1202 gdk_window_shape_combine_mask(window
, mask
, 0, 0);
1210 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
)
1212 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), false,
1213 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1215 GdkWindow
*window
= NULL
;
1218 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
1219 do_shape_combine_region(window
, region
);
1221 window
= m_widget
->window
;
1222 return do_shape_combine_region(window
, region
);
1225 bool wxTopLevelWindowGTK::IsActive()
1227 return (this == (wxTopLevelWindowGTK
*)g_activeFrame
);
1230 void wxTopLevelWindowGTK::RequestUserAttention(int flags
)
1232 bool new_hint_value
= false;
1234 // FIXME: This is a workaround to focus handling problem
1235 // If RequestUserAttention is called for example right after a wxSleep, OnInternalIdle hasn't
1236 // yet been processed, and the internal focus system is not up to date yet.
1237 // wxYieldIfNeeded ensures the processing of it, but can have unwanted side effects - MR
1238 ::wxYieldIfNeeded();
1240 if(m_urgency_hint
>= 0)
1241 gtk_timeout_remove(m_urgency_hint
);
1243 m_urgency_hint
= -2;
1245 if( GTK_WIDGET_REALIZED(m_widget
) && !IsActive() )
1247 new_hint_value
= true;
1249 if (flags
& wxUSER_ATTENTION_INFO
)
1251 m_urgency_hint
= gtk_timeout_add(5000, (GtkFunction
)gtk_frame_urgency_timer_callback
, this);
1253 m_urgency_hint
= -1;
1257 wxgtk_window_set_urgency_hint(GTK_WINDOW( m_widget
), new_hint_value
);
1260 void wxTopLevelWindowGTK::SetWindowStyleFlag( long style
)
1262 // Process wxWindow styles. This also updates the internal variable
1263 // Therefore m_windowStyle bits carry now the _new_ style values
1264 wxWindow::SetWindowStyleFlag(style
);