1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/toplevel.cpp 
   4 // Author:      Robert Roebling 
   5 // Copyright:   (c) 1998 Robert Roebling 
   6 // Licence:     wxWindows licence 
   7 ///////////////////////////////////////////////////////////////////////////// 
   9 // For compilers that support precompilation, includes "wx.h". 
  10 #include "wx/wxprec.h" 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21 #define XIconifyWindow XICONIFYWINDOW 
  24 #include "wx/toplevel.h" 
  33 #include "wx/evtloop.h" 
  34 #include "wx/sysopt.h" 
  37 #ifdef GDK_WINDOWING_X11 
  39     #include <X11/Xatom.h>  // XA_CARDINAL 
  40     #include "wx/unix/utilsx11.h" 
  43 #include "wx/gtk/private.h" 
  44 #include "wx/gtk/private/gtk2-compat.h" 
  45 #include "wx/gtk/private/win_gtk.h" 
  48     #include <hildon-widgets/hildon-program.h> 
  49     #include <hildon-widgets/hildon-window.h> 
  50 #endif // wxUSE_LIBHILDON 
  53     #include <hildon/hildon.h> 
  54 #endif // wxUSE_LIBHILDON2 
  56 // ---------------------------------------------------------------------------- 
  58 // ---------------------------------------------------------------------------- 
  60 // this is incremented while a modal dialog is shown 
  61 int wxOpenModalDialogsCount 
= 0; 
  63 // the frame that is currently active (i.e. its child has focus). It is 
  64 // used to generate wxActivateEvents 
  65 static wxTopLevelWindowGTK 
*g_activeFrame 
= NULL
; 
  66 static wxTopLevelWindowGTK 
*g_lastActiveFrame 
= NULL
; 
  68 // if we detect that the app has got/lost the focus, we set this variable to 
  69 // either TRUE or FALSE and an activate event will be sent during the next 
  70 // OnIdle() call and it is reset to -1: this value means that we shouldn't 
  71 // send any activate events at all 
  72 static int g_sendActivateEvent 
= -1; 
  74 #ifdef GDK_WINDOWING_X11 
  75 // Whether _NET_REQUEST_FRAME_EXTENTS support is working 
  77     RFE_STATUS_UNKNOWN
, RFE_STATUS_WORKING
, RFE_STATUS_BROKEN
 
  78 } gs_requestFrameExtentsStatus
; 
  80 static bool gs_decorCacheValid
; 
  83 //----------------------------------------------------------------------------- 
  84 // RequestUserAttention related functions 
  85 //----------------------------------------------------------------------------- 
  88 static void wxgtk_window_set_urgency_hint (GtkWindow 
*win
, 
  91 #if GTK_CHECK_VERSION(2,7,0) 
  92     if (gtk_check_version(2,7,0) == NULL
) 
  93         gtk_window_set_urgency_hint(win
, setting
); 
  97 #ifdef GDK_WINDOWING_X11 
  98         GdkWindow
* window 
= gtk_widget_get_window(GTK_WIDGET(win
)); 
  99         wxCHECK_RET(window
, "wxgtk_window_set_urgency_hint: GdkWindow not realized"); 
 101         Display
* dpy 
= GDK_WINDOW_XDISPLAY(window
); 
 102         Window xid 
= GDK_WINDOW_XID(window
); 
 103         XWMHints
* wm_hints 
= XGetWMHints(dpy
, xid
); 
 106             wm_hints 
= XAllocWMHints(); 
 109             wm_hints
->flags 
|= XUrgencyHint
; 
 111             wm_hints
->flags 
&= ~XUrgencyHint
; 
 113         XSetWMHints(dpy
, xid
, wm_hints
); 
 115 #endif // GDK_WINDOWING_X11 
 118 #define gtk_window_set_urgency_hint wxgtk_window_set_urgency_hint 
 122 static gboolean 
gtk_frame_urgency_timer_callback( wxTopLevelWindowGTK 
*win 
) 
 124     gtk_window_set_urgency_hint(GTK_WINDOW(win
->m_widget
), false); 
 126     win
->m_urgency_hint 
= -2; 
 131 //----------------------------------------------------------------------------- 
 133 //----------------------------------------------------------------------------- 
 136 static gboolean 
gtk_frame_focus_in_callback( GtkWidget 
*widget
, 
 137                                          GdkEvent 
*WXUNUSED(event
), 
 138                                          wxTopLevelWindowGTK 
*win 
) 
 140     switch ( g_sendActivateEvent 
) 
 143             // we've got focus from outside, synthetize wxActivateEvent 
 144             g_sendActivateEvent 
= 1; 
 148             // another our window just lost focus, it was already ours before 
 149             // - don't send any wxActivateEvent 
 150             g_sendActivateEvent 
= -1; 
 155     g_lastActiveFrame 
= g_activeFrame
; 
 157     // wxPrintf( wxT("active: %s\n"), win->GetTitle().c_str() ); 
 159     // MR: wxRequestUserAttention related block 
 160     switch( win
->m_urgency_hint 
) 
 163             g_source_remove( win
->m_urgency_hint 
); 
 164             // no break, fallthrough to remove hint too 
 166             gtk_window_set_urgency_hint(GTK_WINDOW(widget
), false); 
 167             win
->m_urgency_hint 
= -2; 
 173     wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
); 
 174     wxActivateEvent 
event(wxEVT_ACTIVATE
, true, g_activeFrame
->GetId()); 
 175     event
.SetEventObject(g_activeFrame
); 
 176     g_activeFrame
->HandleWindowEvent(event
); 
 182 //----------------------------------------------------------------------------- 
 184 //----------------------------------------------------------------------------- 
 188 gboolean 
gtk_frame_focus_out_callback(GtkWidget 
* WXUNUSED(widget
), 
 189                                       GdkEventFocus 
*WXUNUSED(gdk_event
), 
 190                                       wxTopLevelWindowGTK 
* WXUNUSED(win
)) 
 192     // if the focus goes out of our app altogether, OnIdle() will send 
 193     // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset 
 194     // g_sendActivateEvent to -1 
 195     g_sendActivateEvent 
= 0; 
 197     // wxASSERT_MSG( (g_activeFrame == win), wxT("TLW deactivatd although it wasn't active") ); 
 199     // wxPrintf( wxT("inactive: %s\n"), win->GetTitle().c_str() ); 
 203         wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
); 
 204         wxActivateEvent 
event(wxEVT_ACTIVATE
, false, g_activeFrame
->GetId()); 
 205         event
.SetEventObject(g_activeFrame
); 
 206         g_activeFrame
->HandleWindowEvent(event
); 
 208         g_activeFrame 
= NULL
; 
 215 // ---------------------------------------------------------------------------- 
 217 // ---------------------------------------------------------------------------- 
 221 wxgtk_tlw_key_press_event(GtkWidget 
*widget
, GdkEventKey 
*event
) 
 223     GtkWindow
