1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/toplevel.cpp 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 // For compilers that support precompilation, includes "wx.h". 
  11 #include "wx/wxprec.h" 
  13 // ============================================================================ 
  15 // ============================================================================ 
  17 // ---------------------------------------------------------------------------- 
  19 // ---------------------------------------------------------------------------- 
  22 #define XIconifyWindow XICONIFYWINDOW 
  25 #include "wx/toplevel.h" 
  34 #include "wx/gtk/private.h" 
  35 #include "wx/evtloop.h" 
  36 #include "wx/sysopt.h" 
  41 #include "wx/gtk/private/win_gtk.h" 
  43 #include "wx/unix/utilsx11.h" 
  46 #include <X11/Xatom.h> 
  49     #include <hildon-widgets/hildon-program.h> 
  50     #include <hildon-widgets/hildon-window.h> 
  51 #endif // wxUSE_LIBHILDON 
  53 // ---------------------------------------------------------------------------- 
  55 // ---------------------------------------------------------------------------- 
  57 // this is incremented while a modal dialog is shown 
  58 int wxOpenModalDialogsCount 
= 0; 
  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 
) 
 120     switch ( g_sendActivateEvent 
) 
 123             // we've got focus from outside, synthetize wxActivateEvent 
 124             g_sendActivateEvent 
= 1; 
 128             // another our window just lost focus, it was already ours before 
 129             // - don't send any wxActivateEvent 
 130             g_sendActivateEvent 
= -1; 
 135     g_lastActiveFrame 
= g_activeFrame
; 
 137     // wxPrintf( wxT("active: %s\n"), win->GetTitle().c_str() ); 
 139     // MR: wxRequestUserAttention related block 
 140     switch( win
->m_urgency_hint 
) 
 143             g_source_remove( win
->m_urgency_hint 
); 
 144             // no break, fallthrough to remove hint too 
 146 #if GTK_CHECK_VERSION(2,7,0) 
 147             if(!gtk_check_version(2,7,0)) 
 148                 gtk_window_set_urgency_hint(GTK_WINDOW( widget 
), FALSE
); 
 152                 wxgtk_window_set_urgency_hint(GTK_WINDOW( widget 
), FALSE
); 
 155             win
->m_urgency_hint 
= -2; 
 161     wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
); 
 162     wxActivateEvent 
event(wxEVT_ACTIVATE
, true, g_activeFrame
->GetId()); 
 163     event
.SetEventObject(g_activeFrame
); 
 164     g_activeFrame
->HandleWindowEvent(event
); 
 170 //----------------------------------------------------------------------------- 
 172 //----------------------------------------------------------------------------- 
 176 gboolean 
gtk_frame_focus_out_callback(GtkWidget 
* WXUNUSED(widget
), 
 177                                       GdkEventFocus 
*WXUNUSED(gdk_event
), 
 178                                       wxTopLevelWindowGTK 
* WXUNUSED(win
)) 
 180     // if the focus goes out of our app alltogether, OnIdle() will send 
 181     // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset 
 182     // g_sendActivateEvent to -1 
 183     g_sendActivateEvent 
= 0; 
 185     // wxASSERT_MSG( (g_activeFrame == win), wxT("TLW deactivatd although it wasn't active") ); 
 187     // wxPrintf( wxT("inactive: %s\n"), win->GetTitle().c_str() ); 
 191         wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
); 
 192         wxActivateEvent 
event(wxEVT_ACTIVATE
, false, g_activeFrame
->GetId()); 
 193         event
.SetEventObject(g_activeFrame
); 
 194         g_activeFrame
->HandleWindowEvent(event
); 
 196         g_activeFrame 
= NULL
; 
 203 //----------------------------------------------------------------------------- 
 204 // "size_allocate" from m_wxwindow 
 205 //----------------------------------------------------------------------------- 
 209 size_allocate(GtkWidget
*, GtkAllocation
* alloc
, wxTopLevelWindowGTK
* win
) 
 211     if (win
->m_oldClientWidth  
!= alloc
->width 
|| 
 212         win
->m_oldClientHeight 
!= alloc
->height
) 
 214         win
->m_oldClientWidth  
= alloc
->width
; 
 215         win
->m_oldClientHeight 
= alloc
->height
; 
 217         wxSize 
size(win
->m_widget
->allocation
.width
, 
 218                     win
->m_widget
->allocation
.height
); 
 219         size 
+= win
->m_decorSize
; 
 220         win
->m_width  
= size
.x
; 
 221         win
->m_height 
= size
.y
; 
 223         if (!win
->IsIconized()) 
 225             wxSizeEvent 
event(size
, win
->GetId()); 
 226             event
.SetEventObject(win
); 
 227             win
->HandleWindowEvent(event
); 
 229         // else the window is currently unmapped, don't generate size events 
 234 // ---------------------------------------------------------------------------- 
 236 // ---------------------------------------------------------------------------- 
 240 void wxgtk_tlw_size_request_callback(GtkWidget 
* WXUNUSED(widget
), 
 241                                      GtkRequisition 
*requisition
, 
 242                                      wxTopLevelWindowGTK 
*win
) 
 244     // we must return the size of the window without WM decorations, otherwise 
 245     // GTK+ gets confused, so don't call just GetSize() here 
 246     win
