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/win_gtk.h" 
  43 #include "wx/unix/utilsx11.h" 
  46 #include <X11/Xatom.h> 
  48 // ---------------------------------------------------------------------------- 
  50 // ---------------------------------------------------------------------------- 
  52 extern int              g_openDialogs
; 
  53 extern wxWindowGTK     
*g_delayedFocus
; 
  55 // the frame that is currently active (i.e. its child has focus). It is 
  56 // used to generate wxActivateEvents 
  57 static wxTopLevelWindowGTK 
*g_activeFrame 
= (wxTopLevelWindowGTK
*) NULL
; 
  58 static wxTopLevelWindowGTK 
*g_lastActiveFrame 
= (wxTopLevelWindowGTK
*) NULL
; 
  60 // if we detect that the app has got/lost the focus, we set this variable to 
  61 // either TRUE or FALSE and an activate event will be sent during the next 
  62 // OnIdle() call and it is reset to -1: this value means that we shouldn't 
  63 // send any activate events at all 
  64 static int g_sendActivateEvent 
= -1; 
  66 //----------------------------------------------------------------------------- 
  67 // RequestUserAttention related functions 
  68 //----------------------------------------------------------------------------- 
  71 static void wxgtk_window_set_urgency_hint (GtkWindow 
*win
, 
  74     wxASSERT_MSG( GTK_WIDGET_REALIZED(win
), wxT("wxgtk_window_set_urgency_hint: GdkWindow not realized") ); 
  75     GdkWindow 
*window 
= GTK_WIDGET(win
)->window
; 
  78     wm_hints 
= XGetWMHints(GDK_WINDOW_XDISPLAY(window
), GDK_WINDOW_XWINDOW(window
)); 
  81         wm_hints 
= XAllocWMHints(); 
  84         wm_hints
->flags 
|= XUrgencyHint
; 
  86         wm_hints
->flags 
&= ~XUrgencyHint
; 
  88     XSetWMHints(GDK_WINDOW_XDISPLAY(window
), GDK_WINDOW_XWINDOW(window
), wm_hints
); 
  92 static gboolean 
gtk_frame_urgency_timer_callback( wxTopLevelWindowGTK 
*win 
) 
  94 #if GTK_CHECK_VERSION(2,7,0) 
  95     if(!gtk_check_version(2,7,0)) 
  96         gtk_window_set_urgency_hint(GTK_WINDOW( win
->m_widget 
), FALSE
); 
  99         wxgtk_window_set_urgency_hint(GTK_WINDOW( win
->m_widget 
), FALSE
); 
 101     win
->m_urgency_hint 
= -2; 
 106 //----------------------------------------------------------------------------- 
 108 //----------------------------------------------------------------------------- 
 111 static gboolean 
gtk_frame_focus_in_callback( GtkWidget 
*widget
, 
 112                                          GdkEvent 
*WXUNUSED(event
), 
 113                                          wxTopLevelWindowGTK 
*win 
) 
 115     switch ( g_sendActivateEvent 
) 
 118             // we've got focus from outside, synthetize wxActivateEvent 
 119             g_sendActivateEvent 
= 1; 
 123             // another our window just lost focus, it was already ours before 
 124             // - don't send any wxActivateEvent 
 125             g_sendActivateEvent 
= -1; 
 130     g_lastActiveFrame 
= g_activeFrame
; 
 132     // wxPrintf( wxT("active: %s\n"), win->GetTitle().c_str() ); 
 134     // MR: wxRequestUserAttention related block 
 135     switch( win
->m_urgency_hint 
) 
 138             g_source_remove( win
->m_urgency_hint 
); 
 139             // no break, fallthrough to remove hint too 
 141 #if GTK_CHECK_VERSION(2,7,0) 
 142             if(!gtk_check_version(2,7,0)) 
 143                 gtk_window_set_urgency_hint(GTK_WINDOW( widget 
), FALSE
); 
 147                 wxgtk_window_set_urgency_hint(GTK_WINDOW( widget 
), FALSE
); 
 150             win
->m_urgency_hint 
= -2; 
 156     wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
); 
 157     wxActivateEvent 
event(wxEVT_ACTIVATE
, true, g_activeFrame
->GetId()); 
 158     event
.SetEventObject(g_activeFrame
); 
 159     g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
 165 //----------------------------------------------------------------------------- 
 167 //----------------------------------------------------------------------------- 
 170 static gboolean 
gtk_frame_focus_out_callback( GtkWidget 
*widget
, 
 171                                           GdkEventFocus 
*WXUNUSED(gdk_event
), 
 172                                           wxTopLevelWindowGTK 
*win 
) 
 174     // if the focus goes out of our app alltogether, OnIdle() will send 
 175     // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset 
 176     // g_sendActivateEvent to -1 
 177     g_sendActivateEvent 