* const window 
= GTK_WINDOW(widget
); 
 225     // By default GTK+ checks for the menu accelerators in this (top level) 
 226     // window first and then propagates the event to the currently focused 
 227     // child from where it bubbles up the window parent chain. In wxWidgets, 
 228     // however, we want the child window to have the event first but still 
 229     // handle it as an accelerator if it's not processed there, so we need to 
 230     // customize this by reversing the order of the steps done in the standard 
 231     // GTK+ gtk_window_key_press_event() handler. 
 233     if ( gtk_window_propagate_key_event(window
, event
) ) 
 236     if ( gtk_window_activate_key(window
, event
) ) 
 239     if (GTK_WIDGET_GET_CLASS(widget
)->key_press_event(widget
, event
)) 
 246 //----------------------------------------------------------------------------- 
 247 // "size_allocate" from m_wxwindow 
 248 //----------------------------------------------------------------------------- 
 252 size_allocate(GtkWidget
*, GtkAllocation
* alloc
, wxTopLevelWindowGTK
* win
) 
 254     win
->m_useCachedClientSize 
= true; 
 255     if (win
->m_clientWidth  
!= alloc
->width 
|| 
 256         win
->m_clientHeight 
!= alloc
->height
) 
 258         win
->m_clientWidth  
= alloc
->width
; 
 259         win
->m_clientHeight 
= alloc
->height
; 
 262         gtk_widget_get_allocation(win
->m_widget
, &a
); 
 263         wxSize 
size(a
.width
, a
.height
); 
 264         size
.x 
+= win
->m_decorSize
.left 
+ win
->m_decorSize
.right
; 
 265         size
.y 
+= win
->m_decorSize
.top 
+ win
->m_decorSize
.bottom
; 
 266         win
->m_width  
= size
.x
; 
 267         win
->m_height 
= size
.y
; 
 269         if (!win
->IsIconized()) 
 271             wxSizeEvent 
event(size
, win
->GetId()); 
 272             event
.SetEventObject(win
); 
 273             win
