1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/toplevel.cpp 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 // ============================================================================ 
  12 // ============================================================================ 
  14 // ---------------------------------------------------------------------------- 
  16 // ---------------------------------------------------------------------------- 
  18 // For compilers that support precompilation, includes "wx.h". 
  19 #include "wx/wxprec.h" 
  22 #define XIconifyWindow XICONIFYWINDOW 
  27 #include "wx/toplevel.h" 
  29 #include "wx/dialog.h" 
  30 #include "wx/control.h" 
  32 #include "wx/dcclient.h" 
  33 #include "wx/gtk/private.h" 
  35 #include "wx/settings.h" 
  36 #include "wx/evtloop.h" 
  41 #include <gdk/gdkkeysyms.h> 
  44 #include "wx/gtk/win_gtk.h" 
  46 #include "wx/unix/utilsx11.h" 
  49 #include <X11/Xatom.h> 
  51 // ---------------------------------------------------------------------------- 
  53 // ---------------------------------------------------------------------------- 
  55 extern wxList           wxPendingDelete
; 
  57 extern int              g_openDialogs
; 
  58 extern wxWindowGTK     
*g_delayedFocus
; 
  60 // the frame that is currently active (i.e. its child has focus). It is 
  61 // used to generate wxActivateEvents 
  62 static wxTopLevelWindowGTK 
*g_activeFrame 
= (wxTopLevelWindowGTK
*) NULL
; 
  63 static wxTopLevelWindowGTK 
*g_lastActiveFrame 
= (wxTopLevelWindowGTK
*) NULL
; 
  65 // if we detect that the app has got/lost the focus, we set this variable to 
  66 // either TRUE or FALSE and an activate event will be sent during the next 
  67 // OnIdle() call and it is reset to -1: this value means that we shouldn't 
  68 // send any activate events at all 
  69 static int g_sendActivateEvent 
= -1; 
  71 //----------------------------------------------------------------------------- 
  72 // RequestUserAttention related functions 
  73 //----------------------------------------------------------------------------- 
  76 static void wxgtk_window_set_urgency_hint (GtkWindow 
*win
, 
  79     wxASSERT_MSG( GTK_WIDGET_REALIZED(win
), wxT("wxgtk_window_set_urgency_hint: GdkWindow not realized") ); 
  80     GdkWindow 
*window 
= GTK_WIDGET(win
)->window
; 
  83     wm_hints 
= XGetWMHints(GDK_WINDOW_XDISPLAY(window
), GDK_WINDOW_XWINDOW(window
)); 
  86         wm_hints 
= XAllocWMHints(); 
  89         wm_hints
->flags 
|= XUrgencyHint
; 
  91         wm_hints
->flags 
&= ~XUrgencyHint
; 
  93     XSetWMHints(GDK_WINDOW_XDISPLAY(window
), GDK_WINDOW_XWINDOW(window
), wm_hints
); 
  97 static gboolean 
gtk_frame_urgency_timer_callback( wxTopLevelWindowGTK 
*win 
) 
  99 #if defined(__WXGTK20__) && GTK_CHECK_VERSION(2,7,0) 
 100     if(!gtk_check_version(2,7,0)) 
 101         gtk_window_set_urgency_hint(GTK_WINDOW( win
->m_widget 
), FALSE
); 
 104         wxgtk_window_set_urgency_hint(GTK_WINDOW( win
->m_widget 
), FALSE
); 
 106     win
->m_urgency_hint 
= -2; 
 111 //----------------------------------------------------------------------------- 
 113 //----------------------------------------------------------------------------- 
 116 static gboolean 
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             g_source_remove( win
->m_urgency_hint 
); 
 147             // no break, fallthrough to remove hint too 
 149 #if defined(__WXGTK20__) && GTK_CHECK_VERSION(2,7,0) 
 150             if(!gtk_check_version(2,7,0)) 
 151                 gtk_window_set_urgency_hint(GTK_WINDOW( widget 
), FALSE
); 
 155                 wxgtk_window_set_urgency_hint(GTK_WINDOW( widget 
), FALSE
); 
 158             win
->m_urgency_hint 
= -2; 
 164     wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
); 
 165     wxActivateEvent 
event(wxEVT_ACTIVATE
, true, g_activeFrame
->GetId()); 
 166     event
.SetEventObject(g_activeFrame
); 
 167     g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
 173 //----------------------------------------------------------------------------- 
 175 //----------------------------------------------------------------------------- 
 178 static gboolean 
gtk_frame_focus_out_callback( GtkWidget 
*widget
, 
 179                                           GdkEventFocus 
*WXUNUSED(gdk_event
), 
 180                                           wxTopLevelWindowGTK 
*win 
) 
 183         wxapp_install_idle_handler(); 
 185     // if the focus goes out of our app alltogether, OnIdle() will send 
 186     // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset 
 187     // g_sendActivateEvent to -1 
 188     g_sendActivateEvent 