->GTKDoGetSize(&requisition
->width
, &requisition
->height
); 
 250 //----------------------------------------------------------------------------- 
 252 //----------------------------------------------------------------------------- 
 256 gtk_frame_delete_callback( GtkWidget 
*WXUNUSED(widget
), 
 257                            GdkEvent 
*WXUNUSED(event
), 
 258                            wxTopLevelWindowGTK 
*win 
) 
 260     if (win
->IsEnabled() && 
 261         (wxOpenModalDialogsCount 
== 0 || (win
->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) || 
 269 //----------------------------------------------------------------------------- 
 271 //----------------------------------------------------------------------------- 
 275 gtk_frame_configure_callback( GtkWidget
* widget
, 
 276                               GdkEventConfigure 
*WXUNUSED(event
), 
 277                               wxTopLevelWindowGTK 
*win 
) 
 279     if (!win
->m_hasVMT 
|| !win
->IsShown()) 
 283     gtk_window_get_position((GtkWindow
*)widget
, &point
.x
, &point
.y
); 
 287     wxMoveEvent 
mevent(point
, win
->GetId()); 
 288     mevent
.SetEventObject( win 
); 
 289     win
->HandleWindowEvent( mevent 
); 
 295 //----------------------------------------------------------------------------- 
 296 // "realize" from m_widget 
 297 //----------------------------------------------------------------------------- 
 299 // we cannot MWM hints and icons before the widget has been realized, 
 300 // so we do this directly after realization 
 304 gtk_frame_realized_callback( GtkWidget 
* WXUNUSED(widget
), 
 305                              wxTopLevelWindowGTK 
*win 
) 
 307     // All this is for Motif Window Manager "hints" and is supposed to be 
 308     // recognized by other WM as well. Not tested. 
 309     gdk_window_set_decorations(win
->m_widget
->window
, 
 310                                (GdkWMDecoration
)win
->m_gdkDecor
); 
 311     gdk_window_set_functions(win
->m_widget
->window
, 
 312                                (GdkWMFunction
)win
->m_gdkFunc
); 
 314     // GTK's shrinking/growing policy 
 315     if ((win
->m_gdkFunc 
& GDK_FUNC_RESIZE
) == 0) 
 316         gtk_window_set_resizable(GTK_WINDOW(win
->m_widget
), FALSE
); 
 318         gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1); 
 321     wxIconBundle iconsOld 
= win
->GetIcons(); 
 322     if ( !iconsOld
.IsEmpty() ) 
 324         win
->SetIcon( wxNullIcon 
); 
 325         win
->SetIcons( iconsOld 
); 
 330 //----------------------------------------------------------------------------- 
 331 // "map_event" from m_widget 
 332 //----------------------------------------------------------------------------- 
 336 gtk_frame_map_callback( GtkWidget
*, 
 337                         GdkEvent 
* WXUNUSED(event
), 
 338                         wxTopLevelWindow 
*win 
) 
 340     const bool wasIconized 
= win
->IsIconized(); 
 342     win
->SetIconizeState(false); 
 346         // Because GetClientSize() returns (0,0) when IsIconized() is true, 
 347         // a size event must be generated, just in case GetClientSize() was 
 348         // called while iconized. This specifically happens when restoring a 
 349         // tlw that was "rolled up" with some WMs. 
 350         // Queue a resize rather than sending size event directly to allow 
 351         // children to be made visible first. 
 352         win
->m_oldClientWidth 
= 0; 
 353         gtk_widget_queue_resize(win
->m_wxwindow
); 
 360 //----------------------------------------------------------------------------- 
 361 // "unmap_event" from m_widget 
 362 //----------------------------------------------------------------------------- 
 366 gtk_frame_unmap_callback( GtkWidget 
* WXUNUSED(widget
), 
 367                           GdkEvent 
* WXUNUSED(event
), 
 368                           wxTopLevelWindow 
*win 
) 
 370     win
->SetIconizeState(true); 
 375 //----------------------------------------------------------------------------- 
 376 // "property_notify_event" from m_widget 
 377 //----------------------------------------------------------------------------- 
 380 static gboolean 
property_notify_event( 
 381     GtkWidget
*, GdkEventProperty
* event
, wxTopLevelWindowGTK
* win
) 
 383     // Watch for changes to _NET_FRAME_EXTENTS property 
 384     static GdkAtom property 
= gdk_atom_intern("_NET_FRAME_EXTENTS", false); 
 385     if (event
->state 
== GDK_PROPERTY_NEW_VALUE 
&& event
->atom 
== property
) 
 387         Atom xproperty 
= gdk_x11_atom_to_xatom_for_display( 
 388                             gdk_drawable_get_display(event
->window
), property
); 
 391         gulong nitems
, bytes_after
; 
 393         Status status 
= XGetWindowProperty( 
 394             gdk_x11_drawable_get_xdisplay(event
->window
), 
 395             gdk_x11_drawable_get_xid(event
->window
), 
 397             0, 4, false, XA_CARDINAL
, 
 398             &type
, &format
, &nitems
, &bytes_after
, &data
); 
 399         if (status 
== Success 
&& data 
&& nitems 
== 4) 
 401             long* p 
= (long*)data
; 
 402             const wxSize decorSize 
= 
 403                 wxSize(int(p
[0] + p
[1]), int(p
[2] + p
[3])); 
 404             win
->GTKUpdateDecorSize(decorSize
); 
 413 BEGIN_EVENT_TABLE(wxTopLevelWindowGTK
, wxTopLevelWindowBase
) 
 414     EVT_SYS_COLOUR_CHANGED(wxTopLevelWindowGTK::OnSysColourChanged
) 
 417 // ---------------------------------------------------------------------------- 
 418 // wxTopLevelWindowGTK creation 
 419 // ---------------------------------------------------------------------------- 
 421 void wxTopLevelWindowGTK::Init() 
 423     m_mainWidget 
= (GtkWidget
*) NULL
; 
 424     m_isIconized 
= false; 
 425     m_fsIsShowing 
= false; 
 426     m_themeEnabled 
= true; 
 427     m_gdkDecor 
= m_gdkFunc 
= 0; 
 434 bool wxTopLevelWindowGTK::Create( wxWindow 
*parent
, 
 436                                   const wxString
& title
, 
 438                                   const wxSize
& sizeOrig
, 
 440                                   const wxString 
&name 
) 
 442     // always create a frame of some reasonable, even if arbitrary, size (at 
 443     // least for MSW compatibility) 
 444     wxSize size 
= sizeOrig
; 
 445     size
.x 
= WidthDefault(size
.x
); 
 446     size
.y 
= HeightDefault(size
.y
); 
 448     wxTopLevelWindows
.Append( this ); 
 450     if (!PreCreation( parent
, pos
, size 
) || 
 451         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
 453         wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") ); 
 459     // NB: m_widget may be !=NULL if it was created by derived class' Create, 
 460     //     e.g. in wxTaskBarIconAreaGTK 
 461     if (m_widget 
== NULL
) 
 464         // we must create HildonWindow and not a normal GtkWindow as the latter 
 465         // doesn't look correctly in Maemo environment and it must also be 
 466         // registered with the main program object 
 467         m_widget 
= hildon_window_new(); 
 468         hildon_program_add_window(wxTheApp
->GetHildonProgram(), 
 469                                   HILDON_WINDOW(m_widget
)); 
 470 #else // !wxUSE_LIBHILDON 
 471         m_widget 
= gtk_window_new(GTK_WINDOW_TOPLEVEL
); 
 472         if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) 
 474             // Tell WM that this is a dialog window and make it center 
 475             // on parent by default (this is what GtkDialog ctor does): 
 476             gtk_window_set_type_hint(GTK_WINDOW(m_widget
), 
 477                                      GDK_WINDOW_TYPE_HINT_DIALOG
); 
 478             gtk_window_set_position(GTK_WINDOW(m_widget
), 
 479                                     GTK_WIN_POS_CENTER_ON_PARENT
); 
 483             if (style 
& wxFRAME_TOOL_WINDOW
) 
 485                 gtk_window_set_type_hint(GTK_WINDOW(m_widget
), 
 486                                          GDK_WINDOW_TYPE_HINT_UTILITY
); 
 488                 // On some WMs, like KDE, a TOOL_WINDOW will still show 
 489                 // on the taskbar, but on Gnome a TOOL_WINDOW will not. 
 490                 // For consistency between WMs and with Windows, we 
 491                 // should set the NO_TASKBAR flag which will apply 
 492                 // the set_skip_taskbar_hint if it is available, 
 493                 // ensuring no taskbar entry will appear. 
 494                 style 
|= wxFRAME_NO_TASKBAR
; 
 497 #endif // wxUSE_LIBHILDON/!wxUSE_LIBHILDON 
 500     wxWindow 
*topParent 
= wxGetTopLevelParent(m_parent
); 
 501     if (topParent 
&& (((GTK_IS_WINDOW(topParent
->m_widget
)) && 
 502                        (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) || 
 503                        (style 
& wxFRAME_FLOAT_ON_PARENT
))) 
 505         gtk_window_set_transient_for( GTK_WINDOW(m_widget
), 
 506                                       GTK_WINDOW(topParent
->m_widget
) ); 
 509     if (style 
& wxFRAME_NO_TASKBAR
) 
 511         gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), TRUE
); 
 514     if (style 
& wxSTAY_ON_TOP
) 
 516         gtk_window_set_keep_above(GTK_WINDOW(m_widget
), TRUE
); 
 521         gtk_window_set_role( GTK_WINDOW(m_widget
), wxGTK_CONV( name 
) ); 
 524     gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title 
) ); 
 525     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
 527     g_signal_connect (m_widget
, "delete_event", 
 528                       G_CALLBACK (gtk_frame_delete_callback
), this); 
 530     // m_mainWidget is a GtkVBox, holding the bars and client area (m_wxwindow) 
 531     m_mainWidget 