= 0; 
 179     // wxASSERT_MSG( (g_activeFrame == win), wxT("TLW deactivatd although it wasn't active") ); 
 181     // wxPrintf( wxT("inactive: %s\n"), win->GetTitle().c_str() ); 
 185         wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
); 
 186         wxActivateEvent 
event(wxEVT_ACTIVATE
, false, g_activeFrame
->GetId()); 
 187         event
.SetEventObject(g_activeFrame
); 
 188         g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
 190         g_activeFrame 
= NULL
; 
 197 //----------------------------------------------------------------------------- 
 199 //----------------------------------------------------------------------------- 
 202 static void gtk_frame_size_callback( GtkWidget 
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxTopLevelWindowGTK 
*win 
) 
 207     if ((win
->m_width 
!= alloc
->width
) || (win
->m_height 
!= alloc
->height
)) 
 210         wxPrintf( wxT("gtk_frame_size_callback from ") ); 
 211         if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
 212            wxPrintf( win->GetClassInfo()->GetClassName() ); 
 213         wxPrintf( wxT(" %d %d %d %d\n"), (int)alloc->x, 
 216                                 (int)alloc->height ); 
 219         // Tell the wxWindow class about the new size 
 220         win
->m_width 
= alloc
->width
; 
 221         win
->m_height 
= alloc
->height
; 
 223         win
->GtkUpdateSize(); 
 228 // ---------------------------------------------------------------------------- 
 230 // ---------------------------------------------------------------------------- 
 233 void wxgtk_tlw_size_request_callback(GtkWidget 
* WXUNUSED(widget
), 
 234                                      GtkRequisition 
*requisition
, 
 235                                      wxTopLevelWindowGTK 
*win
) 
 237     // we must return the size of the window without WM decorations, otherwise 
 238     // GTK+ gets confused, so don't call just GetSize() here 
 240     win
->GTKDoGetSize(&w
, &h
); 
 242     requisition
->height 
= h
; 
 243     requisition
