1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/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"
34 #include "wx/gtk/private.h"
35 #include "wx/evtloop.h"
40 #include "wx/gtk/win_gtk.h"
42 #include "wx/unix/utilsx11.h"
45 #include <X11/Xatom.h>
47 // ----------------------------------------------------------------------------
49 // ----------------------------------------------------------------------------
51 extern int g_openDialogs
;
52 extern wxWindowGTK
*g_delayedFocus
;
54 // the frame that is currently active (i.e. its child has focus). It is
55 // used to generate wxActivateEvents
56 static wxTopLevelWindowGTK
*g_activeFrame
= (wxTopLevelWindowGTK
*) NULL
;
57 static wxTopLevelWindowGTK
*g_lastActiveFrame
= (wxTopLevelWindowGTK
*) NULL
;
59 // if we detect that the app has got/lost the focus, we set this variable to
60 // either TRUE or FALSE and an activate event will be sent during the next
61 // OnIdle() call and it is reset to -1: this value means that we shouldn't
62 // send any activate events at all
63 static int g_sendActivateEvent
= -1;
65 //-----------------------------------------------------------------------------
66 // RequestUserAttention related functions
67 //-----------------------------------------------------------------------------
70 static void wxgtk_window_set_urgency_hint (GtkWindow
*win
,
73 wxASSERT_MSG( GTK_WIDGET_REALIZED(win
), wxT("wxgtk_window_set_urgency_hint: GdkWindow not realized") );
74 GdkWindow
*window
= GTK_WIDGET(win
)->window
;
77 wm_hints
= XGetWMHints(GDK_WINDOW_XDISPLAY(window
), GDK_WINDOW_XWINDOW(window
));
80 wm_hints
= XAllocWMHints();
83 wm_hints
->flags
|= XUrgencyHint
;
85 wm_hints
->flags
&= ~XUrgencyHint
;
87 XSetWMHints(GDK_WINDOW_XDISPLAY(window
), GDK_WINDOW_XWINDOW(window
), wm_hints
);
91 static gboolean
gtk_frame_urgency_timer_callback( wxTopLevelWindowGTK
*win
)
93 #if GTK_CHECK_VERSION(2,7,0)
94 if(!gtk_check_version(2,7,0))
95 gtk_window_set_urgency_hint(GTK_WINDOW( win
->m_widget
), FALSE
);
98 wxgtk_window_set_urgency_hint(GTK_WINDOW( win
->m_widget
), FALSE
);
100 win
->m_urgency_hint
= -2;
105 //-----------------------------------------------------------------------------
107 //-----------------------------------------------------------------------------
110 static gboolean
gtk_frame_focus_in_callback( GtkWidget
*widget
,
111 GdkEvent
*WXUNUSED(event
),
112 wxTopLevelWindowGTK
*win
)
114 // don't need to install idle handler, its done from "event" signal
116 switch ( g_sendActivateEvent
)
119 // we've got focus from outside, synthetize wxActivateEvent
120 g_sendActivateEvent
= 1;
124 // another our window just lost focus, it was already ours before
125 // - don't send any wxActivateEvent
126 g_sendActivateEvent
= -1;
131 g_lastActiveFrame
= g_activeFrame
;
133 // wxPrintf( wxT("active: %s\n"), win->GetTitle().c_str() );
135 // MR: wxRequestUserAttention related block
136 switch( win
->m_urgency_hint
)
139 g_source_remove( win
->m_urgency_hint
);
140 // no break, fallthrough to remove hint too
142 #if GTK_CHECK_VERSION(2,7,0)
143 if(!gtk_check_version(2,7,0))
144 gtk_window_set_urgency_hint(GTK_WINDOW( widget
), FALSE
);
148 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 gboolean
gtk_frame_focus_out_callback( GtkWidget
*widget
,
172 GdkEventFocus
*WXUNUSED(gdk_event
),
173 wxTopLevelWindowGTK
*win
)
175 // don't need to install idle handler, its done from "event" signal
177 // if the focus goes out of our app alltogether, OnIdle() will send
178 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
179 // g_sendActivateEvent to -1
180 g_sendActivateEvent
= 0;
182 // wxASSERT_MSG( (g_activeFrame == win), wxT("TLW deactivatd although it wasn't active") );
184 // wxPrintf( wxT("inactive: %s\n"), win->GetTitle().c_str() );
188 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
);
189 wxActivateEvent
event(wxEVT_ACTIVATE
, false, g_activeFrame
->GetId());
190 event
.SetEventObject(g_activeFrame
);
191 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
193 g_activeFrame
= NULL
;
200 //-----------------------------------------------------------------------------
201 // "focus" from m_window
202 //-----------------------------------------------------------------------------
205 static gboolean
gtk_frame_focus_callback( GtkWidget
*WXUNUSED(widget
),
206 GtkDirectionType
WXUNUSED(d
),
207 wxWindow
*WXUNUSED(win
) )
210 wxapp_install_idle_handler();
212 // This disables GTK's tab traversal
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( wxT("gtk_frame_size_callback from ") );
234 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
235 wxPrintf( win->GetClassInfo()->GetClassName() );
236 wxPrintf( wxT(" %d %d %d %d\n"), (int)alloc->x,
239 (int)alloc->height );
242 // Tell the wxWindow class about the new size
243 win
->m_width
= alloc
->width
;
244 win
->m_height
= alloc
->height
;
246 win
->GtkUpdateSize();
251 // ----------------------------------------------------------------------------
253 // ----------------------------------------------------------------------------
256 void wxgtk_tlw_size_request_callback(GtkWidget
* WXUNUSED(widget
),
257 GtkRequisition
*requisition
,
258 wxTopLevelWindowGTK
*win
)
260 // we must return the size of the window without WM decorations, otherwise
261 // GTK+ gets confused, so don't call just GetSize() here
263 win
->GTKDoGetSize(&w
, &h
);
265 requisition
->height
= h
;
266 requisition
->width
= w
;
269 //-----------------------------------------------------------------------------
271 //-----------------------------------------------------------------------------
275 gtk_frame_delete_callback( GtkWidget
*WXUNUSED(widget
),
276 GdkEvent
*WXUNUSED(event
),
277 wxTopLevelWindowGTK
*win
)
279 // don't need to install idle handler, its done from "event" signal
281 if (win
->IsEnabled() &&
282 (g_openDialogs
== 0 || (win
->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) ||
291 //-----------------------------------------------------------------------------
293 //-----------------------------------------------------------------------------
297 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
),
298 GdkEventConfigure
*WXUNUSED(event
),
299 wxTopLevelWindowGTK
*win
)
301 // don't need to install idle handler, its done from "event" signal
303 if (!win
->m_hasVMT
|| !win
->IsShown())
309 gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y
);
313 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
314 mevent
.SetEventObject( win
);
315 win
->GetEventHandler()->ProcessEvent( mevent
);
321 //-----------------------------------------------------------------------------
322 // "realize" from m_widget
323 //-----------------------------------------------------------------------------
325 // we cannot MWM hints and icons before the widget has been realized,
326 // so we do this directly after realization
330 gtk_frame_realized_callback( GtkWidget
* WXUNUSED(widget
),
331 wxTopLevelWindowGTK
*win
)
334 wxapp_install_idle_handler();
336 // All this is for Motif Window Manager "hints" and is supposed to be
337 // recognized by other WM as well. Not tested.
338 gdk_window_set_decorations(win
->m_widget
->window
,
339 (GdkWMDecoration
)win
->m_gdkDecor
);
340 gdk_window_set_functions(win
->m_widget
->window
,
341 (GdkWMFunction
)win
->m_gdkFunc
);
343 // GTK's shrinking/growing policy
344 if ((win
->m_gdkFunc
& GDK_FUNC_RESIZE
) == 0)
345 gtk_window_set_resizable(GTK_WINDOW(win
->m_widget
), FALSE
);
347 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
350 wxIconBundle iconsOld
= win
->GetIcons();
351 if ( iconsOld
.GetIcon(-1).Ok() )
353 win
->SetIcon( wxNullIcon
);
354 win
->SetIcons( iconsOld
);
359 //-----------------------------------------------------------------------------
360 // "map_event" from m_widget
361 //-----------------------------------------------------------------------------
365 gtk_frame_map_callback( GtkWidget
* WXUNUSED(widget
),
366 GdkEvent
* WXUNUSED(event
),
367 wxTopLevelWindow
*win
)
369 win
->SetIconizeState(false);
373 //-----------------------------------------------------------------------------
374 // "unmap_event" from m_widget
375 //-----------------------------------------------------------------------------
379 gtk_frame_unmap_callback( GtkWidget
* WXUNUSED(widget
),
380 GdkEvent
* WXUNUSED(event
),
381 wxTopLevelWindow
*win
)
383 win
->SetIconizeState(true);
387 //-----------------------------------------------------------------------------
388 // "expose_event" of m_client
389 //-----------------------------------------------------------------------------
393 gtk_window_expose_callback( GtkWidget
*widget
,
394 GdkEventExpose
*gdk_event
,
397 GtkPizza
*pizza
= GTK_PIZZA(widget
);
399 gtk_paint_flat_box (win
->m_widget
->style
,
400 pizza
->bin_window
, GTK_STATE_NORMAL
,
411 // ----------------------------------------------------------------------------
412 // wxTopLevelWindowGTK itself
413 // ----------------------------------------------------------------------------
415 //-----------------------------------------------------------------------------
416 // InsertChild for wxTopLevelWindowGTK
417 //-----------------------------------------------------------------------------
419 /* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
420 * C++ has no virtual methods in a constructor. We have to emulate a
421 * virtual function here as wxWidgets requires different ways to insert
422 * a child in container classes. */
424 static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK
* parent
, wxWindow
* child
)
426 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
428 if (!parent
->m_insertInClientArea
)
430 // these are outside the client area
431 wxTopLevelWindowGTK
* frame
= (wxTopLevelWindowGTK
*) parent
;
432 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
433 GTK_WIDGET(child
->m_widget
),
441 // these are inside the client area
442 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
443 GTK_WIDGET(child
->m_widget
),
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;
465 m_themeEnabled
= true;
466 m_gdkDecor
= m_gdkFunc
= 0;
472 bool wxTopLevelWindowGTK::Create( wxWindow
*parent
,
474 const wxString
& title
,
476 const wxSize
& sizeOrig
,
478 const wxString
&name
)
480 // always create a frame of some reasonable, even if arbitrary, size (at
481 // least for MSW compatibility)
482 wxSize size
= sizeOrig
;
483 size
.x
= WidthDefault(size
.x
);
484 size
.y
= HeightDefault(size
.y
);
486 wxTopLevelWindows
.Append( this );
488 m_needParent
= false;
490 if (!PreCreation( parent
, pos
, size
) ||
491 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
493 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
499 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInTopLevelWindow
;
501 // NB: m_widget may be !=NULL if it was created by derived class' Create,
502 // e.g. in wxTaskBarIconAreaGTK
503 if (m_widget
== NULL
)
505 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)
507 m_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
508 // Tell WM that this is a dialog window and make it center
509 // on parent by default (this is what GtkDialog ctor does):
510 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
511 GDK_WINDOW_TYPE_HINT_DIALOG
);
512 gtk_window_set_position(GTK_WINDOW(m_widget
),
513 GTK_WIN_POS_CENTER_ON_PARENT
);
517 m_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
518 #if GTK_CHECK_VERSION(2,1,0)
519 if (!gtk_check_version(2,1,0))
521 if (style
& wxFRAME_TOOL_WINDOW
)
523 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
524 GDK_WINDOW_TYPE_HINT_UTILITY
);
526 // On some WMs, like KDE, a TOOL_WINDOW will still show
527 // on the taskbar, but on Gnome a TOOL_WINDOW will not.
528 // For consistency between WMs and with Windows, we
529 // should set the NO_TASKBAR flag which will apply
530 // the set_skip_taskbar_hint if it is available,
531 // ensuring no taskbar entry will appear.
532 style
|= wxFRAME_NO_TASKBAR
;
539 wxWindow
*topParent
= wxGetTopLevelParent(m_parent
);
540 if (topParent
&& (((GTK_IS_WINDOW(topParent
->m_widget
)) &&
541 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) ||
542 (style
& wxFRAME_FLOAT_ON_PARENT
)))
544 gtk_window_set_transient_for( GTK_WINDOW(m_widget
),
545 GTK_WINDOW(topParent
->m_widget
) );
548 #if GTK_CHECK_VERSION(2,2,0)
549 if (!gtk_check_version(2,2,0))
551 if (style
& wxFRAME_NO_TASKBAR
)
553 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), TRUE
);
559 if (!gtk_check_version(2,4,0))
561 if (style
& wxSTAY_ON_TOP
)
563 gtk_window_set_keep_above(GTK_WINDOW(m_widget
), TRUE
);
570 gtk_window_set_role( GTK_WINDOW(m_widget
), wxGTK_CONV( name
) );
573 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
574 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
576 g_signal_connect (m_widget
, "delete_event",
577 G_CALLBACK (gtk_frame_delete_callback
), this);
579 // m_mainWidget holds the toolbar, the menubar and the client area
580 m_mainWidget
= gtk_pizza_new();
581 gtk_widget_show( m_mainWidget
);
582 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
583 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
585 if (m_miniEdge
== 0) // wxMiniFrame has its own version.
587 // For m_mainWidget themes
588 g_signal_connect (m_mainWidget
, "expose_event",
589 G_CALLBACK (gtk_window_expose_callback
), this);
592 // m_wxwindow only represents the client area without toolbar and menubar
593 m_wxwindow
= gtk_pizza_new();
594 gtk_widget_show( m_wxwindow
);
595 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
597 // we donm't allow the frame to get the focus as otherwise
598 // the frame will grab it at arbitrary focus changes
599 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
601 if (m_parent
) m_parent
->AddChild( this );
603 // the user resized the frame by dragging etc.
604 g_signal_connect (m_widget
, "size_allocate",
605 G_CALLBACK (gtk_frame_size_callback
), this);
607 g_signal_connect (m_widget
, "size_request",
608 G_CALLBACK (wxgtk_tlw_size_request_callback
), this);
611 if ((m_x
!= -1) || (m_y
!= -1))
612 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
614 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
616 // we cannot set MWM hints and icons before the widget has
617 // been realized, so we do this directly after realization
618 g_signal_connect (m_widget
, "realize",
619 G_CALLBACK (gtk_frame_realized_callback
), this);
621 // map and unmap for iconized state
622 g_signal_connect (m_widget
, "map_event",
623 G_CALLBACK (gtk_frame_map_callback
), this);
624 g_signal_connect (m_widget
, "unmap_event",
625 G_CALLBACK (gtk_frame_unmap_callback
), this);
627 // the only way to get the window size is to connect to this event
628 g_signal_connect (m_widget
, "configure_event",
629 G_CALLBACK (gtk_frame_configure_callback
), this);
631 // disable native tab traversal
632 g_signal_connect (m_widget
, "focus",
633 G_CALLBACK (gtk_frame_focus_callback
), this);
636 g_signal_connect_after (m_widget
, "focus_in_event",
637 G_CALLBACK (gtk_frame_focus_in_callback
), this);
638 g_signal_connect_after (m_widget
, "focus_out_event",
639 G_CALLBACK (gtk_frame_focus_out_callback
), this);
642 if ((style
& wxSIMPLE_BORDER
) || (style
& wxNO_BORDER
))
653 if ((style
& wxRESIZE_BORDER
) != 0)
654 m_gdkFunc
|= GDK_FUNC_RESIZE
;
658 m_gdkDecor
= (long) GDK_DECOR_BORDER
;
659 m_gdkFunc
= (long) GDK_FUNC_MOVE
;
661 // All this is for Motif Window Manager "hints" and is supposed to be
662 // recognized by other WMs as well.
663 if ((style
& wxCAPTION
) != 0)
665 m_gdkDecor
|= GDK_DECOR_TITLE
;
667 if ((style
& wxCLOSE_BOX
) != 0)
669 m_gdkFunc
|= GDK_FUNC_CLOSE
;
671 if ((style
& wxSYSTEM_MENU
) != 0)
673 m_gdkDecor
|= GDK_DECOR_MENU
;
675 if ((style
& wxMINIMIZE_BOX
) != 0)
677 m_gdkFunc
|= GDK_FUNC_MINIMIZE
;
678 m_gdkDecor
|= GDK_DECOR_MINIMIZE
;
680 if ((style
& wxMAXIMIZE_BOX
) != 0)
682 m_gdkFunc
|= GDK_FUNC_MAXIMIZE
;
683 m_gdkDecor
|= GDK_DECOR_MAXIMIZE
;
685 if ((style
& wxRESIZE_BORDER
) != 0)
687 m_gdkFunc
|= GDK_FUNC_RESIZE
;
688 m_gdkDecor
|= GDK_DECOR_RESIZEH
;
695 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
699 wxFAIL_MSG(_T("Window still grabbed"));
703 m_isBeingDeleted
= true;
705 // it may also be GtkScrolledWindow in the case of an MDI child
706 if (GTK_IS_WINDOW(m_widget
))
708 gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL
);
711 if (g_activeFrame
== this)
712 g_activeFrame
= NULL
;
713 if (g_lastActiveFrame
== this)
714 g_lastActiveFrame
= NULL
;
717 bool wxTopLevelWindowGTK::EnableCloseButton( bool enable
)
720 m_gdkFunc
|= GDK_FUNC_CLOSE
;
722 m_gdkFunc
&= ~GDK_FUNC_CLOSE
;
724 if (GTK_WIDGET_REALIZED(m_widget
) && (m_widget
->window
))
725 gdk_window_set_functions( m_widget
->window
, (GdkWMFunction
)m_gdkFunc
);
730 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long style
)
732 if (show
== m_fsIsShowing
)
733 return false; // return what?
735 m_fsIsShowing
= show
;
737 wxX11FullScreenMethod method
=
738 wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(),
739 (WXWindow
)GDK_ROOT_WINDOW());
741 #if GTK_CHECK_VERSION(2,2,0)
742 // NB: gtk_window_fullscreen() uses freedesktop.org's WMspec extensions
743 // to switch to fullscreen, which is not always available. We must
744 // check if WM supports the spec and use legacy methods if it
746 if ( (method
== wxX11_FS_WMSPEC
) && !gtk_check_version(2,2,0) )
750 m_fsSaveFlag
= style
;
751 gtk_window_fullscreen( GTK_WINDOW( m_widget
) );
756 gtk_window_unfullscreen( GTK_WINDOW( m_widget
) );
760 #endif // GTK+ >= 2.2.0
762 GdkWindow
*window
= m_widget
->window
;
766 m_fsSaveFlag
= style
;
767 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
768 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
770 int screen_width
,screen_height
;
771 wxDisplaySize( &screen_width
, &screen_height
);
773 gint client_x
, client_y
, root_x
, root_y
;
776 if (method
!= wxX11_FS_WMSPEC
)
778 // don't do it always, Metacity hates it
779 m_fsSaveGdkFunc
= m_gdkFunc
;
780 m_fsSaveGdkDecor
= m_gdkDecor
;
781 m_gdkFunc
= m_gdkDecor
= 0;
782 gdk_window_set_decorations(window
, (GdkWMDecoration
)0);
783 gdk_window_set_functions(window
, (GdkWMFunction
)0);
786 gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
);
787 gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
,
788 &width
, &height
, NULL
);
790 gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
,
791 screen_width
+ 1, screen_height
+ 1);
793 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
794 (WXWindow
)GDK_ROOT_WINDOW(),
795 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
796 show
, &m_fsSaveFrame
, method
);
801 if (method
!= wxX11_FS_WMSPEC
)
803 // don't do it always, Metacity hates it
804 m_gdkFunc
= m_fsSaveGdkFunc
;
805 m_gdkDecor
= m_fsSaveGdkDecor
;
806 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
);
807 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
);
810 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
811 (WXWindow
)GDK_ROOT_WINDOW(),
812 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
813 show
, &m_fsSaveFrame
, method
);
815 SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
,
816 m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
820 // documented behaviour is to show the window if it's still hidden when
821 // showing it full screen
822 if ( show
&& !IsShown() )
828 // ----------------------------------------------------------------------------
829 // overridden wxWindow methods
830 // ----------------------------------------------------------------------------
832 bool wxTopLevelWindowGTK::Show( bool show
)
834 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
836 if (show
== IsShown())
839 if (show
&& !m_sizeSet
)
841 /* by calling GtkOnSize here, we don't have to call
842 either after showing the frame, which would entail
843 much ugly flicker or from within the size_allocate
844 handler, because GTK 1.1.X forbids that. */
849 // This seems no longer to be needed and the call
850 // itself is deprecated.
853 // gtk_widget_set_uposition( m_widget, m_x, m_y );
855 return wxWindow::Show( show
);
858 void wxTopLevelWindowGTK::Raise()
860 gtk_window_present( GTK_WINDOW( m_widget
) );
863 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
865 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
868 // ----------------------------------------------------------------------------
870 // ----------------------------------------------------------------------------
872 void wxTopLevelWindowGTK::GTKDoGetSize(int *width
, int *height
) const
874 return wxTopLevelWindowBase::DoGetSize(width
, height
);
877 void wxTopLevelWindowGTK::GTKDoSetSize(int width
, int height
)
884 int old_width
= m_width
;
885 int old_height
= m_height
;
892 // GPE's window manager doesn't like size hints at all, esp. when the user
893 // has to use the virtual keyboard, so don't constrain size there
895 int minWidth
= GetMinWidth(),
896 minHeight
= GetMinHeight(),
897 maxWidth
= GetMaxWidth(),
898 maxHeight
= GetMaxHeight();
900 if ( minWidth
!= -1 && m_width
< minWidth
)
902 if ( minHeight
!= -1 && m_height
< minHeight
)
903 m_height
= minHeight
;
904 if ( maxWidth
!= -1 && m_width
> maxWidth
)
906 if ( maxHeight
!= -1 && m_height
> maxHeight
)
907 m_height
= maxHeight
;
910 if ( m_width
!= old_width
|| m_height
!= old_height
)
912 gtk_window_resize( GTK_WINDOW(m_widget
), m_width
, m_height
);
914 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
915 done either directly before the frame is shown or in idle time
916 so that different calls to SetSize() don't lead to flicker. */
923 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
925 wxCHECK_RET( m_widget
, wxT("invalid frame") );
927 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
928 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
931 // deal with the position first
935 if ( !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
937 // -1 means "use existing" unless the flag above is specified
943 else // wxSIZE_ALLOW_MINUS_ONE
949 if ( m_x
!= old_x
|| m_y
!= old_y
)
951 gtk_window_move( GTK_WINDOW(m_widget
), m_x
, m_y
);
955 // and now change the size: as we want to set the size of the entire
956 // window, including decorations, we must adjust the size passed to
957 // GTKDoSetSize() which takes with the size of undecorated frame only
958 if ( width
!= -1 || height
!= -1 )
962 DoGetSize(&wTotal
, &hTotal
);
966 GTKDoGetSize(&wUndec
, &hUndec
);
969 width
-= wTotal
- wUndec
;
971 height
-= hTotal
- hUndec
;
974 GTKDoSetSize(width
, height
);
977 void wxTopLevelWindowGTK::DoGetSize(int *width
, int *height
) const
979 wxCHECK_RET( m_widget
, wxT("invalid frame") );
981 if ( !m_widget
->window
)
983 // this can happen if we're called before the window is realized, so
984 // don't assert but just return the stored values
985 GTKDoGetSize(width
, height
);
990 gdk_window_get_frame_extents(m_widget
->window
, &rect
);
995 *height
= rect
.height
;
998 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height
) const
1002 // for consistency with wxMSW, client area is supposed to be empty for
1003 // the iconized windows
1012 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1016 *height
= m_height
- 2 * m_miniEdge
- m_miniTitle
;
1022 *width
= m_width
- 2 * m_miniEdge
;
1028 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height
)
1030 GTKDoSetSize(width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
);
1033 void wxTopLevelWindowGTK::DoSetSizeHints( int minW
, int minH
,
1035 int incW
, int incH
)
1037 wxTopLevelWindowBase::DoSetSizeHints( minW
, minH
, maxW
, maxH
, incW
, incH
);
1039 const wxSize minSize
= GetMinSize();
1040 const wxSize maxSize
= GetMaxSize();
1043 if (minSize
.x
> 0 || minSize
.y
> 0)
1045 hints_mask
|= GDK_HINT_MIN_SIZE
;
1046 hints
.min_width
= minSize
.x
> 0 ? minSize
.x
: 0;
1047 hints
.min_height
= minSize
.y
> 0 ? minSize
.y
: 0;
1049 if (maxSize
.x
> 0 || maxSize
.y
> 0)
1051 hints_mask
|= GDK_HINT_MAX_SIZE
;
1052 hints
.max_width
= maxSize
.x
> 0 ? maxSize
.x
: INT_MAX
;
1053 hints
.max_height
= maxSize
.y
> 0 ? maxSize
.y
: INT_MAX
;
1055 if (incW
> 0 || incH
> 0)
1057 hints_mask
|= GDK_HINT_RESIZE_INC
;
1058 hints
.width_inc
= incW
> 0 ? incW
: 1;
1059 hints
.height_inc
= incH
> 0 ? incH
: 1;
1061 gtk_window_set_geometry_hints(
1062 (GtkWindow
*)m_widget
, NULL
, &hints
, (GdkWindowHints
)hints_mask
);
1066 void wxTopLevelWindowGTK::GtkOnSize()
1069 if (m_resizing
) return;
1072 if ( m_wxwindow
== NULL
) return;
1074 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
1075 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
1076 set in wxFrame::Create so it is used to check what kind of frame we
1077 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
1078 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
1079 importantly) m_mainWidget */
1081 int minWidth
= GetMinWidth(),
1082 minHeight
= GetMinHeight(),
1083 maxWidth
= GetMaxWidth(),
1084 maxHeight
= GetMaxHeight();
1087 // GPE's window manager doesn't like size hints
1088 // at all, esp. when the user has to use the
1089 // virtual keyboard.
1096 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
1097 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
1098 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
1099 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
1103 // m_mainWidget holds the menubar, the toolbar and the client area,
1104 // which is represented by m_wxwindow.
1105 int client_x
= m_miniEdge
;
1106 int client_y
= m_miniEdge
+ m_miniTitle
;
1107 int client_w
= m_width
- 2*m_miniEdge
;
1108 int client_h
= m_height
- 2*m_miniEdge
- m_miniTitle
;
1114 // Let the parent perform the resize
1115 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
1117 client_x
, client_y
, client_w
, client_h
);
1121 // If there is no m_mainWidget between m_widget and m_wxwindow there
1122 // is no need to set the size or position of m_wxwindow.
1127 // send size event to frame
1128 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1129 event
.SetEventObject( this );
1130 GetEventHandler()->ProcessEvent( event
);
1135 void wxTopLevelWindowGTK::OnInternalIdle()
1137 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
1141 // we'll come back later
1143 wxapp_install_idle_handler();
1147 // set the focus if not done yet and if we can already do it
1148 if ( GTK_WIDGET_REALIZED(m_wxwindow
) )
1150 if ( g_delayedFocus
&&
1151 wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this )
1153 wxLogTrace(_T("focus"),
1154 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
1155 g_delayedFocus
->GetClassInfo()->GetClassName(),
1156 g_delayedFocus
->GetLabel().c_str());
1158 g_delayedFocus
->SetFocus();
1159 g_delayedFocus
= NULL
;
1163 wxWindow::OnInternalIdle();
1165 // Synthetize activate events.
1166 if ( g_sendActivateEvent
!= -1 )
1168 bool activate
= g_sendActivateEvent
!= 0;
1170 // if (!activate) wxPrintf( wxT("de") );
1171 // wxPrintf( wxT("activate\n") );
1174 g_sendActivateEvent
= -1;
1176 wxTheApp
->SetActive(activate
, (wxWindow
*)g_lastActiveFrame
);
1180 // ----------------------------------------------------------------------------
1182 // ----------------------------------------------------------------------------
1184 void wxTopLevelWindowGTK::SetTitle( const wxString
&title
)
1186 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1188 if ( title
== m_title
)
1193 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
1196 void wxTopLevelWindowGTK::SetIcon( const wxIcon
&icon
)
1198 SetIcons( wxIconBundle( icon
) );
1201 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle
&icons
)
1203 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1205 wxTopLevelWindowBase::SetIcons( icons
);
1208 size_t max
= icons
.m_icons
.GetCount();
1210 for (size_t i
= 0; i
< max
; i
++)
1212 if (icons
.m_icons
[i
].Ok())
1214 list
= g_list_prepend(list
, icons
.m_icons
[i
].GetPixbuf());
1217 gtk_window_set_icon_list(GTK_WINDOW(m_widget
), list
);
1221 // ----------------------------------------------------------------------------
1222 // frame state: maximized/iconized/normal
1223 // ----------------------------------------------------------------------------
1225 void wxTopLevelWindowGTK::Maximize(bool maximize
)
1228 gtk_window_maximize( GTK_WINDOW( m_widget
) );
1230 gtk_window_unmaximize( GTK_WINDOW( m_widget
) );
1233 bool wxTopLevelWindowGTK::IsMaximized() const
1235 if(!m_widget
->window
)
1238 return gdk_window_get_state(m_widget
->window
) & GDK_WINDOW_STATE_MAXIMIZED
;
1241 void wxTopLevelWindowGTK::Restore()
1243 // "Present" seems similar enough to "restore"
1244 gtk_window_present( GTK_WINDOW( m_widget
) );
1247 void wxTopLevelWindowGTK::Iconize( bool iconize
)
1250 gtk_window_iconify( GTK_WINDOW( m_widget
) );
1252 gtk_window_deiconify( GTK_WINDOW( m_widget
) );
1255 bool wxTopLevelWindowGTK::IsIconized() const
1257 return m_isIconized
;
1260 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
)
1262 if ( iconize
!= m_isIconized
)
1264 m_isIconized
= iconize
;
1265 (void)SendIconizeEvent(iconize
);
1269 void wxTopLevelWindowGTK::AddGrab()
1274 gtk_grab_add( m_widget
);
1275 wxEventLoop().Run();
1276 gtk_grab_remove( m_widget
);
1280 void wxTopLevelWindowGTK::RemoveGrab()
1291 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
)
1295 if (region
.IsEmpty())
1297 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
1301 gdk_window_shape_combine_region(window
, region
.GetRegion(), 0, 0);
1309 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
)
1311 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), false,
1312 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1314 GdkWindow
*window
= NULL
;
1317 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
1318 do_shape_combine_region(window
, region
);
1320 window
= m_widget
->window
;
1321 return do_shape_combine_region(window
, region
);
1324 bool wxTopLevelWindowGTK::IsActive()
1326 return (this == (wxTopLevelWindowGTK
*)g_activeFrame
);
1329 void wxTopLevelWindowGTK::RequestUserAttention(int flags
)
1331 bool new_hint_value
= false;
1333 // FIXME: This is a workaround to focus handling problem
1334 // If RequestUserAttention is called for example right after a wxSleep, OnInternalIdle hasn't
1335 // yet been processed, and the internal focus system is not up to date yet.
1336 // wxYieldIfNeeded ensures the processing of it, but can have unwanted side effects - MR
1337 ::wxYieldIfNeeded();
1339 if(m_urgency_hint
>= 0)
1340 g_source_remove(m_urgency_hint
);
1342 m_urgency_hint
= -2;
1344 if( GTK_WIDGET_REALIZED(m_widget
) && !IsActive() )
1346 new_hint_value
= true;
1348 if (flags
& wxUSER_ATTENTION_INFO
)
1350 m_urgency_hint
= g_timeout_add(5000, (GSourceFunc
)gtk_frame_urgency_timer_callback
, this);
1352 m_urgency_hint
= -1;
1356 #if GTK_CHECK_VERSION(2,7,0)
1357 if(!gtk_check_version(2,7,0))
1358 gtk_window_set_urgency_hint(GTK_WINDOW( m_widget
), new_hint_value
);
1361 wxgtk_window_set_urgency_hint(GTK_WINDOW( m_widget
), new_hint_value
);
1364 void wxTopLevelWindowGTK::SetWindowStyleFlag( long style
)
1366 #if defined(__WXGTK24__) || GTK_CHECK_VERSION(2,2,0)
1367 // Store which styles were changed
1368 long styleChanges
= style
^ m_windowStyle
;
1371 // Process wxWindow styles. This also updates the internal variable
1372 // Therefore m_windowStyle bits carry now the _new_ style values
1373 wxWindow::SetWindowStyleFlag(style
);
1375 // just return for now if widget does not exist yet
1380 if ( (styleChanges
& wxSTAY_ON_TOP
) && !gtk_check_version(2,4,0) )
1381 gtk_window_set_keep_above(GTK_WINDOW(m_widget
), m_windowStyle
& wxSTAY_ON_TOP
);
1383 #if GTK_CHECK_VERSION(2,2,0)
1384 if ( (styleChanges
& wxFRAME_NO_TASKBAR
) && !gtk_check_version(2,2,0) )
1386 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), m_windowStyle
& wxFRAME_NO_TASKBAR
);
1391 #include <X11/Xlib.h>
1393 /* Get the X Window between child and the root window.
1394 This should usually be the WM managed XID */
1395 static Window
wxGetTopmostWindowX11(Display
*dpy
, Window child
)
1397 Window root
, parent
;
1399 unsigned int nchildren
;
1401 XQueryTree(dpy
, child
, &root
, &parent
, &children
, &nchildren
);
1404 while (parent
!= root
) {
1406 XQueryTree(dpy
, child
, &root
, &parent
, &children
, &nchildren
);
1413 bool wxTopLevelWindowGTK::SetTransparent(wxByte alpha
)
1415 if (!m_widget
|| !m_widget
->window
)
1418 Display
* dpy
= GDK_WINDOW_XDISPLAY (m_widget
->window
);
1419 // We need to get the X Window that has the root window as the immediate parent
1420 // and m_widget->window as a child. This should be the X Window that the WM manages and
1421 // from which the opacity property is checked from.
1422 Window win
= wxGetTopmostWindowX11(dpy
, GDK_WINDOW_XID (m_widget
->window
));
1424 unsigned int opacity
= alpha
* 0x1010101;
1426 // Using pure Xlib to not have a GTK version check mess due to gtk2.0 not having GdkDisplay
1428 XDeleteProperty(dpy
, win
, XInternAtom(dpy
, "_NET_WM_WINDOW_OPACITY", False
));
1430 XChangeProperty(dpy
, win
, XInternAtom(dpy
, "_NET_WM_WINDOW_OPACITY", False
),
1431 XA_CARDINAL
, 32, PropModeReplace
,
1432 (unsigned char *) &opacity
, 1L);
1437 bool wxTopLevelWindowGTK::CanSetTransparent()
1439 #if GTK_CHECK_VERSION(2,10,0)
1440 if (!gtk_check_version(2,10,0))
1442 return (gtk_widget_is_composited (m_widget
));
1445 #endif // In case of lower versions than gtk+-2.10.0 we could look for _NET_WM_CM_Sn ourselves
1450 #if 0 // Don't be optimistic here for the sake of wxAUI
1451 int opcode
, event
, error
;
1452 // Check for the existence of a RGBA visual instead?
1453 return XQueryExtension(gdk_x11_get_default_xdisplay (),
1454 "Composite", &opcode
, &event
, &error
);