= gtk_vbox_new(false, 0); 
 532     gtk_widget_show( m_mainWidget 
); 
 533     GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS 
); 
 534     gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget 
); 
 536     // m_wxwindow is the client area 
 537     m_wxwindow 
= wxPizza::New(); 
 538     gtk_widget_show( m_wxwindow 
); 
 539     gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow 
); 
 541     // we donm't allow the frame to get the focus as otherwise 
 542     // the frame will grab it at arbitrary focus changes 
 543     GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
 545     if (m_parent
) m_parent
->AddChild( this ); 
 547     g_signal_connect(m_wxwindow
, "size_allocate", 
 548         G_CALLBACK(size_allocate
), this); 
 550     g_signal_connect (m_widget
, "size_request", 
 551                       G_CALLBACK (wxgtk_tlw_size_request_callback
), this); 
 554     if ((m_x 
!= -1) || (m_y 
!= -1)) 
 555         gtk_widget_set_uposition( m_widget
, m_x
, m_y 
); 
 557     //  we cannot set MWM hints and icons before the widget has 
 558     //  been realized, so we do this directly after realization 
 559     g_signal_connect (m_widget
, "realize", 
 560                       G_CALLBACK (gtk_frame_realized_callback
), this); 
 562     // map and unmap for iconized state 
 563     g_signal_connect (m_widget
, "map_event", 
 564                       G_CALLBACK (gtk_frame_map_callback
), this); 
 565     g_signal_connect (m_widget
, "unmap_event", 
 566                       G_CALLBACK (gtk_frame_unmap_callback
), this); 
 569     g_signal_connect (m_widget
, "configure_event", 
 570                       G_CALLBACK (gtk_frame_configure_callback
), this); 
 573     g_signal_connect_after (m_widget
, "focus_in_event", 
 574                       G_CALLBACK (gtk_frame_focus_in_callback
), this); 
 575     g_signal_connect_after (m_widget
, "focus_out_event", 
 576                       G_CALLBACK (gtk_frame_focus_out_callback
), this); 
 578     gtk_widget_add_events(m_widget
, GDK_PROPERTY_CHANGE_MASK
); 
 579     g_signal_connect(m_widget
, "property_notify_event", 
 580         G_CALLBACK(property_notify_event
), this); 
 583     if ((style 
& wxSIMPLE_BORDER
) || (style 
& wxNO_BORDER
)) 
 590         m_gdkDecor 