->width 
= w
; 
 246 //----------------------------------------------------------------------------- 
 248 //----------------------------------------------------------------------------- 
 252 gtk_frame_delete_callback( GtkWidget 
*WXUNUSED(widget
), 
 253                            GdkEvent 
*WXUNUSED(event
), 
 254                            wxTopLevelWindowGTK 
*win 
) 
 256     if (win
->IsEnabled() && 
 257         (g_openDialogs 
== 0 || (win
->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) || 
 266 //----------------------------------------------------------------------------- 
 268 //----------------------------------------------------------------------------- 
 272 gtk_frame_configure_callback( GtkWidget
* widget
, 
 273                               GdkEventConfigure 
*WXUNUSED(event
), 
 274                               wxTopLevelWindowGTK 
*win 
) 
 276     if (!win
->m_hasVMT 
|| !win
->IsShown()) 
 280     gtk_window_get_position((GtkWindow
*)widget
, &point
.x
, &point
.y
); 
 284     wxMoveEvent 
mevent(point
, win
->GetId()); 
 285     mevent
.SetEventObject( win 
); 
 286     win
->GetEventHandler()->ProcessEvent( mevent 
); 
 292 //----------------------------------------------------------------------------- 
 293 // "realize" from m_widget 
 294 //----------------------------------------------------------------------------- 
 296 // we cannot MWM hints and icons before the widget has been realized, 
 297 // so we do this directly after realization 
 301 gtk_frame_realized_callback( GtkWidget 
* WXUNUSED(widget
), 
 302                              wxTopLevelWindowGTK 
*win 
) 
 304     // All this is for Motif Window Manager "hints" and is supposed to be 
 305     // recognized by other WM as well. Not tested. 
 306     gdk_window_set_decorations(win
->m_widget
->window
, 
 307                                (GdkWMDecoration
)win
->m_gdkDecor
); 
 308     gdk_window_set_functions(win
->m_widget
->window
, 
 309                                (GdkWMFunction
)win
->m_gdkFunc
); 
 311     // GTK's shrinking/growing policy 
 312     if ((win
->m_gdkFunc 
& GDK_FUNC_RESIZE
) == 0) 
 313         gtk_window_set_resizable(GTK_WINDOW(win
->m_widget
), FALSE
); 
 315         gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1); 
 318     wxIconBundle iconsOld 
= win
->GetIcons(); 
 319     if ( !iconsOld
.IsEmpty() ) 
 321         win
->SetIcon( wxNullIcon 
); 
 322         win
->SetIcons( iconsOld 
); 
 327 //----------------------------------------------------------------------------- 
 328 // "map_event" from m_widget 
 329 //----------------------------------------------------------------------------- 
 333 gtk_frame_map_callback( GtkWidget 
* WXUNUSED(widget
), 
 334                         GdkEvent 
* WXUNUSED(event
), 
 335                         wxTopLevelWindow 
*win 
) 
 337     win
->SetIconizeState(false); 
 342 //----------------------------------------------------------------------------- 
 343 // "unmap_event" from m_widget 
 344 //----------------------------------------------------------------------------- 
 348 gtk_frame_unmap_callback( GtkWidget 
* WXUNUSED(widget
), 
 349                           GdkEvent 
* WXUNUSED(event
), 
 350                           wxTopLevelWindow 
*win 
) 
 352     win
->SetIconizeState(true); 
 357 //----------------------------------------------------------------------------- 
 358 // "expose_event" of m_client 
 359 //----------------------------------------------------------------------------- 
 363 gtk_window_expose_callback( GtkWidget 
*widget
, 
 364                             GdkEventExpose 
*gdk_event
, 
 367     GtkPizza 
*pizza 
= GTK_PIZZA(widget
); 
 369     gtk_paint_flat_box (win
->m_widget
->style
, 
 370                         pizza
->bin_window
, GTK_STATE_NORMAL
, 
 381 // ---------------------------------------------------------------------------- 
 382 // wxTopLevelWindowGTK creation 
 383 // ---------------------------------------------------------------------------- 
 385 void wxTopLevelWindowGTK::Init() 
 390     m_mainWidget 
= (GtkWidget
*) NULL
; 
 391     m_isIconized 
= false; 
 392     m_fsIsShowing 
= false; 
 393     m_themeEnabled 
= true; 
 394     m_gdkDecor 
= m_gdkFunc 
= 0; 
 400 bool wxTopLevelWindowGTK::Create( wxWindow 
*parent
, 
 402                                   const wxString
& title
, 
 404                                   const wxSize
& sizeOrig
, 
 406                                   const wxString 
&name 
) 
 408     // always create a frame of some reasonable, even if arbitrary, size (at 
 409     // least for MSW compatibility) 
 410     wxSize size 
= sizeOrig
; 
 411     size
.x 
= WidthDefault(size
.x
); 
 412     size
.y 
= HeightDefault(size
.y
); 
 414     wxTopLevelWindows
.Append( this ); 
 416     if (!PreCreation( parent
, pos
, size 
) || 
 417         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
 419         wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") ); 
 425     // NB: m_widget may be !=NULL if it was created by derived class' Create, 
 426     //     e.g. in wxTaskBarIconAreaGTK 
 427     if (m_widget 
== NULL
) 
 429         if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) 
 431             m_widget 
= gtk_window_new(GTK_WINDOW_TOPLEVEL
); 
 432             // Tell WM that this is a dialog window and make it center 
 433             // on parent by default (this is what GtkDialog ctor does): 
 434             gtk_window_set_type_hint(GTK_WINDOW(m_widget
), 
 435                                      GDK_WINDOW_TYPE_HINT_DIALOG
); 
 436             gtk_window_set_position(GTK_WINDOW(m_widget
), 
 437                                     GTK_WIN_POS_CENTER_ON_PARENT
); 
 441             m_widget 
= gtk_window_new(GTK_WINDOW_TOPLEVEL
); 
 442 #if GTK_CHECK_VERSION(2,1,0) 
 443             if (!gtk_check_version(2,1,0)) 
 445                 if (style 
& wxFRAME_TOOL_WINDOW
) 
 447                     gtk_window_set_type_hint(GTK_WINDOW(m_widget
), 
 448                                              GDK_WINDOW_TYPE_HINT_UTILITY
); 
 450                     // On some WMs, like KDE, a TOOL_WINDOW will still show 
 451                     // on the taskbar, but on Gnome a TOOL_WINDOW will not. 
 452                     // For consistency between WMs and with Windows, we 
 453                     // should set the NO_TASKBAR flag which will apply 
 454                     // the set_skip_taskbar_hint if it is available, 
 455                     // ensuring no taskbar entry will appear. 
 456                     style 
|= wxFRAME_NO_TASKBAR
; 
 463     wxWindow 
*topParent 
= wxGetTopLevelParent(m_parent
); 
 464     if (topParent 
&& (((GTK_IS_WINDOW(topParent
->m_widget
)) && 
 465                        (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) || 
 466                        (style 
& wxFRAME_FLOAT_ON_PARENT
))) 
 468         gtk_window_set_transient_for( GTK_WINDOW(m_widget
), 
 469                                       GTK_WINDOW(topParent
->m_widget
) ); 
 472 #if GTK_CHECK_VERSION(2,2,0) 
 473     if (!gtk_check_version(2,2,0)) 
 475         if (style 
& wxFRAME_NO_TASKBAR
) 
 477             gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), TRUE
); 
 483     if (!gtk_check_version(2,4,0)) 
 485         if (style 
& wxSTAY_ON_TOP
) 
 487             gtk_window_set_keep_above(GTK_WINDOW(m_widget
), TRUE
); 
 494         gtk_window_set_role( GTK_WINDOW(m_widget
), wxGTK_CONV( name 
) ); 
 497     gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title 
) ); 
 498     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
 500     g_signal_connect (m_widget
, "delete_event", 
 501                       G_CALLBACK (gtk_frame_delete_callback
), this); 
 503     // m_mainWidget holds the toolbar, the menubar and the client area 
 504     m_mainWidget 