->HandleWindowEvent(event
); 
 275         // else the window is currently unmapped, don't generate size events 
 280 //----------------------------------------------------------------------------- 
 282 //----------------------------------------------------------------------------- 
 286 gtk_frame_delete_callback( GtkWidget 
*WXUNUSED(widget
), 
 287                            GdkEvent 
*WXUNUSED(event
), 
 288                            wxTopLevelWindowGTK 
*win 
) 
 290     if (win
->IsEnabled() && 
 291         (wxOpenModalDialogsCount 
== 0 || (win
->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) || 
 299 //----------------------------------------------------------------------------- 
 301 //----------------------------------------------------------------------------- 
 305 gtk_frame_configure_callback( GtkWidget
*, 
 306                               GdkEventConfigure
* gdk_event
, 
 307                               wxTopLevelWindowGTK 
*win 
) 
 309     win
->GTKConfigureEvent(gdk_event
->x
, gdk_event
->y
); 
 314 void wxTopLevelWindowGTK::GTKConfigureEvent(int x
, int y
) 
 317 #ifdef GDK_WINDOWING_X11 
 318     if (gs_decorCacheValid
) 
 320         const DecorSize
& decorSize 
= GetCachedDecorSize(); 
 321         point
.x 
= x 
- decorSize
.left
; 
 322         point
.y 
= y 
- decorSize
.top
; 
 327         gtk_window_get_position(GTK_WINDOW(m_widget
), &point
.x
, &point
.y
); 
 330     if (m_x 
!= point
.x 
|| m_y 
!= point
.y
) 
 334         wxMoveEvent 
event(point
, GetId()); 
 335         event
.SetEventObject(this); 
 336         HandleWindowEvent(event
); 
 340 //----------------------------------------------------------------------------- 
 341 // "realize" from m_widget 
 342 //----------------------------------------------------------------------------- 
 344 // we cannot the WM hints and icons before the widget has been realized, 
 345 // so we do this directly after realization 
 347 void wxTopLevelWindowGTK::GTKHandleRealized() 
 349     wxNonOwnedWindow::GTKHandleRealized(); 
 351     gdk_window_set_decorations(gtk_widget_get_window(m_widget
), 
 352                                (GdkWMDecoration
)m_gdkDecor
); 
 353     gdk_window_set_functions(gtk_widget_get_window(m_widget
), 
 354                                (GdkWMFunction
)m_gdkFunc
); 
 356     const wxIconBundle
& icons 
= GetIcons(); 
 357     if (icons
.GetIconCount()) 
 361     if (gtk_window_get_has_resize_grip(GTK_WINDOW(m_widget
))) 
 363         // Grip window can end up obscured, probably due to deferred show. 
 364         // Reset grip to ensure it is visible. 
 365         gtk_window_set_has_resize_grip(GTK_WINDOW(m_widget
), false); 
 366         gtk_window_set_has_resize_grip(GTK_WINDOW(m_widget
), true); 
 371 //----------------------------------------------------------------------------- 
 372 // "map_event" from m_widget 
 373 //----------------------------------------------------------------------------- 
 377 gtk_frame_map_callback( GtkWidget
*, 
 378                         GdkEvent 
* WXUNUSED(event
), 
 379                         wxTopLevelWindow 
*win 
) 
 381     const bool wasIconized 
= win
->IsIconized(); 
 384         // Because GetClientSize() returns (0,0) when IsIconized() is true, 
 385         // a size event must be generated, just in case GetClientSize() was 
 386         // called while iconized. This specifically happens when restoring a 
 387         // tlw that was "rolled up" with some WMs. 
 388         // Queue a resize rather than sending size event directly to allow 
 389         // children to be made visible first. 
 390         win
->m_useCachedClientSize 
= false; 
 391         win
->m_clientWidth 
= 0; 
 392         gtk_widget_queue_resize(win
->m_wxwindow
); 
 394     // it is possible for m_isShown to be false here, see bug #9909 
 395     if (win
->wxWindowBase::Show(true)) 
 397         wxShowEvent 
eventShow(win
->GetId(), true); 
 398         eventShow
.SetEventObject(win
); 
 399         win
->GetEventHandler()->ProcessEvent(eventShow
); 
 402     // restore focus-on-map setting in case ShowWithoutActivating() was called 
 403     gtk_window_set_focus_on_map(GTK_WINDOW(win
->m_widget
), true); 
 409 //----------------------------------------------------------------------------- 
 410 // "window-state-event" from m_widget 
 411 //----------------------------------------------------------------------------- 
 415 gtk_frame_window_state_callback( GtkWidget
* WXUNUSED(widget
), 
 416                           GdkEventWindowState 
*event
, 
 417                           wxTopLevelWindow 
*win 
) 
 419     if (event
->changed_mask 
& GDK_WINDOW_STATE_ICONIFIED
) 
 420         win
->SetIconizeState((event
->new_window_state 
& GDK_WINDOW_STATE_ICONIFIED
) != 0); 
 422     // if maximized bit changed and it is now set 
 423     if (event
->changed_mask 
& event
->new_window_state 
& GDK_WINDOW_STATE_MAXIMIZED
) 
 425         wxMaximizeEvent 
evt(win
->GetId()); 
 426         evt
.SetEventObject(win
); 
 427         win
->HandleWindowEvent(evt
); 
 430     if (event
->changed_mask 
& GDK_WINDOW_STATE_FULLSCREEN
) 
 431         win
->m_fsIsShowing 
= (event
->new_window_state 
& GDK_WINDOW_STATE_FULLSCREEN
) != 0; 
 437 //----------------------------------------------------------------------------- 
 439 bool wxGetFrameExtents(GdkWindow
* window
, int* left
, int* right
, int* top
, int* bottom
) 
 441 #ifdef GDK_WINDOWING_X11 
 442     static GdkAtom property 
= gdk_atom_intern("_NET_FRAME_EXTENTS", false); 
 443     GdkDisplay
* display 
= gdk_window_get_display(window
); 
 444     Atom xproperty 
= gdk_x11_atom_to_xatom_for_display(display
, property
); 
 447     gulong nitems
, bytes_after
; 
 449     Status status 
= XGetWindowProperty( 
 450         GDK_DISPLAY_XDISPLAY(display
), 
 451         GDK_WINDOW_XID(window
), 
 453         0, 4, false, XA_CARDINAL
, 
 454         &type
, &format
, &nitems
, &bytes_after
, &data
); 
 455     const bool success 
= status 
== Success 
&& data 
&& nitems 
== 4; 
 458         long* p 
= (long*)data
; 
 459         if (left
)   *left   
= int(p
[0]); 
 460         if (right
)  *right  
= int(p
[1]); 
 461         if (top
)    *top    
= int(p
[2]); 
 462         if (bottom
) *bottom 
= int(p
[3]); 
 472 #ifdef GDK_WINDOWING_X11 
 473 //----------------------------------------------------------------------------- 
 474 // "property_notify_event" from m_widget 
 475 //----------------------------------------------------------------------------- 
 478 static gboolean 
property_notify_event( 
 479     GtkWidget
*, GdkEventProperty
* event
, wxTopLevelWindowGTK
* win
) 
 481     // Watch for changes to _NET_FRAME_EXTENTS property 
 482     static GdkAtom property 
= gdk_atom_intern("_NET_FRAME_EXTENTS", false); 
 483     if (event
->state 
== GDK_PROPERTY_NEW_VALUE 
&& event
->atom 
== property
) 
 485         if (win
->m_netFrameExtentsTimerId
) 
 487             // WM support for _NET_REQUEST_FRAME_EXTENTS is working 
 488             gs_requestFrameExtentsStatus 
= RFE_STATUS_WORKING
; 
 489             g_source_remove(win
->m_netFrameExtentsTimerId
); 
 490             win
->m_netFrameExtentsTimerId 
= 0; 
 493         wxTopLevelWindowGTK::DecorSize decorSize 
= win
->m_decorSize
; 
 494         gs_decorCacheValid 
= wxGetFrameExtents(event
->window
, 
 495             &decorSize
.left
, &decorSize
.right
, &decorSize
.top
, &decorSize
.bottom
); 
 497         win
->GTKUpdateDecorSize(decorSize
); 
 504 static gboolean 
request_frame_extents_timeout(void* data
) 
 506     // WM support for _NET_REQUEST_FRAME_EXTENTS is broken 
 507     gs_requestFrameExtentsStatus 
= RFE_STATUS_BROKEN
; 
 509     wxTopLevelWindowGTK
* win 
= static_cast<wxTopLevelWindowGTK
*>(data
); 
 510     win
->m_netFrameExtentsTimerId 
= 0; 
 511     wxTopLevelWindowGTK::DecorSize decorSize 
= win
->m_decorSize
; 
 512     wxGetFrameExtents(gtk_widget_get_window(win
->m_widget
), 
 513         &decorSize
.left
, &decorSize
.right
, &decorSize
.top
, &decorSize
.bottom
); 
 514     win
->GTKUpdateDecorSize(decorSize
); 
 519 #endif // GDK_WINDOWING_X11 
 521 // ---------------------------------------------------------------------------- 
 522 // wxTopLevelWindowGTK creation 
 523 // ---------------------------------------------------------------------------- 
 525 void wxTopLevelWindowGTK::Init() 
 528     m_isIconized 
= false; 
 529     m_fsIsShowing 
= false; 
 530     m_themeEnabled 
= true; 
 535     m_deferShowAllowed 
= true; 
 536     m_updateDecorSize 
= true; 
 537     m_netFrameExtentsTimerId 
= 0; 
 538     m_incWidth 
= m_incHeight 
= 0; 
 539     memset(&m_decorSize
, 0, sizeof(m_decorSize
)); 
 544 bool wxTopLevelWindowGTK::Create( wxWindow 
*parent
, 
 546                                   const wxString
& title
, 
 548                                   const wxSize
& sizeOrig
, 
 550                                   const wxString 
&name 
) 
 552     // always create a frame of some reasonable, even if arbitrary, size (at 
 553     // least for MSW compatibility) 
 554     wxSize size 
= sizeOrig
; 
 555     size
.x 
= WidthDefault(size
.x
); 
 556     size
.y 
= HeightDefault(size
.y
); 
 558     wxTopLevelWindows
.Append( this ); 
 560     if (!PreCreation( parent
, pos
, size 
) || 
 561         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
 563         wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") ); 
 569     // NB: m_widget may be !=NULL if it was created by derived class' Create, 
 570     //     e.g. in wxTaskBarIconAreaGTK 
 571     if (m_widget 
== NULL
) 
 573 #if wxUSE_LIBHILDON || wxUSE_LIBHILDON2 
 574         // we must create HildonWindow and not a normal GtkWindow as the latter 
 575         // doesn't look correctly in Maemo environment and it must also be 
 576         // registered with the main program object 
 577         m_widget 
= hildon_window_new(); 
 578         hildon_program_add_window(wxTheApp
->GetHildonProgram(), 
 579                                   HILDON_WINDOW(m_widget
)); 
 580 #else // !wxUSE_LIBHILDON || !wxUSE_LIBHILDON2 
 581         m_widget 
= gtk_window_new(GTK_WINDOW_TOPLEVEL
); 
 582         if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) 
 584             // Tell WM that this is a dialog window and make it center 
 585             // on parent by default (this is what GtkDialog ctor does): 
 586             gtk_window_set_type_hint(GTK_WINDOW(m_widget
), 
 587                                      GDK_WINDOW_TYPE_HINT_DIALOG
); 
 588             gtk_window_set_position(GTK_WINDOW(m_widget
), 
 589                                     GTK_WIN_POS_CENTER_ON_PARENT
); 
 593             if (style 
& wxFRAME_TOOL_WINDOW
) 
 595                 gtk_window_set_type_hint(GTK_WINDOW(m_widget
), 
 596                                          GDK_WINDOW_TYPE_HINT_UTILITY
); 
 598                 // On some WMs, like KDE, a TOOL_WINDOW will still show 
 599                 // on the taskbar, but on Gnome a TOOL_WINDOW will not. 
 600                 // For consistency between WMs and with Windows, we 
 601                 // should set the NO_TASKBAR flag which will apply 
 602                 // the set_skip_taskbar_hint if it is available, 
 603                 // ensuring no taskbar entry will appear. 
 604                 style 
|= wxFRAME_NO_TASKBAR
; 
 607 #endif // wxUSE_LIBHILDON || wxUSE_LIBHILDON2/!wxUSE_LIBHILDON || !wxUSE_LIBHILDON2 
 609         g_object_ref(m_widget
); 
 612     wxWindow 
*topParent 
= wxGetTopLevelParent(m_parent
); 
 613     if (topParent 
&& (((GTK_IS_WINDOW(topParent
->m_widget
)) && 
 614                        (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) || 
 615                        (style 
& wxFRAME_FLOAT_ON_PARENT
))) 
 617         gtk_window_set_transient_for( GTK_WINDOW(m_widget
), 
 618                                       GTK_WINDOW(topParent
->m_widget
) ); 
 621     if (style 
& wxFRAME_NO_TASKBAR
) 
 623         gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), TRUE
); 
 626     if (style 
& wxSTAY_ON_TOP
) 
 628         gtk_window_set_keep_above(GTK_WINDOW(m_widget
), TRUE
); 
 630     if (style 
& wxMAXIMIZE
) 
 631         gtk_window_maximize(GTK_WINDOW(m_widget
)); 
 635         gtk_window_set_role( GTK_WINDOW(m_widget
), wxGTK_CONV( name 
) ); 
 638     gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title 
) ); 
 639     gtk_widget_set_can_focus(m_widget
, false); 
 641     g_signal_connect (m_widget
, "delete_event", 
 642                       G_CALLBACK (gtk_frame_delete_callback
), this); 
 644     // m_mainWidget is a GtkVBox, holding the bars and client area (m_wxwindow) 
 645     m_mainWidget 
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, 0); 
 646     gtk_widget_show( m_mainWidget 
); 
 647     gtk_widget_set_can_focus(m_mainWidget
, false); 
 648     gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget 
); 
 650     // m_wxwindow is the client area 
 651     m_wxwindow 