= GDK_DECOR_BORDER
; 
 591         m_gdkFunc 
= GDK_FUNC_MOVE
; 
 593         // All this is for Motif Window Manager "hints" and is supposed to be 
 594         // recognized by other WMs as well. 
 595         if ((style 
& wxCAPTION
) != 0) 
 597             m_gdkDecor 
|= GDK_DECOR_TITLE
; 
 599         if ((style 
& wxCLOSE_BOX
) != 0) 
 601             m_gdkFunc 
|= GDK_FUNC_CLOSE
; 
 603         if ((style 
& wxSYSTEM_MENU
) != 0) 
 605             m_gdkDecor 
|= GDK_DECOR_MENU
; 
 607         if ((style 
& wxMINIMIZE_BOX
) != 0) 
 609             m_gdkFunc 
|= GDK_FUNC_MINIMIZE
; 
 610             m_gdkDecor 
|= GDK_DECOR_MINIMIZE
; 
 612         if ((style 
& wxMAXIMIZE_BOX
) != 0) 
 614             m_gdkFunc 
|= GDK_FUNC_MAXIMIZE
; 
 615             m_gdkDecor 
|= GDK_DECOR_MAXIMIZE
; 
 617         if ((style 
& wxRESIZE_BORDER
) != 0) 
 619            m_gdkFunc 
|= GDK_FUNC_RESIZE
; 
 620            m_gdkDecor 
|= GDK_DECOR_RESIZEH
; 
 624     gtk_window_set_default_size(GTK_WINDOW(m_widget
), m_width
, m_height
); 
 629 wxTopLevelWindowGTK::~wxTopLevelWindowGTK() 
 632     // it can also be a (standard) dialog 
 633     if ( HILDON_IS_WINDOW(m_widget
) ) 
 635         hildon_program_remove_window(wxTheApp
->GetHildonProgram(), 
 636                                      HILDON_WINDOW(m_widget
)); 
 638 #endif // wxUSE_LIBHILDON 
 642         wxFAIL_MSG(_T("Window still grabbed")); 
 646     m_isBeingDeleted 
= true; 
 648     // it may also be GtkScrolledWindow in the case of an MDI child 
 649     if (GTK_IS_WINDOW(m_widget
)) 
 651         gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL 
); 
 654     if (g_activeFrame 
== this) 
 655         g_activeFrame 
= NULL
; 
 656     if (g_lastActiveFrame 
== this) 
 657         g_lastActiveFrame 
= NULL
; 
 660 bool wxTopLevelWindowGTK::EnableCloseButton( bool enable 
) 
 663         m_gdkFunc 
|= GDK_FUNC_CLOSE
; 
 665         m_gdkFunc 
&= ~GDK_FUNC_CLOSE
; 
 667     if (GTK_WIDGET_REALIZED(m_widget
) && (m_widget
->window
)) 
 668         gdk_window_set_functions( m_widget
->window
, (GdkWMFunction
)m_gdkFunc 
); 
 673 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long) 
 675     if (show 
== m_fsIsShowing
) 
 676         return false; // return what? 
 678     m_fsIsShowing 
= show
; 
 680     wxX11FullScreenMethod method 
