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" 
  30     #include "wx/dcclient.h" 
  31     #include "wx/dialog.h" 
  33     #include "wx/settings.h" 
  34     #include "wx/control.h" 
  37 #include "wx/gtk/private.h" 
  38 #include "wx/evtloop.h" 
  43 #include <gdk/gdkkeysyms.h> 
  46 #include "wx/gtk/win_gtk.h" 
  48 #include "wx/unix/utilsx11.h" 
  51 #include <X11/Xatom.h> 
  53 // ---------------------------------------------------------------------------- 
  55 // ---------------------------------------------------------------------------- 
  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 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 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
); 
 561         gtk_window_set_role( GTK_WINDOW(m_widget
), wxGTK_CONV( name 
) ); 
 564     gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title 
) ); 
 565     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
 567     g_signal_connect (m_widget
, "delete_event", 
 568                       G_CALLBACK (gtk_frame_delete_callback
), this); 
 570     // m_mainWidget holds the toolbar, the menubar and the client area 
 571     m_mainWidget 
= gtk_pizza_new(); 
 572     gtk_widget_show( m_mainWidget 
); 
 573     GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS 
); 
 574     gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget 
); 
 576     if (m_miniEdge 
== 0) // wxMiniFrame has its own version. 
 578        // For m_mainWidget themes 
 579        g_signal_connect (m_mainWidget
, "expose_event", 
 580                          G_CALLBACK (gtk_window_expose_callback
), this); 
 583     // m_wxwindow only represents the client area without toolbar and menubar 
 584     m_wxwindow 
= gtk_pizza_new(); 
 585     gtk_widget_show( m_wxwindow 
); 
 586     gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow 
); 
 588     // we donm't allow the frame to get the focus as otherwise 
 589     // the frame will grab it at arbitrary focus changes 
 590     GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
 592     if (m_parent
) m_parent
->AddChild( this ); 
 594     // the user resized the frame by dragging etc. 
 595     g_signal_connect (m_widget
, "size_allocate", 
 596                       G_CALLBACK (gtk_frame_size_callback
), this); 
 600     if ((m_x 
!= -1) || (m_y 
!= -1)) 
 601         gtk_widget_set_uposition( m_widget
, m_x
, m_y 
); 
 603     gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height 
); 
 605     //  we cannot set MWM hints and icons before the widget has 
 606     //  been realized, so we do this directly after realization 
 607     g_signal_connect (m_widget
, "realize", 
 608                       G_CALLBACK (gtk_frame_realized_callback
), this); 
 610     // map and unmap for iconized state 
 611     g_signal_connect (m_widget
, "map_event", 
 612                       G_CALLBACK (gtk_frame_map_callback
), this); 
 613     g_signal_connect (m_widget
, "unmap_event", 
 614                       G_CALLBACK (gtk_frame_unmap_callback
), this); 
 616     // the only way to get the window size is to connect to this event 
 617     g_signal_connect (m_widget
, "configure_event", 
 618                       G_CALLBACK (gtk_frame_configure_callback
), this); 
 620     // disable native tab traversal 
 621     g_signal_connect (m_widget
, "focus", 
 622                       G_CALLBACK (gtk_frame_focus_callback
), this); 
 625     g_signal_connect_after (m_widget
, "focus_in_event", 
 626                       G_CALLBACK (gtk_frame_focus_in_callback
), this); 
 627     g_signal_connect_after (m_widget
, "focus_out_event", 
 628                       G_CALLBACK (gtk_frame_focus_out_callback
), this); 
 631     if ((m_miniEdge 
> 0) || (style 
& wxSIMPLE_BORDER
) || (style 
& wxNO_BORDER
)) 
 638         m_gdkDecor 
= (long) GDK_DECOR_BORDER
; 
 639         m_gdkFunc 
= (long) GDK_FUNC_MOVE
; 
 641         // All this is for Motif Window Manager "hints" and is supposed to be 
 642         // recognized by other WMs as well. 
 643         if ((style 
& wxCAPTION
) != 0) 
 645             m_gdkDecor 
|= GDK_DECOR_TITLE
; 
 647         if ((style 
& wxCLOSE_BOX
) != 0) 
 649             m_gdkFunc 
|= GDK_FUNC_CLOSE
; 
 651         if ((style 
& wxSYSTEM_MENU
) != 0) 
 653             m_gdkDecor 