= wxPizza::New(); 
 652     gtk_widget_show( m_wxwindow 
); 
 653     gtk_box_pack_start(GTK_BOX(m_mainWidget
), m_wxwindow
, true, true, 0); 
 655     // we donm't allow the frame to get the focus as otherwise 
 656     // the frame will grab it at arbitrary focus changes 
 657     gtk_widget_set_can_focus(m_wxwindow
, false); 
 659     if (m_parent
) m_parent
->AddChild( this ); 
 661     g_signal_connect(m_wxwindow
, "size_allocate", 
 662         G_CALLBACK(size_allocate
), this); 
 667     if ((m_x 
!= -1) || (m_y 
!= -1)) 
 668         gtk_widget_set_uposition( m_widget
, m_x
, m_y 
); 
 671     // for some reported size corrections 
 672     g_signal_connect (m_widget
, "map_event", 
 673                       G_CALLBACK (gtk_frame_map_callback
), this); 
 675     // for iconized state 
 676     g_signal_connect (m_widget
, "window_state_event", 
 677                       G_CALLBACK (gtk_frame_window_state_callback
), this); 
 681     g_signal_connect (m_widget
, "configure_event", 
 682                       G_CALLBACK (gtk_frame_configure_callback
), this); 
 685     g_signal_connect_after (m_widget
, "focus_in_event", 
 686                       G_CALLBACK (gtk_frame_focus_in_callback
), this); 
 687     g_signal_connect_after (m_widget
, "focus_out_event", 
 688                       G_CALLBACK (gtk_frame_focus_out_callback
), this); 
 690     // We need to customize the default GTK+ logic for key processing to make 
 691     // it conforming to wxWidgets event processing order. 
 692     g_signal_connect (m_widget
, "key_press_event", 
 693                       G_CALLBACK (wxgtk_tlw_key_press_event
), NULL
); 
 695 #ifdef GDK_WINDOWING_X11 
 697     if (GDK_IS_X11_SCREEN(gtk_window_get_screen(GTK_WINDOW(m_widget
)))) 
 700         gtk_widget_add_events(m_widget
, GDK_PROPERTY_CHANGE_MASK
); 
 701         g_signal_connect(m_widget
, "property_notify_event", 
 702             G_CALLBACK(property_notify_event
), this); 
 704 #endif // GDK_WINDOWING_X11 
 706     // translate wx decorations styles into Motif WM hints (they are recognized 
 707     // by other WMs as well) 
 709     // always enable moving the window as we have no separate flag for enabling 
 711     m_gdkFunc 
= GDK_FUNC_MOVE
; 
 713     if ( style 
& wxCLOSE_BOX 
) 
 714         m_gdkFunc 
|= GDK_FUNC_CLOSE
; 
 716     if ( style 
& wxMINIMIZE_BOX 
) 
 717         m_gdkFunc 
|= GDK_FUNC_MINIMIZE
; 
 719     if ( style 
& wxMAXIMIZE_BOX 
) 
 720         m_gdkFunc 
|= GDK_FUNC_MAXIMIZE
; 
 722     if ( (style 
& wxSIMPLE_BORDER
) || (style 
& wxNO_BORDER
) ) 
 728         m_gdkDecor 
= GDK_DECOR_BORDER
; 
 730         if ( style 
& wxCAPTION 
) 
 731             m_gdkDecor 
|= GDK_DECOR_TITLE
; 
 733         if ( style 
& wxSYSTEM_MENU 
) 
 734             m_gdkDecor 
|= GDK_DECOR_MENU
; 
 736         if ( style 
& wxMINIMIZE_BOX 
) 
 737             m_gdkDecor 
|= GDK_DECOR_MINIMIZE
; 
 739         if ( style 
& wxMAXIMIZE_BOX 
) 
 740             m_gdkDecor 
|= GDK_DECOR_MAXIMIZE
; 
 742         if ( style 
& wxRESIZE_BORDER 
) 
 744            m_gdkFunc 
|= GDK_FUNC_RESIZE
; 
 745            m_gdkDecor 