= gtk_pizza_new(); 
 505     gtk_widget_show( m_mainWidget 
); 
 506     GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS 
); 
 507     gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget 
); 
 509     if (m_miniEdge 
== 0) // wxMiniFrame has its own version. 
 511        // For m_mainWidget themes 
 512        g_signal_connect (m_mainWidget
, "expose_event", 
 513                          G_CALLBACK (gtk_window_expose_callback
), this); 
 516     // m_wxwindow only represents the client area without toolbar and menubar 
 517     m_wxwindow 
= gtk_pizza_new(); 
 518     gtk_widget_show( m_wxwindow 
); 
 519     gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow 
); 
 521     // we donm't allow the frame to get the focus as otherwise 
 522     // the frame will grab it at arbitrary focus changes 
 523     GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
 525     if (m_parent
) m_parent
->AddChild( this ); 
 527     // the user resized the frame by dragging etc. 
 528     g_signal_connect (m_widget
, "size_allocate", 
 529                       G_CALLBACK (gtk_frame_size_callback
), this); 
 531     g_signal_connect (m_widget
, "size_request", 
 532                       G_CALLBACK (wxgtk_tlw_size_request_callback
), this); 
 535     if ((m_x 
!= -1) || (m_y 
!= -1)) 
 536         gtk_widget_set_uposition( m_widget
, m_x
, m_y 
); 
 538     gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height 
); 
 540     //  we cannot set MWM hints and icons before the widget has 
 541     //  been realized, so we do this directly after realization 
 542     g_signal_connect (m_widget
, "realize", 
 543                       G_CALLBACK (gtk_frame_realized_callback
), this); 
 545     // map and unmap for iconized state 
 546     g_signal_connect (m_widget
, "map_event", 
 547                       G_CALLBACK (gtk_frame_map_callback
), this); 
 548     g_signal_connect (m_widget
, "unmap_event", 
 549                       G_CALLBACK (gtk_frame_unmap_callback
), this); 
 552     g_signal_connect (m_widget
, "configure_event", 
 553                       G_CALLBACK (gtk_frame_configure_callback
), this); 
 556     g_signal_connect_after (m_widget
, "focus_in_event", 
 557                       G_CALLBACK (gtk_frame_focus_in_callback
), this); 
 558     g_signal_connect_after (m_widget
, "focus_out_event", 
 559                       G_CALLBACK (gtk_frame_focus_out_callback
), this); 
 562     if ((style 
& wxSIMPLE_BORDER
) || (style 
& wxNO_BORDER
)) 
 573         if ((style 
& wxRESIZE_BORDER
) != 0) 
 574            m_gdkFunc 
|= GDK_FUNC_RESIZE
; 
 578         m_gdkDecor 
= (long) GDK_DECOR_BORDER
; 
 579         m_gdkFunc 
= (long) GDK_FUNC_MOVE
; 
 581         // All this is for Motif Window Manager "hints" and is supposed to be 
 582         // recognized by other WMs as well. 
 583         if ((style 
& wxCAPTION
) != 0) 
 585             m_gdkDecor 
|= GDK_DECOR_TITLE
; 
 587         if ((style 
& wxCLOSE_BOX
) != 0) 
 589             m_gdkFunc 
|= GDK_FUNC_CLOSE
; 
 591         if ((style 
& wxSYSTEM_MENU
) != 0) 
 593             m_gdkDecor 
|= GDK_DECOR_MENU
; 
 595         if ((style 
& wxMINIMIZE_BOX
) != 0) 
 597             m_gdkFunc 
|= GDK_FUNC_MINIMIZE
; 
 598             m_gdkDecor 
|= GDK_DECOR_MINIMIZE
; 
 600         if ((style 
& wxMAXIMIZE_BOX
) != 0) 
 602             m_gdkFunc 
|= GDK_FUNC_MAXIMIZE
; 
 603             m_gdkDecor 
|= GDK_DECOR_MAXIMIZE
; 
 605         if ((style 
& wxRESIZE_BORDER
) != 0) 
 607            m_gdkFunc 
|= GDK_FUNC_RESIZE
; 
 608            m_gdkDecor 
|= GDK_DECOR_RESIZEH
; 
 615 wxTopLevelWindowGTK::~wxTopLevelWindowGTK() 
 619         wxFAIL_MSG(_T("Window still grabbed")); 
 623     m_isBeingDeleted 
= true; 
 625     // it may also be GtkScrolledWindow in the case of an MDI child 
 626     if (GTK_IS_WINDOW(m_widget
)) 
 628         gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL 
); 
 631     if (g_activeFrame 
== this) 
 632         g_activeFrame 