= 0; 
 190     // wxASSERT_MSG( (g_activeFrame == win), wxT("TLW deactivatd although it wasn't active") ); 
 192     // wxPrintf( wxT("inactive: %s\n"), win->GetTitle().c_str() ); 
 196         wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
); 
 197         wxActivateEvent 
event(wxEVT_ACTIVATE
, false, g_activeFrame
->GetId()); 
 198         event
.SetEventObject(g_activeFrame
); 
 199         g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
 201         g_activeFrame 
= NULL
; 
 208 //----------------------------------------------------------------------------- 
 209 // "focus" from m_window 
 210 //----------------------------------------------------------------------------- 
 213 static gboolean 
gtk_frame_focus_callback( GtkWidget 
*widget
, GtkDirectionType 
WXUNUSED(d
), wxWindow 
*WXUNUSED(win
) ) 
 216         wxapp_install_idle_handler(); 
 218     // This disables GTK's tab traversal 
 219     g_signal_stop_emission_by_name (widget
, "focus"); 
 224 //----------------------------------------------------------------------------- 
 226 //----------------------------------------------------------------------------- 
 229 static void gtk_frame_size_callback( GtkWidget 
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxTopLevelWindowGTK 
*win 
) 
 232         wxapp_install_idle_handler(); 
 237     if ((win
->m_width 
!= alloc
->width
) || (win
->m_height 
!= alloc
->height
)) 
 240         wxPrintf( "OnSize from " ); 
 241         if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
 242            wxPrintf( win->GetClassInfo()->GetClassName() ); 
 243         wxPrintf( " %d %d %d %d\n", (int)alloc->x, 
 246                                 (int)alloc->height ); 
 249         win
->m_width 
= alloc
->width
; 
 250         win
->m_height 
= alloc
->height
; 
 251         win
->GtkUpdateSize(); 
 256 //----------------------------------------------------------------------------- 
 258 //----------------------------------------------------------------------------- 
 262 gtk_frame_delete_callback( GtkWidget 
*WXUNUSED(widget
), 
 263                            GdkEvent 
*WXUNUSED(event
), 
 264                            wxTopLevelWindowGTK 
*win 
) 
 267         wxapp_install_idle_handler(); 
 269     if (win
->IsEnabled() && 
 270         (g_openDialogs 
== 0 || (win
->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) || 
 279 //----------------------------------------------------------------------------- 
 281 //----------------------------------------------------------------------------- 
 285 gtk_frame_configure_callback( GtkWidget 
*WXUNUSED(widget
), 
 286                               GdkEventConfigure 
*WXUNUSED(event
), 
 287                               wxTopLevelWindowGTK 
*win 
) 
 290         wxapp_install_idle_handler(); 
 292     if (!win
->m_hasVMT 
|| !win
->IsShown()) 
 298     gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y 
); 
 302     wxMoveEvent 
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() ); 
 303     mevent
.SetEventObject( win 
); 
 304     win
->GetEventHandler()->ProcessEvent( mevent 
); 
 310 //----------------------------------------------------------------------------- 
 311 // "realize" from m_widget 
 312 //----------------------------------------------------------------------------- 
 314 // we cannot MWM hints and icons before the widget has been realized, 
 315 // so we do this directly after realization 
 319 gtk_frame_realized_callback( GtkWidget 
* WXUNUSED(widget
), 
 320                              wxTopLevelWindowGTK 
*win 
) 
 323         wxapp_install_idle_handler(); 
 325     // All this is for Motif Window Manager "hints" and is supposed to be 
 326     // recognized by other WM as well. Not tested. 
 327     gdk_window_set_decorations(win
->m_widget
->window
, 
 328                                (GdkWMDecoration
)win
->m_gdkDecor
); 
 329     gdk_window_set_functions(win
->m_widget
->window
, 
 330                                (GdkWMFunction
)win
->m_gdkFunc
); 
 332     // GTK's shrinking/growing policy 
 333     if ((win
->m_gdkFunc 
& GDK_FUNC_RESIZE
) == 0) 
 334         gtk_window_set_resizable(GTK_WINDOW(win
->m_widget
), FALSE
); 
 336         gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1); 
 339     wxIconBundle iconsOld 
= win
->GetIcons(); 
 340     if ( iconsOld
.GetIcon(-1).Ok() ) 
 342         win
->SetIcon( wxNullIcon 
); 
 343         win
->SetIcons( iconsOld 
); 
 348 //----------------------------------------------------------------------------- 
 349 // "map_event" from m_widget 
 350 //----------------------------------------------------------------------------- 
 354 gtk_frame_map_callback( GtkWidget 
* WXUNUSED(widget
), 
 355                         GdkEvent 
* WXUNUSED(event
), 
 356                         wxTopLevelWindow 
*win 
) 
 358     win