|= GDK_DECOR_RESIZEH
; 
 749     if ((style 
& wxRESIZE_BORDER
) == 0) 
 750         gtk_window_set_resizable(GTK_WINDOW(m_widget
), false); 
 753         gtk_window_set_policy(GTK_WINDOW(m_widget
), 1, 1, 1); 
 756     // GTK sometimes chooses very small size if max size hint is not explicitly set 
 757     DoSetSizeHints(m_minWidth
, m_minHeight
, m_maxWidth
, m_maxHeight
, m_incWidth
, m_incHeight
); 
 759     m_decorSize 
= GetCachedDecorSize(); 
 761     GTKDoGetSize(&w
, &h
); 
 762     gtk_window_set_default_size(GTK_WINDOW(m_widget
), w
, h
); 
 767 wxTopLevelWindowGTK::~wxTopLevelWindowGTK() 
 769     if ( m_netFrameExtentsTimerId 
) 
 771         // Don't let the timer callback fire as the window pointer passed to it 
 772         // will become invalid very soon. 
 773         g_source_remove(m_netFrameExtentsTimerId
); 
 776 #if wxUSE_LIBHILDON || wxUSE_LIBHILDON2 
 777     // it can also be a (standard) dialog 
 778     if ( HILDON_IS_WINDOW(m_widget
) ) 
 780         hildon_program_remove_window(wxTheApp
->GetHildonProgram(), 
 781                                      HILDON_WINDOW(m_widget
)); 
 783 #endif // wxUSE_LIBHILDON || wxUSE_LIBHILDON2 
 787         wxFAIL_MSG(wxT("Window still grabbed")); 
 793     // it may also be GtkScrolledWindow in the case of an MDI child 
 794     if (GTK_IS_WINDOW(m_widget
)) 
 796         gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL 
); 
 799     if (g_activeFrame 
== this) 
 800         g_activeFrame 
= NULL
; 
 801     if (g_lastActiveFrame 
== this) 
 802         g_lastActiveFrame 
= NULL
; 
 805 bool wxTopLevelWindowGTK::EnableCloseButton( bool enable 
) 
 808         m_gdkFunc 
|= GDK_FUNC_CLOSE
; 
 810         m_gdkFunc 
&= ~GDK_FUNC_CLOSE
; 
 812     GdkWindow
* window 
= gtk_widget_get_window(m_widget
); 
 814         gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
); 
 819 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long) 
 821     if (show 
== m_fsIsShowing
) 
 822         return false; // return what? 
 824     m_fsIsShowing 
= show
; 
 826 #ifdef GDK_WINDOWING_X11 
 827     Display
* xdpy 
= GDK_DISPLAY_XDISPLAY(gtk_widget_get_display(m_widget
)); 
 828     Window xroot 
= GDK_WINDOW_XID(gtk_widget_get_root_window(m_widget
)); 
 829     wxX11FullScreenMethod method 
= wxGetFullScreenMethodX11(xdpy
, (WXWindow
)xroot
); 
 831     // NB: gtk_window_fullscreen() uses freedesktop.org's WMspec extensions 
 832     //     to switch to fullscreen, which is not always available. We must 
 833     //     check if WM supports the spec and use legacy methods if it 
 835     if ( method 
== wxX11_FS_WMSPEC 
) 
 836 #endif // GDK_WINDOWING_X11 
 839             gtk_window_fullscreen( GTK_WINDOW( m_widget 
) ); 
 841             gtk_window_unfullscreen( GTK_WINDOW( m_widget 
) ); 
 843 #ifdef GDK_WINDOWING_X11 
 846         GdkWindow
* window 
= gtk_widget_get_window(m_widget
); 
 847         Window xid 
= GDK_WINDOW_XID(window
); 
 851             GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y 
); 
 852             GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height 
); 
 854             GdkScreen
* screen 
= gtk_widget_get_screen(m_widget
); 
 855             const int screen_width 
= gdk_screen_get_width(screen
); 
 856             const int screen_height 
= gdk_screen_get_height(screen
); 
 858             gint client_x
, client_y
, root_x
, root_y
; 
 861             m_fsSaveGdkFunc 
= m_gdkFunc
; 
 862             m_fsSaveGdkDecor 
= m_gdkDecor
; 
 863             m_gdkFunc 
= m_gdkDecor 
= 0; 
 864             gdk_window_set_decorations(window
, (GdkWMDecoration
)0); 
 865             gdk_window_set_functions(window
, (GdkWMFunction
)0); 
 867             gdk_window_get_origin(window
, &root_x
, &root_y
); 
 868             gdk_window_get_geometry(window
, &client_x
, &client_y
, &width
, &height
); 
 870             gdk_window_move_resize( 
 871                 window
, -client_x
, -client_y
, screen_width 
+ 1, screen_height 
+ 1); 
 873             wxSetFullScreenStateX11(xdpy
, 
 876                                     show
, &m_fsSaveFrame
, method
); 
 880             m_gdkFunc 
= m_fsSaveGdkFunc
; 
 881             m_gdkDecor 
= m_fsSaveGdkDecor
; 
 882             gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
); 
 883             gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
); 
 885             wxSetFullScreenStateX11(xdpy
, 
 888                                     show
, &m_fsSaveFrame
, method
); 
 890             SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
, 
 891                     m_fsSaveFrame
.width
, m_fsSaveFrame
.height
); 
 894 #endif // GDK_WINDOWING_X11 
 896     // documented behaviour is to show the window if it's still hidden when 
 897     // showing it full screen 
 904 // ---------------------------------------------------------------------------- 
 905 // overridden wxWindow methods 
 906 // ---------------------------------------------------------------------------- 
 908 void wxTopLevelWindowGTK::Refresh( bool WXUNUSED(eraseBackground
), const wxRect 
*WXUNUSED(rect
) ) 
 910     wxCHECK_RET( m_widget
, wxT("invalid frame") ); 
 912     gtk_widget_queue_draw( m_widget 
); 
 914     GdkWindow
* window 
= NULL
; 
 916         window 
= gtk_widget_get_window(m_wxwindow
); 
 918         gdk_window_invalidate_rect(window
, NULL
, true); 
 921 bool wxTopLevelWindowGTK::Show( bool show 
) 
 923     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
 925 #ifdef GDK_WINDOWING_X11 
 926     bool deferShow 
= show 
&& !m_isShown 
&& m_deferShow
; 
 929         deferShow 
= m_deferShowAllowed 
&& 
 930             gs_requestFrameExtentsStatus 
!= RFE_STATUS_BROKEN 
&& 
 931             !gtk_widget_get_realized(m_widget
) && 
 932             g_signal_handler_find(m_widget
, 
 933                 GSignalMatchType(G_SIGNAL_MATCH_ID 
| G_SIGNAL_MATCH_DATA
), 
 934                 g_signal_lookup("property_notify_event", GTK_TYPE_WIDGET
), 
 935                 0, NULL
, NULL
, this); 
 938             GdkScreen
* screen 
= gtk_widget_get_screen(m_widget
); 
 939             GdkAtom atom 
