1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/window.cpp 
   3 // Purpose:     wxWindowGTK implementation 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling, Julian Smart 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 // For compilers that support precompilation, includes "wx.h". 
  11 #include "wx/wxprec.h" 
  14 #define XWarpPointer XWARPPOINTER 
  17 #include "wx/window.h" 
  22     #include "wx/toplevel.h" 
  23     #include "wx/dcclient.h" 
  25     #include "wx/settings.h" 
  26     #include "wx/msgdlg.h" 
  31 #include "wx/tooltip.h" 
  33 #include "wx/fontutil.h" 
  34 #include "wx/scopeguard.h" 
  35 #include "wx/sysopt.h" 
  39 #include "wx/gtk/private.h" 
  40 #include "wx/gtk/private/win_gtk.h" 
  41 #include "wx/gtk/private/event.h" 
  42 using namespace wxGTKImpl
; 
  46 #include <gdk/gdkkeysyms.h> 
  47 #if GTK_CHECK_VERSION(3,0,0) 
  48 #include <gdk/gdkkeysyms-compat.h> 
  51 // gdk_window_set_composited() is only supported since 2.12 
  52 #define wxGTK_VERSION_REQUIRED_FOR_COMPOSITING 2,12,0 
  53 #define wxGTK_HAS_COMPOSITING_SUPPORT GTK_CHECK_VERSION(2,12,0) 
  55 //----------------------------------------------------------------------------- 
  56 // documentation on internals 
  57 //----------------------------------------------------------------------------- 
  60    I have been asked several times about writing some documentation about 
  61    the GTK port of wxWidgets, especially its internal structures. Obviously, 
  62    you cannot understand wxGTK without knowing a little about the GTK, but 
  63    some more information about what the wxWindow, which is the base class 
  64    for all other window classes, does seems required as well. 
  68    What does wxWindow do? It contains the common interface for the following 
  69    jobs of its descendants: 
  71    1) Define the rudimentary behaviour common to all window classes, such as 
  72    resizing, intercepting user input (so as to make it possible to use these 
  73    events for special purposes in a derived class), window names etc. 
  75    2) Provide the possibility to contain and manage children, if the derived 
  76    class is allowed to contain children, which holds true for those window 
  77    classes which do not display a native GTK widget. To name them, these 
  78    classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame- 
  79    work classes are a special case and are handled a bit differently from 
  80    the rest. The same holds true for the wxNotebook class. 
  82    3) Provide the possibility to draw into a client area of a window. This, 
  83    too, only holds true for classes that do not display a native GTK widget 
  86    4) Provide the entire mechanism for scrolling widgets. This actual inter- 
  87    face for this is usually in wxScrolledWindow, but the GTK implementation 
  90    5) A multitude of helper or extra methods for special purposes, such as 
  91    Drag'n'Drop, managing validators etc. 
  93    6) Display a border (sunken, raised, simple or none). 
  95    Normally one might expect, that one wxWidgets window would always correspond 
  96    to one GTK widget. Under GTK, there is no such all-round widget that has all 
  97    the functionality. Moreover, the GTK defines a client area as a different 
  98    widget from the actual widget you are handling. Last but not least some 
  99    special classes (e.g. wxFrame) handle different categories of widgets and 
 100    still have the possibility to draw something in the client area. 
 101    It was therefore required to write a special purpose GTK widget, that would 
 102    represent a client area in the sense of wxWidgets capable to do the jobs 
 103    2), 3) and 4). I have written this class and it resides in win_gtk.c of 
 106    All windows must have a widget, with which they interact with other under- 
 107    lying GTK widgets. It is this widget, e.g. that has to be resized etc and 
 108    the wxWindow class has a member variable called m_widget which holds a 
 109    pointer to this widget. When the window class represents a GTK native widget, 
 110    this is (in most cases) the only GTK widget the class manages. E.g. the 
 111    wxStaticText class handles only a GtkLabel widget a pointer to which you 
 112    can find in m_widget (defined in wxWindow) 
 114    When the class has a client area for drawing into and for containing children 
 115    it has to handle the client area widget (of the type wxPizza, defined in 
 116    win_gtk.cpp), but there could be any number of widgets, handled by a class. 
 117    The common rule for all windows is only, that the widget that interacts with 
 118    the rest of GTK must be referenced in m_widget and all other widgets must be 
 119    children of this widget on the GTK level. The top-most widget, which also 
 120    represents the client area, must be in the m_wxwindow field and must be of 
 123    As I said, the window classes that display a GTK native widget only have 
 124    one widget, so in the case of e.g. the wxButton class m_widget holds a 
 125    pointer to a GtkButton widget. But windows with client areas (for drawing 
 126    and children) have a m_widget field that is a pointer to a GtkScrolled- 
 127    Window and a m_wxwindow field that is pointer to a wxPizza and this 
 128    one is (in the GTK sense) a child of the GtkScrolledWindow. 
 130    If the m_wxwindow field is set, then all input to this widget is inter- 
 131    cepted and sent to the wxWidgets class. If not, all input to the widget 
 132    that gets pointed to by m_widget gets intercepted and sent to the class. 
 136    The design of scrolling in wxWidgets is markedly different from that offered 
 137    by the GTK itself and therefore we cannot simply take it as it is. In GTK, 
 138    clicking on a scrollbar belonging to scrolled window will inevitably move 
 139    the window. In wxWidgets, the scrollbar will only emit an event, send this 
 140    to (normally) a wxScrolledWindow and that class will call ScrollWindow() 
 141    which actually moves the window and its sub-windows. Note that wxPizza 
 142    memorizes how much it has been scrolled but that wxWidgets forgets this 
 143    so that the two coordinates systems have to be kept in synch. This is done 
 144    in various places using the pizza->m_scroll_x and pizza->m_scroll_y values. 
 148    Singularly the most broken code in GTK is the code that is supposed to 
 149    inform subwindows (child windows) about new positions. Very often, duplicate 
 150    events are sent without changes in size or position, equally often no 
 151    events are sent at all (All this is due to a bug in the GtkContainer code 
 152    which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores 
 153    GTK's own system and it simply waits for size events for toplevel windows 
 154    and then iterates down the respective size events to all window. This has 
 155    the disadvantage that windows might get size events before the GTK widget 
 156    actually has the reported size. This doesn't normally pose any problem, but 
 157    the OpenGL drawing routines rely on correct behaviour. Therefore, I have 
 158    added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas, 
 159    i.e. the wxGLCanvas will emit a size event, when (and not before) the X11 
 160    window that is used for OpenGL output really has that size (as reported by 
 165    If someone at some point of time feels the immense desire to have a look at, 
 166    change or attempt to optimise the Refresh() logic, this person will need an 
 167    intimate understanding of what "draw" and "expose" events are and what 
 168    they are used for, in particular when used in connection with GTK's 
 169    own windowless widgets. Beware. 
 173    Cursors, too, have been a constant source of pleasure. The main difficulty 
 174    is that a GdkWindow inherits a cursor if the programmer sets a new cursor 
 175    for the parent. To prevent this from doing too much harm, SetCursor calls 
 176    GTKUpdateCursor, which will recursively re-set the cursors of all child windows. 
 177    Also don't forget that cursors (like much else) are connected to GdkWindows, 
 178    not GtkWidgets and that the "window" field of a GtkWidget might very well 
 179    point to the GdkWindow of the parent widget (-> "window-less widget") and 
 180    that the two obviously have very different meanings. 
 183 //----------------------------------------------------------------------------- 
 185 //----------------------------------------------------------------------------- 
 187 // Don't allow event propagation during drag 
 188 bool g_blockEventsOnDrag
; 
 189 // Don't allow mouse event propagation during scroll 
 190 bool g_blockEventsOnScroll
; 
 191 extern wxCursor   g_globalCursor
; 
 193 // mouse capture state: the window which has it and if the mouse is currently 
 195 static wxWindowGTK  
*g_captureWindow 
= NULL
; 
 196 static bool g_captureWindowHasMouse 
= false; 
 198 // The window that currently has focus: 
 199 static wxWindowGTK 
*gs_currentFocus 
= NULL
; 
 200 // The window that is scheduled to get focus in the next event loop iteration 
 201 // or NULL if there's no pending focus change: 
 202 static wxWindowGTK 
*gs_pendingFocus 
= NULL
; 
 204 // the window that has deferred focus-out event pending, if any (see 
 205 // GTKAddDeferredFocusOut() for details) 
 206 static wxWindowGTK 
*gs_deferredFocusOut 
= NULL
; 
 208 // global variables because GTK+ DnD want to have the 
 209 // mouse event that caused it 
 210 GdkEvent    
*g_lastMouseEvent 
= NULL
; 
 211 int          g_lastButtonNumber 
= 0; 
 213 //----------------------------------------------------------------------------- 
 215 //----------------------------------------------------------------------------- 
 217 // the trace mask used for the focus debugging messages 
 218 #define TRACE_FOCUS wxT("focus") 
 220 //----------------------------------------------------------------------------- 
 221 // "size_request" of m_widget 
 222 //----------------------------------------------------------------------------- 
 226 wxgtk_window_size_request_callback(GtkWidget 
* WXUNUSED(widget
), 
 227                                    GtkRequisition 
*requisition
, 
 231     win
->GetSize( &w
, &h 
); 
 237     requisition
->height 
= h
; 
 238     requisition
->width 
= w
; 
 242 //----------------------------------------------------------------------------- 
 243 // "expose_event" of m_wxwindow 
 244 //----------------------------------------------------------------------------- 
 248 gtk_window_expose_callback( GtkWidget
*, 
 249                             GdkEventExpose 
*gdk_event
, 
 252     if (gdk_event
->window 
== win
->GTKGetDrawingWindow()) 
 254         win
->GetUpdateRegion() = wxRegion( gdk_event
->region 
); 
 255         win
->GtkSendPaintEvents(); 
 257     // Let parent window draw window-less widgets 
 262 #ifndef __WXUNIVERSAL__ 
 263 //----------------------------------------------------------------------------- 
 264 // "expose_event" from m_wxwindow->parent, for drawing border 
 265 //----------------------------------------------------------------------------- 
 269 expose_event_border(GtkWidget
* widget
, GdkEventExpose
* gdk_event
, wxWindow
* win
) 
 271     if (gdk_event
->window 
!= gtk_widget_get_parent_window(win
->m_wxwindow
)) 
 278     gtk_widget_get_allocation(win
->m_wxwindow
, &alloc
); 
 279     const int x 
= alloc
.x
; 
 280     const int y 
= alloc
.y
; 
 281     const int w 
= alloc
.width
; 
 282     const int h 
= alloc
.height
; 
 284     if (w 
<= 0 || h 
<= 0) 
 287     if (win
->HasFlag(wxBORDER_SIMPLE
)) 
 289         gdk_draw_rectangle(gdk_event
->window
, 
 290             gtk_widget_get_style(widget
)->black_gc
, false, x
, y
, w 
- 1, h 
- 1); 
 294         GtkShadowType shadow 
= GTK_SHADOW_IN
; 
 295         if (win
->HasFlag(wxBORDER_RAISED
)) 
 296             shadow 
= GTK_SHADOW_OUT
; 
 298         // Style detail to use 
 300         if (win
->m_widget 
== win
->m_wxwindow
) 
 301             // for non-scrollable wxWindows 
 304             // for scrollable ones 
 307         // clip rect is required to avoid painting background 
 308         // over upper left (w,h) of parent window 
 309         GdkRectangle clipRect 
= { x
, y
, w
, h 
}; 
 311            gtk_widget_get_style(win
->m_wxwindow
), gdk_event
->window
, GTK_STATE_NORMAL
, 
 312            shadow
, &clipRect
, wxGTKPrivate::GetEntryWidget(), detail
, x
, y
, w
, h
); 
 318 //----------------------------------------------------------------------------- 
 319 // "parent_set" from m_wxwindow 
 320 //----------------------------------------------------------------------------- 
 324 parent_set(GtkWidget
* widget
, GtkWidget
* old_parent
, wxWindow
* win
) 
 328         g_signal_handlers_disconnect_by_func( 
 329             old_parent
, (void*)expose_event_border
, win
); 
 331     GtkWidget
* parent 
= gtk_widget_get_parent(widget
); 
 334         g_signal_connect_after(parent
, "expose_event", 
 335             G_CALLBACK(expose_event_border
), win
); 
 339 #endif // !__WXUNIVERSAL__ 
 341 //----------------------------------------------------------------------------- 
 342 // "key_press_event" from any window 
 343 //----------------------------------------------------------------------------- 
 345 // set WXTRACE to this to see the key event codes on the console 
 346 #define TRACE_KEYS  wxT("keyevent") 
 348 // translates an X key symbol to WXK_XXX value 
 350 // if isChar is true it means that the value returned will be used for EVT_CHAR 
 351 // event and then we choose the logical WXK_XXX, i.e. '/' for GDK_KP_Divide, 
 352 // for example, while if it is false it means that the value is going to be 
 353 // used for KEY_DOWN/UP events and then we translate GDK_KP_Divide to 
 355 static long wxTranslateKeySymToWXKey(KeySym keysym
, bool isChar
) 
 361         // Shift, Control and Alt don't generate the CHAR events at all 
 364             key_code 
= isChar 
? 0 : WXK_SHIFT
; 
 368             key_code 
= isChar 
? 0 : WXK_CONTROL
; 
 376             key_code 
= isChar 
? 0 : WXK_ALT
; 
 379         // neither do the toggle modifies 
 380         case GDK_Scroll_Lock
: 
 381             key_code 
= isChar 
? 0 : WXK_SCROLL
; 
 385             key_code 
= isChar 
? 0 : WXK_CAPITAL
; 
 389             key_code 
= isChar 
? 0 : WXK_NUMLOCK
; 
 393         // various other special keys 
 406         case GDK_ISO_Left_Tab
: 
 413             key_code 
= WXK_RETURN
; 
 417             key_code 
= WXK_CLEAR
; 
 421             key_code 
= WXK_PAUSE
; 
 425             key_code 
= WXK_SELECT
; 
 429             key_code 
= WXK_PRINT
; 
 433             key_code 
= WXK_EXECUTE
; 
 437             key_code 
= WXK_ESCAPE
; 
 440         // cursor and other extended keyboard keys 
 442             key_code 
= WXK_DELETE
; 
 458             key_code 
= WXK_RIGHT
; 
 465         case GDK_Prior
:     // == GDK_Page_Up 
 466             key_code 
= WXK_PAGEUP
; 
 469         case GDK_Next
:      // == GDK_Page_Down 
 470             key_code 
= WXK_PAGEDOWN
; 
 482             key_code 
= WXK_INSERT
; 
 497             key_code 
= (isChar 
? '0' : int(WXK_NUMPAD0
)) + keysym 
- GDK_KP_0
; 
 501             key_code 
= isChar 
? ' ' : int(WXK_NUMPAD_SPACE
); 
 505             key_code 
= isChar 
? WXK_TAB 
: WXK_NUMPAD_TAB
; 
 509             key_code 
= isChar 
? WXK_RETURN 
: WXK_NUMPAD_ENTER
; 
 513             key_code 
= isChar 
? WXK_F1 
: WXK_NUMPAD_F1
; 
 517             key_code 
= isChar 
? WXK_F2 
: WXK_NUMPAD_F2
; 
 521             key_code 
= isChar 
? WXK_F3 
: WXK_NUMPAD_F3
; 
 525             key_code 
= isChar 
? WXK_F4 
: WXK_NUMPAD_F4
; 
 529             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_HOME
; 
 533             key_code 
= isChar 
? WXK_LEFT 
: WXK_NUMPAD_LEFT
; 
 537             key_code 
= isChar 
? WXK_UP 
: WXK_NUMPAD_UP
; 
 541             key_code 
= isChar 
? WXK_RIGHT 
: WXK_NUMPAD_RIGHT
; 
 545             key_code 
= isChar 
? WXK_DOWN 
: WXK_NUMPAD_DOWN
; 
 548         case GDK_KP_Prior
: // == GDK_KP_Page_Up 
 549             key_code 
= isChar 
? WXK_PAGEUP 
: WXK_NUMPAD_PAGEUP
; 
 552         case GDK_KP_Next
: // == GDK_KP_Page_Down 
 553             key_code 
= isChar 
? WXK_PAGEDOWN 
: WXK_NUMPAD_PAGEDOWN
; 
 557             key_code 
= isChar 
? WXK_END 
: WXK_NUMPAD_END
; 
 561             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_BEGIN
; 
 565             key_code 
= isChar 
? WXK_INSERT 
: WXK_NUMPAD_INSERT
; 
 569             key_code 
= isChar 
? WXK_DELETE 
: WXK_NUMPAD_DELETE
; 
 573             key_code 
= isChar 
? '=' : int(WXK_NUMPAD_EQUAL
); 
 576         case GDK_KP_Multiply
: 
 577             key_code 
= isChar 
? '*' : int(WXK_NUMPAD_MULTIPLY
); 
 581             key_code 
= isChar 
? '+' : int(WXK_NUMPAD_ADD
); 
 584         case GDK_KP_Separator
: 
 585             // FIXME: what is this? 
 586             key_code 
= isChar 
? '.' : int(WXK_NUMPAD_SEPARATOR
); 
 589         case GDK_KP_Subtract
: 
 590             key_code 
= isChar 
? '-' : int(WXK_NUMPAD_SUBTRACT
); 
 594             key_code 
= isChar 
? '.' : int(WXK_NUMPAD_DECIMAL
); 
 598             key_code 
= isChar 
? '/' : int(WXK_NUMPAD_DIVIDE
); 
 615             key_code 
= WXK_F1 
+ keysym 
- GDK_F1
; 
 625 static inline bool wxIsAsciiKeysym(KeySym ks
) 
 630 static void wxFillOtherKeyEventFields(wxKeyEvent
& event
, 
 632                                       GdkEventKey 
*gdk_event
) 
 634     event
.SetTimestamp( gdk_event
->time 
); 
 635     event
.SetId(win
->GetId()); 
 637     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
) != 0; 
 638     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
) != 0; 
 639     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
) != 0; 
 640     event