->SetIconizeState(false); 
 362 //----------------------------------------------------------------------------- 
 363 // "unmap_event" from m_widget 
 364 //----------------------------------------------------------------------------- 
 368 gtk_frame_unmap_callback( GtkWidget 
* WXUNUSED(widget
), 
 369                           GdkEvent 
* WXUNUSED(event
), 
 370                           wxTopLevelWindow 
*win 
) 
 372     win
->SetIconizeState(true); 
 376 //----------------------------------------------------------------------------- 
 377 // "expose_event" of m_client 
 378 //----------------------------------------------------------------------------- 
 382 gtk_window_expose_callback( GtkWidget 
*widget
, 
 383                             GdkEventExpose 
*gdk_event
, 
 386     GtkPizza 
*pizza 
= GTK_PIZZA(widget
); 
 388     gtk_paint_flat_box (win
->m_widget
->style
, 
 389                         pizza
->bin_window
, GTK_STATE_NORMAL
, 
 400 // ---------------------------------------------------------------------------- 
 401 // wxTopLevelWindowGTK itself 
 402 // ---------------------------------------------------------------------------- 
 404 //----------------------------------------------------------------------------- 
 405 // InsertChild for wxTopLevelWindowGTK 
 406 //----------------------------------------------------------------------------- 
 408 /* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because 
 409  * C++ has no virtual methods in a constructor. We have to emulate a 
 410  * virtual function here as wxWidgets requires different ways to insert 
 411  * a child in container classes. */ 
 413 static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK
* parent
, wxWindow
* child 
) 
 415     wxASSERT( GTK_IS_WIDGET(child
->m_widget
) ); 
 417     if (!parent
->m_insertInClientArea
) 
 419         // these are outside the client area 
 420         wxTopLevelWindowGTK
* frame 
= (wxTopLevelWindowGTK
*) parent
; 
 421         gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
), 
 422                          GTK_WIDGET(child
->m_widget
), 
 430         // these are inside the client area 
 431         gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
), 
 432                          GTK_WIDGET(child
->m_widget
), 
 439     // resize on OnInternalIdle 
 440     parent
->GtkUpdateSize(); 
 443 // ---------------------------------------------------------------------------- 
 444 // wxTopLevelWindowGTK creation 
 445 // ---------------------------------------------------------------------------- 
 447 void wxTopLevelWindowGTK::Init() 
 452     m_mainWidget 
= (GtkWidget
*) NULL
; 
 453     m_insertInClientArea 
= true; 
 454     m_isIconized 
= false; 
 455     m_fsIsShowing 
= false; 
 456     m_themeEnabled 
= true; 
 457     m_gdkDecor 
= m_gdkFunc 
= 0; 
 463 bool wxTopLevelWindowGTK::Create( wxWindow 
*parent
, 
 465                                   const wxString
& title
, 
 467                                   const wxSize
& sizeOrig
, 
 469                                   const wxString 
&name 
) 
 471     // always create a frame of some reasonable, even if arbitrary, size (at 
 472     // least for MSW compatibility) 
 473     wxSize size 
= sizeOrig
; 
 474     size
.x 
= WidthDefault(size
.x
); 
 475     size
.y 
= HeightDefault(size
.y
); 
 477     wxTopLevelWindows
.Append( this ); 
 479     m_needParent 
= false; 
 481     if (!PreCreation( parent
, pos
, size 
) || 
 482         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
 484         wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") ); 
 490     m_insertCallback 
= (wxInsertChildFunction
) wxInsertChildInTopLevelWindow
; 
 492     // NB: m_widget may be !=NULL if it was created by derived class' Create, 
 493     //     e.g. in wxTaskBarIconAreaGTK 
 494     if (m_widget 
== NULL
) 
 496         if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) 
 498             m_widget 
= gtk_window_new(GTK_WINDOW_TOPLEVEL
); 
 499             // Tell WM that this is a dialog window and make it center 
 500             // on parent by default (this is what GtkDialog ctor does): 
 501             gtk_window_set_type_hint(GTK_WINDOW(m_widget
), 
 502                                      GDK_WINDOW_TYPE_HINT_DIALOG
); 
 503             gtk_window_set_position(GTK_WINDOW(m_widget
), 
 504                                     GTK_WIN_POS_CENTER_ON_PARENT
); 
 508             m_widget 
= gtk_window_new(GTK_WINDOW_TOPLEVEL
); 
 509 #if GTK_CHECK_VERSION(2,1,0) 
 510             if (!gtk_check_version(2,1,0)) 
 512                 if (style 
& wxFRAME_TOOL_WINDOW
) 
 514                     gtk_window_set_type_hint(GTK_WINDOW(m_widget
), 
 515                                              GDK_WINDOW_TYPE_HINT_UTILITY
); 
 517                     // On some WMs, like KDE, a TOOL_WINDOW will still show 
 518                     // on the taskbar, but on Gnome a TOOL_WINDOW will not. 
 519                     // For consistency between WMs and with Windows, we 
 520                     // should set the NO_TASKBAR flag which will apply 
 521                     // the set_skip_taskbar_hint if it is available, 
 522                     // ensuring no taskbar entry will appear. 
 523                     style 