= 
 681         wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(), 
 682                                  (WXWindow
)GDK_ROOT_WINDOW()); 
 684     // NB: gtk_window_fullscreen() uses freedesktop.org's WMspec extensions 
 685     //     to switch to fullscreen, which is not always available. We must 
 686     //     check if WM supports the spec and use legacy methods if it 
 688     if ( method 
== wxX11_FS_WMSPEC 
) 
 691             gtk_window_fullscreen( GTK_WINDOW( m_widget 
) ); 
 693             gtk_window_unfullscreen( GTK_WINDOW( m_widget 
) ); 
 697         GdkWindow 
*window 
= m_widget
->window
; 
 701             GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y 
); 
 702             GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height 
); 
 704             int screen_width
,screen_height
; 
 705             wxDisplaySize( &screen_width
, &screen_height 
); 
 707             gint client_x
, client_y
, root_x
, root_y
; 
 710             m_fsSaveGdkFunc 
= m_gdkFunc
; 
 711             m_fsSaveGdkDecor 
= m_gdkDecor
; 
 712             m_gdkFunc 
= m_gdkDecor 
= 0; 
 713             gdk_window_set_decorations(window
, (GdkWMDecoration
)0); 
 714             gdk_window_set_functions(window
, (GdkWMFunction
)0); 
 716             gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
); 
 717             gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
, 
 718                          &width
, &height
, NULL
); 
 720             gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
, 
 721                         screen_width 
+ 1, screen_height 
+ 1); 
 723             wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(), 
 724                                     (WXWindow
)GDK_ROOT_WINDOW(), 
 725                                     (WXWindow
)GDK_WINDOW_XWINDOW(window
), 
 726                                     show
, &m_fsSaveFrame
, method
); 
 730             m_gdkFunc 
= m_fsSaveGdkFunc
; 
 731             m_gdkDecor 
= m_fsSaveGdkDecor
; 
 732             gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
); 
 733             gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
); 
 735             wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(), 
 736                                     (WXWindow
)GDK_ROOT_WINDOW(), 
 737                                     (WXWindow
)GDK_WINDOW_XWINDOW(window
), 
 738                                     show
, &m_fsSaveFrame
, method
); 
 740             SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
, 
 741                     m_fsSaveFrame
.width
, m_fsSaveFrame
.height
); 
 745     // documented behaviour is to show the window if it's still hidden when 
 746     // showing it full screen 
 753 // ---------------------------------------------------------------------------- 
 754 // overridden wxWindow methods 
 755 // ---------------------------------------------------------------------------- 
 757 bool wxTopLevelWindowGTK::Show( bool show 
) 
 759     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
 761     bool deferShow 
= show 
&& m_deferShow
; 
 765         deferShow 
= !GTK_WIDGET_REALIZED(m_widget
) && 
 766             gdk_x11_screen_supports_net_wm_hint( 
 767                 gtk_widget_get_screen(m_widget
), 
 768                 gdk_atom_intern("_NET_REQUEST_FRAME_EXTENTS", false)) && 
 769             g_signal_handler_find(m_widget
, 
 770                 GSignalMatchType(G_SIGNAL_MATCH_ID 
| G_SIGNAL_MATCH_DATA
), 
 771                 g_signal_lookup("property_notify_event", GTK_TYPE_WIDGET
), 
 772                 0, NULL
, NULL
, this); 
 776         // Initial show. If WM supports _NET_REQUEST_FRAME_EXTENTS, defer 
 777         // calling gtk_widget_show() until _NET_FRAME_EXTENTS property 
 778         // notification is received, so correct frame extents are known. 
 779         // This allows resizing m_widget to keep the overall size in sync with 
 780         // what wxWidgets expects it to be without an obvious change in the 
 781         // window size immediately after it becomes visible. 
 783         // Realize m_widget, so m_widget->window can be used. Realizing normally 
 784         // causes the widget tree to be size_allocated, which generates size 
 785         // events in the wrong order. However, the size_allocates will not be 
 786         // done if the allocation is not the default (1,1). 
 787         const int alloc_width 
= m_widget
->allocation
.width
; 
 788         if (alloc_width 
== 1) 
 789             m_widget
->allocation
.width 
= 2; 
 790         gtk_widget_realize(m_widget
); 
 791         if (alloc_width 
== 1) 
 792             m_widget
->allocation
.width 
= 1; 
 794         // send _NET_REQUEST_FRAME_EXTENTS 
 795         XClientMessageEvent xevent
; 
 796         memset(&xevent
, 0, sizeof(xevent
)); 
 797         xevent
.type 
= ClientMessage
; 
 798         xevent
.window 
= gdk_x11_drawable_get_xid(m_widget
->window
); 
 799         xevent
.message_type 
= gdk_x11_atom_to_xatom_for_display( 
 800             gdk_drawable_get_display(m_widget
->window
), 
 801             gdk_atom_intern("_NET_REQUEST_FRAME_EXTENTS", false)); 
 803         Display