= NULL
; 
 633     if (g_lastActiveFrame 
== this) 
 634         g_lastActiveFrame 
= NULL
; 
 637 bool wxTopLevelWindowGTK::EnableCloseButton( bool enable 
) 
 640         m_gdkFunc 
|= GDK_FUNC_CLOSE
; 
 642         m_gdkFunc 
&= ~GDK_FUNC_CLOSE
; 
 644     if (GTK_WIDGET_REALIZED(m_widget
) && (m_widget
->window
)) 
 645         gdk_window_set_functions( m_widget
->window
, (GdkWMFunction
)m_gdkFunc 
); 
 650 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long) 
 652     if (show 
== m_fsIsShowing
) 
 653         return false; // return what? 
 655     m_fsIsShowing 
= show
; 
 657     wxX11FullScreenMethod method 
= 
 658         wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(), 
 659                                  (WXWindow
)GDK_ROOT_WINDOW()); 
 661 #if GTK_CHECK_VERSION(2,2,0) 
 662     // NB: gtk_window_fullscreen() uses freedesktop.org's WMspec extensions 
 663     //     to switch to fullscreen, which is not always available. We must 
 664     //     check if WM supports the spec and use legacy methods if it 
 666     if ( (method 
== wxX11_FS_WMSPEC
) && !gtk_check_version(2,2,0) ) 
 669             gtk_window_fullscreen( GTK_WINDOW( m_widget 
) ); 
 671             gtk_window_unfullscreen( GTK_WINDOW( m_widget 
) ); 
 674 #endif // GTK+ >= 2.2.0 
 676         GdkWindow 
*window 
= m_widget
->window
; 
 680             GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y 
); 
 681             GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height 
); 
 683             int screen_width
,screen_height
; 
 684             wxDisplaySize( &screen_width
, &screen_height 
); 
 686             gint client_x
, client_y
, root_x
, root_y
; 
 689             if (method 
!= wxX11_FS_WMSPEC
) 
 691                 // don't do it always, Metacity hates it 
 692                 m_fsSaveGdkFunc 
= m_gdkFunc
; 
 693                 m_fsSaveGdkDecor 
= m_gdkDecor
; 
 694                 m_gdkFunc 
= m_gdkDecor 
= 0; 
 695                 gdk_window_set_decorations(window
, (GdkWMDecoration
)0); 
 696                 gdk_window_set_functions(window
, (GdkWMFunction
)0); 
 699             gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
); 
 700             gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
, 
 701                          &width
, &height
, NULL
); 
 703             gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
, 
 704                         screen_width 
+ 1, screen_height 
+ 1); 
 706             wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(), 
 707                                     (WXWindow
)GDK_ROOT_WINDOW(), 
 708                                     (WXWindow
)GDK_WINDOW_XWINDOW(window
), 
 709                                     show
, &m_fsSaveFrame
, method
); 
 713             if (method 
!= wxX11_FS_WMSPEC
) 
 715                 // don't do it always, Metacity hates it 
 716                 m_gdkFunc 
= m_fsSaveGdkFunc
; 
 717                 m_gdkDecor 
= m_fsSaveGdkDecor
; 
 718                 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
); 
 719                 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
); 
 722             wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(), 
 723                                     (WXWindow
)GDK_ROOT_WINDOW(), 
 724                                     (WXWindow
)GDK_WINDOW_XWINDOW(window
), 
 725                                     show
, &m_fsSaveFrame
, method
); 
 727             SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
, 
 728                     m_fsSaveFrame
.width
, m_fsSaveFrame
.height
); 
 732     // documented behaviour is to show the window if it's still hidden when 
 733     // showing it full screen 
 740 // ---------------------------------------------------------------------------- 
 741 // overridden wxWindow methods 
 742 // ---------------------------------------------------------------------------- 
 744 bool wxTopLevelWindowGTK::Show( bool show 
) 
 746     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
 748     if (show 
== IsShown()) 
 751     if (show 
&& !m_sizeSet
) 
 753         /* by calling GtkOnSize here, we don't have to call 
 754            either after showing the frame, which would entail 
 755            much ugly flicker or from within the size_allocate 
 756            handler, because GTK 1.1.X forbids that. */ 
 761     wxTopLevelWindowBase::Show(show
); 
 765         // make sure window has a non-default position, so when it is shown 
 766         // again, it won't be repositioned by WM as if it were a new window 
 767         // Note that this must be done _after_ the window is hidden. 
 768         gtk_window_move((GtkWindow
*)m_widget
, m_x
, m_y
); 
 774 void wxTopLevelWindowGTK::Raise() 
 776     gtk_window_present( GTK_WINDOW( m_widget 
) ); 
 779 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) ) 
 781     wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") ); 
 784 // ---------------------------------------------------------------------------- 
 786 // ---------------------------------------------------------------------------- 
 788 void wxTopLevelWindowGTK::GTKDoGetSize(int *width
, int *height
) const 
 790     return wxTopLevelWindowBase::DoGetSize(width
, height
); 
 793 void wxTopLevelWindowGTK::GTKDoSetSize(int width
, int height
) 
 800     int old_width 