|= wxFRAME_NO_TASKBAR
; 
 530     wxWindow 
*topParent 
= wxGetTopLevelParent(m_parent
); 
 531     if (topParent 
&& (((GTK_IS_WINDOW(topParent
->m_widget
)) && 
 532                        (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) || 
 533                        (style 
& wxFRAME_FLOAT_ON_PARENT
))) 
 535         gtk_window_set_transient_for( GTK_WINDOW(m_widget
), 
 536                                       GTK_WINDOW(topParent
->m_widget
) ); 
 539 #if GTK_CHECK_VERSION(2,2,0) 
 540     if (!gtk_check_version(2,2,0)) 
 542         if (style 
& wxFRAME_NO_TASKBAR
) 
 544             gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), TRUE
); 
 550     if (!gtk_check_version(2,4,0)) 
 552         if (style 
& wxSTAY_ON_TOP
) 
 554             gtk_window_set_keep_above(GTK_WINDOW(m_widget
), TRUE
); 
 560         gtk_window_set_wmclass( GTK_WINDOW(m_widget
), wxGTK_CONV( name 
), wxGTK_CONV( name 
) ); 
 562     gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title 
) ); 
 563     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
 565     g_signal_connect (m_widget
, "delete_event", 
 566                       G_CALLBACK (gtk_frame_delete_callback
), this); 
 568     // m_mainWidget holds the toolbar, the menubar and the client area 
 569     m_mainWidget 
= gtk_pizza_new(); 
 570     gtk_widget_show( m_mainWidget 
); 
 571     GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS 
); 
 572     gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget 
); 
 574     if (m_miniEdge 
== 0) // wxMiniFrame has its own version. 
 576        // For m_mainWidget themes 
 577        g_signal_connect (m_mainWidget
, "expose_event", 
 578                          G_CALLBACK (gtk_window_expose_callback
), this); 
 581     // m_wxwindow only represents the client area without toolbar and menubar 
 582     m_wxwindow 
= gtk_pizza_new(); 
 583     gtk_widget_show( m_wxwindow 
); 
 584     gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow 
); 
 586     // we donm't allow the frame to get the focus as otherwise 
 587     // the frame will grab it at arbitrary focus changes 
 588     GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
 590     if (m_parent
) m_parent
->AddChild( this ); 
 592     // the user resized the frame by dragging etc. 
 593     g_signal_connect (m_widget
, "size_allocate", 
 594                       G_CALLBACK (gtk_frame_size_callback
), this); 
 598     if ((m_x 
!= -1) || (m_y 
!= -1)) 
 599         gtk_widget_set_uposition( m_widget
, m_x
, m_y 
); 
 601     gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height 
); 
 603     //  we cannot set MWM hints and icons before the widget has 
 604     //  been realized, so we do this directly after realization 
 605     g_signal_connect (m_widget
, "realize", 
 606                       G_CALLBACK (gtk_frame_realized_callback
), this); 
 608     // map and unmap for iconized state 
 609     g_signal_connect (m_widget
, "map_event", 
 610                       G_CALLBACK (gtk_frame_map_callback
), this); 
 611     g_signal_connect (m_widget
, "unmap_event", 
 612                       G_CALLBACK (gtk_frame_unmap_callback
), this); 
 614     // the only way to get the window size is to connect to this event 
 615     g_signal_connect (m_widget
, "configure_event", 
 616                       G_CALLBACK (gtk_frame_configure_callback
), this); 
 618     // disable native tab traversal 
 619     g_signal_connect (m_widget
, "focus", 
 620                       G_CALLBACK (gtk_frame_focus_callback
), this); 
 623     g_signal_connect_after (m_widget
, "focus_in_event", 
 624                       G_CALLBACK (gtk_frame_focus_in_callback
), this); 
 625     g_signal_connect_after (m_widget
, "focus_out_event", 
 626                       G_CALLBACK (gtk_frame_focus_out_callback
), this); 
 629     if ((m_miniEdge 
> 0) || (style 
& wxSIMPLE_BORDER
) || (style 
& wxNO_BORDER
)) 
 636         m_gdkDecor 
= (long) GDK_DECOR_BORDER
; 
 637         m_gdkFunc 
= (long) GDK_FUNC_MOVE
; 
 639         // All this is for Motif Window Manager "hints" and is supposed to be 
 640         // recognized by other WMs as well. 
 641         if ((style 
& wxCAPTION
) != 0) 
 643             m_gdkDecor 
|= GDK_DECOR_TITLE
; 
 645         if ((style 
& wxCLOSE_BOX
) != 0) 
 647             m_gdkFunc 