.m_metaDown 
= (gdk_event
->state 
& GDK_META_MASK
) != 0; 
 642     // Normally we take the state of modifiers directly from the low level GDK 
 643     // event but unfortunately GDK uses a different convention from MSW for the 
 644     // key events corresponding to the modifier keys themselves: in it, when 
 645     // e.g. Shift key is pressed, GDK_SHIFT_MASK is not set while it is set 
 646     // when Shift is released. Under MSW the situation is exactly reversed and 
 647     // the modifier corresponding to the key is set when it is pressed and 
 648     // unset when it is released. To ensure consistent behaviour between 
 649     // platforms (and because it seems to make slightly more sense, although 
 650     // arguably both behaviours are reasonable) we follow MSW here. 
 652     // Final notice: we set the flags to the desired value instead of just 
 653     // inverting them because they are not set correctly (i.e. in the same way 
 654     // as for the real events generated by the user) for wxUIActionSimulator- 
 655     // produced events and it seems better to keep that class code the same 
 656     // among all platforms and fix the discrepancy here instead of adding 
 657     // wxGTK-specific code to wxUIActionSimulator. 
 658     const bool isPress 
= gdk_event
->type 
== GDK_KEY_PRESS
; 
 659     switch ( gdk_event
->keyval 
) 
 663             event
.m_shiftDown 
= isPress
; 
 668             event
.m_controlDown 
= isPress
; 
 673             event
.m_altDown 
= isPress
; 
 680             event
.m_metaDown 
= isPress
; 
 684     event
.m_rawCode 
= (wxUint32
) gdk_event
->keyval
; 
 685     event
.m_rawFlags 
= gdk_event
->hardware_keycode
; 
 687     wxGetMousePosition(&event
.m_x
, &event
.m_y
); 
 688     win
->ScreenToClient(&event
.m_x
, &event
.m_y
); 
 689     event
.SetEventObject( win 
); 
 694 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
, 
 696                            GdkEventKey 
*gdk_event
) 
 698     // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string 
 699     //     but only event->keyval which is quite useless to us, so remember 
 700     //     the last character from GDK_KEY_PRESS and reuse it as last resort 
 702     // NB: should be MT-safe as we're always called from the main thread only 
 707     } s_lastKeyPress 
= { 0, 0 }; 
 709     KeySym keysym 