= gdk_atom_intern("_NET_REQUEST_FRAME_EXTENTS", false); 
 940             deferShow 
= gdk_x11_screen_supports_net_wm_hint(screen
, atom
) != 0; 
 942             // If _NET_REQUEST_FRAME_EXTENTS not supported, don't allow changes 
 943             // to m_decorSize, it breaks saving/restoring window size with 
 944             // GetSize()/SetSize() because it makes window bigger between each 
 946             m_updateDecorSize 
= deferShow
; 
 949         m_deferShow 
= deferShow
; 
 953         // Initial show. If WM supports _NET_REQUEST_FRAME_EXTENTS, defer 
 954         // calling gtk_widget_show() until _NET_FRAME_EXTENTS property 
 955         // notification is received, so correct frame extents are known. 
 956         // This allows resizing m_widget to keep the overall size in sync with 
 957         // what wxWidgets expects it to be without an obvious change in the 
 958         // window size immediately after it becomes visible. 
 960         // Realize m_widget, so m_widget->window can be used. Realizing normally 
 961         // causes the widget tree to be size_allocated, which generates size 
 962         // events in the wrong order. However, the size_allocates will not be 
 963         // done if the allocation is not the default (1,1). 
 965         gtk_widget_get_allocation(m_widget
, &alloc
); 
 966         const int alloc_width 
= alloc
.width
; 
 967         if (alloc_width 
== 1) 
 970             gtk_widget_set_allocation(m_widget
, &alloc
); 
 972         gtk_widget_realize(m_widget
); 
 973         if (alloc_width 
== 1) 
 976             gtk_widget_set_allocation(m_widget
, &alloc
); 
 979         // send _NET_REQUEST_FRAME_EXTENTS 
 980         XClientMessageEvent xevent
; 
 981         memset(&xevent
, 0, sizeof(xevent
)); 
 982         xevent
.type 
= ClientMessage
; 
 983         GdkWindow
* window 
= gtk_widget_get_window(m_widget
); 
 984         xevent
.window 
= GDK_WINDOW_XID(window
); 
 985         xevent
.message_type 
= gdk_x11_atom_to_xatom_for_display( 
 986             gdk_window_get_display(window
), 
 987             gdk_atom_intern("_NET_REQUEST_FRAME_EXTENTS", false)); 
 989         Display