|= GDK_FUNC_CLOSE
; 
 649         if ((style 
& wxSYSTEM_MENU
) != 0) 
 651             m_gdkDecor 
|= GDK_DECOR_MENU
; 
 653         if ((style 
& wxMINIMIZE_BOX
) != 0) 
 655             m_gdkFunc 
|= GDK_FUNC_MINIMIZE
; 
 656             m_gdkDecor 
|= GDK_DECOR_MINIMIZE
; 
 658         if ((style 
& wxMAXIMIZE_BOX
) != 0) 
 660             m_gdkFunc 
|= GDK_FUNC_MAXIMIZE
; 
 661             m_gdkDecor 
|= GDK_DECOR_MAXIMIZE
; 
 663         if ((style 
& wxRESIZE_BORDER
) != 0) 
 665            m_gdkFunc 
|= GDK_FUNC_RESIZE
; 
 666            m_gdkDecor 
|= GDK_DECOR_RESIZEH
; 
 673 wxTopLevelWindowGTK::~wxTopLevelWindowGTK() 
 677         wxASSERT_MSG( false, _T("Window still grabbed")); 
 681     m_isBeingDeleted 
= true; 
 683     // it may also be GtkScrolledWindow in the case of an MDI child 
 684     if (GTK_IS_WINDOW(m_widget
)) 
 686         gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL 
); 
 689     if (g_activeFrame 
== this) 
 690         g_activeFrame 
= NULL
; 
 691     if (g_lastActiveFrame 
== this) 
 692         g_lastActiveFrame 
= NULL
; 
 697 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long style 
) 
 699     if (show 
== m_fsIsShowing
) 
 700         return false; // return what? 
 702     m_fsIsShowing 
= show
; 
 704     wxX11FullScreenMethod method 
= 
 705         wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(), 
 706                                  (WXWindow
)GDK_ROOT_WINDOW()); 
 708 #if GTK_CHECK_VERSION(2,2,0) 
 709     // NB: gtk_window_fullscreen() uses freedesktop.org's WMspec extensions 
 710     //     to switch to fullscreen, which is not always available. We must 
 711     //     check if WM supports the spec and use legacy methods if it 
 713     if ( (method 
== wxX11_FS_WMSPEC
) && !gtk_check_version(2,2,0) ) 
 716             gtk_window_fullscreen( GTK_WINDOW( m_widget 
) ); 
 718             gtk_window_unfullscreen( GTK_WINDOW( m_widget 
) ); 
 721 #endif // GTK+ >= 2.2.0 
 723         GdkWindow 
*window 
= m_widget
->window
; 
 727             m_fsSaveFlag 
= style
; 
 728             GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y 
); 
 729             GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height 
); 
 731             int screen_width
,screen_height
; 
 732             wxDisplaySize( &screen_width
, &screen_height 
); 
 734             gint client_x
, client_y
, root_x
, root_y
; 
 737             if (method 
!= wxX11_FS_WMSPEC
) 
 739                 // don't do it always, Metacity hates it 
 740                 m_fsSaveGdkFunc 
= m_gdkFunc
; 
 741                 m_fsSaveGdkDecor 
= m_gdkDecor
; 
 742                 m_gdkFunc 
= m_gdkDecor 
= 0; 
 743                 gdk_window_set_decorations(window
, (GdkWMDecoration
)0); 
 744                 gdk_window_set_functions(window
, (GdkWMFunction
)0); 
 747             gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
); 
 748             gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
, 
 749                          &width
, &height
, NULL
); 
 751             gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
, 
 752                         screen_width 
+ 1, screen_height 
+ 1); 
 754             wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(), 
 755                                     (WXWindow
)GDK_ROOT_WINDOW(), 
 756                                     (WXWindow
)GDK_WINDOW_XWINDOW(window
), 
 757                                     show
, &m_fsSaveFrame
, method
); 
 761             if (method 
!= wxX11_FS_WMSPEC
) 
 763                 // don't do it always, Metacity hates it 
 764                 m_gdkFunc 
= m_fsSaveGdkFunc
; 
 765                 m_gdkDecor 
= m_fsSaveGdkDecor
; 
 766                 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
); 
 767                 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
); 
 770             wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(), 
 771                                     (WXWindow
)GDK_ROOT_WINDOW(), 
 772                                     (WXWindow
)GDK_WINDOW_XWINDOW(window
), 
 773                                     show
, &m_fsSaveFrame
, method
); 
 775             SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
, 
 776                     m_fsSaveFrame