|= GDK_DECOR_MENU
; 
 655         if ((style 
& wxMINIMIZE_BOX
) != 0) 
 657             m_gdkFunc 
|= GDK_FUNC_MINIMIZE
; 
 658             m_gdkDecor 
|= GDK_DECOR_MINIMIZE
; 
 660         if ((style 
& wxMAXIMIZE_BOX
) != 0) 
 662             m_gdkFunc 
|= GDK_FUNC_MAXIMIZE
; 
 663             m_gdkDecor 
|= GDK_DECOR_MAXIMIZE
; 
 665         if ((style 
& wxRESIZE_BORDER
) != 0) 
 667            m_gdkFunc 
|= GDK_FUNC_RESIZE
; 
 668            m_gdkDecor 
|= GDK_DECOR_RESIZEH
; 
 675 wxTopLevelWindowGTK::~wxTopLevelWindowGTK() 
 679         wxFAIL_MSG(_T("Window still grabbed")); 
 683     m_isBeingDeleted 
= true; 
 685     // it may also be GtkScrolledWindow in the case of an MDI child 
 686     if (GTK_IS_WINDOW(m_widget
)) 
 688         gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL 
); 
 691     if (g_activeFrame 
== this) 
 692         g_activeFrame 
= NULL
; 
 693     if (g_lastActiveFrame 
== this) 
 694         g_lastActiveFrame 
= NULL
; 
 699 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long style 
) 
 701     if (show 
== m_fsIsShowing
) 
 702         return false; // return what? 
 704     m_fsIsShowing 
= show
; 
 706     wxX11FullScreenMethod method 
= 
 707         wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(), 
 708                                  (WXWindow
)GDK_ROOT_WINDOW()); 
 710 #if GTK_CHECK_VERSION(2,2,0) 
 711     // NB: gtk_window_fullscreen() uses freedesktop.org's WMspec extensions 
 712     //     to switch to fullscreen, which is not always available. We must 
 713     //     check if WM supports the spec and use legacy methods if it 
 715     if ( (method 
== wxX11_FS_WMSPEC
) && !gtk_check_version(2,2,0) ) 
 718             gtk_window_fullscreen( GTK_WINDOW( m_widget 
) ); 
 720             gtk_window_unfullscreen( GTK_WINDOW( m_widget 
) ); 
 723 #endif // GTK+ >= 2.2.0 
 725         GdkWindow 
*window 
= m_widget
->window
; 
 729             m_fsSaveFlag 
= style
; 
 730             GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y 
); 
 731             GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height 
); 
 733             int screen_width
,screen_height
; 
 734             wxDisplaySize( &screen_width
, &screen_height 
); 
 736             gint client_x
, client_y
, root_x
, root_y
; 
 739             if (method 
!= wxX11_FS_WMSPEC
) 
 741                 // don't do it always, Metacity hates it 
 742                 m_fsSaveGdkFunc 
= m_gdkFunc
; 
 743                 m_fsSaveGdkDecor 
= m_gdkDecor
; 
 744                 m_gdkFunc 
= m_gdkDecor 
= 0; 
 745                 gdk_window_set_decorations(window
, (GdkWMDecoration
)0); 
 746                 gdk_window_set_functions(window
, (GdkWMFunction
)0); 
 749             gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
); 
 750             gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
, 
 751                          &width
, &height
, NULL
); 
 753             gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
, 
 754                         screen_width 
+ 1, screen_height 
+ 1); 
 756             wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(), 
 757                                     (WXWindow
)GDK_ROOT_WINDOW(), 
 758                                     (WXWindow
)GDK_WINDOW_XWINDOW(window
), 
 759                                     show
, &m_fsSaveFrame
, method
); 
 763             if (method 
!= wxX11_FS_WMSPEC
) 
 765                 // don't do it always, Metacity hates it 
 766                 m_gdkFunc 
= m_fsSaveGdkFunc
; 
 767                 m_gdkDecor 
= m_fsSaveGdkDecor
; 
 768                 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
); 
 769                 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
); 
 772             wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(), 
 773                                     (WXWindow
)GDK_ROOT_WINDOW(), 
 774                                     (WXWindow
)GDK_WINDOW_XWINDOW(window
), 
 775                                     show
, &m_fsSaveFrame
, method
); 
 777             SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
, 
 778                     m_fsSaveFrame