= gdk_event
->keyval
; 
 711     wxLogTrace(TRACE_KEYS
, wxT("Key %s event: keysym = %ld"), 
 712                event
.GetEventType() == wxEVT_KEY_UP 
? wxT("release") 
 716     long key_code 
= wxTranslateKeySymToWXKey(keysym
, false /* !isChar */); 
 720         // do we have the translation or is it a plain ASCII character? 
 721         if ( (gdk_event
->length 
== 1) || wxIsAsciiKeysym(keysym
) ) 
 723             // we should use keysym if it is ASCII as X does some translations 
 724             // like "I pressed while Control is down" => "Ctrl-I" == "TAB" 
 725             // which we don't want here (but which we do use for OnChar()) 
 726             if ( !wxIsAsciiKeysym(keysym
) ) 
 728                 keysym 
= (KeySym
)gdk_event
->string
[0]; 
 731             // we want to always get the same key code when the same key is 
 732             // pressed regardless of the state of the modifiers, i.e. on a 
 733             // standard US keyboard pressing '5' or '%' ('5' key with 
 734             // Shift) should result in the same key code in OnKeyDown(): 
 735             // '5' (although OnChar() will get either '5' or '%'). 
 737             // to do it we first translate keysym to keycode (== scan code) 
 738             // and then back but always using the lower register 
 739             Display 
*dpy 
= (Display 
*)wxGetDisplay(); 
 740             KeyCode keycode 
= XKeysymToKeycode(dpy
, keysym
); 
 742             wxLogTrace(TRACE_KEYS
, wxT("\t-> keycode %d"), keycode
); 
 744             KeySym keysymNormalized 
= XKeycodeToKeysym(dpy
, keycode
, 0); 
 746             // use the normalized, i.e. lower register, keysym if we've 
 748             key_code 
= keysymNormalized 
? keysymNormalized 
: keysym
; 
 750             // as explained above, we want to have lower register key codes 
 751             // normally but for the letter keys we want to have the upper ones 
 753             // NB: don't use XConvertCase() here, we want to do it for letters 
 755             key_code 
= toupper(key_code
); 
 757         else // non ASCII key, what to do? 
 759             // by default, ignore it 
 762             // but if we have cached information from the last KEY_PRESS 
 763             if ( gdk_event
->type 
== GDK_KEY_RELEASE 
) 
 766                 if ( keysym 
== s_lastKeyPress
.keysym 
) 
 768                     key_code 
= s_lastKeyPress
.keycode
; 
 773         if ( gdk_event
->type 
== GDK_KEY_PRESS 
) 
 775             // remember it to be reused for KEY_UP event later 
 776             s_lastKeyPress
.keysym 
= keysym
; 
 777             s_lastKeyPress
.keycode 
= key_code
; 
 781     wxLogTrace(TRACE_KEYS
, wxT("\t-> wxKeyCode %ld"), key_code
); 
 783     // sending unknown key events doesn't really make sense 
 787     event
.m_keyCode 
= key_code
; 
 790     event
.m_uniChar 
= gdk_keyval_to_unicode(key_code 
? key_code 
: keysym
); 
 791     if ( !event
.m_uniChar 
&& event
.m_keyCode 
<= WXK_DELETE 
) 
 793         // Set Unicode key code to the ASCII equivalent for compatibility. E.g. 
 794         // let RETURN generate the key event with both key and Unicode key 
 796         event
.m_uniChar 
= event
.m_keyCode
; 
 798 #endif // wxUSE_UNICODE 
 800     // now fill all the other fields 
 801     wxFillOtherKeyEventFields(event
, win
, gdk_event
); 
 809     GtkIMContext 
*context
; 
 810     GdkEventKey  
*lastKeyEvent
; 
 814         context 
= gtk_im_multicontext_new(); 
 819         g_object_unref (context
); 
 826 // Send wxEVT_CHAR_HOOK event to the parent of the window and return true only 
 827 // if it was processed (and not skipped). 
 828 bool SendCharHookEvent(const wxKeyEvent
& event
, wxWindow 
*win
) 
 830     // wxEVT_CHAR_HOOK must be sent to allow the parent windows (e.g. a dialog 
 831     // which typically closes when Esc key is pressed in any of its controls) 
 832     // to handle key events in all of its children unless the mouse is captured 
 833     // in which case we consider that the keyboard should be "captured" too. 
 834     if ( !g_captureWindow 
) 
 836         wxKeyEvent 
eventCharHook(wxEVT_CHAR_HOOK
, event
); 
 837         if ( win
->HandleWindowEvent(eventCharHook
) 
 838                 && !event
.IsNextEventAllowed() ) 
 845 // Adjust wxEVT_CHAR event key code fields. This function takes care of two 
 847 // (a) Ctrl-letter key presses generate key codes in range 1..26 
 848 // (b) Unicode key codes are same as key codes for the codes in 1..255 range 
 849 void AdjustCharEventKeyCodes(wxKeyEvent
& event
) 
 851     const int code 
= event
.m_keyCode
; 
 853     // Check for (a) above. 
 854     if ( event
.ControlDown() ) 
 856         // We intentionally don't use isupper/lower() here, we really need 
 857         // ASCII letters only as it doesn't make sense to translate any other 
 858         // ones into this range which has only 26 slots. 
 859         if ( code 
>= 'a' && code 
<= 'z' ) 
 860             event
.m_keyCode 
= code 
- 'a' + 1; 
 861         else if ( code 
>= 'A' && code 
<= 'Z' ) 
 862             event
.m_keyCode 
= code 
- 'A' + 1; 
 865         // Adjust the Unicode equivalent in the same way too. 
 866         if ( event
.m_keyCode 
!= code 
) 
 867             event
.m_uniChar 
= event
.m_keyCode
; 
 868 #endif // wxUSE_UNICODE 
 872     // Check for (b) from above. 
 874     // FIXME: Should we do it for key codes up to 255? 
 875     if ( !event
.m_uniChar 
&& code 
< WXK_DELETE 
) 
 876         event
.m_uniChar 
= code
; 
 877 #endif // wxUSE_UNICODE 
 880 } // anonymous namespace 
 884 gtk_window_key_press_callback( GtkWidget 
*WXUNUSED(widget
), 
 885                                GdkEventKey 
*gdk_event
, 
 890     if (g_blockEventsOnDrag
) 
 893     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
 895     bool return_after_IM 
= false; 
 897     if( wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
 899         // Send the CHAR_HOOK event first 
 900         if ( SendCharHookEvent(event
, win
) ) 
 902             // Don't do anything at all with this event any more. 
 906         // Emit KEY_DOWN event 
 907         ret 
= win
->HandleWindowEvent( event 
); 
 911         // Return after IM processing as we cannot do 
 912         // anything with it anyhow. 
 913         return_after_IM 
= true; 
 916     if (!ret 
&& win
->m_imData
) 
 918         win
->m_imData
->lastKeyEvent 
= gdk_event
; 
 920         // We should let GTK+ IM filter key event first. According to GTK+ 2.0 API 
 921         // docs, if IM filter returns true, no further processing should be done. 
 922         // we should send the key_down event anyway. 
 923         bool intercepted_by_IM 
= gtk_im_context_filter_keypress(win
->m_imData
->context
, gdk_event
); 
 924         win
->m_imData
->lastKeyEvent 
= NULL
; 
 925         if (intercepted_by_IM
) 
 927             wxLogTrace(TRACE_KEYS
, wxT("Key event intercepted by IM")); 
 938         wxWindowGTK 
*ancestor 
= win
; 
 941             int command 
= ancestor
->GetAcceleratorTable()->GetCommand( event 
); 
 944                 wxCommandEvent 
menu_event( wxEVT_COMMAND_MENU_SELECTED
, command 
); 
 945                 ret 
= ancestor
->HandleWindowEvent( menu_event 
); 
 949                     // if the accelerator wasn't handled as menu event, try 
 950                     // it as button click (for compatibility with other 
 952                     wxCommandEvent 
button_event( wxEVT_COMMAND_BUTTON_CLICKED
, command 
); 
 953                     ret 
= ancestor
->HandleWindowEvent( button_event 
); 
 958             if (ancestor
->IsTopLevel()) 
 960             ancestor 
= ancestor
->GetParent(); 
 963 #endif // wxUSE_ACCEL 
 965     // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x 
 966     // will only be sent if it is not in an accelerator table. 
 970         KeySym keysym 
= gdk_event
->keyval
; 
 971         // Find key code for EVT_CHAR and EVT_CHAR_HOOK events 
 972         key_code 
= wxTranslateKeySymToWXKey(keysym
, true /* isChar */); 
 975             if ( wxIsAsciiKeysym(keysym
) ) 
 978                 key_code 
= (unsigned char)keysym
; 
 980             // gdk_event->string is actually deprecated 
 981             else if ( gdk_event
->length 
== 1 ) 
 983                 key_code 
= (unsigned char)gdk_event
->string
[0]; 
 989             wxKeyEvent 
eventChar(wxEVT_CHAR
, event
); 
 991             wxLogTrace(TRACE_KEYS
, wxT("Char event: %ld"), key_code
); 
 993             eventChar
.m_keyCode 
= key_code
; 
 995             AdjustCharEventKeyCodes(eventChar
); 
 997             ret 
= win
->HandleWindowEvent(eventChar
); 
1007 gtk_wxwindow_commit_cb (GtkIMContext 
* WXUNUSED(context
), 
1011     wxKeyEvent 
event( wxEVT_CHAR 
); 
1013     // take modifiers, cursor position, timestamp etc. from the last 
1014     // key_press_event that was fed into Input Method: 
1015     if (window
->m_imData
->lastKeyEvent
) 
1017         wxFillOtherKeyEventFields(event
, 
1018                                   window
, window
->m_imData
->lastKeyEvent
); 
1022         event
.SetEventObject( window 
); 
1025     const wxString 
data(wxGTK_CONV_BACK_SYS(str
)); 
1029     for( wxString::const_iterator pstr 
= data
.begin(); pstr 
!= data
.end(); ++pstr 
) 
1032         event
.m_uniChar 
= *pstr
; 
1033         // Backward compatible for ISO-8859-1 
1034         event
.m_keyCode 
= *pstr 
< 256 ? event
.m_uniChar 
: 0; 
1035         wxLogTrace(TRACE_KEYS
, wxT("IM sent character '%c'"), event
.m_uniChar
); 
1037         event
.m_keyCode 
= (char)*pstr
; 
1038 #endif  // wxUSE_UNICODE 
1040         AdjustCharEventKeyCodes(event
); 
1042         window
->HandleWindowEvent(event
); 
1048 //----------------------------------------------------------------------------- 
1049 // "key_release_event" from any window 
1050 //----------------------------------------------------------------------------- 
1054 gtk_window_key_release_callback( GtkWidget 
* WXUNUSED(widget
), 
1055                                  GdkEventKey 
*gdk_event
, 
1061     if (g_blockEventsOnDrag
) 
1064     wxKeyEvent 
event( wxEVT_KEY_UP 
); 
1065     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1067         // unknown key pressed, ignore (the event would be useless anyhow) 
1071     return win
->GTKProcessEvent(event
); 
1075 //----------------------------------------------------------------------------- 
1076 // key and mouse events, after, from m_widget 
1077 //----------------------------------------------------------------------------- 
1080 static gboolean 
key_and_mouse_event_after(GtkWidget
* widget
, GdkEventKey
*, wxWindow
*) 
1082     // If a widget does not handle a key or mouse event, GTK+ sends it up the 
1083     // parent chain until it is handled. These events are not supposed to 
1084     // propagate in wxWidgets, so prevent it unless widget is in a native 
1086     return WX_IS_PIZZA(gtk_widget_get_parent(widget
)); 
1090 // ============================================================================ 
1092 // ============================================================================ 
1094 // ---------------------------------------------------------------------------- 
1095 // mouse event processing helpers 
1096 // ---------------------------------------------------------------------------- 
1098 static void AdjustEventButtonState(wxMouseEvent
& event
) 
1100     // GDK reports the old state of the button for a button press event, but 
1101     // for compatibility with MSW and common sense we want m_leftDown be TRUE 
1102     // for a LEFT_DOWN event, not FALSE, so we will invert 
1103     // left/right/middleDown for the corresponding click events 
1105     if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) || 
1106         (event
.GetEventType() == wxEVT_LEFT_DCLICK
) || 
1107         (event
.GetEventType() == wxEVT_LEFT_UP
)) 
1109         event
.m_leftDown 
= !event
.m_leftDown
; 
1113     if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) || 
1114         (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) || 
1115         (event
.GetEventType() == wxEVT_MIDDLE_UP
)) 
1117         event
.m_middleDown 
= !event
.m_middleDown
; 
1121     if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) || 
1122         (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) || 
1123         (event
.GetEventType() == wxEVT_RIGHT_UP
)) 
1125         event
.m_rightDown 
= !event
.m_rightDown
; 
1129     if ((event
.GetEventType() == wxEVT_AUX1_DOWN
) || 
1130         (event
.GetEventType() == wxEVT_AUX1_DCLICK
)) 
1132         event
.m_aux1Down 
= true; 
1136     if ((event
.GetEventType() == wxEVT_AUX2_DOWN
) || 
1137         (event
.GetEventType() == wxEVT_AUX2_DCLICK
)) 
1139         event
.m_aux2Down 
= true; 
1144 // find the window to send the mouse event too 
1146 wxWindowGTK 
*FindWindowForMouseEvent(wxWindowGTK 
*win
, wxCoord
& x
, wxCoord
& y
) 
1151     if (win
->m_wxwindow
) 
1153         wxPizza
* pizza 
= WX_PIZZA(win
->m_wxwindow
); 
1154         xx 
+= pizza
->m_scroll_x
; 
1155         yy 
+= pizza
->m_scroll_y
; 
1158     wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
1161         wxWindowGTK 
*child 
= node
->GetData(); 
1163         node 
= node
->GetNext(); 
1164         if (!child
->IsShown()) 
1167         if (child
->GTKIsTransparentForMouse()) 
1169             // wxStaticBox is transparent in the box itself 
1170             int xx1 
= child
->m_x
; 
1171             int yy1 
= child
->m_y
; 
1172             int xx2 
= child
->m_x 
+ child
->m_width
; 
1173             int yy2 
= child
->m_y 
+ child
->m_height
; 
1176             if (((xx 
>= xx1
) && (xx 
<= xx1
+10) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1178                 ((xx 
>= xx2
-10) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1180                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy1
+10)) || 
1182                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy2
-1) && (yy 
<= yy2
))) 
1193             if ((child
->m_wxwindow 
== NULL
) && 
1194                 (child
->m_x 
<= xx
) && 
1195                 (child
->m_y 
<= yy
) && 
1196                 (child
->m_x
+child
->m_width  
>= xx
) && 
1197                 (child
->m_y
+child
->m_height 
>= yy
)) 
1210 // ---------------------------------------------------------------------------- 
1211 // common event handlers helpers 
1212 // ---------------------------------------------------------------------------- 
1214 bool wxWindowGTK::GTKProcessEvent(wxEvent
& event
) const 
1216     // nothing special at this level 
1217     return HandleWindowEvent(event
); 
1220 bool wxWindowGTK::GTKShouldIgnoreEvent() const 
1222     return !m_hasVMT 
|| g_blockEventsOnDrag
; 
1225 int wxWindowGTK::GTKCallbackCommonPrologue(GdkEventAny 
*event
) const 
1229     if (g_blockEventsOnDrag
) 
1231     if (g_blockEventsOnScroll
) 
1234     if (!GTKIsOwnWindow(event
->window
)) 
1240 // overloads for all GDK event types we use here: we need to have this as 
1241 // GdkEventXXX can't be implicitly cast to GdkEventAny even if it, in fact, 
1242 // derives from it in the sense that the structs have the same layout 
1243 #define wxDEFINE_COMMON_PROLOGUE_OVERLOAD(T)                                  \ 
1244     static int wxGtkCallbackCommonPrologue(T *event, wxWindowGTK *win)        \ 
1246         return win->GTKCallbackCommonPrologue((GdkEventAny *)event);          \ 
1249 wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventButton
) 
1250 wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventMotion
) 
1251 wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventCrossing
) 
1253 #undef wxDEFINE_COMMON_PROLOGUE_OVERLOAD 
1255 #define wxCOMMON_CALLBACK_PROLOGUE(event, win)                                \ 
1256     const int rc = wxGtkCallbackCommonPrologue(event, win);                   \ 
1260 // all event handlers must have C linkage as they're called from GTK+ C code 
1264 //----------------------------------------------------------------------------- 
1265 // "button_press_event" 
1266 //----------------------------------------------------------------------------- 
1269 gtk_window_button_press_callback( GtkWidget 
*widget
, 
1270                                   GdkEventButton 
*gdk_event
, 
1273     wxCOMMON_CALLBACK_PROLOGUE(gdk_event
, win
); 
1275     g_lastButtonNumber 
= gdk_event
->button
; 
1277     // GDK sends surplus button down events 
1278     // before a double click event. We 
1279     // need to filter these out. 
1280     if ((gdk_event
->type 
== GDK_BUTTON_PRESS
) && (win
->m_wxwindow
)) 
1282         GdkEvent 
*peek_event 
= gdk_event_peek(); 
1285             if ((peek_event
->type 
== GDK_2BUTTON_PRESS
) || 
1286                 (peek_event
->type 
== GDK_3BUTTON_PRESS
)) 
1288                 gdk_event_free( peek_event 
); 
1293                 gdk_event_free( peek_event 
); 
1298     wxEventType event_type 
= wxEVT_NULL
; 
1300     if ( gdk_event
->type 
== GDK_2BUTTON_PRESS 
&& 
1301             gdk_event
->button 
>= 1 && gdk_event
->button 
<= 3 ) 
1303         // Reset GDK internal timestamp variables in order to disable GDK 
1304         // triple click events. GDK will then next time believe no button has 
1305         // been clicked just before, and send a normal button click event. 
1306         GdkDisplay
* display 
= gtk_widget_get_display (widget
); 
1307         display
->button_click_time
[1] = 0; 
1308         display
->button_click_time
[0] = 0; 
1311     if (gdk_event
->button 
== 1) 
1313         // note that GDK generates triple click events which are not supported 
1314         // by wxWidgets but still have to be passed to the app as otherwise 
1315         // clicks would simply go missing 
1316         switch (gdk_event
->type
) 
1318             // we shouldn't get triple clicks at all for GTK2 because we 
1319             // suppress them artificially using the code above but we still 
1320             // should map them to something for GTK1 and not just ignore them 
1321             // as this would lose clicks 
1322             case GDK_3BUTTON_PRESS
:     // we could also map this to DCLICK... 
1323             case GDK_BUTTON_PRESS
: 
1324                 event_type 
= wxEVT_LEFT_DOWN
; 
1327             case GDK_2BUTTON_PRESS
: 
1328                 event_type 
= wxEVT_LEFT_DCLICK
; 
1332                 // just to silence gcc warnings 
1336     else if (gdk_event
->button 
== 2) 
1338         switch (gdk_event
->type
) 
1340             case GDK_3BUTTON_PRESS
: 
1341             case GDK_BUTTON_PRESS
: 
1342                 event_type 
= wxEVT_MIDDLE_DOWN
; 
1345             case GDK_2BUTTON_PRESS
: 
1346                 event_type 
= wxEVT_MIDDLE_DCLICK
; 
1353     else if (gdk_event
->button 
== 3) 
1355         switch (gdk_event
->type
) 
1357             case GDK_3BUTTON_PRESS
: 
1358             case GDK_BUTTON_PRESS
: 
1359                 event_type 
= wxEVT_RIGHT_DOWN
; 
1362             case GDK_2BUTTON_PRESS
: 
1363                 event_type 
= wxEVT_RIGHT_DCLICK
; 
1371     else if (gdk_event
->button 
== 8) 
1373         switch (gdk_event
->type
) 
1375             case GDK_3BUTTON_PRESS
: 
1376             case GDK_BUTTON_PRESS
: 
1377                 event_type 
= wxEVT_AUX1_DOWN
; 
1380             case GDK_2BUTTON_PRESS
: 
1381                 event_type 
= wxEVT_AUX1_DCLICK
; 
1389     else if (gdk_event
->button 
== 9) 
1391         switch (gdk_event
->type
) 
1393             case GDK_3BUTTON_PRESS
: 
1394             case GDK_BUTTON_PRESS
: 
1395                 event_type 
= wxEVT_AUX2_DOWN
; 
1398             case GDK_2BUTTON_PRESS
: 
1399                 event_type 
= wxEVT_AUX2_DCLICK
; 
1407     if ( event_type 
== wxEVT_NULL 
) 
1409         // unknown mouse button or click type 
1413     g_lastMouseEvent 
= (GdkEvent
*) gdk_event
; 
1415     wxMouseEvent 
event( event_type 
); 
1416     InitMouseEvent( win
, event
, gdk_event 
); 
1418     AdjustEventButtonState(event
); 
1420     // find the correct window to send the event to: it may be a different one 
1421     // from the one which got it at GTK+ level because some controls don't have 
1422     // their own X window and thus cannot get any events. 
1423     if ( !g_captureWindow 
) 
1424         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1426     // reset the event object and id in case win changed. 
1427     event
.SetEventObject( win 
); 
1428     event
.SetId( win
->GetId() ); 
1430     bool ret 
= win
->GTKProcessEvent( event 
); 
1431     g_lastMouseEvent 
= NULL
; 
1435     if ((event_type 
== wxEVT_LEFT_DOWN
) && !win
->IsOfStandardClass() && 
1436         (gs_currentFocus 
!= win
) /* && win->IsFocusable() */) 
1441     if (event_type 
== wxEVT_RIGHT_DOWN
) 
1443         // generate a "context menu" event: this is similar to right mouse 
1444         // click under many GUIs except that it is generated differently 
1445         // (right up under MSW, ctrl-click under Mac, right down here) and 
1447         // (a) it's a command event and so is propagated to the parent 
1448         // (b) under some ports it can be generated from kbd too 
1449         // (c) it uses screen coords (because of (a)) 
1450         wxContextMenuEvent 
evtCtx( 
1453             win
->ClientToScreen(event
.GetPosition())); 
1454         evtCtx
.SetEventObject(win
); 
1455         return win
->GTKProcessEvent(evtCtx
); 
1461 //----------------------------------------------------------------------------- 
1462 // "button_release_event" 
1463 //----------------------------------------------------------------------------- 
1466 gtk_window_button_release_callback( GtkWidget 
*WXUNUSED(widget
), 
1467                                     GdkEventButton 
*gdk_event
, 
1470     wxCOMMON_CALLBACK_PROLOGUE(gdk_event
, win
); 
1472     g_lastButtonNumber 
= 0; 
1474     wxEventType event_type 
= wxEVT_NULL
; 
1476     switch (gdk_event
->button
) 
1479             event_type 
= wxEVT_LEFT_UP
; 
1483             event_type 
= wxEVT_MIDDLE_UP
; 
1487             event_type 
= wxEVT_RIGHT_UP
; 
1491             event_type 
= wxEVT_AUX1_UP
; 
1495             event_type 
= wxEVT_AUX2_UP
; 
1499             // unknown button, don't process 
1503     g_lastMouseEvent 
= (GdkEvent
*) gdk_event
; 
1505     wxMouseEvent 
event( event_type 
); 
1506     InitMouseEvent( win
, event
, gdk_event 
); 
1508     AdjustEventButtonState(event
); 
1510     if ( !g_captureWindow 
) 
1511         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1513     // reset the event object and id in case win changed. 
1514     event
.SetEventObject( win 
); 
1515     event
.SetId( win
->GetId() ); 
1517     bool ret 
= win
->GTKProcessEvent(event
); 
1519     g_lastMouseEvent 
= NULL
; 
1524 //----------------------------------------------------------------------------- 
1525 // "motion_notify_event" 
1526 //----------------------------------------------------------------------------- 
1529 gtk_window_motion_notify_callback( GtkWidget 
* WXUNUSED(widget
), 
1530                                    GdkEventMotion 
*gdk_event
, 
1533     wxCOMMON_CALLBACK_PROLOGUE(gdk_event
, win
); 
1535     if (gdk_event
->is_hint
) 
1539         GdkModifierType state
; 
1540         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1545     g_lastMouseEvent 
= (GdkEvent
*) gdk_event
; 
1547     wxMouseEvent 
event( wxEVT_MOTION 
); 
1548     InitMouseEvent(win
, event
, gdk_event
); 
1550     if ( g_captureWindow 
) 
1552         // synthesise a mouse enter or leave event if needed 
1553         GdkWindow 
*winUnderMouse 
= gdk_window_at_pointer(NULL
, NULL
); 
1554         // This seems to be necessary and actually been added to 
1555         // GDK itself in version 2.0.X 
1558         bool hasMouse 
= winUnderMouse 
== gdk_event
->window
; 
1559         if ( hasMouse 
!= g_captureWindowHasMouse 
) 
1561             // the mouse changed window 
1562             g_captureWindowHasMouse 
= hasMouse
; 
1564             wxMouseEvent 
eventM(g_captureWindowHasMouse 
? wxEVT_ENTER_WINDOW
 
1565                                                         : wxEVT_LEAVE_WINDOW
); 
1566             InitMouseEvent(win
, eventM
, gdk_event
); 
1567             eventM
.SetEventObject(win
); 
1568             win
->GTKProcessEvent(eventM
); 
1573         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1575         // reset the event object and id in case win changed. 
1576         event
.SetEventObject( win 
); 
1577         event
.SetId( win
->GetId() ); 
1580     if ( !g_captureWindow 
) 
1582         wxSetCursorEvent 
cevent( event
.m_x
, event
.m_y 
); 
1583         if (win
->GTKProcessEvent( cevent 
)) 
1585             win
->SetCursor( cevent
.GetCursor() ); 
1589     bool ret 
= win
->GTKProcessEvent(event
); 
1591     g_lastMouseEvent 
= NULL
; 
1596 //----------------------------------------------------------------------------- 
1597 // "scroll_event" (mouse wheel event) 
1598 //----------------------------------------------------------------------------- 
1601 window_scroll_event_hscrollbar(GtkWidget
*, GdkEventScroll
* gdk_event
, wxWindow
* win
) 
1603     if (gdk_event
->direction 
!= GDK_SCROLL_LEFT 
&& 
1604         gdk_event
->direction 
!= GDK_SCROLL_RIGHT
) 
1609     GtkRange 
*range 
= win
->m_scrollBar
[wxWindow::ScrollDir_Horz
]; 
1611     if (range 
&& gtk_widget_get_visible(GTK_WIDGET(range
))) 
1613         GtkAdjustment
* adj 
= gtk_range_get_adjustment(range
); 
1614         double delta 
= gtk_adjustment_get_step_increment(adj
) * 3; 
1615         if (gdk_event
->direction 
== GDK_SCROLL_LEFT
) 
1618         gtk_range_set_value(range
, gtk_adjustment_get_value(adj
) + delta
); 
1627 window_scroll_event(GtkWidget
*, GdkEventScroll
* gdk_event
, wxWindow
* win
) 
1629     if (gdk_event
->direction 
!= GDK_SCROLL_UP 
&& 
1630         gdk_event
->direction 
!= GDK_SCROLL_DOWN
) 
1635     wxMouseEvent 
event(wxEVT_MOUSEWHEEL
); 
1636     InitMouseEvent(win
, event
, gdk_event
); 
1638     // FIXME: Get these values from GTK or GDK 
1639     event
.m_linesPerAction 
= 3; 
1640     event
.m_wheelDelta 
= 120; 
1641     if (gdk_event
->direction 
== GDK_SCROLL_UP
) 
1642         event
.m_wheelRotation 
= 120; 
1644         event
.m_wheelRotation 
= -120; 
1646     if (win
->GTKProcessEvent(event
)) 
1649     GtkRange 
*range 
= win
->m_scrollBar
[wxWindow::ScrollDir_Vert
]; 
1651     if (range 
&& gtk_widget_get_visible(GTK_WIDGET(range
))) 
1653         GtkAdjustment
* adj 
= gtk_range_get_adjustment(range
); 
1654         double delta 
= gtk_adjustment_get_step_increment(adj
) * 3; 
1655         if (gdk_event
->direction 
== GDK_SCROLL_UP
) 
1658         gtk_range_set_value(range
, gtk_adjustment_get_value(adj
) + delta
); 
1666 //----------------------------------------------------------------------------- 
1668 //----------------------------------------------------------------------------- 
1670 static gboolean 
wxgtk_window_popup_menu_callback(GtkWidget
*, wxWindowGTK
* win
) 
1672     wxContextMenuEvent 
event(wxEVT_CONTEXT_MENU
, win
->GetId(), wxPoint(-1, -1)); 
1673     event
.SetEventObject(win
); 
1674     return win
->GTKProcessEvent(event
); 
1677 //----------------------------------------------------------------------------- 
1679 //----------------------------------------------------------------------------- 
1682 gtk_window_focus_in_callback( GtkWidget 
* WXUNUSED(widget
), 
1683                               GdkEventFocus 
*WXUNUSED(event
), 
1686     return win
->GTKHandleFocusIn(); 
1689 //----------------------------------------------------------------------------- 
1690 // "focus_out_event" 
1691 //----------------------------------------------------------------------------- 
1694 gtk_window_focus_out_callback( GtkWidget 
* WXUNUSED(widget
), 
1695                                GdkEventFocus 
* WXUNUSED(gdk_event
), 
1698     return win
->GTKHandleFocusOut(); 
1701 //----------------------------------------------------------------------------- 
1703 //----------------------------------------------------------------------------- 
1706 wx_window_focus_callback(GtkWidget 
*widget
, 
1707                          GtkDirectionType 
WXUNUSED(direction
), 
1710     // the default handler for focus signal in GtkScrolledWindow sets 
1711     // focus to the window itself even if it doesn't accept focus, i.e. has no 
1712     // GTK_CAN_FOCUS in its style -- work around this by forcibly preventing 
1713     // the signal from reaching gtk_scrolled_window_focus() if we don't have 
1714     // any children which might accept focus (we know we don't accept the focus 
1715     // ourselves as this signal is only connected in this case) 
1716     if ( win
->GetChildren().empty() ) 
1717         g_signal_stop_emission_by_name(widget
, "focus"); 
1719     // we didn't change the focus 
1723 //----------------------------------------------------------------------------- 
1724 // "enter_notify_event" 
1725 //----------------------------------------------------------------------------- 
1728 gtk_window_enter_callback( GtkWidget 
*widget
, 
1729                            GdkEventCrossing 
*gdk_event
, 
1732     wxCOMMON_CALLBACK_PROLOGUE(gdk_event
, win
); 
1734     // Event was emitted after a grab 
1735     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
1739     GdkModifierType state 
= (GdkModifierType
)0; 
1741     gdk_window_get_pointer(gtk_widget_get_window(widget
), &x
, &y
, &state
); 
1743     wxMouseEvent 
event( wxEVT_ENTER_WINDOW 
); 
1744     InitMouseEvent(win
, event
, gdk_event
); 
1745     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1746     event
.m_x 
= x 
+ pt
.x
; 
1747     event
.m_y 
= y 
+ pt
.y
; 
1749     if ( !g_captureWindow 
) 
1751         wxSetCursorEvent 
cevent( event
.m_x
, event
.m_y 
); 
1752         if (win
->GTKProcessEvent( cevent 
)) 
1754             win
->SetCursor( cevent
.GetCursor() ); 
1758     return win
->GTKProcessEvent(event
); 
1761 //----------------------------------------------------------------------------- 
1762 // "leave_notify_event" 
1763 //----------------------------------------------------------------------------- 
1766 gtk_window_leave_callback( GtkWidget 
*widget
, 
1767                            GdkEventCrossing 
*gdk_event
, 
1770     wxCOMMON_CALLBACK_PROLOGUE(gdk_event
, win
); 
1772     // Event was emitted after an ungrab 
1773     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
1775     wxMouseEvent 
event( wxEVT_LEAVE_WINDOW 
); 
1779     GdkModifierType state 
= (GdkModifierType
)0; 
1781     gdk_window_get_pointer(gtk_widget_get_window(widget
), &x
, &y
, &state
); 
1783     InitMouseEvent(win
, event
, gdk_event
); 
1785     return win
->GTKProcessEvent(event
); 
1788 //----------------------------------------------------------------------------- 
1789 // "value_changed" from scrollbar 
1790 //----------------------------------------------------------------------------- 
1793 gtk_scrollbar_value_changed(GtkRange
* range
, wxWindow
* win
) 
1795     wxEventType eventType 
= win
->GTKGetScrollEventType(range
); 
1796     if (eventType 
!= wxEVT_NULL
) 
1798         // Convert scroll event type to scrollwin event type 
1799         eventType 
+= wxEVT_SCROLLWIN_TOP 
- wxEVT_SCROLL_TOP
; 
1801         // find the scrollbar which generated the event 
1802         wxWindowGTK::ScrollDir dir 
= win
->ScrollDirFromRange(range
); 
1804         // generate the corresponding wx event 
1805         const int orient 
= wxWindow::OrientFromScrollDir(dir
); 
1806         wxScrollWinEvent 
event(eventType
, win
->GetScrollPos(orient
), orient
); 
1807         event
.SetEventObject(win
); 
1809         win
->GTKProcessEvent(event
); 
1813 //----------------------------------------------------------------------------- 
1814 // "button_press_event" from scrollbar 
1815 //----------------------------------------------------------------------------- 
1818 gtk_scrollbar_button_press_event(GtkRange
*, GdkEventButton
*, wxWindow
* win
) 
1820     g_blockEventsOnScroll 
= true; 
1821     win
->m_mouseButtonDown 
= true; 
1826 //----------------------------------------------------------------------------- 
1827 // "event_after" from scrollbar 
1828 //----------------------------------------------------------------------------- 
1831 gtk_scrollbar_event_after(GtkRange
* range
, GdkEvent
* event
, wxWindow
* win
) 
1833     if (event
->type 
== GDK_BUTTON_RELEASE
) 
1835         g_signal_handlers_block_by_func(range
, (void*)gtk_scrollbar_event_after
, win
); 
1837         const int orient 
= wxWindow::OrientFromScrollDir( 
1838                                         win
->ScrollDirFromRange(range
)); 
1839         wxScrollWinEvent 
evt(wxEVT_SCROLLWIN_THUMBRELEASE
, 
1840                                 win
->GetScrollPos(orient
), orient
); 
1841         evt
.SetEventObject(win
); 
1842         win
->GTKProcessEvent(evt
); 
1846 //----------------------------------------------------------------------------- 
1847 // "button_release_event" from scrollbar 
1848 //----------------------------------------------------------------------------- 
1851 gtk_scrollbar_button_release_event(GtkRange
* range
, GdkEventButton
*, wxWindow
* win
) 
1853     g_blockEventsOnScroll 
= false; 
1854     win
->m_mouseButtonDown 
= false; 
1855     // If thumb tracking 
1856     if (win
->m_isScrolling
) 
1858         win
->m_isScrolling 
= false; 
1859         // Hook up handler to send thumb release event after this emission is finished. 
1860         // To allow setting scroll position from event handler, sending event must 
1861         // be deferred until after the GtkRange handler for this signal has run 
1862         g_signal_handlers_unblock_by_func(range
, (void*)gtk_scrollbar_event_after
, win
); 
1868 //----------------------------------------------------------------------------- 
1869 // "realize" from m_widget 
1870 //----------------------------------------------------------------------------- 
1873 gtk_window_realized_callback(GtkWidget
* WXUNUSED(widget
), wxWindowGTK
* win
) 
1875     win
->GTKHandleRealized(); 
1878 //----------------------------------------------------------------------------- 
1879 // "unrealize" from m_wxwindow 
1880 //----------------------------------------------------------------------------- 
1882 static void unrealize(GtkWidget
*, wxWindowGTK
* win
) 
1885         gtk_im_context_set_client_window(win
->m_imData
->context
, NULL
); 
1888 //----------------------------------------------------------------------------- 
1889 // "size_allocate" from m_wxwindow or m_widget 
1890 //----------------------------------------------------------------------------- 
1893 size_allocate(GtkWidget
*, GtkAllocation
* alloc
, wxWindow
* win
) 
1895     int w 
= alloc
->width
; 
1896     int h 
= alloc
->height
; 
1897     if (win
->m_wxwindow
) 
1899         int border_x
, border_y
; 
1900         WX_PIZZA(win
->m_wxwindow
)->get_border_widths(border_x
, border_y
); 
1906     if (win
->m_oldClientWidth 
!= w 
|| win
->m_oldClientHeight 
!= h
) 
1908         win
->m_oldClientWidth  
= w
; 
1909         win
->m_oldClientHeight 
= h
; 
1910         // this callback can be connected to m_wxwindow, 
1911         // so always get size from m_widget->allocation 
1913         gtk_widget_get_allocation(win
->m_widget
, &a
); 
1914         win
->m_width  
= a
.width
; 
1915         win
->m_height 
= a
.height
; 
1916         if (!win
->m_nativeSizeEvent
) 
1918             wxSizeEvent 
event(win
->GetSize(), win
->GetId()); 
1919             event
.SetEventObject(win
); 
1920             win
->GTKProcessEvent(event
); 
1925 //----------------------------------------------------------------------------- 
1927 //----------------------------------------------------------------------------- 
1929 #if GTK_CHECK_VERSION(2, 8, 0) 
1931 gtk_window_grab_broken( GtkWidget
*, 
1932                         GdkEventGrabBroken 
*event
, 
1935     // Mouse capture has been lost involuntarily, notify the application 
1936     if(!event
->keyboard 
&& wxWindow::GetCapture() == win
) 
1938         wxMouseCaptureLostEvent 
evt( win
->GetId() ); 
1939         evt
.SetEventObject( win 
); 
1940         win
->HandleWindowEvent( evt 
); 
1946 //----------------------------------------------------------------------------- 
1948 //----------------------------------------------------------------------------- 
1951 void gtk_window_style_set_callback( GtkWidget 
*WXUNUSED(widget
), 
1952                                GtkStyle 
*previous_style
, 
1955     if (win 
&& previous_style
) 
1957         if (win
->IsTopLevel()) 
1959             wxSysColourChangedEvent event
; 
1960             event
.SetEventObject(win
); 
1961             win
->GTKProcessEvent(event
); 
1965             // Border width could change, which will change client size. 
1966             // Make sure size event occurs for this 
1967             win
->m_oldClientWidth 
= 0; 
1974 void wxWindowGTK::GTKHandleRealized() 
1978         gtk_im_context_set_client_window
 
1981             m_wxwindow 
? GTKGetDrawingWindow() 
1982                        : gtk_widget_get_window(m_widget
) 
1986     // Use composited window if background is transparent, if supported. 
1987     if (m_backgroundStyle 
== wxBG_STYLE_TRANSPARENT
) 
1989 #if wxGTK_HAS_COMPOSITING_SUPPORT 
1990         if (IsTransparentBackgroundSupported()) 
1992             GdkWindow
* const window 
= GTKGetDrawingWindow(); 
1994                 gdk_window_set_composited(window
, true); 
1997 #endif // wxGTK_HAS_COMPOSITING_SUPPORT 
1999             // We revert to erase mode if transparency is not supported 
2000             m_backgroundStyle 
= wxBG_STYLE_ERASE
; 
2005     // We cannot set colours and fonts before the widget 
2006     // been realized, so we do this directly after realization 
2007     // or otherwise in idle time 
2009     if (m_needsStyleChange
) 
2011         SetBackgroundStyle(GetBackgroundStyle()); 
2012         m_needsStyleChange 
= false; 
2015     wxWindowCreateEvent 
event(static_cast<wxWindow
*>(this)); 
2016     event
.SetEventObject( this ); 
2017     GTKProcessEvent( event 
); 
2019     GTKUpdateCursor(true, false); 
2022 // ---------------------------------------------------------------------------- 
2023 // this wxWindowBase function is implemented here (in platform-specific file) 
2024 // because it is static and so couldn't be made virtual 
2025 // ---------------------------------------------------------------------------- 
2027 wxWindow 
*wxWindowBase::DoFindFocus() 
2029     wxWindowGTK 
*focus 
= gs_pendingFocus 
? gs_pendingFocus 
: gs_currentFocus
; 
2030     // the cast is necessary when we compile in wxUniversal mode 
2031     return static_cast<wxWindow
*>(focus
); 
2034 void wxWindowGTK::AddChildGTK(wxWindowGTK
* child
) 
2036     wxASSERT_MSG(m_wxwindow
, "Cannot add a child to a window without a client area"); 
2038     // the window might have been scrolled already, we 
2039     // have to adapt the position 
2040     wxPizza
* pizza 
= WX_PIZZA(m_wxwindow
); 
2041     child
->m_x 
+= pizza
->m_scroll_x
; 
2042     child
->m_y 
+= pizza
->m_scroll_y
; 
2044     gtk_widget_set_size_request( 
2045         child
->m_widget
, child
->m_width
, child
->m_height
); 
2046     pizza
->put(child
->m_widget
, child
->m_x
, child
->m_y
); 
2049 //----------------------------------------------------------------------------- 
2051 //----------------------------------------------------------------------------- 
2053 wxWindow 
*wxGetActiveWindow() 
2055     return wxWindow::FindFocus(); 
2059 wxMouseState 
wxGetMouseState() 
2065     GdkModifierType mask
; 
2067     gdk_window_get_pointer(NULL
, &x
, &y
, &mask
); 
2071     ms
.SetLeftDown((mask 
& GDK_BUTTON1_MASK
) != 0); 
2072     ms
.SetMiddleDown((mask 
& GDK_BUTTON2_MASK
) != 0); 
2073     ms
.SetRightDown((mask 
& GDK_BUTTON3_MASK
) != 0); 
2074     // see the comment in InitMouseEvent() 
2075     ms
.SetAux1Down((mask 
& GDK_BUTTON4_MASK
) != 0); 
2076     ms
.SetAux2Down((mask 
& GDK_BUTTON5_MASK
) != 0); 
2078     ms
.SetControlDown((mask 
& GDK_CONTROL_MASK
) != 0); 
2079     ms
.SetShiftDown((mask 
& GDK_SHIFT_MASK
) != 0); 
2080     ms
.SetAltDown((mask 
& GDK_MOD1_MASK
) != 0); 
2081     ms
.SetMetaDown((mask 
& GDK_META_MASK
) != 0); 
2086 //----------------------------------------------------------------------------- 
2088 //----------------------------------------------------------------------------- 
2090 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
2092 #ifdef __WXUNIVERSAL__ 
2093     IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
) 
2094 #endif // __WXUNIVERSAL__ 
2096 void wxWindowGTK::Init() 
2101     m_focusWidget 
= NULL
; 
2111     m_showOnIdle 
= false; 
2114     m_nativeSizeEvent 
= false; 
2116     m_isScrolling 
= false; 
2117     m_mouseButtonDown 
= false; 
2119     // initialize scrolling stuff 
2120     for ( int dir 
= 0; dir 
< ScrollDir_Max
; dir
++ ) 
2122         m_scrollBar
[dir
] = NULL
; 
2123         m_scrollPos
[dir
] = 0; 
2127     m_oldClientHeight 
= 0; 
2129     m_clipPaintRegion 
= false; 
2131     m_needsStyleChange 
= false; 
2133     m_cursor 
= *wxSTANDARD_CURSOR
; 
2136     m_dirtyTabOrder 
= false; 
2139 wxWindowGTK::wxWindowGTK() 
2144 wxWindowGTK::wxWindowGTK( wxWindow 
*parent
, 
2149                           const wxString 
&name  
) 
2153     Create( parent
, id
, pos
, size
, style
, name 
); 
2156 bool wxWindowGTK::Create( wxWindow 
*parent
, 
2161                           const wxString 
&name  
) 
2163     // Get default border 
2164     wxBorder border 
= GetBorder(style
); 
2166     style 
&= ~wxBORDER_MASK
; 
2169     if (!PreCreation( parent
, pos
, size 
) || 
2170         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
2172         wxFAIL_MSG( wxT("wxWindowGTK creation failed") ); 
2176         // We should accept the native look 
2178         GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2179         scroll_class
->scrollbar_spacing 
= 0; 
2183     m_wxwindow 
= wxPizza::New(m_windowStyle
); 
2184 #ifndef __WXUNIVERSAL__ 
2185     if (HasFlag(wxPizza::BORDER_STYLES
)) 
2187         g_signal_connect(m_wxwindow
, "parent_set", 
2188             G_CALLBACK(parent_set
), this); 
2191     if (!HasFlag(wxHSCROLL
) && !HasFlag(wxVSCROLL
)) 
2192         m_widget 
= m_wxwindow
; 
2195         m_widget 
= gtk_scrolled_window_new( NULL
, NULL 
); 
2197         GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
2199         // There is a conflict with default bindings at GTK+ 
2200         // level between scrolled windows and notebooks both of which want to use 
2201         // Ctrl-PageUp/Down: scrolled windows for scrolling in the horizontal 
2202         // direction and notebooks for changing pages -- we decide that if we don't 
2203         // have wxHSCROLL style we can safely sacrifice horizontal scrolling if it 
2204         // means we can get working keyboard navigation in notebooks 
2205         if ( !HasFlag(wxHSCROLL
) ) 
2208                 bindings 
= gtk_binding_set_by_class(G_OBJECT_GET_CLASS(m_widget
)); 
2211                 gtk_binding_entry_remove(bindings
, GDK_Page_Up
, GDK_CONTROL_MASK
); 
2212                 gtk_binding_entry_remove(bindings
, GDK_Page_Down
, GDK_CONTROL_MASK
); 
2216         if (HasFlag(wxALWAYS_SHOW_SB
)) 
2218             gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_ALWAYS
, GTK_POLICY_ALWAYS 
); 
2222             gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
2225         m_scrollBar
[ScrollDir_Horz
] = GTK_RANGE(gtk_scrolled_window_get_hscrollbar(scrolledWindow
)); 
2226         m_scrollBar
[ScrollDir_Vert
] = GTK_RANGE(gtk_scrolled_window_get_vscrollbar(scrolledWindow
)); 
2227         if (GetLayoutDirection() == wxLayout_RightToLeft
) 
2228             gtk_range_set_inverted( m_scrollBar
[ScrollDir_Horz
], TRUE 
); 
2230         gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
2232         // connect various scroll-related events 
2233         for ( int dir 
= 0; dir 
< ScrollDir_Max
; dir
++ ) 
2235             // these handlers block mouse events to any window during scrolling 
2236             // such as motion events and prevent GTK and wxWidgets from fighting 
2237             // over where the slider should be 
2238             g_signal_connect(m_scrollBar
[dir
], "button_press_event", 
2239                          G_CALLBACK(gtk_scrollbar_button_press_event
), this); 
2240             g_signal_connect(m_scrollBar
[dir
], "button_release_event", 
2241                          G_CALLBACK(gtk_scrollbar_button_release_event
), this); 
2243             gulong handler_id 
= g_signal_connect(m_scrollBar
[dir
], "event_after", 
2244                                 G_CALLBACK(gtk_scrollbar_event_after
), this); 
2245             g_signal_handler_block(m_scrollBar
[dir
], handler_id
); 
2247             // these handlers get notified when scrollbar slider moves 
2248             g_signal_connect_after(m_scrollBar
[dir
], "value_changed", 
2249                          G_CALLBACK(gtk_scrollbar_value_changed
), this); 
2252         gtk_widget_show( m_wxwindow 
); 
2254     g_object_ref(m_widget
); 
2257         m_parent
->DoAddChild( this ); 
2259     m_focusWidget 
= m_wxwindow
; 
2261     SetCanFocus(AcceptsFocus()); 
2268 wxWindowGTK::~wxWindowGTK() 
2272     if (gs_currentFocus 
== this) 
2273         gs_currentFocus 
= NULL
; 
2274     if (gs_pendingFocus 
== this) 
2275         gs_pendingFocus 
= NULL
; 
2277     if ( gs_deferredFocusOut 
== this ) 
2278         gs_deferredFocusOut 
= NULL
; 
2282     // destroy children before destroying this window itself 
2285     // unhook focus handlers to prevent stray events being 
2286     // propagated to this (soon to be) dead object 
2287     if (m_focusWidget 
!= NULL
) 
2289         g_signal_handlers_disconnect_by_func (m_focusWidget
, 
2290                                               (gpointer
) gtk_window_focus_in_callback
, 
2292         g_signal_handlers_disconnect_by_func (m_focusWidget
, 
2293                                               (gpointer
) gtk_window_focus_out_callback
, 
2300     // delete before the widgets to avoid a crash on solaris 
2304     // avoid problem with GTK+ 2.18 where a frozen window causes the whole 
2305     // TLW to be frozen, and if the window is then destroyed, nothing ever 
2306     // gets painted again 
2312         // Note that gtk_widget_destroy() does not destroy the widget, it just 
2313         // emits the "destroy" signal. The widget is not actually destroyed 
2314         // until its reference count drops to zero. 
2315         gtk_widget_destroy(m_widget
); 
2316         // Release our reference, should be the last one 
2317         g_object_unref(m_widget
); 
2323 bool wxWindowGTK::PreCreation( wxWindowGTK 
*parent
, const wxPoint 
&pos
,  const wxSize 
&size 
) 
2325     if ( GTKNeedsParent() ) 
2327         wxCHECK_MSG( parent
, false, wxT("Must have non-NULL parent") ); 
2330     // Use either the given size, or the default if -1 is given. 
2331     // See wxWindowBase for these functions. 
2332     m_width 
= WidthDefault(size
.x
) ; 
2333     m_height 
= HeightDefault(size
.y
); 
2341 void wxWindowGTK::PostCreation() 
2343     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2345 #if wxGTK_HAS_COMPOSITING_SUPPORT 
2346     // Set RGBA visual as soon as possible to minimize the possibility that 
2347     // somebody uses the wrong one. 
2348     if ( m_backgroundStyle 
== wxBG_STYLE_TRANSPARENT 
&& 
2349             IsTransparentBackgroundSupported() ) 
2351         GdkScreen 
*screen 
= gtk_widget_get_screen (m_widget
); 
2353         GdkColormap 
*rgba_colormap 
= gdk_screen_get_rgba_colormap (screen
); 
2356             gtk_widget_set_colormap(m_widget
, rgba_colormap
); 
2358 #endif // wxGTK_HAS_COMPOSITING_SUPPORT 
2364             // these get reported to wxWidgets -> wxPaintEvent 
2366             g_signal_connect (m_wxwindow
, "expose_event", 
2367                               G_CALLBACK (gtk_window_expose_callback
), this); 
2369             if (GetLayoutDirection() == wxLayout_LeftToRight
) 
2370                 gtk_widget_set_redraw_on_allocate(m_wxwindow
, HasFlag(wxFULL_REPAINT_ON_RESIZE
)); 
2373         // Create input method handler 
2374         m_imData 
= new wxGtkIMData
; 
2376         // Cannot handle drawing preedited text yet 
2377         gtk_im_context_set_use_preedit( m_imData
->context
, FALSE 
); 
2379         g_signal_connect (m_imData
->context
, "commit", 
2380                           G_CALLBACK (gtk_wxwindow_commit_cb
), this); 
2381         g_signal_connect(m_wxwindow
, "unrealize", G_CALLBACK(unrealize
), this); 
2386     if (!GTK_IS_WINDOW(m_widget
)) 
2388         if (m_focusWidget 
== NULL
) 
2389             m_focusWidget 
= m_widget
; 
2393             g_signal_connect (m_focusWidget
, "focus_in_event", 
2394                           G_CALLBACK (gtk_window_focus_in_callback
), this); 
2395             g_signal_connect (m_focusWidget
, "focus_out_event", 
2396                                 G_CALLBACK (gtk_window_focus_out_callback
), this); 
2400             g_signal_connect_after (m_focusWidget
, "focus_in_event", 
2401                           G_CALLBACK (gtk_window_focus_in_callback
), this); 
2402             g_signal_connect_after (m_focusWidget
, "focus_out_event", 
2403                                 G_CALLBACK (gtk_window_focus_out_callback
), this); 
2407     if ( !AcceptsFocusFromKeyboard() ) 
2411         g_signal_connect(m_widget
, "focus", 
2412                             G_CALLBACK(wx_window_focus_callback
), this); 
2415     // connect to the various key and mouse handlers 
2417     GtkWidget 
*connect_widget 
= GetConnectWidget(); 
2419     ConnectWidget( connect_widget 
); 
2421     // connect handler to prevent events from propagating up parent chain 
2422     g_signal_connect_after(m_widget
, 
2423         "key_press_event", G_CALLBACK(key_and_mouse_event_after
), this); 
2424     g_signal_connect_after(m_widget
, 
2425         "key_release_event", G_CALLBACK(key_and_mouse_event_after
), this); 
2426     g_signal_connect_after(m_widget
, 
2427         "button_press_event", G_CALLBACK(key_and_mouse_event_after
), this); 
2428     g_signal_connect_after(m_widget
, 
2429         "button_release_event", G_CALLBACK(key_and_mouse_event_after
), this); 
2430     g_signal_connect_after(m_widget
, 
2431         "motion_notify_event", G_CALLBACK(key_and_mouse_event_after
), this); 
2433     // We cannot set colours, fonts and cursors before the widget has been 
2434     // realized, so we do this directly after realization -- unless the widget 
2435     // was in fact realized already. 
2436     if ( gtk_widget_get_realized(connect_widget
) ) 
2438         gtk_window_realized_callback(connect_widget
, this); 
2442         g_signal_connect (connect_widget
, "realize", 
2443                           G_CALLBACK (gtk_window_realized_callback
), this); 
2448         g_signal_connect(m_wxwindow 
? m_wxwindow 
: m_widget
, "size_allocate", 
2449             G_CALLBACK(size_allocate
), this); 
2452 #if GTK_CHECK_VERSION(2, 8, 0) 
2453     if ( gtk_check_version(2,8,0) == NULL 
) 
2455         // Make sure we can notify the app when mouse capture is lost 
2458             g_signal_connect (m_wxwindow
, "grab_broken_event", 
2459                           G_CALLBACK (gtk_window_grab_broken
), this); 
2462         if ( connect_widget 
!= m_wxwindow 
) 
2464             g_signal_connect (connect_widget
, "grab_broken_event", 
2465                         G_CALLBACK (gtk_window_grab_broken
), this); 
2468 #endif // GTK+ >= 2.8 
2470     if ( GTKShouldConnectSizeRequest() ) 
2472         // This is needed if we want to add our windows into native 
2473         // GTK controls, such as the toolbar. With this callback, the 
2474         // toolbar gets to know the correct size (the one set by the 
2475         // programmer). Sadly, it misbehaves for wxComboBox. 
2476         g_signal_connect (m_widget
, "size_request", 
2477                           G_CALLBACK (wxgtk_window_size_request_callback
), 
2481     InheritAttributes(); 
2485     SetLayoutDirection(wxLayout_Default
); 
2487     // unless the window was created initially hidden (i.e. Hide() had been 
2488     // called before Create()), we should show it at GTK+ level as well 
2490         gtk_widget_show( m_widget 
); 
2494 wxWindowGTK::GTKConnectWidget(const char *signal
, wxGTKCallback callback
) 
2496     return g_signal_connect(m_widget
, signal
, callback
, this); 
2499 void wxWindowGTK::ConnectWidget( GtkWidget 
*widget 
) 
2501     g_signal_connect (widget
, "key_press_event", 
2502                       G_CALLBACK (gtk_window_key_press_callback
), this); 
2503     g_signal_connect (widget
, "key_release_event", 
2504                       G_CALLBACK (gtk_window_key_release_callback
), this); 
2505     g_signal_connect (widget
, "button_press_event", 
2506                       G_CALLBACK (gtk_window_button_press_callback
), this); 
2507     g_signal_connect (widget
, "button_release_event", 
2508                       G_CALLBACK (gtk_window_button_release_callback
), this); 
2509     g_signal_connect (widget
, "motion_notify_event", 
2510                       G_CALLBACK (gtk_window_motion_notify_callback
), this); 
2512     g_signal_connect (widget
, "scroll_event", 
2513                       G_CALLBACK (window_scroll_event
), this); 
2514     if (m_scrollBar
[ScrollDir_Horz
]) 
2515         g_signal_connect (m_scrollBar
[ScrollDir_Horz
], "scroll_event", 
2516                       G_CALLBACK (window_scroll_event_hscrollbar
), this); 
2517     if (m_scrollBar
[ScrollDir_Vert
]) 
2518         g_signal_connect (m_scrollBar
[ScrollDir_Vert
], "scroll_event", 
2519                       G_CALLBACK (window_scroll_event
), this); 
2521     g_signal_connect (widget
, "popup_menu", 
2522                      G_CALLBACK (wxgtk_window_popup_menu_callback
), this); 
2523     g_signal_connect (widget
, "enter_notify_event", 
2524                       G_CALLBACK (gtk_window_enter_callback
), this); 
2525     g_signal_connect (widget
, "leave_notify_event", 
2526                       G_CALLBACK (gtk_window_leave_callback
), this); 
2528     if (m_wxwindow 
&& (IsTopLevel() || HasFlag(wxBORDER_RAISED 
| wxBORDER_SUNKEN 
| wxBORDER_THEME
))) 
2529         g_signal_connect (m_wxwindow
, "style_set", 
2530                               G_CALLBACK (gtk_window_style_set_callback
), this); 
2533 bool wxWindowGTK::Destroy() 
2537     return wxWindowBase::Destroy(); 
2540 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
) 
2542     gtk_widget_set_size_request(m_widget
, width
, height
); 
2544     // inform the parent to perform the move 
2545     wxASSERT_MSG(m_parent 
&& m_parent
->m_wxwindow
, 
2546                  "the parent window has no client area?"); 
2547     WX_PIZZA(m_parent
->m_wxwindow
)->move(m_widget
, x
, y
); 
2550 void wxWindowGTK::ConstrainSize() 
2553     // GPE's window manager doesn't like size hints at all, esp. when the user 
2554     // has to use the virtual keyboard, so don't constrain size there 
2558         const wxSize minSize 
= GetMinSize(); 
2559         const wxSize maxSize 
= GetMaxSize(); 
2560         if (minSize
.x 
> 0 && m_width  
< minSize
.x
) m_width  
= minSize
.x
; 
2561         if (minSize
.y 
> 0 && m_height 
< minSize
.y
) m_height 
= minSize
.y
; 
2562         if (maxSize
.x 
> 0 && m_width  
> maxSize
.x
) m_width  
= maxSize
.x
; 
2563         if (maxSize
.y 
> 0 && m_height 
> maxSize
.y
) m_height 
= maxSize
.y
; 
2567 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
2569     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2570     wxASSERT_MSG( (m_parent 
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") ); 
2572     if ((sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) == 0 && (x 
== -1 || y 
== -1)) 
2574         int currentX
, currentY
; 
2575         GetPosition(¤tX
, ¤tY
); 
2581     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
2583     // calculate the best size if we should auto size the window 
2584     if ( ((sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1) || 
2585          ((sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1) ) 
2587         const wxSize sizeBest 
= GetBestSize(); 
2588         if ( (sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1 ) 
2590         if ( (sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1 ) 
2591             height 
= sizeBest
.y
; 
2594     const wxSize 
oldSize(m_width
, m_height
); 
2600     if (m_parent
->m_wxwindow
) 
2602         wxPizza
* pizza 
= WX_PIZZA(m_parent
->m_wxwindow
); 
2603         m_x 
= x 
+ pizza
->m_scroll_x
; 
2604         m_y 
= y 
+ pizza
->m_scroll_y
; 
2606         int left_border 
= 0; 
2607         int right_border 
= 0; 
2609         int bottom_border 
= 0; 
2611         /* the default button has a border around it */ 
2612         if (gtk_widget_get_can_default(m_widget
)) 
2614             GtkBorder 
*default_border 
= NULL
; 
2615             gtk_widget_style_get( m_widget
, "default_border", &default_border
, NULL 
); 
2618                 left_border 
+= default_border
->left
; 
2619                 right_border 
+= default_border
->right
; 
2620                 top_border 
+= default_border
->top
; 
2621                 bottom_border 
+= default_border
->bottom
; 
2622                 gtk_border_free( default_border 
); 
2626         DoMoveWindow( m_x 
- left_border
, 
2628                       m_width
+left_border
+right_border
, 
2629                       m_height
+top_border
+bottom_border 
); 
2632     if (m_width 
!= oldSize
.x 
|| m_height 
!= oldSize
.y
) 
2634         // update these variables to keep size_allocate handler 
2635         // from sending another size event for this change 
2636         GetClientSize( &m_oldClientWidth
, &m_oldClientHeight 
); 
2638         gtk_widget_queue_resize(m_widget
); 
2639         if (!m_nativeSizeEvent
) 
2641             wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
2642             event
.SetEventObject( this ); 
2643             HandleWindowEvent( event 
); 
2646     if (sizeFlags 
& wxSIZE_FORCE_EVENT
) 
2648         wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
2649         event
.SetEventObject( this ); 
2650         HandleWindowEvent( event 
); 
2654 bool wxWindowGTK::GTKShowFromOnIdle() 
2656     if (IsShown() && m_showOnIdle 
&& !gtk_widget_get_visible (m_widget
)) 
2658         GtkAllocation alloc
; 
2661         alloc
.width 
= m_width
; 
2662         alloc
.height 
= m_height
; 
2663         gtk_widget_size_allocate( m_widget
, &alloc 
); 
2664         gtk_widget_show( m_widget 
); 
2665         wxShowEvent 
eventShow(GetId(), true); 
2666         eventShow
.SetEventObject(this); 
2667         HandleWindowEvent(eventShow
); 
2668         m_showOnIdle 
= false; 
2675 void wxWindowGTK::OnInternalIdle() 
2677     if ( gs_deferredFocusOut 
) 
2678         GTKHandleDeferredFocusOut(); 
2680     // Check if we have to show window now 
2681     if (GTKShowFromOnIdle()) return; 
2683     if ( m_dirtyTabOrder 
) 
2685         m_dirtyTabOrder 
= false; 
2689     wxWindowBase::OnInternalIdle(); 
2692 void wxWindowGTK::DoGetSize( int *width
, int *height 
) const 
2694     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2696     if (width
) (*width
) = m_width
; 
2697     if (height
) (*height
) = m_height
; 
2700 void wxWindowGTK::DoSetClientSize( int width
, int height 
) 
2702     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2704     const wxSize size 
= GetSize(); 
2705     const wxSize clientSize 
= GetClientSize(); 
2706     SetSize(width 
+ (size
.x 
- clientSize
.x
), height 
+ (size
.y 
- clientSize
.y
)); 
2709 void wxWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
2711     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2718         // if window is scrollable, account for scrollbars 
2719         if ( GTK_IS_SCROLLED_WINDOW(m_widget
) ) 
2721             GtkPolicyType policy
[ScrollDir_Max
]; 
2722             gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(m_widget
), 
2723                                            &policy
[ScrollDir_Horz
], 
2724                                            &policy
[ScrollDir_Vert
]); 
2726             for ( int i 
= 0; i 
< ScrollDir_Max
; i
++ ) 
2728                 // don't account for the scrollbars we don't have 
2729                 GtkRange 
* const range 
= m_scrollBar
[i
]; 
2733                 // nor for the ones we have but don't current show 
2734                 switch ( policy
[i
] ) 
2736                     case GTK_POLICY_NEVER
: 
2737                         // never shown so doesn't take any place 
2740                     case GTK_POLICY_ALWAYS
: 
2741                         // no checks necessary 
2744                     case GTK_POLICY_AUTOMATIC
: 
2745                         // may be shown or not, check 
2746                         GtkAdjustment 
*adj 
= gtk_range_get_adjustment(range
); 
2747                         if (gtk_adjustment_get_upper(adj
) <= gtk_adjustment_get_page_size(adj
)) 
2751                 GtkScrolledWindowClass 
*scroll_class 
= 
2752                     GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2755                 gtk_widget_size_request(GTK_WIDGET(range
), &req
); 
2756                 if (i 
== ScrollDir_Horz
) 
2757                     h 
-= req
.height 
+ scroll_class
->scrollbar_spacing
; 
2759                     w 
-= req
.width 
+ scroll_class
->scrollbar_spacing
; 
2763         const wxSize sizeBorders 
= DoGetBorderSize(); 
2773     if (width
) *width 
= w
; 
2774     if (height
) *height 
= h
; 
2777 wxSize 
wxWindowGTK::DoGetBorderSize() const 
2780         return wxWindowBase::DoGetBorderSize(); 
2783     WX_PIZZA(m_wxwindow
)->get_border_widths(x
, y
); 
2785     return 2*wxSize(x
, y
); 
2788 void wxWindowGTK::DoGetPosition( int *x
, int *y 
) const 
2790     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2794     if (!IsTopLevel() && m_parent 
&& m_parent
->m_wxwindow
) 
2796         wxPizza
* pizza 
= WX_PIZZA(m_parent
->m_wxwindow
); 
2797         dx 
= pizza
->m_scroll_x
; 
2798         dy 
= pizza
->m_scroll_y
; 
2801     if (m_x 
== -1 && m_y 
== -1) 
2803         GdkWindow 
*source 
= NULL
; 
2805             source 
= gtk_widget_get_window(m_wxwindow
); 
2807             source 
= gtk_widget_get_window(m_widget
); 
2813             gdk_window_get_origin( source
, &org_x
, &org_y 
); 
2816                 m_parent
->ScreenToClient(&org_x
, &org_y
); 
2818             const_cast<wxWindowGTK
*>(this)->m_x 
= org_x
; 
2819             const_cast<wxWindowGTK
*>(this)->m_y 
= org_y
; 
2823     if (x
) (*x
) = m_x 
- dx
; 
2824     if (y
) (*y
) = m_y 
- dy
; 
2827 void wxWindowGTK::DoClientToScreen( int *x
, int *y 
) const 
2829     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2831     if (gtk_widget_get_window(m_widget
) == NULL
) return; 
2833     GdkWindow 
*source 
= NULL
; 
2835         source 
= gtk_widget_get_window(m_wxwindow
); 
2837         source 
= gtk_widget_get_window(m_widget
); 
2841     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
2845         if (!gtk_widget_get_has_window(m_widget
)) 
2848             gtk_widget_get_allocation(m_widget
, &a
); 
2857         if (GetLayoutDirection() == wxLayout_RightToLeft
) 
2858             *x 
= (GetClientSize().x 
- *x
) + org_x
; 
2866 void wxWindowGTK::DoScreenToClient( int *x
, int *y 
) const 
2868     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2870     if (!gtk_widget_get_realized(m_widget
)) return; 
2872     GdkWindow 
*source 
= NULL
; 
2874         source 
= gtk_widget_get_window(m_wxwindow
); 
2876         source 
= gtk_widget_get_window(m_widget
); 
2880     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
2884         if (!gtk_widget_get_has_window(m_widget
)) 
2887             gtk_widget_get_allocation(m_widget
, &a
); 
2895         if (GetLayoutDirection() == wxLayout_RightToLeft
) 
2896             *x 
= (GetClientSize().x 
- *x
) - org_x
; 
2903 bool wxWindowGTK::Show( bool show 
) 
2905     if ( !wxWindowBase::Show(show
) ) 
2911     // notice that we may call Hide() before the window is created and this is 
2912     // actually useful to create it hidden initially -- but we can't call 
2913     // Show() before it is created 
2916         wxASSERT_MSG( !show
, "can't show invalid window" ); 
2924             // defer until later 
2928         gtk_widget_show(m_widget
); 
2932         gtk_widget_hide(m_widget
); 
2935     wxShowEvent 
eventShow(GetId(), show
); 
2936     eventShow
.SetEventObject(this); 
2937     HandleWindowEvent(eventShow
); 
2942 void wxWindowGTK::DoEnable( bool enable 
) 
2944     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2946     gtk_widget_set_sensitive( m_widget
, enable 
); 
2947     if (m_wxwindow 
&& (m_wxwindow 
!= m_widget
)) 
2948         gtk_widget_set_sensitive( m_wxwindow
, enable 
); 
2951 int wxWindowGTK::GetCharHeight() const 
2953     wxCHECK_MSG( (m_widget 
!= NULL
), 12, wxT("invalid window") ); 
2955     wxFont font 
= GetFont(); 
2956     wxCHECK_MSG( font
.IsOk(), 12, wxT("invalid font") ); 
2958     PangoContext
* context 
= gtk_widget_get_pango_context(m_widget
); 
2963     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
2964     PangoLayout 
*layout 
= pango_layout_new(context
); 
2965     pango_layout_set_font_description(layout
, desc
); 
2966     pango_layout_set_text(layout
, "H", 1); 
2967     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
2969     PangoRectangle rect
; 
2970     pango_layout_line_get_extents(line
, NULL
, &rect
); 
2972     g_object_unref (layout
); 
2974     return (int) PANGO_PIXELS(rect
.height
); 
2977 int wxWindowGTK::GetCharWidth() const 
2979     wxCHECK_MSG( (m_widget 
!= NULL
), 8, wxT("invalid window") ); 
2981     wxFont font 
= GetFont(); 
2982     wxCHECK_MSG( font
.IsOk(), 8, wxT("invalid font") ); 
2984     PangoContext
* context 
= gtk_widget_get_pango_context(m_widget
); 
2989     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
2990     PangoLayout 
*layout 
= pango_layout_new(context
); 
2991     pango_layout_set_font_description(layout
, desc
); 
2992     pango_layout_set_text(layout
, "g", 1); 
2993     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
2995     PangoRectangle rect
; 
2996     pango_layout_line_get_extents(line
, NULL
, &rect
); 
2998     g_object_unref (layout
); 
3000     return (int) PANGO_PIXELS(rect
.width
); 
3003 void wxWindowGTK::DoGetTextExtent( const wxString
& string
, 
3007                                    int *externalLeading
, 
3008                                    const wxFont 
*theFont 
) const 
3010     wxFont fontToUse 
= theFont 
? *theFont 
: GetFont(); 
3012     wxCHECK_RET( fontToUse
.IsOk(), wxT("invalid font") ); 
3021     PangoContext 
*context 
= NULL
; 
3023         context 
= gtk_widget_get_pango_context( m_widget 
); 
3032     PangoFontDescription 
*desc 
= fontToUse
.GetNativeFontInfo()->description
; 
3033     PangoLayout 
*layout 
= pango_layout_new(context
); 
3034     pango_layout_set_font_description(layout
, desc
); 
3036         const wxCharBuffer data 
= wxGTK_CONV( string 
); 
3038             pango_layout_set_text(layout
, data
, strlen(data
)); 
3041     PangoRectangle rect
; 
3042     pango_layout_get_extents(layout
, NULL
, &rect
); 
3044     if (x
) (*x
) = (wxCoord
) PANGO_PIXELS(rect
.width
); 
3045     if (y
) (*y
) = (wxCoord
) PANGO_PIXELS(rect
.height
); 
3048         PangoLayoutIter 
*iter 
= pango_layout_get_iter(layout
); 
3049         int baseline 
= pango_layout_iter_get_baseline(iter
); 
3050         pango_layout_iter_free(iter
); 
3051         *descent 
= *y 
- PANGO_PIXELS(baseline
); 
3053     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3055     g_object_unref (layout
); 
3058 void wxWindowGTK::GTKDisableFocusOutEvent() 
3060     g_signal_handlers_block_by_func( m_focusWidget
, 
3061                                 (gpointer
) gtk_window_focus_out_callback
, this); 
3064 void wxWindowGTK::GTKEnableFocusOutEvent() 
3066     g_signal_handlers_unblock_by_func( m_focusWidget
, 
3067                                 (gpointer
) gtk_window_focus_out_callback
, this); 
3070 bool wxWindowGTK::GTKHandleFocusIn() 
3072     // Disable default focus handling for custom windows since the default GTK+ 
3073     // handler issues a repaint 
3074     const bool retval 
= m_wxwindow 
? true : false; 
3077     // NB: if there's still unprocessed deferred focus-out event (see 
3078     //     GTKHandleFocusOut() for explanation), we need to process it first so 
3079     //     that the order of focus events -- focus-out first, then focus-in 
3080     //     elsewhere -- is preserved 
3081     if ( gs_deferredFocusOut 
) 
3083         if ( GTKNeedsToFilterSameWindowFocus() && 
3084              gs_deferredFocusOut 
== this ) 
3086             // GTK+ focus changed from this wxWindow back to itself, so don't 
3087             // emit any events at all 
3088             wxLogTrace(TRACE_FOCUS
, 
3089                        "filtered out spurious focus change within %s(%p, %s)", 
3090                        GetClassInfo()->GetClassName(), this, GetLabel()); 
3091             gs_deferredFocusOut 
= NULL
; 
3095         // otherwise we need to send focus-out first 
3096         wxASSERT_MSG ( gs_deferredFocusOut 
!= this, 
3097                        "GTKHandleFocusIn(GTKFocus_Normal) called even though focus changed back to itself - derived class should handle this" ); 
3098         GTKHandleDeferredFocusOut(); 
3102     wxLogTrace(TRACE_FOCUS
, 
3103                "handling focus_in event for %s(%p, %s)", 
3104                GetClassInfo()->GetClassName(), this, GetLabel()); 
3107         gtk_im_context_focus_in(m_imData
->context
); 
3109     gs_currentFocus 
= this; 
3110     gs_pendingFocus 
= NULL
; 
3113     // caret needs to be informed about focus change 
3114     wxCaret 
*caret 
= GetCaret(); 
3117         caret
->OnSetFocus(); 
3119 #endif // wxUSE_CARET 
3121     // Notify the parent keeping track of focus for the kbd navigation 
3122     // purposes that we got it. 
3123     wxChildFocusEvent 
eventChildFocus(static_cast<wxWindow
*>(this)); 
3124     GTKProcessEvent(eventChildFocus
); 
3126     wxFocusEvent 
eventFocus(wxEVT_SET_FOCUS
, GetId()); 
3127     eventFocus
.SetEventObject(this); 
3128     GTKProcessEvent(eventFocus
); 
3133 bool wxWindowGTK::GTKHandleFocusOut() 
3135     // Disable default focus handling for custom windows since the default GTK+ 
3136     // handler issues a repaint 
3137     const bool retval 
= m_wxwindow 
? true : false; 
3140     // NB: If a control is composed of several GtkWidgets and when focus 
3141     //     changes from one of them to another within the same wxWindow, we get 
3142     //     a focus-out event followed by focus-in for another GtkWidget owned 
3143     //     by the same wx control. We don't want to generate two spurious 
3144     //     wxEVT_SET_FOCUS events in this case, so we defer sending wx events 
3145     //     from GTKHandleFocusOut() until we know for sure it's not coming back 
3146     //     (i.e. in GTKHandleFocusIn() or at idle time). 
3147     if ( GTKNeedsToFilterSameWindowFocus() ) 
3149         wxASSERT_MSG( gs_deferredFocusOut 
== NULL
, 
3150                       "deferred focus out event already pending" ); 
3151         wxLogTrace(TRACE_FOCUS
, 
3152                    "deferring focus_out event for %s(%p, %s)", 
3153                    GetClassInfo()->GetClassName(), this, GetLabel()); 
3154         gs_deferredFocusOut 
= this; 
3158     GTKHandleFocusOutNoDeferring(); 
3163 void wxWindowGTK::GTKHandleFocusOutNoDeferring() 
3165     wxLogTrace(TRACE_FOCUS
, 
3166                "handling focus_out event for %s(%p, %s)", 
3167                GetClassInfo()->GetClassName(), this, GetLabel()); 
3170         gtk_im_context_focus_out(m_imData
->context
); 
3172     if ( gs_currentFocus 
!= this ) 
3174         // Something is terribly wrong, gs_currentFocus is out of sync with the 
3175         // real focus. We will reset it to NULL anyway, because after this 
3176         // focus-out event is handled, one of the following with happen: 
3178         // * either focus will go out of the app altogether, in which case 
3179         //   gs_currentFocus _should_ be NULL 
3181         // * or it goes to another control, in which case focus-in event will 
3182         //   follow immediately and it will set gs_currentFocus to the right 
3184         wxLogDebug("window %s(%p, %s) lost focus even though it didn't have it", 
3185                    GetClassInfo()->GetClassName(), this, GetLabel()); 
3187     gs_currentFocus 
= NULL
; 
3190     // caret needs to be informed about focus change 
3191     wxCaret 
*caret 
= GetCaret(); 
3194         caret
->OnKillFocus(); 
3196 #endif // wxUSE_CARET 
3198     wxFocusEvent 
event( wxEVT_KILL_FOCUS
, GetId() ); 
3199     event
.SetEventObject( this ); 
3200     event
.SetWindow( FindFocus() ); 
3201     GTKProcessEvent( event 
); 
3205 void wxWindowGTK::GTKHandleDeferredFocusOut() 
3207     // NB: See GTKHandleFocusOut() for explanation. This function is called 
3208     //     from either GTKHandleFocusIn() or OnInternalIdle() to process 
3210     if ( gs_deferredFocusOut 
) 
3212         wxWindowGTK 
*win 
= gs_deferredFocusOut
; 
3213         gs_deferredFocusOut 
= NULL
; 
3215         wxLogTrace(TRACE_FOCUS
, 
3216                    "processing deferred focus_out event for %s(%p, %s)", 
3217                    win
->GetClassInfo()->GetClassName(), win
, win
->GetLabel()); 
3219         win
->GTKHandleFocusOutNoDeferring(); 
3223 void wxWindowGTK::SetFocus() 
3225     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3227     // Setting "physical" focus is not immediate in GTK+ and while 
3228     // gtk_widget_is_focus ("determines if the widget is the focus widget 
3229     // within its toplevel", i.e. returns true for one widget per TLW, not 
3230     // globally) returns true immediately after grabbing focus, 
3231     // GTK_WIDGET_HAS_FOCUS (which returns true only for the one widget that 
3232     // has focus at the moment) takes effect only after the window is shown 
3233     // (if it was hidden at the moment of the call) or at the next event loop 
3236     // Because we want to FindFocus() call immediately following 
3237     // foo->SetFocus() to return foo, we have to keep track of "pending" focus 
3239     gs_pendingFocus 
= this; 
3241     GtkWidget 
*widget 
= m_wxwindow 
? m_wxwindow 
: m_focusWidget
; 
3243     if ( GTK_IS_CONTAINER(widget
) && 
3244          !gtk_widget_get_can_focus(widget
) ) 
3246         wxLogTrace(TRACE_FOCUS
, 
3247                    wxT("Setting focus to a child of %s(%p, %s)"), 
3248                    GetClassInfo()->GetClassName(), this, GetLabel().c_str()); 
3249         gtk_widget_child_focus(widget
, GTK_DIR_TAB_FORWARD
); 
3253         wxLogTrace(TRACE_FOCUS
, 
3254                    wxT("Setting focus to %s(%p, %s)"), 
3255                    GetClassInfo()->GetClassName(), this, GetLabel().c_str()); 
3256         gtk_widget_grab_focus(widget
); 
3260 void wxWindowGTK::SetCanFocus(bool canFocus
) 
3262     gtk_widget_set_can_focus(m_widget
, canFocus
); 
3264     if ( m_wxwindow 
&& (m_widget 
!= m_wxwindow
) ) 
3266         gtk_widget_set_can_focus(m_wxwindow
, canFocus
); 
3270 bool wxWindowGTK::Reparent( wxWindowBase 
*newParentBase 
) 
3272     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3274     wxWindowGTK 
* const newParent 
= (wxWindowGTK 
*)newParentBase
; 
3276     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3278     if ( !wxWindowBase::Reparent(newParent
) ) 
3281     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3283     // Notice that old m_parent pointer might be non-NULL here but the widget 
3284     // still not have any parent at GTK level if it's a notebook page that had 
3285     // been removed from the notebook so test this at GTK level and not wx one. 
3286     if ( GtkWidget 
*parentGTK 
= gtk_widget_get_parent(m_widget
) ) 
3287         gtk_container_remove(GTK_CONTAINER(parentGTK
), m_widget
); 
3289     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3293         if (gtk_widget_get_visible (newParent
->m_widget
)) 
3295             m_showOnIdle 
= true; 
3296             gtk_widget_hide( m_widget 
); 
3298         /* insert GTK representation */ 
3299         newParent
->AddChildGTK(this); 
3302     SetLayoutDirection(wxLayout_Default
); 
3307 void wxWindowGTK::DoAddChild(wxWindowGTK 
*child
) 
3309     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3310     wxASSERT_MSG( (child 
!= NULL
), wxT("invalid child window") ); 
3315     /* insert GTK representation */ 
3319 void wxWindowGTK::AddChild(wxWindowBase 
*child
) 
3321     wxWindowBase::AddChild(child
); 
3322     m_dirtyTabOrder 
= true; 
3323     wxTheApp
->WakeUpIdle(); 
3326 void wxWindowGTK::RemoveChild(wxWindowBase 
*child
) 
3328     wxWindowBase::RemoveChild(child
); 
3329     m_dirtyTabOrder 
= true; 
3330     wxTheApp
->WakeUpIdle(); 
3334 wxLayoutDirection 
wxWindowGTK::GTKGetLayout(GtkWidget 
*widget
) 
3336     return gtk_widget_get_direction(widget
) == GTK_TEXT_DIR_RTL
 
3337                 ? wxLayout_RightToLeft
 
3338                 : wxLayout_LeftToRight
; 
3342 void wxWindowGTK::GTKSetLayout(GtkWidget 
*widget
, wxLayoutDirection dir
) 
3344     wxASSERT_MSG( dir 
!= wxLayout_Default
, wxT("invalid layout direction") ); 
3346     gtk_widget_set_direction(widget
, 
3347                              dir 
== wxLayout_RightToLeft 
? GTK_TEXT_DIR_RTL
 
3348                                                          : GTK_TEXT_DIR_LTR
); 
3351 wxLayoutDirection 
wxWindowGTK::GetLayoutDirection() const 
3353     return GTKGetLayout(m_widget
); 
3356 void wxWindowGTK::SetLayoutDirection(wxLayoutDirection dir
) 
3358     if ( dir 
== wxLayout_Default 
) 
3360         const wxWindow 
*const parent 
= GetParent(); 
3363             // inherit layout from parent. 
3364             dir 
= parent
->GetLayoutDirection(); 
3366         else // no parent, use global default layout 
3368             dir 
= wxTheApp
->GetLayoutDirection(); 
3372     if ( dir 
== wxLayout_Default 
) 
3375     GTKSetLayout(m_widget
, dir
); 
3377     if (m_wxwindow 
&& (m_wxwindow 
!= m_widget
)) 
3378         GTKSetLayout(m_wxwindow
, dir
); 
3382 wxWindowGTK::AdjustForLayoutDirection(wxCoord x
, 
3383                                       wxCoord 
WXUNUSED(width
), 
3384                                       wxCoord 
WXUNUSED(widthTotal
)) const 
3386     // We now mirror the coordinates of RTL windows in wxPizza 
3390 void wxWindowGTK::DoMoveInTabOrder(wxWindow 
*win
, WindowOrder move
) 
3392     wxWindowBase::DoMoveInTabOrder(win
, move
); 
3393     m_dirtyTabOrder 
= true; 
3394     wxTheApp
->WakeUpIdle(); 
3397 bool wxWindowGTK::DoNavigateIn(int flags
) 
3399     if ( flags 
& wxNavigationKeyEvent::WinChange 
) 
3401         wxFAIL_MSG( wxT("not implemented") ); 
3405     else // navigate inside the container 
3407         wxWindow 
*parent 
= wxGetTopLevelParent((wxWindow 
*)this); 
3408         wxCHECK_MSG( parent
, false, wxT("every window must have a TLW parent") ); 
3410         GtkDirectionType dir
; 
3411         dir 
= flags 
& wxNavigationKeyEvent::IsForward 
? GTK_DIR_TAB_FORWARD
 
3412                                                       : GTK_DIR_TAB_BACKWARD
; 
3415         g_signal_emit_by_name(parent
->m_widget
, "focus", dir
, &rc
); 
3421 bool wxWindowGTK::GTKWidgetNeedsMnemonic() const 
3423     // none needed by default 
3427 void wxWindowGTK::GTKWidgetDoSetMnemonic(GtkWidget
* WXUNUSED(w
)) 
3429     // nothing to do by default since none is needed 
3432 void wxWindowGTK::RealizeTabOrder() 
3436         if ( !m_children
.empty() ) 
3438             // we don't only construct the correct focus chain but also use 
3439             // this opportunity to update the mnemonic widgets for the widgets 
3442             GList 
*chain 
= NULL
; 
3443             wxWindowGTK
* mnemonicWindow 
= NULL
; 
3445             for ( wxWindowList::const_iterator i 
= m_children
.begin(); 
3446                   i 
!= m_children
.end(); 
3449                 wxWindowGTK 
*win 
= *i
; 
3451                 bool focusableFromKeyboard 
= win
->AcceptsFocusFromKeyboard(); 
3453                 if ( mnemonicWindow 
) 
3455                     if ( focusableFromKeyboard 
) 
3457                         // wxComboBox et al. needs to focus on on a different 
3458                         // widget than m_widget, so if the main widget isn't 
3459                         // focusable try the connect widget 
3460                         GtkWidget
* w 
= win
->m_widget
; 
3461                         if ( !gtk_widget_get_can_focus(w
) ) 
3463                             w 
= win
->GetConnectWidget(); 
3464                             if ( !gtk_widget_get_can_focus(w
) ) 
3470                             mnemonicWindow
->GTKWidgetDoSetMnemonic(w
); 
3471                             mnemonicWindow 
= NULL
; 
3475                 else if ( win
->GTKWidgetNeedsMnemonic() ) 
3477                     mnemonicWindow 
= win
; 
3480                 if ( focusableFromKeyboard 
) 
3481                     chain 
= g_list_prepend(chain
, win
->m_widget
); 
3484             chain 
= g_list_reverse(chain
); 
3486             gtk_container_set_focus_chain(GTK_CONTAINER(m_wxwindow
), chain
); 
3491             gtk_container_unset_focus_chain(GTK_CONTAINER(m_wxwindow
)); 
3496 void wxWindowGTK::Raise() 
3498     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3500     if (m_wxwindow 
&& gtk_widget_get_window(m_wxwindow
)) 
3502         gdk_window_raise(gtk_widget_get_window(m_wxwindow
)); 
3504     else if (gtk_widget_get_window(m_widget
)) 
3506         gdk_window_raise(gtk_widget_get_window(m_widget
)); 
3510 void wxWindowGTK::Lower() 
3512     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3514     if (m_wxwindow 
&& gtk_widget_get_window(m_wxwindow
)) 
3516         gdk_window_lower(gtk_widget_get_window(m_wxwindow
)); 
3518     else if (gtk_widget_get_window(m_widget
)) 
3520         gdk_window_lower(gtk_widget_get_window(m_widget
)); 
3524 bool wxWindowGTK::SetCursor( const wxCursor 
&cursor 
) 
3526     if ( !wxWindowBase::SetCursor(cursor
.IsOk() ? cursor 
: *wxSTANDARD_CURSOR
) ) 
3534 void wxWindowGTK::GTKUpdateCursor(bool update_self 
/*=true*/, bool recurse 
/*=true*/) 
3538         wxCursor 
cursor(g_globalCursor
.IsOk() ? g_globalCursor 
: GetCursor()); 
3539         if ( cursor
.IsOk() ) 
3541             wxArrayGdkWindows windowsThis
; 
3542             GdkWindow
* window 
= GTKGetWindow(windowsThis
); 
3544                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3547                 const size_t count 
= windowsThis
.size(); 
3548                 for ( size_t n 
= 0; n 
< count
; n
++ ) 
3550                     GdkWindow 
*win 
= windowsThis
[n
]; 
3551                     // It can be zero if the window has not been realized yet. 
3554                         gdk_window_set_cursor(win
, cursor
.GetCursor()); 
3563         for (wxWindowList::iterator it 
= GetChildren().begin(); it 
!= GetChildren().end(); ++it
) 
3565             (*it
)->GTKUpdateCursor( true ); 
3570 void wxWindowGTK::WarpPointer( int x
, int y 
) 
3572     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3574     ClientToScreen(&x
, &y
); 
3575     GdkDisplay
* display 
= gtk_widget_get_display(m_widget
); 
3576     GdkScreen
* screen 
= gtk_widget_get_screen(m_widget
); 
3578     GdkDeviceManager
* manager 
= gdk_display_get_device_manager(display
); 
3579     gdk_device_warp(gdk_device_manager_get_client_pointer(manager
), screen
, x
, y
); 
3581     XWarpPointer(GDK_DISPLAY_XDISPLAY(display
), 
3583         GDK_WINDOW_XID(gdk_screen_get_root_window(screen
)), 
3588 wxWindowGTK::ScrollDir 
wxWindowGTK::ScrollDirFromRange(GtkRange 
*range
) const 
3590     // find the scrollbar which generated the event 
3591     for ( int dir 
= 0; dir 
< ScrollDir_Max
; dir
++ ) 
3593         if ( range 
== m_scrollBar
[dir
] ) 
3594             return (ScrollDir
)dir
; 
3597     wxFAIL_MSG( wxT("event from unknown scrollbar received") ); 
3599     return ScrollDir_Max
; 
3602 bool wxWindowGTK::DoScrollByUnits(ScrollDir dir
, ScrollUnit unit
, int units
) 
3604     bool changed 
= false; 
3605     GtkRange
* range 
= m_scrollBar
[dir
]; 
3606     if ( range 
&& units 
) 
3608         GtkAdjustment
* adj 
= gtk_range_get_adjustment(range
); 
3609         double inc 
= unit 
== ScrollUnit_Line 
? gtk_adjustment_get_step_increment(adj
) 
3610                                              : gtk_adjustment_get_page_increment(adj
); 
3612         const int posOld 
= wxRound(gtk_adjustment_get_value(adj
)); 
3613         gtk_range_set_value(range
, posOld 
+ units
*inc
); 
3615         changed 
= wxRound(gtk_adjustment_get_value(adj
)) != posOld
; 
3621 bool wxWindowGTK::ScrollLines(int lines
) 
3623     return DoScrollByUnits(ScrollDir_Vert
, ScrollUnit_Line
, lines
); 
3626 bool wxWindowGTK::ScrollPages(int pages
) 
3628     return DoScrollByUnits(ScrollDir_Vert
, ScrollUnit_Page
, pages
); 
3631 void wxWindowGTK::Refresh(bool WXUNUSED(eraseBackground
), 
3636         if (gtk_widget_get_mapped(m_wxwindow
)) 
3638             GdkWindow
* window 
= gtk_widget_get_window(m_wxwindow
); 
3641                 GdkRectangle r 
= { rect
->x
, rect
->y
, rect
->width
, rect
->height 
}; 
3642                 if (GetLayoutDirection() == wxLayout_RightToLeft
) 
3643                     r
.x 
= gdk_window_get_width(window
) - r
.x 
- rect
->width
; 
3644                 gdk_window_invalidate_rect(window
, &r
, true); 
3647                 gdk_window_invalidate_rect(window
, NULL
, true); 
3652         if (gtk_widget_get_mapped(m_widget
)) 
3655                 gtk_widget_queue_draw_area(m_widget
, rect
->x
, rect
->y
, rect
->width
, rect
->height
); 
3657                 gtk_widget_queue_draw(m_widget
); 
3662 void wxWindowGTK::Update() 
3664     if (m_widget 
&& gtk_widget_get_mapped(m_widget
)) 
3666         GdkDisplay
* display 
= gtk_widget_get_display(m_widget
); 
3667         // Flush everything out to the server, and wait for it to finish. 
3668         // This ensures nothing will overwrite the drawing we are about to do. 
3669         gdk_display_sync(display
); 
3671         GdkWindow
* window 
= GTKGetDrawingWindow(); 
3673             window 
= gtk_widget_get_window(m_widget
); 
3674         gdk_window_process_updates(window
, true); 
3676         // Flush again, but no need to wait for it to finish 
3677         gdk_display_flush(display
); 
3681 bool wxWindowGTK::DoIsExposed( int x
, int y 
) const 
3683     return m_updateRegion
.Contains(x
, y
) != wxOutRegion
; 
3686 bool wxWindowGTK::DoIsExposed( int x
, int y
, int w
, int h 
) const 
3688     if (GetLayoutDirection() == wxLayout_RightToLeft
) 
3689         return m_updateRegion
.Contains(x
-w
, y
, w
, h
) != wxOutRegion
; 
3691         return m_updateRegion
.Contains(x
, y
, w
, h
) != wxOutRegion
; 
3694 void wxWindowGTK::GtkSendPaintEvents() 
3698         m_updateRegion
.Clear(); 
3701 #if wxGTK_HAS_COMPOSITING_SUPPORT 
3704     // Clip to paint region in wxClientDC 
3705     m_clipPaintRegion 
= true; 
3707     m_nativeUpdateRegion 
= m_updateRegion
; 
3709     if (GetLayoutDirection() == wxLayout_RightToLeft
) 
3711         // Transform m_updateRegion under RTL 
3712         m_updateRegion
.Clear(); 
3715         gdk_drawable_get_size(gtk_widget_get_window(m_wxwindow
), &width
, NULL
); 
3717         wxRegionIterator 
upd( m_nativeUpdateRegion 
); 
3721             rect
.x 
= upd
.GetX(); 
3722             rect
.y 
= upd
.GetY(); 
3723             rect
.width 
= upd
.GetWidth(); 
3724             rect
.height 
= upd
.GetHeight(); 
3726             rect
.x 
= width 
- rect
.x 
- rect
.width
; 
3727             m_updateRegion
.Union( rect 
); 
3733     switch ( GetBackgroundStyle() ) 
3735         case wxBG_STYLE_TRANSPARENT
: 
3736 #if wxGTK_HAS_COMPOSITING_SUPPORT 
3737             if (IsTransparentBackgroundSupported()) 
3739                 // Set a transparent background, so that overlaying in parent 
3740                 // might indeed let see through where this child did not 
3741                 // explicitly paint. 
3742                 // NB: it works also for top level windows (but this is the 
3743                 // windows manager which then does the compositing job) 
3744                 cr 
= gdk_cairo_create(m_wxwindow
->window
); 
3745                 gdk_cairo_region(cr
, m_nativeUpdateRegion
.GetRegion()); 
3748                 cairo_set_operator(cr
, CAIRO_OPERATOR_CLEAR
); 
3750                 cairo_set_operator(cr
, CAIRO_OPERATOR_OVER
); 
3751                 cairo_surface_flush(cairo_get_target(cr
)); 
3753 #endif // wxGTK_HAS_COMPOSITING_SUPPORT 
3756         case wxBG_STYLE_ERASE
: 
3758                 wxWindowDC 
dc( (wxWindow
*)this ); 
3759                 dc
.SetDeviceClippingRegion( m_updateRegion 
); 
3761                 // Work around gtk-qt <= 0.60 bug whereby the window colour 
3765                             GetOptionInt("gtk.window.force-background-colour") ) 
3767                     dc
.SetBackground(GetBackgroundColour()); 
3771                 wxEraseEvent 
erase_event( GetId(), &dc 
); 
3772                 erase_event
.SetEventObject( this ); 
3774                 if ( HandleWindowEvent(erase_event
) ) 
3776                     // background erased, don't do it again 
3782         case wxBG_STYLE_SYSTEM
: 
3783             if ( GetThemeEnabled() ) 
3785                 // find ancestor from which to steal background 
3786                 wxWindow 
*parent 
= wxGetTopLevelParent((wxWindow 
*)this); 
3788                     parent 
= (wxWindow
*)this; 
3790                 if (gtk_widget_get_mapped(parent
->m_widget
)) 
3792                     wxRegionIterator 
upd( m_nativeUpdateRegion 
); 
3796                         rect
.x 
= upd
.GetX(); 
3797                         rect
.y 
= upd
.GetY(); 
3798                         rect
.width 
= upd
.GetWidth(); 
3799                         rect
.height 
= upd
.GetHeight(); 
3801                         gtk_paint_flat_box(gtk_widget_get_style(parent
->m_widget
), 
3802                                     GTKGetDrawingWindow(), 
3803                                     gtk_widget_get_state(m_wxwindow
), 
3816         case wxBG_STYLE_PAINT
: 
3817             // nothing to do: window will be painted over in EVT_PAINT 
3821             wxFAIL_MSG( "unsupported background style" ); 
3824     wxNcPaintEvent 
nc_paint_event( GetId() ); 
3825     nc_paint_event
.SetEventObject( this ); 
3826     HandleWindowEvent( nc_paint_event 
); 
3828     wxPaintEvent 
paint_event( GetId() ); 
3829     paint_event
.SetEventObject( this ); 
3830     HandleWindowEvent( paint_event 
); 
3832 #if wxGTK_HAS_COMPOSITING_SUPPORT 
3833     if (IsTransparentBackgroundSupported()) 
3834     { // now composite children which need it 
3835         // Overlay all our composite children on top of the painted area 
3836         wxWindowList::compatibility_iterator node
; 
3837         for ( node 
= m_children
.GetFirst(); node 
; node 
= node
->GetNext() ) 
3839             wxWindow 
*compositeChild 
= node
->GetData(); 
3840             if (compositeChild
->GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT
) 
3844                     cr 
= gdk_cairo_create(m_wxwindow
->window
); 
3845                     gdk_cairo_region(cr
, m_nativeUpdateRegion
.GetRegion()); 
3849                 GtkWidget 
*child 
= compositeChild
->m_wxwindow
; 
3850                 GtkAllocation alloc
; 
3851                 gtk_widget_get_allocation(child
, &alloc
); 
3853                 // The source data is the (composited) child 
3854                 gdk_cairo_set_source_window( 
3855                     cr
, gtk_widget_get_window(child
), alloc
.x
, alloc
.y
); 
3863 #endif // wxGTK_HAS_COMPOSITING_SUPPORT 
3865     m_clipPaintRegion 
= false; 
3867     m_updateRegion
.Clear(); 
3868     m_nativeUpdateRegion
.Clear(); 
3871 void wxWindowGTK::SetDoubleBuffered( bool on 
) 
3873     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3876         gtk_widget_set_double_buffered( m_wxwindow
, on 
); 
3879 bool wxWindowGTK::IsDoubleBuffered() const 
3881     return gtk_widget_get_double_buffered( m_wxwindow 
); 
3884 void wxWindowGTK::ClearBackground() 
3886     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3890 void wxWindowGTK::DoSetToolTip( wxToolTip 
*tip 
) 
3892     if (m_tooltip 
!= tip
) 
3894         wxWindowBase::DoSetToolTip(tip
); 
3897             m_tooltip
->GTKSetWindow(static_cast<wxWindow
*>(this)); 
3899             GTKApplyToolTip(NULL
); 
3903 void wxWindowGTK::GTKApplyToolTip(const char* tip
) 
3905     wxToolTip::GTKApply(GetConnectWidget(), tip
); 
3907 #endif // wxUSE_TOOLTIPS 
3909 bool wxWindowGTK::SetBackgroundColour( const wxColour 
&colour 
) 
3911     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3913     if (!wxWindowBase::SetBackgroundColour(colour
)) 
3918         // We need the pixel value e.g. for background clearing. 
3919         m_backgroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
3922     // apply style change (forceStyle=true so that new style is applied 
3923     // even if the bg colour changed from valid to wxNullColour) 
3924     GTKApplyWidgetStyle(true); 
3929 bool wxWindowGTK::SetForegroundColour( const wxColour 
&colour 
) 
3931     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3933     if (!wxWindowBase::SetForegroundColour(colour
)) 
3940         // We need the pixel value e.g. for background clearing. 
3941         m_foregroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
3944     // apply style change (forceStyle=true so that new style is applied 
3945     // even if the bg colour changed from valid to wxNullColour): 
3946     GTKApplyWidgetStyle(true); 
3951 PangoContext 
*wxWindowGTK::GTKGetPangoDefaultContext() 
3953     return gtk_widget_get_pango_context( m_widget 
); 
3956 GtkRcStyle 
*wxWindowGTK::GTKCreateWidgetStyle(bool forceStyle
) 
3958     // do we need to apply any changes at all? 
3961          !m_foregroundColour
.IsOk() && !m_backgroundColour
.IsOk() ) 
3966     GtkRcStyle 
*style 
= gtk_rc_style_new(); 
3968     if ( m_font
.IsOk() ) 
3971             pango_font_description_copy( m_font
.GetNativeFontInfo()->description 
); 
3974     int flagsNormal 
= 0, 
3977         flagsInsensitive 
= 0; 
3979     if ( m_foregroundColour
.IsOk() ) 
3981         const GdkColor 
*fg 
= m_foregroundColour
.GetColor(); 
3983         style
->fg
[GTK_STATE_NORMAL
] = 
3984         style
->text
[GTK_STATE_NORMAL
] = *fg
; 
3985         flagsNormal 
|= GTK_RC_FG 
| GTK_RC_TEXT
; 
3987         style
->fg
[GTK_STATE_PRELIGHT
] = 
3988         style
->text
[GTK_STATE_PRELIGHT
] = *fg
; 
3989         flagsPrelight 
|= GTK_RC_FG 
| GTK_RC_TEXT
; 
3991         style
->fg
[GTK_STATE_ACTIVE
] = 
3992         style
->text
[GTK_STATE_ACTIVE
] = *fg
; 
3993         flagsActive 
|= GTK_RC_FG 
| GTK_RC_TEXT
; 
3996     if ( m_backgroundColour
.IsOk() ) 
3998         const GdkColor 
*bg 
= m_backgroundColour
.GetColor(); 
4000         style
->bg
[GTK_STATE_NORMAL
] = 
4001         style
->base
[GTK_STATE_NORMAL
] = *bg
; 
4002         flagsNormal 
|= GTK_RC_BG 
| GTK_RC_BASE
; 
4004         style
->bg
[GTK_STATE_PRELIGHT
] = 
4005         style
->base
[GTK_STATE_PRELIGHT
] = *bg
; 
4006         flagsPrelight 
|= GTK_RC_BG 
| GTK_RC_BASE
; 
4008         style
->bg
[GTK_STATE_ACTIVE
] = 
4009         style
->base
[GTK_STATE_ACTIVE
] = *bg
; 
4010         flagsActive 
|= GTK_RC_BG 
| GTK_RC_BASE
; 
4012         style
->bg
[GTK_STATE_INSENSITIVE
] = 
4013         style
->base
[GTK_STATE_INSENSITIVE
] = *bg
; 
4014         flagsInsensitive 
|= GTK_RC_BG 
| GTK_RC_BASE
; 
4017     style
->color_flags
[GTK_STATE_NORMAL
] = (GtkRcFlags
)flagsNormal
; 
4018     style
->color_flags
[GTK_STATE_PRELIGHT
] = (GtkRcFlags
)flagsPrelight
; 
4019     style
->color_flags
[GTK_STATE_ACTIVE
] = (GtkRcFlags
)flagsActive
; 
4020     style
->color_flags
[GTK_STATE_INSENSITIVE
] = (GtkRcFlags
)flagsInsensitive
; 
4025 void wxWindowGTK::GTKApplyWidgetStyle(bool forceStyle
) 
4027     GtkRcStyle 
*style 
= GTKCreateWidgetStyle(forceStyle
); 
4030         DoApplyWidgetStyle(style
); 
4031         g_object_unref(style
); 
4034     // Style change may affect GTK+'s size calculation: 
4035     InvalidateBestSize(); 
4038 void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
4042         // block the signal temporarily to avoid sending 
4043         // wxSysColourChangedEvents when we change the colours ourselves 
4044         bool unblock 
= false; 
4048             g_signal_handlers_block_by_func( 
4049                 m_wxwindow
, (void *)gtk_window_style_set_callback
, this); 
4052         gtk_widget_modify_style(m_wxwindow
, style
); 
4056             g_signal_handlers_unblock_by_func( 
4057                 m_wxwindow
, (void *)gtk_window_style_set_callback
, this); 
4062         gtk_widget_modify_style(m_widget
, style
); 
4066 bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style
) 
4068     if (!wxWindowBase::SetBackgroundStyle(style
)) 
4074         window 
= GTKGetDrawingWindow(); 
4078         GtkWidget 
* const w 
= GetConnectWidget(); 
4079         window 
= w 
? gtk_widget_get_window(w
) : NULL
; 
4082     bool wantNoBackPixmap 
= style 
== wxBG_STYLE_PAINT 
|| style 
== wxBG_STYLE_TRANSPARENT
; 
4084     if ( wantNoBackPixmap 
) 
4088             // Make sure GDK/X11 doesn't refresh the window 
4090             gdk_window_set_back_pixmap( window
, None
, False 
); 
4091             m_needsStyleChange 
= false; 
4093         else // window not realized yet 
4095             // Do when window is realized 
4096             m_needsStyleChange 
= true; 
4099         // Don't apply widget style, or we get a grey background 
4103         // apply style change (forceStyle=true so that new style is applied 
4104         // even if the bg colour changed from valid to wxNullColour): 
4105         GTKApplyWidgetStyle(true); 
4111 bool wxWindowGTK::IsTransparentBackgroundSupported(wxString
* reason
) const 
4113 #if wxGTK_HAS_COMPOSITING_SUPPORT 
4114     if (gtk_check_version(wxGTK_VERSION_REQUIRED_FOR_COMPOSITING
) != NULL
) 
4118             *reason 
= _("GTK+ installed on this machine is too old to " 
4119                         "support screen compositing, please install " 
4120                         "GTK+ 2.12 or later."); 
4126     // NB: We don't check here if the particular kind of widget supports 
4127     // transparency, we check only if it would be possible for a generic window 
4129     wxCHECK_MSG ( m_widget
, false, "Window must be created first" ); 
4131     if (!gdk_screen_is_composited(gtk_widget_get_screen(m_widget
))) 
4135             *reason 
= _("Compositing not supported by this system, " 
4136                         "please enable it in your Window Manager."); 
4146         *reason 
= _("This program was compiled with a too old version of GTK+, " 
4147                     "please rebuild with GTK+ 2.12 or newer."); 
4149 #endif // wxGTK_HAS_COMPOSITING_SUPPORT/!wxGTK_HAS_COMPOSITING_SUPPORT 
4154 // ---------------------------------------------------------------------------- 
4155 // Pop-up menu stuff 
4156 // ---------------------------------------------------------------------------- 
4158 #if wxUSE_MENUS_NATIVE 
4162 void wxPopupMenuPositionCallback( GtkMenu 
*menu
, 
4164                                   gboolean 
* WXUNUSED(whatever
), 
4165                                   gpointer user_data 
) 
4167     // ensure that the menu appears entirely on screen 
4169     gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
); 
4171     wxSize sizeScreen 
= wxGetDisplaySize(); 
4172     wxPoint 
*pos 
= (wxPoint
*)user_data
; 
4174     gint xmax 
= sizeScreen
.x 
- req
.width
, 
4175          ymax 
= sizeScreen
.y 
- req
.height
; 
4177     *x 
= pos
->x 
< xmax 
? pos
->x 
: xmax
; 
4178     *y 
= pos
->y 
< ymax 
? pos
->y 
: ymax
; 
4182 bool wxWindowGTK::DoPopupMenu( wxMenu 
*menu
, int x
, int y 
) 
4184     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
4186     // For compatibility with other ports, pretend that the window showing the 
4187     // menu has focus while the menu is shown. This is needed because the popup 
4188     // menu actually steals the focus from the window it's associated it in 
4189     // wxGTK unlike, say, wxMSW. 
4190     wxWindowGTK
* const oldPendingFocus 
= gs_pendingFocus
; 
4191     gs_pendingFocus 
= this; 
4192     wxON_BLOCK_EXIT_SET( gs_pendingFocus
, oldPendingFocus 
); 
4198     GtkMenuPositionFunc posfunc
; 
4199     if ( x 
== -1 && y 
== -1 ) 
4201         // use GTK's default positioning algorithm 
4207         pos 
= ClientToScreen(wxPoint(x
, y
)); 
4209         posfunc 
= wxPopupMenuPositionCallback
; 
4212     menu
->m_popupShown 
= true; 
4214                   GTK_MENU(menu
->m_menu
), 
4215                   NULL
,           // parent menu shell 
4216                   NULL
,           // parent menu item 
4217                   posfunc
,                      // function to position it 
4218                   userdata
,                     // client data 
4219                   0,                            // button used to activate it 
4220                   gtk_get_current_event_time() 
4223     while (menu
->m_popupShown
) 
4225         gtk_main_iteration(); 
4231 #endif // wxUSE_MENUS_NATIVE 
4233 #if wxUSE_DRAG_AND_DROP 
4235 void wxWindowGTK::SetDropTarget( wxDropTarget 
*dropTarget 
) 
4237     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4239     GtkWidget 
*dnd_widget 
= GetConnectWidget(); 
4241     if (m_dropTarget
) m_dropTarget
->GtkUnregisterWidget( dnd_widget 
); 
4243     if (m_dropTarget
) delete m_dropTarget
; 
4244     m_dropTarget 
= dropTarget
; 
4246     if (m_dropTarget
) m_dropTarget
->GtkRegisterWidget( dnd_widget 
); 
4249 #endif // wxUSE_DRAG_AND_DROP 
4251 GtkWidget
* wxWindowGTK::GetConnectWidget() 
4253     GtkWidget 
*connect_widget 
= m_widget
; 
4254     if (m_wxwindow
) connect_widget 
= m_wxwindow
; 
4256     return connect_widget
; 
4259 bool wxWindowGTK::GTKIsOwnWindow(GdkWindow 
*window
) const 
4261     wxArrayGdkWindows windowsThis
; 
4262     GdkWindow 
* const winThis 
= GTKGetWindow(windowsThis
); 
4264     return winThis 
? window 
== winThis
 
4265                    : windowsThis
.Index(window
) != wxNOT_FOUND
; 
4268 GdkWindow 
*wxWindowGTK::GTKGetWindow(wxArrayGdkWindows
& WXUNUSED(windows
)) const 
4270     return m_wxwindow 
? GTKGetDrawingWindow() : gtk_widget_get_window(m_widget
); 
4273 bool wxWindowGTK::SetFont( const wxFont 
&font 
) 
4275     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
4277     if (!wxWindowBase::SetFont(font
)) 
4280     // apply style change (forceStyle=true so that new style is applied 
4281     // even if the font changed from valid to wxNullFont): 
4282     GTKApplyWidgetStyle(true); 
4287 void wxWindowGTK::DoCaptureMouse() 
4289     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4291     GdkWindow 
*window 
= NULL
; 
4293         window 
= GTKGetDrawingWindow(); 
4295         window 
= gtk_widget_get_window(GetConnectWidget()); 
4297     wxCHECK_RET( window
, wxT("CaptureMouse() failed") ); 
4299     const wxCursor
* cursor 
= &m_cursor
; 
4300     if (!cursor
->IsOk()) 
4301         cursor 
= wxSTANDARD_CURSOR
; 
4303     gdk_pointer_grab( window
, FALSE
, 
4305                          (GDK_BUTTON_PRESS_MASK 
| 
4306                           GDK_BUTTON_RELEASE_MASK 
| 
4307                           GDK_POINTER_MOTION_HINT_MASK 
| 
4308                           GDK_POINTER_MOTION_MASK
), 
4310                       cursor
->GetCursor(), 
4311                       (guint32
)GDK_CURRENT_TIME 
); 
4312     g_captureWindow 
= this; 
4313     g_captureWindowHasMouse 
= true; 
4316 void wxWindowGTK::DoReleaseMouse() 
4318     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4320     wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") ); 
4322     g_captureWindow 
= NULL
; 
4324     GdkWindow 
*window 
= NULL
; 
4326         window 
= GTKGetDrawingWindow(); 
4328         window 
= gtk_widget_get_window(GetConnectWidget()); 
4333     gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME 
); 
4336 void wxWindowGTK::GTKReleaseMouseAndNotify() 
4339     wxMouseCaptureLostEvent 
evt(GetId()); 
4340     evt
.SetEventObject( this ); 
4341     HandleWindowEvent( evt 
); 
4345 wxWindow 
*wxWindowBase::GetCapture() 
4347     return (wxWindow 
*)g_captureWindow
; 
4350 bool wxWindowGTK::IsRetained() const 
4355 void wxWindowGTK::SetScrollbar(int orient
, 
4359                                bool WXUNUSED(update
)) 
4361     const int dir 
= ScrollDirFromOrient(orient
); 
4362     GtkRange
* const sb 
= m_scrollBar
[dir
]; 
4363     wxCHECK_RET( sb
, wxT("this window is not scrollable") ); 
4367         // GtkRange requires upper > lower 
4372     g_signal_handlers_block_by_func( 
4373         sb
, (void*)gtk_scrollbar_value_changed
, this); 
4375     gtk_range_set_increments(sb
, 1, thumbVisible
); 
4376     gtk_adjustment_set_page_size(gtk_range_get_adjustment(sb
), thumbVisible
); 
4377     gtk_range_set_range(sb
, 0, range
); 
4378     gtk_range_set_value(sb
, pos
); 
4379     m_scrollPos
[dir
] = gtk_range_get_value(sb
); 
4381     g_signal_handlers_unblock_by_func( 
4382         sb
, (void*)gtk_scrollbar_value_changed
, this); 
4385 void wxWindowGTK::SetScrollPos(int orient
, int pos
, bool WXUNUSED(refresh
)) 
4387     const int dir 
= ScrollDirFromOrient(orient
); 
4388     GtkRange 
* const sb 
= m_scrollBar
[dir
]; 
4389     wxCHECK_RET( sb
, wxT("this window is not scrollable") ); 
4391     // This check is more than an optimization. Without it, the slider 
4392     //   will not move smoothly while tracking when using wxScrollHelper. 
4393     if (GetScrollPos(orient
) != pos
) 
4395         g_signal_handlers_block_by_func( 
4396             sb
, (void*)gtk_scrollbar_value_changed
, this); 
4398         gtk_range_set_value(sb
, pos
); 
4399         m_scrollPos
[dir
] = gtk_range_get_value(sb
); 
4401         g_signal_handlers_unblock_by_func( 
4402             sb
, (void*)gtk_scrollbar_value_changed
, this); 
4406 int wxWindowGTK::GetScrollThumb(int orient
) const 
4408     GtkRange 
* const sb 
= m_scrollBar
[ScrollDirFromOrient(orient
)]; 
4409     wxCHECK_MSG( sb
, 0, wxT("this window is not scrollable") ); 
4411     return wxRound(gtk_adjustment_get_page_size(gtk_range_get_adjustment(sb
))); 
4414 int wxWindowGTK::GetScrollPos( int orient 
) const 
4416     GtkRange 
* const sb 
= m_scrollBar
[ScrollDirFromOrient(orient
)]; 
4417     wxCHECK_MSG( sb
, 0, wxT("this window is not scrollable") ); 
4419     return wxRound(gtk_range_get_value(sb
)); 
4422 int wxWindowGTK::GetScrollRange( int orient 
) const 
4424     GtkRange 
* const sb 
= m_scrollBar
[ScrollDirFromOrient(orient
)]; 
4425     wxCHECK_MSG( sb
, 0, wxT("this window is not scrollable") ); 
4427     return wxRound(gtk_adjustment_get_upper(gtk_range_get_adjustment(sb
))); 
4430 // Determine if increment is the same as +/-x, allowing for some small 
4431 //   difference due to possible inexactness in floating point arithmetic 
4432 static inline bool IsScrollIncrement(double increment
, double x
) 
4434     wxASSERT(increment 
> 0); 
4435     const double tolerance 
= 1.0 / 1024; 
4436     return fabs(increment 
- fabs(x
)) < tolerance
; 
4439 wxEventType 
wxWindowGTK::GTKGetScrollEventType(GtkRange
* range
) 
4441     wxASSERT(range 
== m_scrollBar
[0] || range 
== m_scrollBar
[1]); 
4443     const int barIndex 
= range 
== m_scrollBar
[1]; 
4445     const double value 
= gtk_range_get_value(range
); 
4447     // save previous position 
4448     const double oldPos 
= m_scrollPos
[barIndex
]; 
4449     // update current position 
4450     m_scrollPos
[barIndex
] = value
; 
4451     // If event should be ignored, or integral position has not changed 
4452     if (!m_hasVMT 
|| g_blockEventsOnDrag 
|| wxRound(value
) == wxRound(oldPos
)) 
4457     wxEventType eventType 
= wxEVT_SCROLL_THUMBTRACK
; 
4460         // Difference from last change event 
4461         const double diff 
= value 
- oldPos
; 
4462         const bool isDown 
= diff 
> 0; 
4464         GtkAdjustment
* adj 
= gtk_range_get_adjustment(range
); 
4465         if (IsScrollIncrement(gtk_adjustment_get_step_increment(adj
), diff
)) 
4467             eventType 
= isDown 
? wxEVT_SCROLL_LINEDOWN 
: wxEVT_SCROLL_LINEUP
; 
4469         else if (IsScrollIncrement(gtk_adjustment_get_page_increment(adj
), diff
)) 
4471             eventType 
= isDown 
? wxEVT_SCROLL_PAGEDOWN 
: wxEVT_SCROLL_PAGEUP
; 
4473         else if (m_mouseButtonDown
) 
4475             // Assume track event 
4476             m_isScrolling 
= true; 
4482 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) ) 
4484     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4486     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4488     // No scrolling requested. 
4489     if ((dx 
== 0) && (dy 
== 0)) return; 
4491     m_clipPaintRegion 
= true; 
4493     WX_PIZZA(m_wxwindow
)->scroll(dx
, dy
); 
4495     m_clipPaintRegion 
= false; 
4498     bool restoreCaret 
= (GetCaret() != NULL 
&& GetCaret()->IsVisible()); 
4501         wxRect 
caretRect(GetCaret()->GetPosition(), GetCaret()->GetSize()); 
4503             caretRect
.width 
+= dx
; 
4506             caretRect
.x 
+= dx
; caretRect
.width 
-= dx
; 
4509             caretRect
.height 
+= dy
; 
4512             caretRect
.y 
+= dy
; caretRect
.height 
-= dy
; 
4515         RefreshRect(caretRect
); 
4517 #endif // wxUSE_CARET 
4520 void wxWindowGTK::GTKScrolledWindowSetBorder(GtkWidget
* w
, int wxstyle
) 
4522     //RN: Note that static controls usually have no border on gtk, so maybe 
4523     //it makes sense to treat that as simply no border at the wx level 
4525     if (!(wxstyle 
& wxNO_BORDER
) && !(wxstyle 
& wxBORDER_STATIC
)) 
4527         GtkShadowType gtkstyle
; 
4529         if(wxstyle 
& wxBORDER_RAISED
) 
4530             gtkstyle 
= GTK_SHADOW_OUT
; 
4531         else if ((wxstyle 
& wxBORDER_SUNKEN
) || (wxstyle 
& wxBORDER_THEME
)) 
4532             gtkstyle 
= GTK_SHADOW_IN
; 
4535         else if (wxstyle 
& wxBORDER_DOUBLE
) 
4536             gtkstyle 
= GTK_SHADOW_ETCHED_IN
; 
4539             gtkstyle 
= GTK_SHADOW_IN
; 
4541         gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(w
), 
4546 // Find the wxWindow at the current mouse position, also returning the mouse 
4548 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
4550     pt 
= wxGetMousePosition(); 
4551     wxWindow
* found 
= wxFindWindowAtPoint(pt
); 
4555 // Get the current mouse position. 
4556 wxPoint 
wxGetMousePosition() 
4558     wxWindow
* tlw 
= NULL
; 
4559     if (!wxTopLevelWindows
.empty()) 
4560         tlw 
= wxTopLevelWindows
.front(); 
4561     GdkDisplay
* display
; 
4562     if (tlw 
&& tlw
->m_widget
) 
4563         display 
= gtk_widget_get_display(tlw
->m_widget
); 
4565         display 
= gdk_display_get_default(); 
4568     gdk_display_get_pointer(display
, NULL
, &x
, &y
, NULL
); 
4569     return wxPoint(x
, y
); 
4572 GdkWindow
* wxWindowGTK::GTKGetDrawingWindow() const 
4574     GdkWindow
* window 
= NULL
; 
4576         window 
= gtk_widget_get_window(m_wxwindow
); 
4580 // ---------------------------------------------------------------------------- 
4582 // ---------------------------------------------------------------------------- 
4587 // this is called if we attempted to freeze unrealized widget when it finally 
4588 // is realized (and so can be frozen): 
4589 static void wx_frozen_widget_realize(GtkWidget
* w
, wxWindowGTK
* win
) 
4591     wxASSERT( w 
&& gtk_widget_get_has_window(w
) ); 
4592     wxASSERT( gtk_widget_get_realized(w
) ); 
4594     g_signal_handlers_disconnect_by_func
 
4597         (void*)wx_frozen_widget_realize
, 
4602     if (w 
== win
->m_wxwindow
) 
4603         window 
= win
->GTKGetDrawingWindow(); 
4605         window 
= gtk_widget_get_window(w
); 
4606     gdk_window_freeze_updates(window
); 
4611 void wxWindowGTK::GTKFreezeWidget(GtkWidget 
*w
) 
4613     if ( !w 
|| !gtk_widget_get_has_window(w
) ) 
4614         return; // window-less widget, cannot be frozen 
4616     GdkWindow
* window 
= gtk_widget_get_window(w
); 
4619         // we can't thaw unrealized widgets because they don't have GdkWindow, 
4620         // so set it up to be done immediately after realization: 
4621         g_signal_connect_after
 
4625             G_CALLBACK(wx_frozen_widget_realize
), 
4631     if (w 
== m_wxwindow
) 
4632         window 
= GTKGetDrawingWindow(); 
4633     gdk_window_freeze_updates(window
); 
4636 void wxWindowGTK::GTKThawWidget(GtkWidget 
*w
) 
4638     if ( !w 
|| !gtk_widget_get_has_window(w
) ) 
4639         return; // window-less widget, cannot be frozen 
4641     GdkWindow
* window 
= gtk_widget_get_window(w
); 
4644         // the widget wasn't realized yet, no need to thaw 
4645         g_signal_handlers_disconnect_by_func
 
4648             (void*)wx_frozen_widget_realize
, 
4654     if (w 
== m_wxwindow
) 
4655         window 
= GTKGetDrawingWindow(); 
4656     gdk_window_thaw_updates(window
); 
4659 void wxWindowGTK::DoFreeze() 
4661     GTKFreezeWidget(m_widget
); 
4662     if ( m_wxwindow 
&& m_widget 
!= m_wxwindow 
) 
4663         GTKFreezeWidget(m_wxwindow
); 
4666 void wxWindowGTK::DoThaw() 
4668     GTKThawWidget(m_widget
); 
4669     if ( m_wxwindow 
&& m_widget 
!= m_wxwindow 
) 
4670         GTKThawWidget(m_wxwindow
);