.width
, m_fsSaveFrame
.height
); 
 780     // documented behaviour is to show the window if it's still hidden when 
 781     // showing it full screen 
 782     if ( show 
&& !IsShown() ) 
 788 // ---------------------------------------------------------------------------- 
 789 // overridden wxWindow methods 
 790 // ---------------------------------------------------------------------------- 
 792 bool wxTopLevelWindowGTK::Show( bool show 
) 
 794     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
 796     if (show 
&& !m_sizeSet
) 
 798         /* by calling GtkOnSize here, we don't have to call 
 799            either after showing the frame, which would entail 
 800            much ugly flicker or from within the size_allocate 
 801            handler, because GTK 1.1.X forbids that. */ 
 803         GtkOnSize( m_x
, m_y
, m_width
, m_height 
); 
 807         gtk_widget_set_uposition( m_widget
, m_x
, m_y 
); 
 809     return wxWindow::Show( show 
); 
 812 void wxTopLevelWindowGTK::Raise() 
 814     gtk_window_present( GTK_WINDOW( m_widget 
) ); 
 817 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) ) 
 819     wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") ); 
 822 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
 824     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
 826     // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow 
 827     wxASSERT_MSG( (m_wxwindow 
!= NULL
), wxT("invalid frame") ); 
 837     int old_width 
= m_width
; 
 838     int old_height 
= m_height
; 
 840     if ((sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) == 0) 
 842         if (x 
!= -1) m_x 
= x
; 
 843         if (y 
!= -1) m_y 
= y
; 
 850     if (width 
!= -1) m_width 
= width
; 
 851     if (height 
!= -1) m_height 
= height
; 
 854     if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH) 
 856         if (width == -1) m_width = 80; 
 859     if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT) 
 861        if (height == -1) m_height = 26; 
 865     int minWidth 
= GetMinWidth(), 
 866         minHeight 
= GetMinHeight(), 
 867         maxWidth 
= GetMaxWidth(), 
 868         maxHeight 
= GetMaxHeight(); 
 871     // GPE's window manager doesn't like size hints 
 872     // at all, esp. when the user has to use the 
 880     if ((minWidth 
!= -1) && (m_width 
< minWidth
)) m_width 
= minWidth
; 
 881     if ((minHeight 
!= -1) && (m_height 
< minHeight
)) m_height 
= minHeight
; 
 882     if ((maxWidth 
!= -1) && (m_width 
> maxWidth
)) m_width 
= maxWidth
; 
 883     if ((maxHeight 
!= -1) && (m_height 
> maxHeight
)) m_height 
= maxHeight
; 
 885     if ((m_x 
!= -1) || (m_y 
!= -1)) 
 887         if ((m_x 
!= old_x
) || (m_y 
!= old_y
)) 
 889             gtk_widget_set_uposition( m_widget
, m_x
, m_y 
); 
 893     if ((m_width 
!= old_width
) || (m_height 
!= old_height
)) 
 895         if (m_widget
->window
) 
 896             gdk_window_resize( m_widget
->window
, m_width
, m_height 
); 
 898             gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height 
); 
 900         /* we set the size in GtkOnSize, i.e. mostly the actual resizing is 
 901            done either directly before the frame is shown or in idle time 
 902            so that different calls to SetSize() don't lead to flicker. */ 
 909 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
 911     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
 913     wxWindow::DoGetClientSize( width
, height 
); 
 917         *height 
-= m_miniEdge
*2 + m_miniTitle
; 
 921         *width 
-= m_miniEdge
*2; 
 925 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height 
) 
 927     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
 930               width 
+ m_miniEdge
*2, height  
+ m_miniEdge
*2 + m_miniTitle
, 0); 
 933 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
), 
 934                                      int width
, int height 
) 
 936     // due to a bug in gtk, x,y are always 0 
 941     if (m_resizing
) return; 
 944     if ( m_wxwindow 
== NULL 
) return; 
 949     /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses 
 950        wxWindow::Create to create it's GTK equivalent. m_mainWidget is only 
 951        set in wxFrame::Create so it is used to check what kind of frame we 
 952        have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we 
 953        skip the part which handles m_frameMenuBar, m_frameToolBar and (most 
 954        importantly) m_mainWidget */ 
 956     int minWidth 
= GetMinWidth(), 
 957         minHeight 
= GetMinHeight(), 
 958         maxWidth 
= GetMaxWidth(), 
 959         maxHeight 
= GetMaxHeight(); 
 962     // GPE's window manager doesn't like size hints 
 963     // at all, esp. when the user has to use the 
 971     if ((minWidth 
!= -1) && (m_width 
< minWidth
)) m_width 
= minWidth
; 
 972     if ((minHeight 
!= -1) && (m_height 
< minHeight
)) m_height 
= minHeight
; 
 973     if ((maxWidth 
!= -1) && (m_width 
> maxWidth
)) m_width 
= maxWidth
; 
 974     if ((maxHeight 
!= -1) && (m_height 
> maxHeight
)) m_height 
= maxHeight
; 
 979         gint            flag 
= 0; // GDK_HINT_POS; 
 982         if ((minWidth 
!= -1) || (minHeight 
!= -1)) flag 
|= GDK_HINT_MIN_SIZE
; 
 983         if ((maxWidth 
!= -1) || (maxHeight 
!= -1)) flag 
|= GDK_HINT_MAX_SIZE
; 
 985         geom