= m_width
; 
 801     int old_height 
= m_height
; 
 810     if ( m_width 
!= old_width 
|| m_height 
!= old_height 
) 
 812         gtk_window_resize( GTK_WINDOW(m_widget
), m_width
, m_height 
); 
 814         /* we set the size in GtkOnSize, i.e. mostly the actual resizing is 
 815            done either directly before the frame is shown or in idle time 
 816            so that different calls to SetSize() don't lead to flicker. */ 
 823 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
 825     wxCHECK_RET( m_widget
, wxT("invalid frame") ); 
 827     // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow 
 828     wxASSERT_MSG( (m_wxwindow 
!= NULL
), wxT("invalid frame") ); 
 831     // deal with the position first 
 835     if ( !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
 837         // -1 means "use existing" unless the flag above is specified 
 843     else // wxSIZE_ALLOW_MINUS_ONE 
 849     if ( m_x 
!= old_x 
|| m_y 
!= old_y 
) 
 851         gtk_window_move( GTK_WINDOW(m_widget
), m_x
, m_y 
); 
 855     // and now change the size: as we want to set the size of the entire 
 856     // window, including decorations, we must adjust the size passed to 
 857     // GTKDoSetSize() which takes with the size of undecorated frame only 
 858     if ( width 
!= -1 || height 
!= -1 ) 
 862         DoGetSize(&wTotal
, &hTotal
); 
 866         GTKDoGetSize(&wUndec
, &hUndec
); 
 869             width 
-= wTotal 
- wUndec
; 
 871             height 
-= hTotal 
- hUndec
; 
 874     GTKDoSetSize(width
, height
); 
 877 void wxTopLevelWindowGTK::DoGetSize(int *width
, int *height
) const 
 879     wxCHECK_RET( m_widget
, wxT("invalid frame") ); 
 881     if ( !m_widget
->window 
) 
 883         // this can happen if we're called before the window is realized, so 
 884         // don't assert but just return the stored values 
 885         GTKDoGetSize(width
, height
); 
 890     gdk_window_get_frame_extents(m_widget
->window
, &rect
); 
 895         *height 
= rect
.height
; 
 898 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
 902         // for consistency with wxMSW, client area is supposed to be empty for 
 903         // the iconized windows 
 912     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
 916         *height 
= m_height 
- 2 * m_miniEdge 
- m_miniTitle
; 
 922         *width 
= m_width 
- 2 * m_miniEdge
; 
 928 void wxTopLevelWindowGTK::DoSetSizeHints( int minW
, int minH
, 
 932     wxTopLevelWindowBase::DoSetSizeHints( minW
, minH
, maxW
, maxH
, incW
, incH 
); 
 934     const wxSize minSize 
= GetMinSize(); 
 935     const wxSize maxSize 
= GetMaxSize(); 
 938     if (minSize
.x 
> 0 || minSize
.y 
> 0) 
 940         hints_mask 
|= GDK_HINT_MIN_SIZE
; 
 941         hints
.min_width  
= minSize
.x 
> 0 ? minSize
.x 
: 0; 
 942         hints
.min_height 
= minSize
.y 
> 0 ? minSize
.y 
: 0; 
 944     if (maxSize
.x 
> 0 || maxSize
.y 
> 0) 
 946         hints_mask 
|= GDK_HINT_MAX_SIZE
; 
 947         hints
.max_width  
= maxSize
.x 
> 0 ? maxSize
.x 
: INT_MAX
; 
 948         hints
.max_height 
= maxSize
.y 
> 0 ? maxSize
.y 
: INT_MAX
; 
 950     if (incW 
> 0 || incH 
> 0) 
 952         hints_mask 
|= GDK_HINT_RESIZE_INC
; 
 953         hints
.width_inc  
= incW 
> 0 ? incW 
: 1; 
 954         hints
.height_inc 
= incH 
> 0 ? incH 
: 1; 
 956     gtk_window_set_geometry_hints( 
 957         (GtkWindow
*)m_widget
, NULL
, &hints
, (GdkWindowHints
)hints_mask
); 
 961 void wxTopLevelWindowGTK::GtkOnSize() 
 964     if (m_resizing
) return; 
 967     if ( m_wxwindow 
== NULL 
) return; 
 973         gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
), 
 975                               0, 0, m_width
, m_height
); 
 980     // send size event to frame 
 981     wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
 982     event