.width
, m_fsSaveFrame
.height
); 
 782     // documented behaviour is to show the window if it's still hidden when 
 783     // showing it full screen 
 784     if ( show 
&& !IsShown() ) 
 790 // ---------------------------------------------------------------------------- 
 791 // overridden wxWindow methods 
 792 // ---------------------------------------------------------------------------- 
 794 bool wxTopLevelWindowGTK::Show( bool show 
) 
 796     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
 798     if (show 
&& !m_sizeSet
) 
 800         /* by calling GtkOnSize here, we don't have to call 
 801            either after showing the frame, which would entail 
 802            much ugly flicker or from within the size_allocate 
 803            handler, because GTK 1.1.X forbids that. */ 
 805         GtkOnSize( m_x
, m_y
, m_width
, m_height 
); 
 809         gtk_widget_set_uposition( m_widget
, m_x
, m_y 
); 
 811     return wxWindow::Show( show 
); 
 814 void wxTopLevelWindowGTK::Raise() 
 816     gtk_window_present( GTK_WINDOW( m_widget 
) ); 
 819 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) ) 
 821     wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") ); 
 824 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
 826     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
 828     // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow 
 829     wxASSERT_MSG( (m_wxwindow 
!= NULL
), wxT("invalid frame") ); 
 839     int old_width 
= m_width
; 
 840     int old_height 
= m_height
; 
 842     if ((sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) == 0) 
 844         if (x 
!= -1) m_x 
= x
; 
 845         if (y 
!= -1) m_y 
= y
; 
 852     if (width 
!= -1) m_width 
= width
; 
 853     if (height 
!= -1) m_height 
= height
; 
 856     if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH) 
 858         if (width == -1) m_width = 80; 
 861     if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT) 
 863        if (height == -1) m_height = 26; 
 867     int minWidth 
= GetMinWidth(), 
 868         minHeight 
= GetMinHeight(), 
 869         maxWidth 
= GetMaxWidth(), 
 870         maxHeight 
= GetMaxHeight(); 
 873     // GPE's window manager doesn't like size hints 
 874     // at all, esp. when the user has to use the 
 882     if ((minWidth 
!= -1) && (m_width 
< minWidth
)) m_width 
= minWidth
; 
 883     if ((minHeight 
!= -1) && (m_height 
< minHeight
)) m_height 
= minHeight
; 
 884     if ((maxWidth 
!= -1) && (m_width 
> maxWidth
)) m_width 
= maxWidth
; 
 885     if ((maxHeight 
!= -1) && (m_height 
> maxHeight
)) m_height 
= maxHeight
; 
 887     if ((m_x 
!= -1) || (m_y 
!= -1)) 
 889         if ((m_x 
!= old_x
) || (m_y 
!= old_y
)) 
 891             gtk_widget_set_uposition( m_widget
, m_x
, m_y 
); 
 895     if ((m_width 
!= old_width
) || (m_height 
!= old_height
)) 
 897         if (m_widget
->window
) 
 898             gdk_window_resize( m_widget
->window
, m_width
, m_height 
); 
 900             gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height 
); 
 902         /* we set the size in GtkOnSize, i.e. mostly the actual resizing is 
 903            done either directly before the frame is shown or in idle time 
 904            so that different calls to SetSize() don't lead to flicker. */ 
 911 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
 913     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
 915     wxWindow::DoGetClientSize( width
, height 
); 
 919         *height 
-= m_miniEdge
*2 + m_miniTitle
; 
 923         *width 
-= m_miniEdge
*2; 
 927 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height 
) 
 929     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
 932               width 
+ m_miniEdge
*2, height  
+ m_miniEdge
*2 + m_miniTitle
, 0); 
 935 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
), 
 936                                      int width
, int height 
) 
 938     // due to a bug in gtk, x,y are always 0 
 943     if (m_resizing
) return; 
 946     if ( m_wxwindow 
== NULL 
) return; 
 951     /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses 
 952        wxWindow::Create to create it's GTK equivalent. m_mainWidget is only 
 953        set in wxFrame::Create so it is used to check what kind of frame we 
 954        have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we 
 955        skip the part which handles m_frameMenuBar, m_frameToolBar and (most 
 956        importantly) m_mainWidget */ 
 958     int minWidth 
= GetMinWidth(), 
 959         minHeight 
= GetMinHeight(), 
 960         maxWidth 
= GetMaxWidth(), 
 961         maxHeight 