.min_width 
= minWidth
; 
 986         geom
.min_height 
= minHeight
; 
 988             // Because of the way we set GDK_HINT_MAX_SIZE above, if either of 
 989             // maxHeight or maxWidth is set, we must set them both, else the 
 990             // remaining -1 will be taken literally. 
 992             // I'm certain this also happens elsewhere, and is the probable 
 993             // cause of other such things as: 
 994             // Gtk-WARNING **: gtk_widget_size_allocate(): 
 995             //       attempt to allocate widget with width 65535 and height 600 
 996             // but I don't have time to track them all now.. 
 998             // Really we need to encapulate all this height/width business and 
 999             // stop any old method from ripping at the members directly and 
1000             // scattering -1's without regard for who might resolve them later. 
1002         geom
.max_width 
= ( maxHeight 
== -1 ) ? maxWidth
 
1003                          : ( maxWidth 
== -1 ) ? wxGetDisplaySize().GetWidth() 
1006         geom
.max_height 
= ( maxWidth 
== -1 ) ? maxHeight    
// ( == -1 here ) 
1007                           : ( maxHeight 
== -1 ) ? wxGetDisplaySize().GetHeight() 
1010         gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
), 
1013                                        (GdkWindowHints
) flag 
); 
1015         /* I revert back to wxGTK's original behaviour. m_mainWidget holds the 
1016          * menubar, the toolbar and the client area, which is represented by 
1018          * this hurts in the eye, but I don't want to call SetSize() 
1019          * because I don't want to call any non-native functions here. */ 
1021         int client_x 
= m_miniEdge
; 
1022         int client_y 
= m_miniEdge 
+ m_miniTitle
; 
1023         int client_w 
= m_width 
- 2*m_miniEdge
; 
1024         int client_h 
= m_height 
- 2*m_miniEdge 
- m_miniTitle
; 
1026         gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
), 
1028                               client_x
, client_y
, client_w
, client_h 
); 
1032         // If there is no m_mainWidget between m_widget and m_wxwindow there 
1033         // is no need to set the size or position of m_wxwindow. 
1038     // send size event to frame 
1039     wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
1040     event
.SetEventObject( this ); 
1041     GetEventHandler()->ProcessEvent( event 
); 
1046 void wxTopLevelWindowGTK::OnInternalIdle() 
1048     if (!m_sizeSet 
&& GTK_WIDGET_REALIZED(m_wxwindow
)) 
1050         GtkOnSize( m_x
, m_y
, m_width
, m_height 
); 
1052         // we'll come back later 
1054             wxapp_install_idle_handler(); 
1058     // set the focus if not done yet and if we can already do it 
1059     if ( GTK_WIDGET_REALIZED(m_wxwindow
) ) 
1061         if ( g_delayedFocus 
&& 
1062              wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this ) 
1064             wxLogTrace(_T("focus"), 
1065                        _T("Setting focus from wxTLW::OnIdle() to %s(%s)"), 
1066                        g_delayedFocus
->GetClassInfo()->GetClassName(), 
1067                        g_delayedFocus
->GetLabel().c_str()); 
1069             g_delayedFocus
->SetFocus(); 
1070             g_delayedFocus 
= NULL
; 
1074     wxWindow::OnInternalIdle(); 
1076     // Synthetize activate events. 
1077     if ( g_sendActivateEvent 
!= -1 ) 
1079         bool activate 
= g_sendActivateEvent 
!= 0; 
1081         // if (!activate) wxPrintf( wxT("de") ); 
1082         // wxPrintf( wxT("activate\n") ); 
1085         g_sendActivateEvent 
= -1; 
1087         wxTheApp
->SetActive(activate
, (wxWindow 
*)g_lastActiveFrame
); 
1091 // ---------------------------------------------------------------------------- 
1093 // ---------------------------------------------------------------------------- 
1095 void wxTopLevelWindowGTK::SetTitle( const wxString 
&title 
) 
1097     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
1099     if ( title 
== m_title 
) 
1104     gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title 
) ); 
1107 void wxTopLevelWindowGTK::SetIcon( const wxIcon 
&icon 
) 
1109     SetIcons( wxIconBundle( icon 
) ); 
1112 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle 
&icons 
) 
1114     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
1116     wxTopLevelWindowBase::SetIcons( icons 
); 
1119     size_t max 
= icons
.m_icons
.GetCount(); 
1121     for (size_t i 
= 0; i 
< max
; i
++) 
1123         if (icons
.m_icons
[i
].Ok()) 
1125             list 
= g_list_prepend(list
, icons
.m_icons
[i
].GetPixbuf()); 
1128     gtk_window_set_icon_list(GTK_WINDOW(m_widget
), list
); 
1132 // ---------------------------------------------------------------------------- 
1133 // frame state: maximized/iconized/normal 
1134 // ---------------------------------------------------------------------------- 
1136 void wxTopLevelWindowGTK::Maximize(bool maximize
) 
1139         gtk_window_maximize( GTK_WINDOW( m_widget 
) ); 
1141         gtk_window_unmaximize( GTK_WINDOW( m_widget 
) ); 
1144 bool wxTopLevelWindowGTK::IsMaximized() const 
1146     if(!m_widget
->window
) 
1149     return gdk_window_get_state(m_widget
->window
) & GDK_WINDOW_STATE_MAXIMIZED
; 
1152 void wxTopLevelWindowGTK::Restore() 
1154     // "Present" seems similar enough to "restore" 
1155     gtk_window_present( GTK_WINDOW( m_widget 
) ); 
1158 void wxTopLevelWindowGTK::Iconize( bool iconize 
) 
1161         gtk_window_iconify( GTK_WINDOW( m_widget 
) ); 
1163         gtk_window_deiconify( GTK_WINDOW( m_widget 
) ); 
1166 bool wxTopLevelWindowGTK::IsIconized() const 
1168     return m_isIconized
; 
1171 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
) 
1173     if ( iconize 
!= m_isIconized 
) 
1175         m_isIconized 
= iconize
; 
1176         (void)SendIconizeEvent(iconize
); 
1180 void wxTopLevelWindowGTK::AddGrab() 
1185         gtk_grab_add( m_widget 
); 
1186         wxEventLoop().Run(); 
1187         gtk_grab_remove( m_widget 
); 
1191 void wxTopLevelWindowGTK::RemoveGrab() 
1202 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
) 
1206         if (region
.IsEmpty()) 
1208             gdk_window_shape_combine_mask(window
, NULL
, 0, 0); 
1212             gdk_window_shape_combine_region(window
, region
.GetRegion(), 0, 0); 
1220 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
) 
1222     wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), false, 
1223                  _T("Shaped windows must be created with the wxFRAME_SHAPED style.")); 
1225     GdkWindow 
*window 
= NULL
; 
1228         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
1229         do_shape_combine_region(window
, region
); 
1231     window 
= m_widget
->window
; 
1232     return do_shape_combine_region(window
, region
); 
1235 bool wxTopLevelWindowGTK::IsActive() 
1237     return (this == (wxTopLevelWindowGTK
*)g_activeFrame
); 
1240 void wxTopLevelWindowGTK::RequestUserAttention(int flags
) 
1242     bool new_hint_value 
= false; 
1244     // FIXME: This is a workaround to focus handling problem 
1245     // If RequestUserAttention is called for example right after a wxSleep, OnInternalIdle hasn't 
1246     // yet been processed, and the internal focus system is not up to date yet. 
1247     // wxYieldIfNeeded ensures the processing of it, but can have unwanted side effects - MR 
1248     ::wxYieldIfNeeded(); 
1250     if(m_urgency_hint 
>= 0) 
1251         g_source_remove(m_urgency_hint
); 
1253     m_urgency_hint 
= -2; 
1255     if( GTK_WIDGET_REALIZED(m_widget
) && !IsActive() ) 
1257         new_hint_value 
= true; 
1259         if (flags 
& wxUSER_ATTENTION_INFO
) 
1261             m_urgency_hint 
= g_timeout_add(5000, (GSourceFunc
)gtk_frame_urgency_timer_callback
, this); 
1263             m_urgency_hint 
= -1; 
1267 #if defined(__WXGTK20__) && GTK_CHECK_VERSION(2,7,0) 
1268     if(!gtk_check_version(2,7,0)) 
1269         gtk_window_set_urgency_hint(GTK_WINDOW( m_widget 
), new_hint_value
); 
1272         wxgtk_window_set_urgency_hint(GTK_WINDOW( m_widget 
), new_hint_value
); 
1275 void wxTopLevelWindowGTK::SetWindowStyleFlag( long style 
) 
1277 #if defined(__WXGTK24__) || GTK_CHECK_VERSION(2,2,0) 
1278     // Store which styles were changed 
1279     long styleChanges 
= style 
^ m_windowStyle
; 
1282     // Process wxWindow styles. This also updates the internal variable 
1283     // Therefore m_windowStyle bits carry now the _new_ style values 
1284     wxWindow::SetWindowStyleFlag(style
); 
1286     // just return for now if widget does not exist yet 
1291     if ( (styleChanges 
& wxSTAY_ON_TOP
) && !gtk_check_version(2,4,0) ) 
1292         gtk_window_set_keep_above(GTK_WINDOW(m_widget
), m_windowStyle 
& wxSTAY_ON_TOP
); 
1294 #if GTK_CHECK_VERSION(2,2,0) 
1295     if ( (styleChanges 
& wxFRAME_NO_TASKBAR
) && !gtk_check_version(2,2,0) ) 
1297         gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), m_windowStyle 
& wxFRAME_NO_TASKBAR
);