.SetEventObject( this ); 
 983     GetEventHandler()->ProcessEvent( event 
); 
 988 void wxTopLevelWindowGTK::OnInternalIdle() 
 990     if (!m_sizeSet 
&& GTK_WIDGET_REALIZED(m_wxwindow
)) 
 994         // we'll come back later 
 998     // set the focus if not done yet and if we can already do it 
 999     if ( GTK_WIDGET_REALIZED(m_wxwindow
) ) 
1001         if ( g_delayedFocus 
&& 
1002              wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this ) 
1004             wxLogTrace(_T("focus"), 
1005                        _T("Setting focus from wxTLW::OnIdle() to %s(%s)"), 
1006                        g_delayedFocus
->GetClassInfo()->GetClassName(), 
1007                        g_delayedFocus
->GetLabel().c_str()); 
1009             g_delayedFocus
->SetFocus(); 
1010             g_delayedFocus 
= NULL
; 
1014     wxWindow::OnInternalIdle(); 
1016     // Synthetize activate events. 
1017     if ( g_sendActivateEvent 
!= -1 ) 
1019         bool activate 
= g_sendActivateEvent 
!= 0; 
1021         // if (!activate) wxPrintf( wxT("de") ); 
1022         // wxPrintf( wxT("activate\n") ); 
1025         g_sendActivateEvent 
= -1; 
1027         wxTheApp
->SetActive(activate
, (wxWindow 
*)g_lastActiveFrame
); 
1031 // ---------------------------------------------------------------------------- 
1033 // ---------------------------------------------------------------------------- 
1035 void wxTopLevelWindowGTK::SetTitle( const wxString 
&title 
) 
1037     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
1039     if ( title 
== m_title 
) 
1044     gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title 
) ); 
1047 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle 
&icons 
) 
1049     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
1051     wxTopLevelWindowBase::SetIcons( icons 
); 
1055     const size_t numIcons 
= icons
.GetIconCount(); 
1056     for ( size_t i 
= 0; i 
< numIcons
; i
++ ) 
1058         list 
= g_list_prepend(list
, icons
.GetIconByIndex(i
).GetPixbuf()); 
1061     gtk_window_set_icon_list(GTK_WINDOW(m_widget
), list
); 
1065 // ---------------------------------------------------------------------------- 
1066 // frame state: maximized/iconized/normal 
1067 // ---------------------------------------------------------------------------- 
1069 void wxTopLevelWindowGTK::Maximize(bool maximize
) 
1072         gtk_window_maximize( GTK_WINDOW( m_widget 
) ); 
1074         gtk_window_unmaximize( GTK_WINDOW( m_widget 
) ); 
1077 bool wxTopLevelWindowGTK::IsMaximized() const 
1079     if(!m_widget
->window
) 
1082     return gdk_window_get_state(m_widget
->window
) & GDK_WINDOW_STATE_MAXIMIZED
; 
1085 void wxTopLevelWindowGTK::Restore() 
1087     // "Present" seems similar enough to "restore" 
1088     gtk_window_present( GTK_WINDOW( m_widget 
) ); 
1091 void wxTopLevelWindowGTK::Iconize( bool iconize 
) 
1094         gtk_window_iconify( GTK_WINDOW( m_widget 
) ); 
1096         gtk_window_deiconify( GTK_WINDOW( m_widget 
) ); 
1099 bool wxTopLevelWindowGTK::IsIconized() const 
1101     return m_isIconized
; 
1104 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
) 
1106     if ( iconize 
!= m_isIconized 
) 
1108         m_isIconized 
= iconize
; 
1109         (void)SendIconizeEvent(iconize
); 
1113 void wxTopLevelWindowGTK::AddGrab() 
1118         gtk_grab_add( m_widget 
); 
1119         wxGUIEventLoop().Run(); 
1120         gtk_grab_remove( m_widget 
); 
1124 void wxTopLevelWindowGTK::RemoveGrab() 
1135 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
) 
1139         if (region
.IsEmpty()) 
1141             gdk_window_shape_combine_mask(window
, NULL
, 0, 0); 
1145             gdk_window_shape_combine_region(window
, region
.GetRegion(), 0, 0); 
1153 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
) 
1155     wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), false, 
1156                  _T("Shaped windows must be created with the wxFRAME_SHAPED style.")); 
1158     GdkWindow 
*window 
= NULL
; 
1161         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
1162         do_shape_combine_region(window
, region
); 
1164     window 
= m_widget
->window
; 
1165     return do_shape_combine_region(window
, region
); 
1168 bool wxTopLevelWindowGTK::IsActive() 
1170     return (this == (wxTopLevelWindowGTK
*)g_activeFrame
); 
1173 void wxTopLevelWindowGTK::RequestUserAttention(int flags
) 
1175     bool new_hint_value 
= false; 
1177     // FIXME: This is a workaround to focus handling problem 
1178     // If RequestUserAttention is called for example right after a wxSleep, OnInternalIdle hasn't 
1179     // yet been processed, and the internal focus system is not up to date yet. 
1180     // wxYieldIfNeeded ensures the processing of it, but can have unwanted side effects - MR 
1181     ::wxYieldIfNeeded(); 
1183     if(m_urgency_hint 
>= 0) 
1184         g_source_remove(m_urgency_hint
); 
1186     m_urgency_hint 
= -2; 
1188     if( GTK_WIDGET_REALIZED(m_widget
) && !IsActive() ) 
1190         new_hint_value 
= true; 
1192         if (flags 
& wxUSER_ATTENTION_INFO
) 
1194             m_urgency_hint 
= g_timeout_add(5000, (GSourceFunc
)gtk_frame_urgency_timer_callback
, this); 
1196             m_urgency_hint 
= -1; 
1200 #if GTK_CHECK_VERSION(2,7,0) 
1201     if(!gtk_check_version(2,7,0)) 
1202         gtk_window_set_urgency_hint(GTK_WINDOW( m_widget 
), new_hint_value
); 
1205         wxgtk_window_set_urgency_hint(GTK_WINDOW( m_widget 
), new_hint_value
); 
1208 void wxTopLevelWindowGTK::SetWindowStyleFlag( long style 
) 
1210 #if defined(__WXGTK24__) || GTK_CHECK_VERSION(2,2,0) 
1211     // Store which styles were changed 
1212     long styleChanges 
= style 
^ m_windowStyle
; 
1215     // Process wxWindow styles. This also updates the internal variable 
1216     // Therefore m_windowStyle bits carry now the _new_ style values 
1217     wxWindow::SetWindowStyleFlag(style
); 
1219     // just return for now if widget does not exist yet 
1224     if ( (styleChanges 
& wxSTAY_ON_TOP
) && !gtk_check_version(2,4,0) ) 
1225         gtk_window_set_keep_above(GTK_WINDOW(m_widget
), m_windowStyle 
& wxSTAY_ON_TOP
); 
1227 #if GTK_CHECK_VERSION(2,2,0) 
1228     if ( (styleChanges 
& wxFRAME_NO_TASKBAR
) && !gtk_check_version(2,2,0) ) 
1230         gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), m_windowStyle 
& wxFRAME_NO_TASKBAR
); 
1235 #include <X11/Xlib.h> 
1237 /* Get the X Window between child and the root window. 
1238    This should usually be the WM managed XID */ 
1239 static Window 
wxGetTopmostWindowX11(Display 
*dpy
, Window child
) 
1241     Window root
, parent
; 
1243     unsigned int nchildren
; 
1245     XQueryTree(dpy
, child
, &root
, &parent
, &children
, &nchildren
); 
1248     while (parent 
!= root
) { 
1250         XQueryTree(dpy
, child
, &root
, &parent
, &children
, &nchildren
); 
1257 bool wxTopLevelWindowGTK::SetTransparent(wxByte alpha
) 
1259     if (!m_widget 
|| !m_widget
->window
) 
1262     Display
* dpy 
= GDK_WINDOW_XDISPLAY (m_widget
->window
); 
1263     // We need to get the X Window that has the root window as the immediate parent 
1264     // and m_widget->window as a child. This should be the X Window that the WM manages and 
1265     // from which the opacity property is checked from. 
1266     Window win 
= wxGetTopmostWindowX11(dpy
, GDK_WINDOW_XID (m_widget
->window
)); 
1268     unsigned int opacity 
= alpha 
* 0x1010101; 
1270     // Using pure Xlib to not have a GTK version check mess due to gtk2.0 not having GdkDisplay 
1272         XDeleteProperty(dpy
, win
, XInternAtom(dpy
, "_NET_WM_WINDOW_OPACITY", False
)); 
1274         XChangeProperty(dpy
, win
, XInternAtom(dpy
, "_NET_WM_WINDOW_OPACITY", False
), 
1275                         XA_CARDINAL
, 32, PropModeReplace
, 
1276                         (unsigned char *) &opacity
, 1L); 
1281 bool wxTopLevelWindowGTK::CanSetTransparent() 
1283     // allow to override automatic detection as it's far from perfect 
1284     static const wxChar 
*SYSOPT_TRANSPARENT 
= wxT("gtk.tlw.can-set-transparent"); 
1285     if ( wxSystemOptions::HasOption(SYSOPT_TRANSPARENT
) ) 
1287         return wxSystemOptions::GetOptionInt(SYSOPT_TRANSPARENT
) != 0; 
1290 #if GTK_CHECK_VERSION(2,10,0) 
1291     if (!gtk_check_version(2,10,0)) 
1293         return (gtk_widget_is_composited (m_widget
)); 
1296 #endif // In case of lower versions than gtk+-2.10.0 we could look for _NET_WM_CM_Sn ourselves 
1301 #if 0 // Don't be optimistic here for the sake of wxAUI 
1302     int opcode
, event
, error
; 
1303     // Check for the existence of a RGBA visual instead? 
1304     return XQueryExtension(gdk_x11_get_default_xdisplay (), 
1305                            "Composite", &opcode
, &event
, &error
);