* display 
= gdk_x11_drawable_get_xdisplay(m_widget
->window
); 
 804         XSendEvent(display
, DefaultRootWindow(display
), false, 
 805             SubstructureNotifyMask 
| SubstructureRedirectMask
, 
 808         // defer calling gtk_widget_show() 
 813     if (show 
&& !GTK_WIDGET_REALIZED(m_widget
)) 
 815         // size_allocate signals occur in reverse order (bottom to top). 
 816         // Things work better if the initial wxSizeEvents are sent (from the 
 817         // top down), before the initial size_allocate signals occur. 
 818         wxSizeEvent 
event(GetSize(), GetId()); 
 819         event
.SetEventObject(this); 
 820         HandleWindowEvent(event
); 
 823     bool change 
= wxTopLevelWindowBase::Show(show
); 
 827         // make sure window has a non-default position, so when it is shown 
 828         // again, it won't be repositioned by WM as if it were a new window 
 829         // Note that this must be done _after_ the window is hidden. 
 830         gtk_window_move((GtkWindow
*)m_widget
, m_x
, m_y
); 
 836 void wxTopLevelWindowGTK::Raise() 
 838     gtk_window_present( GTK_WINDOW( m_widget 
) ); 
 841 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) ) 
 843     wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") ); 
 846 // ---------------------------------------------------------------------------- 
 848 // ---------------------------------------------------------------------------- 
 850 void wxTopLevelWindowGTK::GTKDoGetSize(int *width
, int *height
) const 
 852     wxSize 