= GetMaxHeight(); 
 964     // GPE's window manager doesn't like size hints 
 965     // at all, esp. when the user has to use the 
 973     if ((minWidth 
!= -1) && (m_width 
< minWidth
)) m_width 
= minWidth
; 
 974     if ((minHeight 
!= -1) && (m_height 
< minHeight
)) m_height 
= minHeight
; 
 975     if ((maxWidth 
!= -1) && (m_width 
> maxWidth
)) m_width 
= maxWidth
; 
 976     if ((maxHeight 
!= -1) && (m_height 
> maxHeight
)) m_height 
= maxHeight
; 
 981         gint            flag 
= 0; // GDK_HINT_POS; 
 984         if ((minWidth 
!= -1) || (minHeight 
!= -1)) flag 
|= GDK_HINT_MIN_SIZE
; 
 985         if ((maxWidth 
!= -1) || (maxHeight 
!= -1)) flag 
|= GDK_HINT_MAX_SIZE
; 
 987         geom
.min_width 
= minWidth
; 
 988         geom
.min_height 
= minHeight
; 
 990             // Because of the way we set GDK_HINT_MAX_SIZE above, if either of 
 991             // maxHeight or maxWidth is set, we must set them both, else the 
 992             // remaining -1 will be taken literally. 
 994             // I'm certain this also happens elsewhere, and is the probable 
 995             // cause of other such things as: 
 996             // Gtk-WARNING **: gtk_widget_size_allocate(): 
 997             //       attempt to allocate widget with width 65535 and height 600 
 998             // but I don't have time to track them all now.. 
1000             // Really we need to encapulate all this height/width business and 
1001             // stop any old method from ripping at the members directly and 
1002             // scattering -1's without regard for who might resolve them later. 
1004         geom
.max_width 
= ( maxHeight 
== -1 ) ? maxWidth
 
