1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // ============================================================================
12 // ============================================================================
14 // ----------------------------------------------------------------------------
16 // ----------------------------------------------------------------------------
18 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
19 #pragma implementation "toplevel.h"
22 // For compilers that support precompilation, includes "wx.h".
23 #include "wx/wxprec.h"
26 #define XIconifyWindow XICONIFYWINDOW
31 #include "wx/toplevel.h"
33 #include "wx/dialog.h"
34 #include "wx/control.h"
36 #include "wx/dcclient.h"
37 #include "wx/gtk/private.h"
39 #include "wx/settings.h"
40 #include "wx/evtloop.h"
45 #include <gdk/gdkkeysyms.h>
48 #include "wx/gtk/win_gtk.h"
50 #include "wx/unix/utilsx11.h"
53 #include <X11/Xatom.h>
55 // ----------------------------------------------------------------------------
57 // ----------------------------------------------------------------------------
59 extern void wxapp_install_idle_handler();
62 // ----------------------------------------------------------------------------
64 // ----------------------------------------------------------------------------
66 extern wxList wxPendingDelete
;
68 extern int g_openDialogs
;
69 extern wxWindowGTK
*g_delayedFocus
;
71 // the frame that is currently active (i.e. its child has focus). It is
72 // used to generate wxActivateEvents
73 static wxTopLevelWindowGTK
*g_activeFrame
= (wxTopLevelWindowGTK
*) NULL
;
74 static wxTopLevelWindowGTK
*g_lastActiveFrame
= (wxTopLevelWindowGTK
*) NULL
;
76 // if we detect that the app has got/lost the focus, we set this variable to
77 // either TRUE or FALSE and an activate event will be sent during the next
78 // OnIdle() call and it is reset to -1: this value means that we shouldn't
79 // send any activate events at all
80 static int g_sendActivateEvent
= -1;
82 //-----------------------------------------------------------------------------
83 // RequestUserAttention related functions
84 //-----------------------------------------------------------------------------
87 static void wxgtk_window_set_urgency_hint (GtkWindow
*win
,
90 wxASSERT_MSG( GTK_WIDGET_REALIZED(win
), wxT("wxgtk_window_set_urgency_hint: GdkWindow not realized") );
91 GdkWindow
*window
= GTK_WIDGET(win
)->window
;
94 wm_hints
= XGetWMHints(GDK_WINDOW_XDISPLAY(window
), GDK_WINDOW_XWINDOW(window
));
97 wm_hints
= XAllocWMHints();
100 wm_hints
->flags
|= XUrgencyHint
;
102 wm_hints
->flags
&= ~XUrgencyHint
;
104 XSetWMHints(GDK_WINDOW_XDISPLAY(window
), GDK_WINDOW_XWINDOW(window
), wm_hints
);
108 static gint
gtk_frame_urgency_timer_callback( wxTopLevelWindowGTK
*win
)
110 #if defined(__WXGTK20__) && GTK_CHECK_VERSION(2,7,0)
111 if(!gtk_check_version(2,7,0))
112 gtk_window_set_urgency_hint(GTK_WINDOW( win
->m_widget
), FALSE
);
115 wxgtk_window_set_urgency_hint(GTK_WINDOW( win
->m_widget
), FALSE
);
117 win
->m_urgency_hint
= -2;
122 //-----------------------------------------------------------------------------
124 //-----------------------------------------------------------------------------
127 static gint
gtk_frame_focus_in_callback( GtkWidget
*widget
,
128 GdkEvent
*WXUNUSED(event
),
129 wxTopLevelWindowGTK
*win
)
132 wxapp_install_idle_handler();
134 switch ( g_sendActivateEvent
)
137 // we've got focus from outside, synthetize wxActivateEvent
138 g_sendActivateEvent
= 1;
142 // another our window just lost focus, it was already ours before
143 // - don't send any wxActivateEvent
144 g_sendActivateEvent
= -1;
149 g_lastActiveFrame
= g_activeFrame
;
151 // wxPrintf( wxT("active: %s\n"), win->GetTitle().c_str() );
153 // MR: wxRequestUserAttention related block
154 switch( win
->m_urgency_hint
)
157 gtk_timeout_remove( win
->m_urgency_hint
);
158 // no break, fallthrough to remove hint too
160 #if defined(__WXGTK20__) && GTK_CHECK_VERSION(2,7,0)
161 if(!gtk_check_version(2,7,0))
162 gtk_window_set_urgency_hint(GTK_WINDOW( widget
), FALSE
);
166 wxgtk_window_set_urgency_hint(GTK_WINDOW( widget
), FALSE
);
169 win
->m_urgency_hint
= -2;
175 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
);
176 wxActivateEvent
event(wxEVT_ACTIVATE
, true, g_activeFrame
->GetId());
177 event
.SetEventObject(g_activeFrame
);
178 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
184 //-----------------------------------------------------------------------------
186 //-----------------------------------------------------------------------------
189 static gint
gtk_frame_focus_out_callback( GtkWidget
*widget
,
190 GdkEventFocus
*WXUNUSED(gdk_event
),
191 wxTopLevelWindowGTK
*win
)
194 wxapp_install_idle_handler();
196 // if the focus goes out of our app alltogether, OnIdle() will send
197 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
198 // g_sendActivateEvent to -1
199 g_sendActivateEvent
= 0;
201 // wxASSERT_MSG( (g_activeFrame == win), wxT("TLW deactivatd although it wasn't active") );
203 // wxPrintf( wxT("inactive: %s\n"), win->GetTitle().c_str() );
207 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
);
208 wxActivateEvent
event(wxEVT_ACTIVATE
, false, g_activeFrame
->GetId());
209 event
.SetEventObject(g_activeFrame
);
210 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
212 g_activeFrame
= NULL
;
219 //-----------------------------------------------------------------------------
220 // "focus" from m_window
221 //-----------------------------------------------------------------------------
224 static gint
gtk_frame_focus_callback( GtkWidget
*widget
, GtkDirectionType
WXUNUSED(d
), wxWindow
*WXUNUSED(win
) )
227 wxapp_install_idle_handler();
229 // This disables GTK's tab traversal
230 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus" );
235 //-----------------------------------------------------------------------------
237 //-----------------------------------------------------------------------------
240 static void gtk_frame_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxTopLevelWindowGTK
*win
)
243 wxapp_install_idle_handler();
248 if ((win
->m_width
!= alloc
->width
) || (win
->m_height
!= alloc
->height
))
251 wxPrintf( "OnSize from " );
252 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
253 wxPrintf( win->GetClassInfo()->GetClassName() );
254 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
257 (int)alloc->height );
260 win
->m_width
= alloc
->width
;
261 win
->m_height
= alloc
->height
;
262 win
->GtkUpdateSize();
267 //-----------------------------------------------------------------------------
269 //-----------------------------------------------------------------------------
272 static gint
gtk_frame_delete_callback( GtkWidget
*WXUNUSED(widget
), GdkEvent
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
275 wxapp_install_idle_handler();
277 if (win
->IsEnabled() &&
278 (g_openDialogs
== 0 || (win
->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) ||
287 //-----------------------------------------------------------------------------
289 //-----------------------------------------------------------------------------
293 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
296 wxapp_install_idle_handler();
298 if (!win
->m_hasVMT
|| !win
->IsShown())
304 gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y
);
308 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
309 mevent
.SetEventObject( win
);
310 win
->GetEventHandler()->ProcessEvent( mevent
);
316 //-----------------------------------------------------------------------------
317 // "realize" from m_widget
318 //-----------------------------------------------------------------------------
320 // we cannot MWM hints and icons before the widget has been realized,
321 // so we do this directly after realization
325 gtk_frame_realized_callback( GtkWidget
* WXUNUSED(widget
),
326 wxTopLevelWindowGTK
*win
)
329 wxapp_install_idle_handler();
331 // All this is for Motif Window Manager "hints" and is supposed to be
332 // recognized by other WM as well. Not tested.
333 gdk_window_set_decorations(win
->m_widget
->window
,
334 (GdkWMDecoration
)win
->m_gdkDecor
);
335 gdk_window_set_functions(win
->m_widget
->window
,
336 (GdkWMFunction
)win
->m_gdkFunc
);
338 // GTK's shrinking/growing policy
339 if ((win
->m_gdkFunc
& GDK_FUNC_RESIZE
) == 0)
340 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 0, 0, 1);
342 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
345 wxIconBundle iconsOld
= win
->GetIcons();
346 if ( iconsOld
.GetIcon(-1).Ok() )
348 win
->SetIcon( wxNullIcon
);
349 win
->SetIcons( iconsOld
);
354 //-----------------------------------------------------------------------------
355 // "map_event" from m_widget
356 //-----------------------------------------------------------------------------
360 gtk_frame_map_callback( GtkWidget
* WXUNUSED(widget
),
361 GdkEvent
* WXUNUSED(event
),
362 wxTopLevelWindow
*win
)
364 win
->SetIconizeState(false);
368 //-----------------------------------------------------------------------------
369 // "unmap_event" from m_widget
370 //-----------------------------------------------------------------------------
374 gtk_frame_unmap_callback( GtkWidget
* WXUNUSED(widget
),
375 GdkEvent
* WXUNUSED(event
),
376 wxTopLevelWindow
*win
)
378 win
->SetIconizeState(TRUE
);
382 //-----------------------------------------------------------------------------
383 // "expose_event" of m_client
384 //-----------------------------------------------------------------------------
387 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
389 GtkPizza
*pizza
= GTK_PIZZA(widget
);
391 gtk_paint_flat_box (win
->m_widget
->style
,
392 pizza
->bin_window
, GTK_STATE_NORMAL
,
403 //-----------------------------------------------------------------------------
404 // "draw" of m_client
405 //-----------------------------------------------------------------------------
410 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
412 GtkPizza
*pizza
= GTK_PIZZA(widget
);
414 gtk_paint_flat_box (win
->m_widget
->style
,
415 pizza
->bin_window
, GTK_STATE_NORMAL
,
426 // ----------------------------------------------------------------------------
427 // wxTopLevelWindowGTK itself
428 // ----------------------------------------------------------------------------
430 //-----------------------------------------------------------------------------
431 // InsertChild for wxTopLevelWindowGTK
432 //-----------------------------------------------------------------------------
434 /* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
435 * C++ has no virtual methods in a constructor. We have to emulate a
436 * virtual function here as wxWidgets requires different ways to insert
437 * a child in container classes. */
439 static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK
* parent
, wxWindow
* child
)
441 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
443 if (!parent
->m_insertInClientArea
)
445 // these are outside the client area
446 wxTopLevelWindowGTK
* frame
= (wxTopLevelWindowGTK
*) parent
;
447 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
448 GTK_WIDGET(child
->m_widget
),
456 // these are inside the client area
457 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
458 GTK_WIDGET(child
->m_widget
),
465 // resize on OnInternalIdle
466 parent
->GtkUpdateSize();
469 // ----------------------------------------------------------------------------
470 // wxTopLevelWindowGTK creation
471 // ----------------------------------------------------------------------------
473 void wxTopLevelWindowGTK::Init()
478 m_mainWidget
= (GtkWidget
*) NULL
;
479 m_insertInClientArea
= true;
480 m_isIconized
= false;
481 m_fsIsShowing
= false;
482 m_themeEnabled
= true;
483 m_gdkDecor
= m_gdkFunc
= 0;
489 bool wxTopLevelWindowGTK::Create( wxWindow
*parent
,
491 const wxString
& title
,
493 const wxSize
& sizeOrig
,
495 const wxString
&name
)
497 // always create a frame of some reasonable, even if arbitrary, size (at
498 // least for MSW compatibility)
499 wxSize size
= sizeOrig
;
500 size
.x
= WidthDefault(size
.x
);
501 size
.y
= HeightDefault(size
.y
);
503 wxTopLevelWindows
.Append( this );
505 m_needParent
= false;
507 if (!PreCreation( parent
, pos
, size
) ||
508 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
510 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
516 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInTopLevelWindow
;
518 // NB: m_widget may be !=NULL if it was created by derived class' Create,
519 // e.g. in wxTaskBarIconAreaGTK
520 if (m_widget
== NULL
)
522 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)
525 m_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
526 // Tell WM that this is a dialog window and make it center
527 // on parent by default (this is what GtkDialog ctor does):
528 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
529 GDK_WINDOW_TYPE_HINT_DIALOG
);
530 gtk_window_set_position(GTK_WINDOW(m_widget
),
531 GTK_WIN_POS_CENTER_ON_PARENT
);
533 m_widget
= gtk_window_new(GTK_WINDOW_DIALOG
);
538 m_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
539 #if GTK_CHECK_VERSION(2,1,0)
540 if (!gtk_check_version(2,1,0))
542 if (style
& wxFRAME_TOOL_WINDOW
)
544 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
545 GDK_WINDOW_TYPE_HINT_UTILITY
);
547 // On some WMs, like KDE, a TOOL_WINDOW will still show
548 // on the taskbar, but on Gnome a TOOL_WINDOW will not.
549 // For consistency between WMs and with Windows, we
550 // should set the NO_TASKBAR flag which will apply
551 // the set_skip_taskbar_hint if it is available,
552 // ensuring no taskbar entry will appear.
553 style
|= wxFRAME_NO_TASKBAR
;
560 wxWindow
*topParent
= wxGetTopLevelParent(m_parent
);
561 if (topParent
&& (((GTK_IS_WINDOW(topParent
->m_widget
)) &&
562 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) ||
563 (style
& wxFRAME_FLOAT_ON_PARENT
)))
565 gtk_window_set_transient_for( GTK_WINDOW(m_widget
),
566 GTK_WINDOW(topParent
->m_widget
) );
569 #if GTK_CHECK_VERSION(2,2,0)
570 if (!gtk_check_version(2,2,0))
572 if (style
& wxFRAME_NO_TASKBAR
)
574 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), TRUE
);
579 #if GTK_CHECK_VERSION(2,4,0)
580 if (!gtk_check_version(2,4,0))
582 if (style
& wxSTAY_ON_TOP
)
584 gtk_window_set_keep_above(GTK_WINDOW(m_widget
), TRUE
);
590 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), wxGTK_CONV( name
), wxGTK_CONV( name
) );
592 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
593 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
595 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
596 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
598 // m_mainWidget holds the toolbar, the menubar and the client area
599 m_mainWidget
= gtk_pizza_new();
600 gtk_widget_show( m_mainWidget
);
601 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
602 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
604 if (m_miniEdge
== 0) // wxMiniFrame has its own version.
606 // For m_mainWidget themes
607 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
608 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
610 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
611 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
615 // m_wxwindow only represents the client area without toolbar and menubar
616 m_wxwindow
= gtk_pizza_new();
617 gtk_widget_show( m_wxwindow
);
618 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
620 // we donm't allow the frame to get the focus as otherwise
621 // the frame will grab it at arbitrary focus changes
622 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
624 if (m_parent
) m_parent
->AddChild( this );
626 // the user resized the frame by dragging etc.
627 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
628 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
632 if ((m_x
!= -1) || (m_y
!= -1))
633 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
635 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
637 // we cannot set MWM hints and icons before the widget has
638 // been realized, so we do this directly after realization
639 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
640 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
642 // map and unmap for iconized state
643 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
644 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
645 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
646 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
648 // the only way to get the window size is to connect to this event
649 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
650 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
652 // disable native tab traversal
653 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
654 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
657 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
658 GTK_SIGNAL_FUNC(gtk_frame_focus_in_callback
), (gpointer
)this );
659 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
660 GTK_SIGNAL_FUNC(gtk_frame_focus_out_callback
), (gpointer
)this );
663 if ((m_miniEdge
> 0) || (style
& wxSIMPLE_BORDER
) || (style
& wxNO_BORDER
))
670 m_gdkDecor
= (long) GDK_DECOR_BORDER
;
671 m_gdkFunc
= (long) GDK_FUNC_MOVE
;
673 // All this is for Motif Window Manager "hints" and is supposed to be
674 // recognized by other WMs as well.
675 if ((style
& wxCAPTION
) != 0)
677 m_gdkDecor
|= GDK_DECOR_TITLE
;
679 if ((style
& wxCLOSE_BOX
) != 0)
681 m_gdkFunc
|= GDK_FUNC_CLOSE
;
683 if ((style
& wxSYSTEM_MENU
) != 0)
685 m_gdkDecor
|= GDK_DECOR_MENU
;
687 if ((style
& wxMINIMIZE_BOX
) != 0)
689 m_gdkFunc
|= GDK_FUNC_MINIMIZE
;
690 m_gdkDecor
|= GDK_DECOR_MINIMIZE
;
692 if ((style
& wxMAXIMIZE_BOX
) != 0)
694 m_gdkFunc
|= GDK_FUNC_MAXIMIZE
;
695 m_gdkDecor
|= GDK_DECOR_MAXIMIZE
;
697 if ((style
& wxRESIZE_BORDER
) != 0)
699 m_gdkFunc
|= GDK_FUNC_RESIZE
;
700 m_gdkDecor
|= GDK_DECOR_RESIZEH
;
707 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
711 wxASSERT_MSG( FALSE
, _T("Window still grabbed"));
715 m_isBeingDeleted
= true;
717 // it may also be GtkScrolledWindow in the case of an MDI child
718 if (GTK_IS_WINDOW(m_widget
))
720 gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL
);
723 if (g_activeFrame
== this)
724 g_activeFrame
= NULL
;
725 if (g_lastActiveFrame
== this)
726 g_lastActiveFrame
= NULL
;
731 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long style
)
733 if (show
== m_fsIsShowing
)
734 return false; // return what?
736 m_fsIsShowing
= show
;
738 wxX11FullScreenMethod method
=
739 wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(),
740 (WXWindow
)GDK_ROOT_WINDOW());
742 #if GTK_CHECK_VERSION(2,2,0)
743 // NB: gtk_window_fullscreen() uses freedesktop.org's WMspec extensions
744 // to switch to fullscreen, which is not always available. We must
745 // check if WM supports the spec and use legacy methods if it
747 if ( (method
== wxX11_FS_WMSPEC
) && !gtk_check_version(2,2,0) )
750 gtk_window_fullscreen( GTK_WINDOW( m_widget
) );
752 gtk_window_unfullscreen( GTK_WINDOW( m_widget
) );
755 #endif // GTK+ >= 2.2.0
757 GdkWindow
*window
= m_widget
->window
;
761 m_fsSaveFlag
= style
;
762 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
763 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
765 int screen_width
,screen_height
;
766 wxDisplaySize( &screen_width
, &screen_height
);
768 gint client_x
, client_y
, root_x
, root_y
;
771 if (method
!= wxX11_FS_WMSPEC
)
773 // don't do it always, Metacity hates it
774 m_fsSaveGdkFunc
= m_gdkFunc
;
775 m_fsSaveGdkDecor
= m_gdkDecor
;
776 m_gdkFunc
= m_gdkDecor
= 0;
777 gdk_window_set_decorations(window
, (GdkWMDecoration
)0);
778 gdk_window_set_functions(window
, (GdkWMFunction
)0);
781 gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
);
782 gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
,
783 &width
, &height
, NULL
);
785 gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
,
786 screen_width
+ 1, screen_height
+ 1);
788 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
789 (WXWindow
)GDK_ROOT_WINDOW(),
790 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
791 show
, &m_fsSaveFrame
, method
);
795 if (method
!= wxX11_FS_WMSPEC
)
797 // don't do it always, Metacity hates it
798 m_gdkFunc
= m_fsSaveGdkFunc
;
799 m_gdkDecor
= m_fsSaveGdkDecor
;
800 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
);
801 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
);
804 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
805 (WXWindow
)GDK_ROOT_WINDOW(),
806 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
807 show
, &m_fsSaveFrame
, method
);
809 SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
,
810 m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
814 // documented behaviour is to show the window if it's still hidden when
815 // showing it full screen
816 if ( show
&& !IsShown() )
822 // ----------------------------------------------------------------------------
823 // overridden wxWindow methods
824 // ----------------------------------------------------------------------------
826 bool wxTopLevelWindowGTK::Show( bool show
)
828 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
830 if (show
&& !m_sizeSet
)
832 /* by calling GtkOnSize here, we don't have to call
833 either after showing the frame, which would entail
834 much ugly flicker or from within the size_allocate
835 handler, because GTK 1.1.X forbids that. */
837 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
841 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
843 return wxWindow::Show( show
);
846 void wxTopLevelWindowGTK::Raise()
849 gtk_window_present( GTK_WINDOW( m_widget
) );
855 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
857 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
860 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
862 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
864 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
865 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
875 int old_width
= m_width
;
876 int old_height
= m_height
;
878 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
880 if (x
!= -1) m_x
= x
;
881 if (y
!= -1) m_y
= y
;
888 if (width
!= -1) m_width
= width
;
889 if (height
!= -1) m_height
= height
;
892 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
894 if (width == -1) m_width = 80;
897 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
899 if (height == -1) m_height = 26;
903 int minWidth
= GetMinWidth(),
904 minHeight
= GetMinHeight(),
905 maxWidth
= GetMaxWidth(),
906 maxHeight
= GetMaxHeight();
909 // GPE's window manager doesn't like size hints
910 // at all, esp. when the user has to use the
918 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
919 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
920 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
921 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
923 if ((m_x
!= -1) || (m_y
!= -1))
925 if ((m_x
!= old_x
) || (m_y
!= old_y
))
927 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
931 if ((m_width
!= old_width
) || (m_height
!= old_height
))
933 if (m_widget
->window
)
934 gdk_window_resize( m_widget
->window
, m_width
, m_height
);
936 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
938 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
939 done either directly before the frame is shown or in idle time
940 so that different calls to SetSize() don't lead to flicker. */
947 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height
) const
949 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
951 wxWindow::DoGetClientSize( width
, height
);
955 *height
-= m_miniEdge
*2 + m_miniTitle
;
959 *width
-= m_miniEdge
*2;
963 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height
)
965 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
968 width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0);
971 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
972 int width
, int height
)
974 // due to a bug in gtk, x,y are always 0
979 if (m_resizing
) return;
982 if ( m_wxwindow
== NULL
) return;
987 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
988 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
989 set in wxFrame::Create so it is used to check what kind of frame we
990 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
991 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
992 importantly) m_mainWidget */
994 int minWidth
= GetMinWidth(),
995 minHeight
= GetMinHeight(),
996 maxWidth
= GetMaxWidth(),
997 maxHeight
= GetMaxHeight();
1000 // GPE's window manager doesn't like size hints
1001 // at all, esp. when the user has to use the
1002 // virtual keyboard.
1009 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
1010 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
1011 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
1012 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
1017 gint flag
= 0; // GDK_HINT_POS;
1020 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
1021 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
1023 geom
.min_width
= minWidth
;
1024 geom
.min_height
= minHeight
;
1026 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
1027 // maxHeight or maxWidth is set, we must set them both, else the
1028 // remaining -1 will be taken literally.
1030 // I'm certain this also happens elsewhere, and is the probable
1031 // cause of other such things as:
1032 // Gtk-WARNING **: gtk_widget_size_allocate():
1033 // attempt to allocate widget with width 65535 and height 600
1034 // but I don't have time to track them all now..
1036 // Really we need to encapulate all this height/width business and
1037 // stop any old method from ripping at the members directly and
1038 // scattering -1's without regard for who might resolve them later.
1040 geom
.max_width
= ( maxHeight
== -1 ) ? maxWidth
1041 : ( maxWidth
== -1 ) ? wxGetDisplaySize().GetWidth()
1044 geom
.max_height
= ( maxWidth
== -1 ) ? maxHeight
// ( == -1 here )
1045 : ( maxHeight
== -1 ) ? wxGetDisplaySize().GetHeight()
1048 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
1051 (GdkWindowHints
) flag
);
1053 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
1054 * menubar, the toolbar and the client area, which is represented by
1056 * this hurts in the eye, but I don't want to call SetSize()
1057 * because I don't want to call any non-native functions here. */
1059 int client_x
= m_miniEdge
;
1060 int client_y
= m_miniEdge
+ m_miniTitle
;
1061 int client_w
= m_width
- 2*m_miniEdge
;
1062 int client_h
= m_height
- 2*m_miniEdge
- m_miniTitle
;
1064 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
1066 client_x
, client_y
, client_w
, client_h
);
1070 // If there is no m_mainWidget between m_widget and m_wxwindow there
1071 // is no need to set the size or position of m_wxwindow.
1076 // send size event to frame
1077 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1078 event
.SetEventObject( this );
1079 GetEventHandler()->ProcessEvent( event
);
1084 void wxTopLevelWindowGTK::OnInternalIdle()
1086 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
1088 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
1090 // we'll come back later
1092 wxapp_install_idle_handler();
1096 // set the focus if not done yet and if we can already do it
1097 if ( GTK_WIDGET_REALIZED(m_wxwindow
) )
1099 if ( g_delayedFocus
&&
1100 wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this )
1102 wxLogTrace(_T("focus"),
1103 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
1104 g_delayedFocus
->GetClassInfo()->GetClassName(),
1105 g_delayedFocus
->GetLabel().c_str());
1107 g_delayedFocus
->SetFocus();
1108 g_delayedFocus
= NULL
;
1112 wxWindow::OnInternalIdle();
1114 // Synthetize activate events.
1115 if ( g_sendActivateEvent
!= -1 )
1117 bool activate
= g_sendActivateEvent
!= 0;
1119 // if (!activate) wxPrintf( wxT("de") );
1120 // wxPrintf( wxT("activate\n") );
1123 g_sendActivateEvent
= -1;
1125 wxTheApp
->SetActive(activate
, (wxWindow
*)g_lastActiveFrame
);
1129 // ----------------------------------------------------------------------------
1131 // ----------------------------------------------------------------------------
1133 void wxTopLevelWindowGTK::SetTitle( const wxString
&title
)
1135 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1138 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
1141 void wxTopLevelWindowGTK::SetIcon( const wxIcon
&icon
)
1143 SetIcons( wxIconBundle( icon
) );
1146 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle
&icons
)
1148 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1150 wxTopLevelWindowBase::SetIcons( icons
);
1154 size_t max
= icons
.m_icons
.GetCount();
1156 for (size_t i
= 0; i
< max
; i
++)
1158 if (icons
.m_icons
[i
].Ok())
1160 list
= g_list_prepend(list
, icons
.m_icons
[i
].GetPixbuf());
1163 gtk_window_set_icon_list(GTK_WINDOW(m_widget
), list
);
1166 #else // !__WXGTK20__
1167 GdkWindow
* window
= m_widget
->window
;
1171 wxIcon icon
= icons
.GetIcon(-1);
1174 wxMask
*mask
= icon
.GetMask();
1175 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1176 if (mask
) bm
= mask
->GetBitmap();
1178 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
1181 wxSetIconsX11( (WXDisplay
*)GDK_WINDOW_XDISPLAY( window
),
1182 (WXWindow
)GDK_WINDOW_XWINDOW( window
), icons
);
1183 #endif // !__WXGTK20__
1186 // ----------------------------------------------------------------------------
1187 // frame state: maximized/iconized/normal
1188 // ----------------------------------------------------------------------------
1190 void wxTopLevelWindowGTK::Maximize(bool maximize
)
1194 gtk_window_maximize( GTK_WINDOW( m_widget
) );
1196 gtk_window_unmaximize( GTK_WINDOW( m_widget
) );
1198 wxFAIL_MSG( _T("not implemented") );
1202 bool wxTopLevelWindowGTK::IsMaximized() const
1205 if(!m_widget
->window
)
1208 return gdk_window_get_state(m_widget
->window
) & GDK_WINDOW_STATE_MAXIMIZED
;
1210 // wxFAIL_MSG( _T("not implemented") );
1212 // This is an approximation
1217 void wxTopLevelWindowGTK::Restore()
1220 // "Present" seems similar enough to "restore"
1221 gtk_window_present( GTK_WINDOW( m_widget
) );
1223 wxFAIL_MSG( _T("not implemented") );
1227 void wxTopLevelWindowGTK::Iconize( bool iconize
)
1231 gtk_window_iconify( GTK_WINDOW( m_widget
) );
1233 gtk_window_deiconify( GTK_WINDOW( m_widget
) );
1237 GdkWindow
*window
= m_widget
->window
;
1239 // you should do it later, for example from OnCreate() handler
1240 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
1242 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
1243 GDK_WINDOW_XWINDOW( window
),
1244 DefaultScreen( GDK_DISPLAY() ) );
1249 bool wxTopLevelWindowGTK::IsIconized() const
1251 return m_isIconized
;
1254 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
)
1256 if ( iconize
!= m_isIconized
)
1258 m_isIconized
= iconize
;
1259 (void)SendIconizeEvent(iconize
);
1263 void wxTopLevelWindowGTK::AddGrab()
1268 gtk_grab_add( m_widget
);
1269 wxEventLoop().Run();
1270 gtk_grab_remove( m_widget
);
1274 void wxTopLevelWindowGTK::RemoveGrab()
1285 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
)
1289 if (region
.IsEmpty())
1291 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
1296 gdk_window_shape_combine_region(window
, region
.GetRegion(), 0, 0);
1298 wxBitmap bmp
= region
.ConvertToBitmap();
1299 bmp
.SetMask(new wxMask(bmp
, *wxBLACK
));
1300 GdkBitmap
* mask
= bmp
.GetMask()->GetBitmap();
1301 gdk_window_shape_combine_mask(window
, mask
, 0, 0);
1310 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
)
1312 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), false,
1313 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1315 GdkWindow
*window
= NULL
;
1318 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
1319 do_shape_combine_region(window
, region
);
1321 window
= m_widget
->window
;
1322 return do_shape_combine_region(window
, region
);
1325 bool wxTopLevelWindowGTK::IsActive()
1327 return (this == (wxTopLevelWindowGTK
*)g_activeFrame
);
1330 void wxTopLevelWindowGTK::RequestUserAttention(int flags
)
1332 bool new_hint_value
= false;
1334 // FIXME: This is a workaround to focus handling problem
1335 // If RequestUserAttention is called for example right after a wxSleep, OnInternalIdle hasn't
1336 // yet been processed, and the internal focus system is not up to date yet.
1337 // wxYieldIfNeeded ensures the processing of it, but can have unwanted side effects - MR
1338 ::wxYieldIfNeeded();
1340 if(m_urgency_hint
>= 0)
1341 gtk_timeout_remove(m_urgency_hint
);
1343 m_urgency_hint
= -2;
1345 if( GTK_WIDGET_REALIZED(m_widget
) && !IsActive() )
1347 new_hint_value
= true;
1349 if (flags
& wxUSER_ATTENTION_INFO
)
1351 m_urgency_hint
= gtk_timeout_add(5000, (GtkFunction
)gtk_frame_urgency_timer_callback
, this);
1353 m_urgency_hint
= -1;
1357 #if defined(__WXGTK20__) && GTK_CHECK_VERSION(2,7,0)
1358 if(!gtk_check_version(2,7,0))
1359 gtk_window_set_urgency_hint(GTK_WINDOW( m_widget
), new_hint_value
);
1362 wxgtk_window_set_urgency_hint(GTK_WINDOW( m_widget
), new_hint_value
);