size(m_width
, m_height
); 
 854     if (size
.x 
< 0) size
.x 
= 0; 
 855     if (size
.y 
< 0) size
.y 
= 0; 
 856     if (width
)  *width  
= size
.x
; 
 857     if (height
) *height 
= size
.y
; 
 860 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
 862     wxCHECK_RET( m_widget
, wxT("invalid frame") ); 
 864     // deal with the position first 
 868     if ( !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
 870         // -1 means "use existing" unless the flag above is specified 
 876     else // wxSIZE_ALLOW_MINUS_ONE 
 882     if ( m_x 
!= old_x 
|| m_y 
!= old_y 
) 
 884         gtk_window_move( GTK_WINDOW(m_widget
), m_x
, m_y 
); 
 887     const wxSize 
oldSize(m_width
, m_height
); 
 893     if (m_width 
!= oldSize
.x 
|| m_height 
!= oldSize
.y
) 
 896         GTKDoGetSize(&w
, &h
); 
 897         gtk_window_resize(GTK_WINDOW(m_widget
), w
, h
); 
 899         GetClientSize(&m_oldClientWidth
, &m_oldClientHeight
); 
 900         wxSizeEvent 
event(GetSize(), GetId()); 
 901         event
.SetEventObject(this); 
 902         HandleWindowEvent(event
); 
 906 void wxTopLevelWindowGTK::DoSetClientSize(int width
, int height
) 
 908     if (m_deferShow 
&& !m_isShown
) 
 909         // Since client size is being explicitly set, don't change it later 
 911     wxTopLevelWindowBase::DoSetClientSize(width
, height
); 
 914 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
 916     wxASSERT_MSG(m_widget
, wxT("invalid frame")); 
 920         // for consistency with wxMSW, client area is supposed to be empty for 
 921         // the iconized windows 
 929         GTKDoGetSize(width
, height
); 
 933 void wxTopLevelWindowGTK::DoSetSizeHints( int minW
, int minH
, 
 937     wxTopLevelWindowBase::DoSetSizeHints( minW
, minH
, maxW
, maxH
, incW
, incH 
); 
 939     const wxSize minSize 
= GetMinSize(); 
 940     const wxSize maxSize 
= GetMaxSize(); 
 943     if (minSize
.x 
> 0 || minSize
.y 
> 0) 
 945         hints_mask 
|= GDK_HINT_MIN_SIZE
; 
 946         hints
.min_width 
= minSize
.x 
- m_decorSize
.x
; 
 947         if (hints
.min_width 
< 0) 
 949         hints
.min_height 
= minSize
.y 
- m_decorSize
.y
; 
 950         if (hints
.min_height 
< 0) 
 951             hints
.min_height 
= 0; 
 953     if (maxSize
.x 
> 0 || maxSize
.y 
> 0) 
 955         hints_mask 
|= GDK_HINT_MAX_SIZE
; 
 956         hints
.max_width 
= maxSize
.x 
- m_decorSize
.x
; 
 957         if (hints
.max_width 
< 0) 
 958             hints
.max_width 
= INT_MAX
; 
 959         hints
.max_height 
= maxSize
.y 
- m_decorSize
.y
; 
 960         if (hints
.max_height 
< 0) 
 961             hints
.max_height 
= INT_MAX
; 
 963     if (incW 
> 0 || incH 
> 0) 
 965         hints_mask 
|= GDK_HINT_RESIZE_INC
; 
 966         hints
.width_inc  
= incW 
> 0 ? incW 
: 1; 
 967         hints
.height_inc 
= incH 
> 0 ? incH 
: 1; 
 969     gtk_window_set_geometry_hints( 
 970         (GtkWindow
*)m_widget
, NULL
, &hints
, (GdkWindowHints
)hints_mask
); 
 973 void wxTopLevelWindowGTK::GTKUpdateDecorSize(const wxSize
& decorSize
) 
 975     if (m_decorSize 
!= decorSize
) 
 977         const wxSize diff 
= decorSize 
- m_decorSize
; 
 978         m_decorSize 
= decorSize
; 
 979         bool resized 
= false; 
 982             // keep overall size unchanged by shrinking m_widget 
 984             GTKDoGetSize(&w
, &h
); 
 985             // but not if size would be less than minimum, it won't take effect 
 986             const wxSize minSize 
= GetMinSize(); 
 987             if (w 
>= minSize
.x 
&& h 
>= minSize
.y
) 
 989                 gtk_window_resize(GTK_WINDOW(m_widget
), w
, h
); 
 995             // adjust overall size to match change in frame extents 
 998             if (m_width  
< 0) m_width  
= 0; 
 999             if (m_height 
< 0) m_height 
= 0; 
1000             m_oldClientWidth 
= 0; 
1001             gtk_widget_queue_resize(m_wxwindow
); 
1006         // gtk_widget_show() was deferred, do it now 
1007         m_deferShow 
= false; 
1008         GetClientSize(&m_oldClientWidth
, &m_oldClientHeight
); 
1009         wxSizeEvent 
sizeEvent(GetSize(), GetId()); 
1010         sizeEvent
.SetEventObject(this); 
1011         HandleWindowEvent(sizeEvent
); 
1013         gtk_widget_show(m_widget
); 
1015         wxShowEvent 
showEvent(GetId(), true); 
1016         showEvent
.SetEventObject(this); 
1017         HandleWindowEvent(showEvent
); 
1021 void wxTopLevelWindowGTK::OnInternalIdle() 
1023     wxWindow::OnInternalIdle(); 
1025     // Synthetize activate events. 
1026     if ( g_sendActivateEvent 
!= -1 ) 
1028         bool activate 
= g_sendActivateEvent 
!= 0; 
1030         // if (!activate) wxPrintf( wxT("de") ); 
1031         // wxPrintf( wxT("activate\n") ); 
1034         g_sendActivateEvent 
= -1; 
1036         wxTheApp
->SetActive(activate
, (wxWindow 
*)g_lastActiveFrame
); 
1040 // ---------------------------------------------------------------------------- 
1042 // ---------------------------------------------------------------------------- 
1044 void wxTopLevelWindowGTK::SetTitle( const wxString 
&title 
) 
1046     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
1048     if ( title 
== m_title 
) 
1053     gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title 
) ); 
1056 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle 
&icons 
) 
1058     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
1060     wxTopLevelWindowBase::SetIcons( icons 
); 
1064     const size_t numIcons 
= icons
.GetIconCount(); 
1065     for ( size_t i 
= 0; i 
< numIcons
; i
++ ) 
1067         list 
= g_list_prepend(list
, icons
.GetIconByIndex(i
).GetPixbuf()); 
1070     gtk_window_set_icon_list(GTK_WINDOW(m_widget
), list
); 
1074 // ---------------------------------------------------------------------------- 
1075 // frame state: maximized/iconized/normal 
1076 // ---------------------------------------------------------------------------- 
1078 void wxTopLevelWindowGTK::Maximize(bool maximize
) 
1081         gtk_window_maximize( GTK_WINDOW( m_widget 
) ); 
1083         gtk_window_unmaximize( GTK_WINDOW( m_widget 
) ); 
1086 bool wxTopLevelWindowGTK::IsMaximized() const 
1088     if(!m_widget
->window
) 
1091     return gdk_window_get_state(m_widget
->window
) & GDK_WINDOW_STATE_MAXIMIZED
; 
1094 void wxTopLevelWindowGTK::Restore() 
1096     // "Present" seems similar enough to "restore" 
1097     gtk_window_present( GTK_WINDOW( m_widget 
) ); 
1100 void wxTopLevelWindowGTK::Iconize( bool iconize 
) 
1103         gtk_window_iconify( GTK_WINDOW( m_widget 
) ); 
1105         gtk_window_deiconify( GTK_WINDOW( m_widget 
) ); 
1108 bool wxTopLevelWindowGTK::IsIconized() const 
1110     return m_isIconized
; 
1113 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
) 
1115     if ( iconize 
!= m_isIconized 
) 
1117         m_isIconized 
= iconize
; 
1118         (void)SendIconizeEvent(iconize
); 
1122 void wxTopLevelWindowGTK::AddGrab() 
1127         gtk_grab_add( m_widget 
); 
1128         wxGUIEventLoop().Run(); 
1129         gtk_grab_remove( m_widget 
); 
1133 void wxTopLevelWindowGTK::RemoveGrab() 
1144 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
) 
1148         if (region
.IsEmpty()) 
1150             gdk_window_shape_combine_mask(window
, NULL
, 0, 0); 
1154             gdk_window_shape_combine_region(window
, region
.GetRegion(), 0, 0); 
1162 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
) 
1164     wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), false, 
1165                  _T("Shaped windows must be created with the wxFRAME_SHAPED style.")); 
1167     GdkWindow 
*window 
= NULL
; 
1170         do_shape_combine_region(m_wxwindow
->window
, region
); 
1172     window 
= m_widget
->window
; 
1173     return do_shape_combine_region(window
, region
); 
1176 bool wxTopLevelWindowGTK::IsActive() 
1178     return (this == (wxTopLevelWindowGTK
*)g_activeFrame
); 
1181 void wxTopLevelWindowGTK::RequestUserAttention(int flags
) 
1183     bool new_hint_value 
= false; 
1185     // FIXME: This is a workaround to focus handling problem 
1186     // If RequestUserAttention is called for example right after a wxSleep, OnInternalIdle hasn't 
1187     // yet been processed, and the internal focus system is not up to date yet. 
1188     // wxYieldIfNeeded ensures the processing of it, but can have unwanted side effects - MR 
1189     ::wxYieldIfNeeded(); 
1191     if(m_urgency_hint 
>= 0) 
1192         g_source_remove(m_urgency_hint
); 
1194     m_urgency_hint 
= -2; 
1196     if( GTK_WIDGET_REALIZED(m_widget
) && !IsActive() ) 
1198         new_hint_value 
= true; 
1200         if (flags 
& wxUSER_ATTENTION_INFO
) 
1202             m_urgency_hint 
= g_timeout_add(5000, (GSourceFunc
)gtk_frame_urgency_timer_callback
, this); 
1204             m_urgency_hint 
= -1; 
1208 #if GTK_CHECK_VERSION(2,7,0) 
1209     if(!gtk_check_version(2,7,0)) 
1210         gtk_window_set_urgency_hint(GTK_WINDOW( m_widget 
), new_hint_value
); 
1213         wxgtk_window_set_urgency_hint(GTK_WINDOW( m_widget 
), new_hint_value
); 
1216 void wxTopLevelWindowGTK::SetWindowStyleFlag( long style 
) 
1218     // Store which styles were changed 
1219     long styleChanges 
= style 
^ m_windowStyle
; 
1221     // Process wxWindow styles. This also updates the internal variable 
1222     // Therefore m_windowStyle bits carry now the _new_ style values 
1223     wxWindow::SetWindowStyleFlag(style
); 
1225     // just return for now if widget does not exist yet 
1229     if ( styleChanges 
& wxSTAY_ON_TOP 
) 
1231         gtk_window_set_keep_above(GTK_WINDOW(m_widget
), 
1232                                   m_windowStyle 
& wxSTAY_ON_TOP
); 
1235     if ( styleChanges 
& wxFRAME_NO_TASKBAR 
) 
1237         gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), 
1238                                          m_windowStyle 
& wxFRAME_NO_TASKBAR
); 
1242 /* Get the X Window between child and the root window. 
1243    This should usually be the WM managed XID */ 
1244 static Window 
wxGetTopmostWindowX11(Display 
*dpy
, Window child
) 
1246     Window root
, parent
; 
1248     unsigned int nchildren
; 
1250     XQueryTree(dpy
, child
, &root
, &parent
, &children
, &nchildren
); 
1253     while (parent 
!= root
) { 
1255         XQueryTree(dpy
, child
, &root
, &parent
, &children
, &nchildren
); 
1262 bool wxTopLevelWindowGTK::SetTransparent(wxByte alpha
) 
1264     if (!m_widget 
|| !m_widget
->window
) 
1267     Display
* dpy 
= GDK_WINDOW_XDISPLAY (m_widget
->window
); 
1268     // We need to get the X Window that has the root window as the immediate parent 
1269     // and m_widget->window as a child. This should be the X Window that the WM manages and 
1270     // from which the opacity property is checked from. 
1271     Window win 
= wxGetTopmostWindowX11(dpy
, GDK_WINDOW_XID (m_widget
->window
)); 
1274     // Using pure Xlib to not have a GTK version check mess due to gtk2.0 not having GdkDisplay 
1276         XDeleteProperty(dpy
, win
, XInternAtom(dpy
, "_NET_WM_WINDOW_OPACITY", False
)); 
1279         long opacity 
= alpha 
* 0x1010101L
; 
1280         XChangeProperty(dpy
, win
, XInternAtom(dpy
, "_NET_WM_WINDOW_OPACITY", False
), 
1281                         XA_CARDINAL
, 32, PropModeReplace
, 
1282                         (unsigned char *) &opacity
, 1L); 
1288 bool wxTopLevelWindowGTK::CanSetTransparent() 
1290     // allow to override automatic detection as it's far from perfect 
1291     static const wxChar 
*SYSOPT_TRANSPARENT 
= wxT("gtk.tlw.can-set-transparent"); 
1292     if ( wxSystemOptions::HasOption(SYSOPT_TRANSPARENT
) ) 
1294         return wxSystemOptions::GetOptionInt(SYSOPT_TRANSPARENT
) != 0; 
1297 #if GTK_CHECK_VERSION(2,10,0) 
1298     if (!gtk_check_version(2,10,0)) 
1300         return (gtk_widget_is_composited (m_widget
)); 
1303 #endif // In case of lower versions than gtk+-2.10.0 we could look for _NET_WM_CM_Sn ourselves 
1308 #if 0 // Don't be optimistic here for the sake of wxAUI 
1309     int opcode
, event
, error
; 
1310     // Check for the existence of a RGBA visual instead? 
1311     return XQueryExtension(gdk_x11_get_default_xdisplay (), 
1312                            "Composite", &opcode
, &event
, &error
); 
1316 void wxTopLevelWindowGTK::OnSysColourChanged(wxSysColourChangedEvent
& event
) 
1318     // We don't know the order in which top-level windows will 
1319     // be notified, so we need to clear the system objects 
1320     // for each top-level window. 
1321     extern void wxClearGtkSystemObjects(); 
1322     wxClearGtkSystemObjects(); 
1324     // wxWindowBase::OnSysColourChanged will propagate event