1005                          : ( maxWidth 
== -1 ) ? wxGetDisplaySize().GetWidth() 
1008         geom
.max_height 
= ( maxWidth 
== -1 ) ? maxHeight    
// ( == -1 here ) 
1009                           : ( maxHeight 
== -1 ) ? wxGetDisplaySize().GetHeight() 
1012         gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
), 
1015                                        (GdkWindowHints
) flag 
); 
1017         /* I revert back to wxGTK's original behaviour. m_mainWidget holds the 
1018          * menubar, the toolbar and the client area, which is represented by 
1020          * this hurts in the eye, but I don't want to call SetSize() 
1021          * because I don't want to call any non-native functions here. */ 
1023         int client_x 
= m_miniEdge
; 
1024         int client_y 
= m_miniEdge 
+ m_miniTitle
; 
1025         int client_w 
= m_width 
- 2*m_miniEdge
; 
1026         int client_h 
= m_height 
- 2*m_miniEdge 
- m_miniTitle
; 
1028         gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
), 
1030                               client_x
, client_y
, client_w
, client_h 
); 
1034         // If there is no m_mainWidget between m_widget and m_wxwindow there 
1035         // is no need to set the size or position of m_wxwindow. 
1040     // send size event to frame 
1041     wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
1042     event
.SetEventObject( this ); 
1043     GetEventHandler()->ProcessEvent( event 
); 
1048 void wxTopLevelWindowGTK::OnInternalIdle() 
1050     if (!m_sizeSet 
&& GTK_WIDGET_REALIZED(m_wxwindow
)) 
1052         GtkOnSize( m_x
, m_y
, m_width
, m_height 
); 
1054         // we'll come back later 
1056             wxapp_install_idle_handler(); 
1060     // set the focus if not done yet and if we can already do it 
1061     if ( GTK_WIDGET_REALIZED(m_wxwindow
) ) 
1063         if ( g_delayedFocus 
&& 
1064              wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this ) 
1066             wxLogTrace(_T("focus"), 
1067                        _T("Setting focus from wxTLW::OnIdle() to %s(%s)"), 
1068                        g_delayedFocus
->GetClassInfo()->GetClassName(), 
1069                        g_delayedFocus
->GetLabel().c_str()); 
1071             g_delayedFocus
->SetFocus(); 
1072             g_delayedFocus 
= NULL
; 
1076     wxWindow::OnInternalIdle(); 
1078     // Synthetize activate events. 
1079     if ( g_sendActivateEvent 
!= -1 ) 
1081         bool activate 
= g_sendActivateEvent 
!= 0; 
1083         // if (!activate) wxPrintf( wxT("de") ); 
1084         // wxPrintf( wxT("activate\n") ); 
1087         g_sendActivateEvent 
= -1; 
1089         wxTheApp
->SetActive(activate
, (wxWindow 
*)g_lastActiveFrame
); 
1093 // ---------------------------------------------------------------------------- 
1095 // ---------------------------------------------------------------------------- 
1097 void wxTopLevelWindowGTK::SetTitle( const wxString 
&title 
) 
1099     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
1101     if ( title 
== m_title 
) 
1106     gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title 
) ); 
1109 void wxTopLevelWindowGTK::SetIcon( const wxIcon 
&icon 
) 
1111     SetIcons( wxIconBundle( icon 
) ); 
1114 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle 
&icons 
) 
1116     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
1118     wxTopLevelWindowBase::SetIcons( icons 
); 
1121     size_t max 
= icons
.m_icons
.GetCount(); 
1123     for (size_t i 
= 0; i 
< max
; i
++) 
1125         if (icons
.m_icons
[i
].Ok()) 
1127             list 
= g_list_prepend(list
, icons
.m_icons
[i
].GetPixbuf()); 
1130     gtk_window_set_icon_list(GTK_WINDOW(m_widget
), list
); 
1134 // ---------------------------------------------------------------------------- 
1135 // frame state: maximized/iconized/normal 
1136 // ---------------------------------------------------------------------------- 
1138 void wxTopLevelWindowGTK::Maximize(bool maximize
) 
1141         gtk_window_maximize( GTK_WINDOW( m_widget 
) ); 
1143         gtk_window_unmaximize( GTK_WINDOW( m_widget 
) ); 
1146 bool wxTopLevelWindowGTK::IsMaximized() const 
1148     if(!m_widget
->window
) 
1151     return gdk_window_get_state(m_widget
->window
) & GDK_WINDOW_STATE_MAXIMIZED
; 
1154 void wxTopLevelWindowGTK::Restore() 
1156     // "Present" seems similar enough to "restore" 
1157     gtk_window_present( GTK_WINDOW( m_widget 
) ); 
1160 void wxTopLevelWindowGTK::Iconize( bool iconize 
) 
1163         gtk_window_iconify( GTK_WINDOW( m_widget 
) ); 
1165         gtk_window_deiconify( GTK_WINDOW( m_widget 
) ); 
1168 bool wxTopLevelWindowGTK::IsIconized() const 
1170     return m_isIconized
; 
1173 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
) 
1175     if ( iconize 
!= m_isIconized 
) 
1177         m_isIconized 
= iconize
; 
1178         (void)SendIconizeEvent(iconize
); 
1182 void wxTopLevelWindowGTK::AddGrab() 
1187         gtk_grab_add( m_widget 
); 
1188         wxEventLoop().Run(); 
1189         gtk_grab_remove( m_widget 
); 
1193 void wxTopLevelWindowGTK::RemoveGrab() 
1204 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
) 
1208         if (region
.IsEmpty()) 
1210             gdk_window_shape_combine_mask(window
, NULL
, 0, 0); 
1214             gdk_window_shape_combine_region(window
, region
.GetRegion(), 0, 0); 
1222 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
) 
1224     wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), false, 
1225                  _T("Shaped windows must be created with the wxFRAME_SHAPED style.")); 
1227     GdkWindow 
*window 
= NULL
; 
1230         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
1231         do_shape_combine_region(window
, region
); 
1233     window 
= m_widget
->window
; 
1234     return do_shape_combine_region(window
, region
); 
1237 bool wxTopLevelWindowGTK::IsActive() 
1239     return (this == (wxTopLevelWindowGTK
*)g_activeFrame
); 
1242 void wxTopLevelWindowGTK::RequestUserAttention(int flags
) 
1244     bool new_hint_value 
= false; 
1246     // FIXME: This is a workaround to focus handling problem 
1247     // If RequestUserAttention is called for example right after a wxSleep, OnInternalIdle hasn't 
1248     // yet been processed, and the internal focus system is not up to date yet. 
1249     // wxYieldIfNeeded ensures the processing of it, but can have unwanted side effects - MR 
1250     ::wxYieldIfNeeded(); 
1252     if(m_urgency_hint 
>= 0) 
1253         g_source_remove(m_urgency_hint
); 
1255     m_urgency_hint 
= -2; 
1257     if( GTK_WIDGET_REALIZED(m_widget
) && !IsActive() ) 
1259         new_hint_value 
= true; 
1261         if (flags 
& wxUSER_ATTENTION_INFO
) 
1263             m_urgency_hint 
= g_timeout_add(5000, (GSourceFunc
)gtk_frame_urgency_timer_callback
, this); 
1265             m_urgency_hint 
= -1; 
1269 #if GTK_CHECK_VERSION(2,7,0) 
1270     if(!gtk_check_version(2,7,0)) 
1271         gtk_window_set_urgency_hint(GTK_WINDOW( m_widget 
), new_hint_value
); 
1274         wxgtk_window_set_urgency_hint(GTK_WINDOW( m_widget 
), new_hint_value
); 
1277 void wxTopLevelWindowGTK::SetWindowStyleFlag( long style 
) 
1279 #if defined(__WXGTK24__) || GTK_CHECK_VERSION(2,2,0) 
1280     // Store which styles were changed 
1281     long styleChanges 
= style 
^ m_windowStyle
; 
1284     // Process wxWindow styles. This also updates the internal variable 
1285     // Therefore m_windowStyle bits carry now the _new_ style values 
1286     wxWindow::SetWindowStyleFlag(style
); 
1288     // just return for now if widget does not exist yet 
1293     if ( (styleChanges 
& wxSTAY_ON_TOP
) && !gtk_check_version(2,4,0) ) 
1294         gtk_window_set_keep_above(GTK_WINDOW(m_widget
), m_windowStyle 
& wxSTAY_ON_TOP
); 
1296 #if GTK_CHECK_VERSION(2,2,0) 
1297     if ( (styleChanges 
& wxFRAME_NO_TASKBAR
) && !gtk_check_version(2,2,0) ) 
1299         gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), m_windowStyle 
& wxFRAME_NO_TASKBAR
); 
1304 #include <X11/Xlib.h> 
1306 /* Get the X Window between child and the root window. 
1307    This should usually be the WM managed XID */ 
1308 static Window 
wxGetTopmostWindowX11(Display 
*dpy
, Window child
) 
1310     Window root
, parent
; 
1312     unsigned int nchildren
; 
1314     XQueryTree(dpy
, child
, &root
, &parent
, &children
, &nchildren
); 
1317     while (parent 
!= root
) { 
1319         XQueryTree(dpy
, child
, &root
, &parent
, &children
, &nchildren
); 
1326 bool wxTopLevelWindowGTK::SetTransparent(wxByte alpha
) 
1328     if (!m_widget 
|| !m_widget
->window
) 
1331     Display
* dpy 
= GDK_WINDOW_XDISPLAY (m_widget
->window
); 
1332     // We need to get the X Window that has the root window as the immediate parent 
1333     // and m_widget->window as a child. This should be the X Window that the WM manages and 
1334     // from which the opacity property is checked from. 
1335     Window win 
= wxGetTopmostWindowX11(dpy
, GDK_WINDOW_XID (m_widget
->window
)); 
1337     unsigned int opacity 
= alpha 
* 0x1010101; 
1339     // Using pure Xlib to not have a GTK version check mess due to gtk2.0 not having GdkDisplay 
1341         XDeleteProperty(dpy
, win
, XInternAtom(dpy
, "_NET_WM_WINDOW_OPACITY", False
)); 
1343         XChangeProperty(dpy
, win
, XInternAtom(dpy
, "_NET_WM_WINDOW_OPACITY", False
), 
1344                         XA_CARDINAL
, 32, PropModeReplace
, 
1345                         (unsigned char *) &opacity
, 1L); 
1350 bool wxTopLevelWindowGTK::CanSetTransparent() 
1352 #if GTK_CHECK_VERSION(2,10,0) 
1353     if (!gtk_check_version(2,10,0)) 
1355         if (gtk_widget_is_composited (m_widget
)) 
1359 #endif // In case of lower versions than gtk+-2.10.0 we could look for _NET_WM_CM_Sn ourselves 
1364 #if 0 // Don't be optimistic here for the sake of wxAUI 
1365     int opcode
, event
, error
; 
1366     // Check for the existence of a RGBA visual instead? 
1367     return XQueryExtension(gdk_x11_get_default_xdisplay (), 
1368                            "Composite", &opcode
, &event
, &error
);