* display 
= GDK_DISPLAY_XDISPLAY(gdk_window_get_display(window
)); 
 990         XSendEvent(display
, DefaultRootWindow(display
), false, 
 991             SubstructureNotifyMask 
| SubstructureRedirectMask
, 
 994         if (gs_requestFrameExtentsStatus 
== RFE_STATUS_UNKNOWN
) 
 996             // if WM does not respond to request within 1 second, 
 997             // we assume support for _NET_REQUEST_FRAME_EXTENTS is not working 
 998             m_netFrameExtentsTimerId 
= 
 999                 g_timeout_add(1000, request_frame_extents_timeout
, this); 
1002         // defer calling gtk_widget_show() 
1006 #endif // GDK_WINDOWING_X11 
1008     if (show 
&& !gtk_widget_get_realized(m_widget
)) 
1010         // size_allocate signals occur in reverse order (bottom to top). 
1011         // Things work better if the initial wxSizeEvents are sent (from the 
1012         // top down), before the initial size_allocate signals occur. 
1013         wxSizeEvent 
event(GetSize(), GetId()); 
1014         event
.SetEventObject(this); 
1015         HandleWindowEvent(event
); 
1018     bool change 
= base_type::Show(show
); 
1020     if (change 
&& !show
) 
1022         // make sure window has a non-default position, so when it is shown 
1023         // again, it won't be repositioned by WM as if it were a new window 
1024         // Note that this must be done _after_ the window is hidden. 
1025         gtk_window_move((GtkWindow
*)m_widget
, m_x
, m_y
); 
1031 void wxTopLevelWindowGTK::ShowWithoutActivating() 
1035         gtk_window_set_focus_on_map(GTK_WINDOW(m_widget
), false); 
1040 void wxTopLevelWindowGTK::Raise() 
1042     gtk_window_present( GTK_WINDOW( m_widget 
) ); 
1045 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) ) 
1047     wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") ); 
1050 // ---------------------------------------------------------------------------- 
1052 // ---------------------------------------------------------------------------- 
1054 void wxTopLevelWindowGTK::GTKDoGetSize(int *width
, int *height
) const 
1056     wxSize 
size(m_width
, m_height
); 
1057     size
.x 
-= m_decorSize
.left 
+ m_decorSize
.right
; 
1058     size
.y 
-= m_decorSize
.top 
+ m_decorSize
.bottom
; 
1059     if (size
.x 
< 0) size
.x 
= 0; 
1060     if (size
.y 
< 0) size
.y 
= 0; 
1061 #if wxUSE_LIBHILDON2 
1071        else if (size
.y 
== 270) 
1076 #else // wxUSE_LIBHILDON2 
1077     if (width
)  *width  
= size
.x
; 
1078     if (height
) *height 
= size
.y
; 
1079 #endif // wxUSE_LIBHILDON2 /!wxUSE_LIBHILDON2 
1082 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
1084     wxCHECK_RET( m_widget
, wxT("invalid frame") ); 
1086     // deal with the position first 
1090     if ( !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
1092         // -1 means "use existing" unless the flag above is specified 
1098     else // wxSIZE_ALLOW_MINUS_ONE 
1104     if ( m_x 
!= old_x 
|| m_y 
!= old_y 
) 
1106         gtk_window_move( GTK_WINDOW(m_widget
), m_x
, m_y 
); 
1107         wxMoveEvent 
event(wxPoint(m_x
, m_y
), GetId()); 
1108         event
.SetEventObject(this); 
1109         HandleWindowEvent(event
); 
1112     const wxSize 
oldSize(m_width
, m_height
); 
1118     if (m_width 
< 1) m_width 
= 1; 
1119     if (m_height 
< 1) m_height 
= 1; 
1120     if (m_width 
!= oldSize
.x 
|| m_height 
!= oldSize
.y
) 
1122         m_deferShowAllowed 
= true; 
1123         m_useCachedClientSize 
= false; 
1126         GTKDoGetSize(&w
, &h
); 
1127         gtk_window_resize(GTK_WINDOW(m_widget
), w
, h
); 
1129         DoGetClientSize(&m_clientWidth
, &m_clientHeight
); 
1130         wxSizeEvent 
event(GetSize(), GetId()); 
1131         event
.SetEventObject(this); 
1132         HandleWindowEvent(event
); 
1136 void wxTopLevelWindowGTK::DoSetClientSize(int width
, int height
) 
1138     base_type::DoSetClientSize(width
, height
); 
1140     // Since client size is being explicitly set, don't change it later 
1141     // Has to be done after calling base because it calls SetSize, 
1142     // which sets this true 
1143     m_deferShowAllowed 
= false; 
1146 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
1148     wxASSERT_MSG(m_widget
, wxT("invalid frame")); 
1152         // for consistency with wxMSW, client area is supposed to be empty for 
1153         // the iconized windows 
1159     else if (m_useCachedClientSize
) 
1160         base_type::DoGetClientSize(width
, height
); 
1163         GTKDoGetSize(width
, height
); 
1167 void wxTopLevelWindowGTK::DoSetSizeHints( int minW
, int minH
, 
1169                                           int incW
, int incH 
) 
1171     base_type::DoSetSizeHints(minW
, minH
, maxW
, maxH
, incW
, incH
); 
1175     const wxSize minSize 
= GetMinSize(); 
1176     const wxSize maxSize 
= GetMaxSize(); 
1178     // always set both min and max hints, otherwise GTK will 
1179     // make assumptions we don't want about the unset values 
1180     int hints_mask 
= GDK_HINT_MIN_SIZE 
| GDK_HINT_MAX_SIZE
; 
1181     hints
.min_width 
= 1; 
1182     hints
.min_height 
= 1; 
1183     hints
.max_width 
= INT_MAX
; 
1184     hints
.max_height 
= INT_MAX
; 
1185     const int decorSize_x 
= m_decorSize
.left 
+ m_decorSize
.right
; 
1186     const int decorSize_y 
= m_decorSize
.top 
+ m_decorSize
.bottom
; 
1187     if (minSize
.x 
> decorSize_x
) 
1188         hints
.min_width 
= minSize
.x 
- decorSize_x
; 
1189     if (minSize
.y 
> decorSize_y
) 
1190         hints
.min_height 
= minSize
.y 
- decorSize_y
; 
1193         hints
.max_width 
= maxSize
.x 
- decorSize_x
; 
1194         if (hints
.max_width 
< hints
.min_width
) 
1195             hints
.max_width 
= hints
.min_width
; 
1199         hints
.max_height 
= maxSize
.y 
- decorSize_y
; 
1200         if (hints
.max_height 
< hints
.min_height
) 
1201             hints
.max_height 
= hints
.min_height
; 
1203     if (incW 
> 0 || incH 
> 0) 
1205         hints_mask 
|= GDK_HINT_RESIZE_INC
; 
1206         hints
.width_inc  
= incW 
> 0 ? incW 
: 1; 
1207         hints
.height_inc 
= incH 
> 0 ? incH 
: 1; 
1209     gtk_window_set_geometry_hints( 
1210         (GtkWindow
*)m_widget
, NULL
, &hints
, (GdkWindowHints
)hints_mask
); 
1213 #ifdef GDK_WINDOWING_X11 
1214 void wxTopLevelWindowGTK::GTKUpdateDecorSize(const DecorSize
& decorSize
) 
1216     if (!IsMaximized() && !IsFullScreen()) 
1217         GetCachedDecorSize() = decorSize
; 
1218     if (m_updateDecorSize 
&& memcmp(&m_decorSize
, &decorSize
, sizeof(DecorSize
))) 
1220         m_useCachedClientSize 
= false; 
1222             decorSize
.left 
- m_decorSize
.left 
+ decorSize
.right 
- m_decorSize
.right
, 
1223             decorSize
.top 
- m_decorSize
.top 
+ decorSize
.bottom 
- m_decorSize
.bottom
); 
1224         m_decorSize 
= decorSize
; 
1225         bool resized 
= false; 
1226         if (m_minWidth 
> 0 || m_minHeight 
> 0 || m_maxWidth 
> 0 || m_maxHeight 
> 0) 
1228             // update size hints, they depend on m_decorSize 
1229             DoSetSizeHints(m_minWidth
, m_minHeight
, m_maxWidth
, m_maxHeight
, m_incWidth
, m_incHeight
); 
1233             // keep overall size unchanged by shrinking m_widget 
1235             GTKDoGetSize(&w
, &h
); 
1236             // but not if size would be less than minimum, it won't take effect 
1237             if (w 
>= m_minWidth 
- (decorSize
.left 
+ decorSize
.right
) && 
1238                 h 
>= m_minHeight 
- (decorSize
.top 
+ decorSize
.bottom
)) 
1240                 gtk_window_resize(GTK_WINDOW(m_widget
), w
, h
); 
1246             // adjust overall size to match change in frame extents 
1249             if (m_width  
< 1) m_width  
= 1; 
1250             if (m_height 
< 1) m_height 
= 1; 
1252             gtk_widget_queue_resize(m_wxwindow
); 
1257         // gtk_widget_show() was deferred, do it now 
1258         m_deferShow 
= false; 
1259         DoGetClientSize(&m_clientWidth
, &m_clientHeight
); 
1260         wxSizeEvent 
sizeEvent(GetSize(), GetId()); 
1261         sizeEvent
.SetEventObject(this); 
1262         HandleWindowEvent(sizeEvent
); 
1264         gtk_widget_show(m_widget
); 
1266         wxShowEvent 
showEvent(GetId(), true); 
1267         showEvent
.SetEventObject(this); 
1268         HandleWindowEvent(showEvent
); 
1271 #endif // GDK_WINDOWING_X11 
1273 wxTopLevelWindowGTK::DecorSize
& wxTopLevelWindowGTK::GetCachedDecorSize() 
1275     static DecorSize size
[8]; 
1279     if (m_gdkDecor 
& (GDK_DECOR_MENU 
| GDK_DECOR_MINIMIZE 
| GDK_DECOR_MAXIMIZE 
| GDK_DECOR_TITLE
)) 
1282     if (m_gdkDecor 
& GDK_DECOR_BORDER
) 
1284     // utility window decor can be different 
1285     if (m_windowStyle 
& wxFRAME_TOOL_WINDOW
) 
1290 void wxTopLevelWindowGTK::OnInternalIdle() 
1292     wxTopLevelWindowBase::OnInternalIdle(); 
1294     // Synthetize activate events. 
1295     if ( g_sendActivateEvent 
!= -1 ) 
1297         bool activate 
= g_sendActivateEvent 
!= 0; 
1299         // if (!activate) wxPrintf( wxT("de") ); 
1300         // wxPrintf( wxT("activate\n") ); 
1303         g_sendActivateEvent 
= -1; 
1305         wxTheApp
->SetActive(activate
, (wxWindow 
*)g_lastActiveFrame
); 
1309 // ---------------------------------------------------------------------------- 
1311 // ---------------------------------------------------------------------------- 
1313 void wxTopLevelWindowGTK::SetTitle( const wxString 
&title 
) 
1315     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
1317     if ( title 
== m_title 
) 
1322     gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title 
) ); 
1325 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle 
&icons 
) 
1327     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
1329     base_type::SetIcons(icons
); 
1331     // Setting icons before window is realized can cause a GTK assertion if 
1332     // another TLW is realized before this one, and it has this one as it's 
1333     // transient parent. The life demo exibits this problem. 
1334     if (gtk_widget_get_realized(m_widget
)) 
1337         for (size_t i 
= icons
.GetIconCount(); i
--;) 
1338             list 
= g_list_prepend(list
, icons
.GetIconByIndex(i
).GetPixbuf()); 
1339         gtk_window_set_icon_list(GTK_WINDOW(m_widget
), list
); 
1344 // ---------------------------------------------------------------------------- 
1345 // frame state: maximized/iconized/normal 
1346 // ---------------------------------------------------------------------------- 
1348 void wxTopLevelWindowGTK::Maximize(bool maximize
) 
1351         gtk_window_maximize( GTK_WINDOW( m_widget 
) ); 
1353         gtk_window_unmaximize( GTK_WINDOW( m_widget 
) ); 
1356 bool wxTopLevelWindowGTK::IsMaximized() const 
1358     GdkWindow
* window 
= NULL
; 
1360         window 
= gtk_widget_get_window(m_widget
); 
1361     return window 
&& (gdk_window_get_state(window
) & GDK_WINDOW_STATE_MAXIMIZED
); 
1364 void wxTopLevelWindowGTK::Restore() 
1366     // "Present" seems similar enough to "restore" 
1367     gtk_window_present( GTK_WINDOW( m_widget 
) ); 
1370 void wxTopLevelWindowGTK::Iconize( bool iconize 
) 
1373         gtk_window_iconify( GTK_WINDOW( m_widget 
) ); 
1375         gtk_window_deiconify( GTK_WINDOW( m_widget 
) ); 
1378 bool wxTopLevelWindowGTK::IsIconized() const 
1380     return m_isIconized
; 
1383 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
) 
1385     if ( iconize 
!= m_isIconized 
) 
1387         m_isIconized 
= iconize
; 
1388         (void)SendIconizeEvent(iconize
); 
1392 void wxTopLevelWindowGTK::AddGrab() 
1397         gtk_grab_add( m_widget 
); 
1398         wxGUIEventLoop().Run(); 
1399         gtk_grab_remove( m_widget 
); 
1403 void wxTopLevelWindowGTK::RemoveGrab() 
1412 bool wxTopLevelWindowGTK::IsActive() 
1414     return (this == (wxTopLevelWindowGTK
*)g_activeFrame
); 
1417 void wxTopLevelWindowGTK::RequestUserAttention(int flags
) 
1419     bool new_hint_value 
= false; 
1421     // FIXME: This is a workaround to focus handling problem 
1422     // If RequestUserAttention is called for example right after a wxSleep, OnInternalIdle 
1423     // hasn't yet been processed, and the internal focus system is not up to date yet. 
1424     // YieldFor(wxEVT_CATEGORY_UI) ensures the processing of it (hopefully it 
1425     // won't have side effects) - MR 
1426     wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI
); 
1428     if(m_urgency_hint 
>= 0) 
1429         g_source_remove(m_urgency_hint
); 
1431     m_urgency_hint 
= -2; 
1433     if( gtk_widget_get_realized(m_widget
) && !IsActive() ) 
1435         new_hint_value 
= true; 
1437         if (flags 
& wxUSER_ATTENTION_INFO
) 
1439             m_urgency_hint 
= g_timeout_add(5000, (GSourceFunc
)gtk_frame_urgency_timer_callback
, this); 
1441             m_urgency_hint 
= -1; 
1445     gtk_window_set_urgency_hint(GTK_WINDOW(m_widget
), new_hint_value
); 
1448 void wxTopLevelWindowGTK::SetWindowStyleFlag( long style 
) 
1450     // Store which styles were changed 
1451     long styleChanges 
= style 
^ m_windowStyle
; 
1453     // Process wxWindow styles. This also updates the internal variable 
1454     // Therefore m_windowStyle bits carry now the _new_ style values 
1455     wxWindow::SetWindowStyleFlag(style
); 
1457     // just return for now if widget does not exist yet 
1461     if ( styleChanges 
& wxSTAY_ON_TOP 
) 
1463         gtk_window_set_keep_above(GTK_WINDOW(m_widget
), 
1464                                   m_windowStyle 
& wxSTAY_ON_TOP
); 
1467     if ( styleChanges 
& wxFRAME_NO_TASKBAR 
) 
1469         gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), 
1470                                          m_windowStyle 
& wxFRAME_NO_TASKBAR
); 
1474 bool wxTopLevelWindowGTK::SetTransparent(wxByte alpha
) 
1476     GdkWindow
* window 
= NULL
; 
1478         window 
= gtk_widget_get_window(m_widget
); 
1482 #ifdef GDK_WINDOWING_X11 
1483     Display
* dpy 
= GDK_WINDOW_XDISPLAY(window
); 
1484     Window win 
= GDK_WINDOW_XID(window
); 
1486     // Using pure Xlib to not have a GTK version check mess due to gtk2.0 not having GdkDisplay 
1488         XDeleteProperty(dpy
, win
, XInternAtom(dpy
, "_NET_WM_WINDOW_OPACITY", False
)); 
1491         long opacity 
= alpha 
* 0x1010101L
; 
1492         XChangeProperty(dpy
, win
, XInternAtom(dpy
, "_NET_WM_WINDOW_OPACITY", False
), 
1493                         XA_CARDINAL
, 32, PropModeReplace
, 
1494                         (unsigned char *) &opacity
, 1L); 
1498 #else // !GDK_WINDOWING_X11 
1500 #endif // GDK_WINDOWING_X11 / !GDK_WINDOWING_X11 
1503 bool wxTopLevelWindowGTK::CanSetTransparent() 
1505     // allow to override automatic detection as it's far from perfect 
1506     const wxString SYSOPT_TRANSPARENT 
= "gtk.tlw.can-set-transparent"; 
1507     if ( wxSystemOptions::HasOption(SYSOPT_TRANSPARENT
) ) 
1509         return wxSystemOptions::GetOptionInt(SYSOPT_TRANSPARENT
) != 0; 
1513     return gtk_widget_is_composited(m_widget
) != 0; 
1515 #if GTK_CHECK_VERSION(2,10,0) 
1516     if (!gtk_check_version(2,10,0)) 
1518         return gtk_widget_is_composited(m_widget
) != 0; 
1521 #endif // In case of lower versions than gtk+-2.10.0 we could look for _NET_WM_CM_Sn ourselves 
1525 #endif // !__WXGTK3__ 
1527 #if 0 // Don't be optimistic here for the sake of wxAUI 
1528     int opcode
, event
, error
; 
1529     // Check for the existence of a RGBA visual instead? 
1530     return XQueryExtension(gdk_x11_get_default_xdisplay (), 
1531                            "Composite", &opcode
, &event
, &error
);