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/sysopt.h" 
  38 #include "wx/gtk/private.h" 
  39 #include "wx/gtk/private/win_gtk.h" 
  40 #include <gdk/gdkkeysyms.h> 
  43 #if !GTK_CHECK_VERSION(2,10,0) 
  44     // GTK+ can reliably detect Meta key state only since 2.10 when 
  45     // GDK_META_MASK was introduced -- there wasn't any way to detect it 
  46     // in older versions. wxGTK used GDK_MOD2_MASK for this purpose, but 
  47     // GDK_MOD2_MASK is documented as: 
  49     //     the fifth modifier key (it depends on the modifier mapping of the X 
  50     //     server which key is interpreted as this modifier) 
  52     // In other words, it isn't guaranteed to map to Meta. This is a real 
  53     // problem: it is common to map NumLock to it (in fact, it's an exception 
  54     // if the X server _doesn't_ use it for NumLock).  So the old code caused 
  55     // wxKeyEvent::MetaDown() to always return true as long as NumLock was on 
  56     // on many systems, which broke all applications using 
  57     // wxKeyEvent::GetModifiers() to check modifiers state (see e.g.  here: 
  58     // http://tinyurl.com/56lsk2). 
  60     // Because of this, it's better to not detect Meta key state at all than 
  61     // to detect it incorrectly. Hence the following #define, which causes 
  62     // m_metaDown to be always set to false. 
  63     #define GDK_META_MASK 0 
  66 //----------------------------------------------------------------------------- 
  67 // documentation on internals 
  68 //----------------------------------------------------------------------------- 
  71    I have been asked several times about writing some documentation about 
  72    the GTK port of wxWidgets, especially its internal structures. Obviously, 
  73    you cannot understand wxGTK without knowing a little about the GTK, but 
  74    some more information about what the wxWindow, which is the base class 
  75    for all other window classes, does seems required as well. 
  79    What does wxWindow do? It contains the common interface for the following 
  80    jobs of its descendants: 
  82    1) Define the rudimentary behaviour common to all window classes, such as 
  83    resizing, intercepting user input (so as to make it possible to use these 
  84    events for special purposes in a derived class), window names etc. 
  86    2) Provide the possibility to contain and manage children, if the derived 
  87    class is allowed to contain children, which holds true for those window 
  88    classes which do not display a native GTK widget. To name them, these 
  89    classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame- 
  90    work classes are a special case and are handled a bit differently from 
  91    the rest. The same holds true for the wxNotebook class. 
  93    3) Provide the possibility to draw into a client area of a window. This, 
  94    too, only holds true for classes that do not display a native GTK widget 
  97    4) Provide the entire mechanism for scrolling widgets. This actual inter- 
  98    face for this is usually in wxScrolledWindow, but the GTK implementation 
 101    5) A multitude of helper or extra methods for special purposes, such as 
 102    Drag'n'Drop, managing validators etc. 
 104    6) Display a border (sunken, raised, simple or none). 
 106    Normally one might expect, that one wxWidgets window would always correspond 
 107    to one GTK widget. Under GTK, there is no such all-round widget that has all 
 108    the functionality. Moreover, the GTK defines a client area as a different 
 109    widget from the actual widget you are handling. Last but not least some 
 110    special classes (e.g. wxFrame) handle different categories of widgets and 
 111    still have the possibility to draw something in the client area. 
 112    It was therefore required to write a special purpose GTK widget, that would 
 113    represent a client area in the sense of wxWidgets capable to do the jobs 
 114    2), 3) and 4). I have written this class and it resides in win_gtk.c of 
 117    All windows must have a widget, with which they interact with other under- 
 118    lying GTK widgets. It is this widget, e.g. that has to be resized etc and 
 119    the wxWindow class has a member variable called m_widget which holds a 
 120    pointer to this widget. When the window class represents a GTK native widget, 
 121    this is (in most cases) the only GTK widget the class manages. E.g. the 
 122    wxStaticText class handles only a GtkLabel widget a pointer to which you 
 123    can find in m_widget (defined in wxWindow) 
 125    When the class has a client area for drawing into and for containing children 
 126    it has to handle the client area widget (of the type wxPizza, defined in 
 127    win_gtk.cpp), but there could be any number of widgets, handled by a class. 
 128    The common rule for all windows is only, that the widget that interacts with 
 129    the rest of GTK must be referenced in m_widget and all other widgets must be 
 130    children of this widget on the GTK level. The top-most widget, which also 
 131    represents the client area, must be in the m_wxwindow field and must be of 
 134    As I said, the window classes that display a GTK native widget only have 
 135    one widget, so in the case of e.g. the wxButton class m_widget holds a 
 136    pointer to a GtkButton widget. But windows with client areas (for drawing 
 137    and children) have a m_widget field that is a pointer to a GtkScrolled- 
 138    Window and a m_wxwindow field that is pointer to a wxPizza and this 
 139    one is (in the GTK sense) a child of the GtkScrolledWindow. 
 141    If the m_wxwindow field is set, then all input to this widget is inter- 
 142    cepted and sent to the wxWidgets class. If not, all input to the widget 
 143    that gets pointed to by m_widget gets intercepted and sent to the class. 
 147    The design of scrolling in wxWidgets is markedly different from that offered 
 148    by the GTK itself and therefore we cannot simply take it as it is. In GTK, 
 149    clicking on a scrollbar belonging to scrolled window will inevitably move 
 150    the window. In wxWidgets, the scrollbar will only emit an event, send this 
 151    to (normally) a wxScrolledWindow and that class will call ScrollWindow() 
 152    which actually moves the window and its sub-windows. Note that wxPizza 
 153    memorizes how much it has been scrolled but that wxWidgets forgets this 
 154    so that the two coordinates systems have to be kept in synch. This is done 
 155    in various places using the pizza->m_scroll_x and pizza->m_scroll_y values. 
 159    Singularly the most broken code in GTK is the code that is supposed to 
 160    inform subwindows (child windows) about new positions. Very often, duplicate 
 161    events are sent without changes in size or position, equally often no 
 162    events are sent at all (All this is due to a bug in the GtkContainer code 
 163    which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores 
 164    GTK's own system and it simply waits for size events for toplevel windows 
 165    and then iterates down the respective size events to all window. This has 
 166    the disadvantage that windows might get size events before the GTK widget 
 167    actually has the reported size. This doesn't normally pose any problem, but 
 168    the OpenGL drawing routines rely on correct behaviour. Therefore, I have 
 169    added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas, 
 170    i.e. the wxGLCanvas will emit a size event, when (and not before) the X11 
 171    window that is used for OpenGL output really has that size (as reported by 
 176    If someone at some point of time feels the immense desire to have a look at, 
 177    change or attempt to optimise the Refresh() logic, this person will need an 
 178    intimate understanding of what "draw" and "expose" events are and what 
 179    they are used for, in particular when used in connection with GTK's 
 180    own windowless widgets. Beware. 
 184    Cursors, too, have been a constant source of pleasure. The main difficulty 
 185    is that a GdkWindow inherits a cursor if the programmer sets a new cursor 
 186    for the parent. To prevent this from doing too much harm, SetCursor calls 
 187    GTKUpdateCursor, which will recursively re-set the cursors of all child windows. 
 188    Also don't forget that cursors (like much else) are connected to GdkWindows, 
 189    not GtkWidgets and that the "window" field of a GtkWidget might very well 
 190    point to the GdkWindow of the parent widget (-> "window-less widget") and 
 191    that the two obviously have very different meanings. 
 194 //----------------------------------------------------------------------------- 
 196 //----------------------------------------------------------------------------- 
 198 // Don't allow event propagation during drag 
 199 bool g_blockEventsOnDrag
; 
 200 // Don't allow mouse event propagation during scroll 
 201 bool g_blockEventsOnScroll
; 
 202 extern wxCursor   g_globalCursor
; 
 204 // mouse capture state: the window which has it and if the mouse is currently 
 206 static wxWindowGTK  
*g_captureWindow 
= NULL
; 
 207 static bool g_captureWindowHasMouse 
= false; 
 209 // The window that currently has focus: 
 210 static wxWindowGTK 
*gs_currentFocus 
= NULL
; 
 211 // The window that is scheduled to get focus in the next event loop iteration 
 212 // or NULL if there's no pending focus change: 
 213 static wxWindowGTK 
*gs_pendingFocus 
= NULL
; 
 215 // the window that has deferred focus-out event pending, if any (see 
 216 // GTKAddDeferredFocusOut() for details) 
 217 static wxWindowGTK 
*gs_deferredFocusOut 
= NULL
; 
 219 // global variables because GTK+ DnD want to have the 
 220 // mouse event that caused it 
 221 GdkEvent    
*g_lastMouseEvent 
= NULL
; 
 222 int          g_lastButtonNumber 
= 0; 
 224 //----------------------------------------------------------------------------- 
 226 //----------------------------------------------------------------------------- 
 228 // the trace mask used for the focus debugging messages 
 229 #define TRACE_FOCUS wxT("focus") 
 231 //----------------------------------------------------------------------------- 
 232 // missing gdk functions 
 233 //----------------------------------------------------------------------------- 
 236 gdk_window_warp_pointer (GdkWindow      
*window
, 
 241     window 
= gdk_get_default_root_window(); 
 243   if (!GDK_WINDOW_DESTROYED(window
)) 
 245       XWarpPointer (GDK_WINDOW_XDISPLAY(window
), 
 246                     None
,              /* not source window -> move from anywhere */ 
 247                     GDK_WINDOW_XID(window
),  /* dest window */ 
 248                     0, 0, 0, 0,        /* not source window -> move from anywhere */ 
 254 //----------------------------------------------------------------------------- 
 255 // "size_request" of m_widget 
 256 //----------------------------------------------------------------------------- 
 260 wxgtk_window_size_request_callback(GtkWidget 
* WXUNUSED(widget
), 
 261                                    GtkRequisition 
*requisition
, 
 265     win
->GetSize( &w
, &h 
); 
 271     requisition
->height 
= h
; 
 272     requisition
->width 
= w
; 
 276 //----------------------------------------------------------------------------- 
 277 // "expose_event" of m_wxwindow 
 278 //----------------------------------------------------------------------------- 
 282 gtk_window_expose_callback( GtkWidget
*, 
 283                             GdkEventExpose 
*gdk_event
, 
 286     if (gdk_event
->window 
== win
->GTKGetDrawingWindow()) 
 288         win
->GetUpdateRegion() = wxRegion( gdk_event
->region 
); 
 289         win
->GtkSendPaintEvents(); 
 291     // Let parent window draw window-less widgets 
 296 #ifndef __WXUNIVERSAL__ 
 297 //----------------------------------------------------------------------------- 
 298 // "expose_event" from m_wxwindow->parent, for drawing border 
 299 //----------------------------------------------------------------------------- 
 303 expose_event_border(GtkWidget
* widget
, GdkEventExpose
* gdk_event
, wxWindow
* win
) 
 305     if (gdk_event
->window 
!= gtk_widget_get_parent_window(win
->m_wxwindow
)) 
 311     const GtkAllocation
& alloc 
= win
->m_wxwindow
->allocation
; 
 312     const int x 
= alloc
.x
; 
 313     const int y 
= alloc
.y
; 
 314     const int w 
= alloc
.width
; 
 315     const int h 
= alloc
.height
; 
 317     if (w 
<= 0 || h 
<= 0) 
 320     if (win
->HasFlag(wxBORDER_SIMPLE
)) 
 322         gdk_draw_rectangle(gdk_event
->window
, 
 323             widget
->style
->black_gc
, false, x
, y
, w 
- 1, h 
- 1); 
 327         GtkShadowType shadow 
= GTK_SHADOW_IN
; 
 328         if (win
->HasFlag(wxBORDER_RAISED
)) 
 329             shadow 
= GTK_SHADOW_OUT
; 
 331         // Style detail to use 
 333         if (win
->m_widget 
== win
->m_wxwindow
) 
 334             // for non-scrollable wxWindows 
 337             // for scrollable ones 
 341            win
->m_wxwindow
->style
, gdk_event
->window
, GTK_STATE_NORMAL
, 
 342            shadow
, NULL
, wxGTKPrivate::GetEntryWidget(), detail
, x
, y
, w
, h
); 
 348 //----------------------------------------------------------------------------- 
 349 // "parent_set" from m_wxwindow 
 350 //----------------------------------------------------------------------------- 
 354 parent_set(GtkWidget
* widget
, GtkObject
* old_parent
, wxWindow
* win
) 
 358         g_signal_handlers_disconnect_by_func( 
 359             old_parent
, (void*)expose_event_border
, win
); 
 363         g_signal_connect_after(widget
->parent
, "expose_event", 
 364             G_CALLBACK(expose_event_border
), win
); 
 368 #endif // !__WXUNIVERSAL__ 
 370 //----------------------------------------------------------------------------- 
 371 // "key_press_event" from any window 
 372 //----------------------------------------------------------------------------- 
 374 // These are used when transforming Ctrl-alpha to ascii values 1-26 
 375 inline bool wxIsLowerChar(int code
) 
 377     return (code 
>= 'a' && code 
<= 'z' ); 
 380 inline bool wxIsUpperChar(int code
) 
 382     return (code 
>= 'A' && code 
<= 'Z' ); 
 386 // set WXTRACE to this to see the key event codes on the console 
 387 #define TRACE_KEYS  wxT("keyevent") 
 389 // translates an X key symbol to WXK_XXX value 
 391 // if isChar is true it means that the value returned will be used for EVT_CHAR 
 392 // event and then we choose the logical WXK_XXX, i.e. '/' for GDK_KP_Divide, 
 393 // for example, while if it is false it means that the value is going to be 
 394 // used for KEY_DOWN/UP events and then we translate GDK_KP_Divide to 
 396 static long wxTranslateKeySymToWXKey(KeySym keysym
, bool isChar
) 
 402         // Shift, Control and Alt don't generate the CHAR events at all 
 405             key_code 
= isChar 
? 0 : WXK_SHIFT
; 
 409             key_code 
= isChar 
? 0 : WXK_CONTROL
; 
 417             key_code 
= isChar 
? 0 : WXK_ALT
; 
 420         // neither do the toggle modifies 
 421         case GDK_Scroll_Lock
: 
 422             key_code 
= isChar 
? 0 : WXK_SCROLL
; 
 426             key_code 
= isChar 
? 0 : WXK_CAPITAL
; 
 430             key_code 
= isChar 
? 0 : WXK_NUMLOCK
; 
 434         // various other special keys 
 447         case GDK_ISO_Left_Tab
: 
 454             key_code 
= WXK_RETURN
; 
 458             key_code 
= WXK_CLEAR
; 
 462             key_code 
= WXK_PAUSE
; 
 466             key_code 
= WXK_SELECT
; 
 470             key_code 
= WXK_PRINT
; 
 474             key_code 
= WXK_EXECUTE
; 
 478             key_code 
= WXK_ESCAPE
; 
 481         // cursor and other extended keyboard keys 
 483             key_code 
= WXK_DELETE
; 
 499             key_code 
= WXK_RIGHT
; 
 506         case GDK_Prior
:     // == GDK_Page_Up 
 507             key_code 
= WXK_PAGEUP
; 
 510         case GDK_Next
:      // == GDK_Page_Down 
 511             key_code 
= WXK_PAGEDOWN
; 
 523             key_code 
= WXK_INSERT
; 
 538             key_code 
= (isChar 
? '0' : int(WXK_NUMPAD0
)) + keysym 
- GDK_KP_0
; 
 542             key_code 
= isChar 
? ' ' : int(WXK_NUMPAD_SPACE
); 
 546             key_code 
= isChar 
? WXK_TAB 
: WXK_NUMPAD_TAB
; 
 550             key_code 
= isChar 
? WXK_RETURN 
: WXK_NUMPAD_ENTER
; 
 554             key_code 
= isChar 
? WXK_F1 
: WXK_NUMPAD_F1
; 
 558             key_code 
= isChar 
? WXK_F2 
: WXK_NUMPAD_F2
; 
 562             key_code 
= isChar 
? WXK_F3 
: WXK_NUMPAD_F3
; 
 566             key_code 
= isChar 
? WXK_F4 
: WXK_NUMPAD_F4
; 
 570             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_HOME
; 
 574             key_code 
= isChar 
? WXK_LEFT 
: WXK_NUMPAD_LEFT
; 
 578             key_code 
= isChar 
? WXK_UP 
: WXK_NUMPAD_UP
; 
 582             key_code 
= isChar 
? WXK_RIGHT 
: WXK_NUMPAD_RIGHT
; 
 586             key_code 
= isChar 
? WXK_DOWN 
: WXK_NUMPAD_DOWN
; 
 589         case GDK_KP_Prior
: // == GDK_KP_Page_Up 
 590             key_code 
= isChar 
? WXK_PAGEUP 
: WXK_NUMPAD_PAGEUP
; 
 593         case GDK_KP_Next
: // == GDK_KP_Page_Down 
 594             key_code 
= isChar 
? WXK_PAGEDOWN 
: WXK_NUMPAD_PAGEDOWN
; 
 598             key_code 
= isChar 
? WXK_END 
: WXK_NUMPAD_END
; 
 602             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_BEGIN
; 
 606             key_code 
= isChar 
? WXK_INSERT 
: WXK_NUMPAD_INSERT
; 
 610             key_code 
= isChar 
? WXK_DELETE 
: WXK_NUMPAD_DELETE
; 
 614             key_code 
= isChar 
? '=' : int(WXK_NUMPAD_EQUAL
); 
 617         case GDK_KP_Multiply
: 
 618             key_code 
= isChar 
? '*' : int(WXK_NUMPAD_MULTIPLY
); 
 622             key_code 
= isChar 
? '+' : int(WXK_NUMPAD_ADD
); 
 625         case GDK_KP_Separator
: 
 626             // FIXME: what is this? 
 627             key_code 
= isChar 
? '.' : int(WXK_NUMPAD_SEPARATOR
); 
 630         case GDK_KP_Subtract
: 
 631             key_code 
= isChar 
? '-' : int(WXK_NUMPAD_SUBTRACT
); 
 635             key_code 
= isChar 
? '.' : int(WXK_NUMPAD_DECIMAL
); 
 639             key_code 
= isChar 
? '/' : int(WXK_NUMPAD_DIVIDE
); 
 656             key_code 
= WXK_F1 
+ keysym 
- GDK_F1
; 
 666 static inline bool wxIsAsciiKeysym(KeySym ks
) 
 671 static void wxFillOtherKeyEventFields(wxKeyEvent
& event
, 
 673                                       GdkEventKey 
*gdk_event
) 
 677     GdkModifierType state
; 
 678     if (gdk_event
->window
) 
 679         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
 681     event
.SetTimestamp( gdk_event
->time 
); 
 682     event
.SetId(win
->GetId()); 
 684     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
) != 0; 
 685     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
) != 0; 
 686     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
) != 0; 
 687     event
.m_metaDown 
= (gdk_event
->state 
& GDK_META_MASK
) != 0; 
 689     // Normally we take the state of modifiers directly from the low level GDK 
 690     // event but unfortunately GDK uses a different convention from MSW for the 
 691     // key events corresponding to the modifier keys themselves: in it, when 
 692     // e.g. Shift key is pressed, GDK_SHIFT_MASK is not set while it is set 
 693     // when Shift is released. Under MSW the situation is exactly reversed and 
 694     // the modifier corresponding to the key is set when it is pressed and 
 695     // unset when it is released. To ensure consistent behaviour between 
 696     // platforms (and because it seems to make slightly more sense, although 
 697     // arguably both behaviours are reasonable) we follow MSW here. 
 699     // Final notice: we set the flags to the desired value instead of just 
 700     // inverting them because they are not set correctly (i.e. in the same way 
 701     // as for the real events generated by the user) for wxUIActionSimulator- 
 702     // produced events and it seems better to keep that class code the same 
 703     // among all platforms and fix the discrepancy here instead of adding 
 704     // wxGTK-specific code to wxUIActionSimulator. 
 705     const bool isPress 
= gdk_event
->type 
== GDK_KEY_PRESS
; 
 706     switch ( gdk_event
->keyval 
) 
 710             event
.m_shiftDown 
= isPress
; 
 715             event
.m_controlDown 
= isPress
; 
 720             event
.m_altDown 
= isPress
; 
 727             event
.m_metaDown 
= isPress
; 
 731     event
.m_rawCode 
= (wxUint32
) gdk_event
->keyval
; 
 732     event
.m_rawFlags 
= gdk_event
->hardware_keycode
; 
 734     wxGetMousePosition( &x
, &y 
); 
 735     win
->ScreenToClient( &x
, &y 
); 
 738     event
.SetEventObject( win 
); 
 743 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
, 
 745                            GdkEventKey 
*gdk_event
) 
 747     // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string 
 748     //     but only event->keyval which is quite useless to us, so remember 
 749     //     the last character from GDK_KEY_PRESS and reuse it as last resort 
 751     // NB: should be MT-safe as we're always called from the main thread only 
 756     } s_lastKeyPress 
= { 0, 0 }; 
 758     KeySym keysym 
= gdk_event
->keyval
; 
 760     wxLogTrace(TRACE_KEYS
, wxT("Key %s event: keysym = %ld"), 
 761                event
.GetEventType() == wxEVT_KEY_UP 
? wxT("release") 
 765     long key_code 
= wxTranslateKeySymToWXKey(keysym
, false /* !isChar */); 
 769         // do we have the translation or is it a plain ASCII character? 
 770         if ( (gdk_event
->length 
== 1) || wxIsAsciiKeysym(keysym
) ) 
 772             // we should use keysym if it is ASCII as X does some translations 
 773             // like "I pressed while Control is down" => "Ctrl-I" == "TAB" 
 774             // which we don't want here (but which we do use for OnChar()) 
 775             if ( !wxIsAsciiKeysym(keysym
) ) 
 777                 keysym 
= (KeySym
)gdk_event
->string
[0]; 
 780             // we want to always get the same key code when the same key is 
 781             // pressed regardless of the state of the modifiers, i.e. on a 
 782             // standard US keyboard pressing '5' or '%' ('5' key with 
 783             // Shift) should result in the same key code in OnKeyDown(): 
 784             // '5' (although OnChar() will get either '5' or '%'). 
 786             // to do it we first translate keysym to keycode (== scan code) 
 787             // and then back but always using the lower register 
 788             Display 
*dpy 
= (Display 
*)wxGetDisplay(); 
 789             KeyCode keycode 
= XKeysymToKeycode(dpy
, keysym
); 
 791             wxLogTrace(TRACE_KEYS
, wxT("\t-> keycode %d"), keycode
); 
 793             KeySym keysymNormalized 
= XKeycodeToKeysym(dpy
, keycode
, 0); 
 795             // use the normalized, i.e. lower register, keysym if we've 
 797             key_code 
= keysymNormalized 
? keysymNormalized 
: keysym
; 
 799             // as explained above, we want to have lower register key codes 
 800             // normally but for the letter keys we want to have the upper ones 
 802             // NB: don't use XConvertCase() here, we want to do it for letters 
 804             key_code 
= toupper(key_code
); 
 806         else // non ASCII key, what to do? 
 808             // by default, ignore it 
 811             // but if we have cached information from the last KEY_PRESS 
 812             if ( gdk_event
->type 
== GDK_KEY_RELEASE 
) 
 815                 if ( keysym 
== s_lastKeyPress
.keysym 
) 
 817                     key_code 
= s_lastKeyPress
.keycode
; 
 822         if ( gdk_event
->type 
== GDK_KEY_PRESS 
) 
 824             // remember it to be reused for KEY_UP event later 
 825             s_lastKeyPress
.keysym 
= keysym
; 
 826             s_lastKeyPress
.keycode 
= key_code
; 
 830     wxLogTrace(TRACE_KEYS
, wxT("\t-> wxKeyCode %ld"), key_code
); 
 832     // sending unknown key events doesn't really make sense 
 836     event
.m_keyCode 
= key_code
; 
 839     event
.m_uniChar 
= gdk_keyval_to_unicode(key_code 
? key_code 
: keysym
); 
 840     if ( !event
.m_uniChar 
&& event
.m_keyCode 
<= WXK_DELETE 
) 
 842         // Set Unicode key code to the ASCII equivalent for compatibility. E.g. 
 843         // let RETURN generate the key event with both key and Unicode key 
 845         event
.m_uniChar 
= event
.m_keyCode
; 
 847 #endif // wxUSE_UNICODE 
 849     // now fill all the other fields 
 850     wxFillOtherKeyEventFields(event
, win
, gdk_event
); 
 858     GtkIMContext 
*context
; 
 859     GdkEventKey  
*lastKeyEvent
; 
 863         context 
= gtk_im_multicontext_new(); 
 868         g_object_unref (context
); 
 875 // Send wxEVT_CHAR_HOOK event to the parent of the window and if it wasn't 
 876 // processed, send wxEVT_CHAR to the window itself. Return true if either of 
 879 SendCharHookAndCharEvents(const wxKeyEvent
& event
, wxWindow 
*win
) 
 881     // wxEVT_CHAR_HOOK must be sent to the top level parent window to allow it 
 882     // to handle key events in all of its children. 
 883     wxWindow 
* const parent 
= wxGetTopLevelParent(win
); 
 886         // We need to make a copy of the event object because it is 
 887         // modified while it's handled, notably its WasProcessed() flag 
 888         // is set after it had been processed once. 
 889         wxKeyEvent 
eventCharHook(event
); 
 890         eventCharHook
.SetEventType(wxEVT_CHAR_HOOK
); 
 891         if ( parent
->HandleWindowEvent(eventCharHook
) ) 
 895     // As above, make a copy of the event first. 
 896     wxKeyEvent 
eventChar(event
); 
 897     eventChar
.SetEventType(wxEVT_CHAR
); 
 898     return win
->HandleWindowEvent(eventChar
); 
 901 } // anonymous namespace 
 905 gtk_window_key_press_callback( GtkWidget 
*WXUNUSED(widget
), 
 906                                GdkEventKey 
*gdk_event
, 
 911     if (g_blockEventsOnDrag
) 
 914     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
 916     bool return_after_IM 
= false; 
 918     if( wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
 920         // Emit KEY_DOWN event 
 921         ret 
= win
->HandleWindowEvent( event 
); 
 925         // Return after IM processing as we cannot do 
 926         // anything with it anyhow. 
 927         return_after_IM 
= true; 
 930     if (!ret 
&& win
->m_imData
) 
 932         win
->m_imData
->lastKeyEvent 
= gdk_event
; 
 934         // We should let GTK+ IM filter key event first. According to GTK+ 2.0 API 
 935         // docs, if IM filter returns true, no further processing should be done. 
 936         // we should send the key_down event anyway. 
 937         bool intercepted_by_IM 
= gtk_im_context_filter_keypress(win
->m_imData
->context
, gdk_event
); 
 938         win
->m_imData
->lastKeyEvent 
= NULL
; 
 939         if (intercepted_by_IM
) 
 941             wxLogTrace(TRACE_KEYS
, wxT("Key event intercepted by IM")); 
 952         wxWindowGTK 
*ancestor 
= win
; 
 955             int command 
= ancestor
->GetAcceleratorTable()->GetCommand( event 
); 
 958                 wxCommandEvent 
menu_event( wxEVT_COMMAND_MENU_SELECTED
, command 
); 
 959                 ret 
= ancestor
->HandleWindowEvent( menu_event 
); 
 963                     // if the accelerator wasn't handled as menu event, try 
 964                     // it as button click (for compatibility with other 
 966                     wxCommandEvent 
button_event( wxEVT_COMMAND_BUTTON_CLICKED
, command 
); 
 967                     ret 
= ancestor
->HandleWindowEvent( button_event 
); 
 972             if (ancestor
->IsTopLevel()) 
 974             ancestor 
= ancestor
->GetParent(); 
 977 #endif // wxUSE_ACCEL 
 979     // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x 
 980     // will only be sent if it is not in an accelerator table. 
 984         KeySym keysym 
= gdk_event
->keyval
; 
 985         // Find key code for EVT_CHAR and EVT_CHAR_HOOK events 
 986         key_code 
= wxTranslateKeySymToWXKey(keysym
, true /* isChar */); 
 989             if ( wxIsAsciiKeysym(keysym
) ) 
 992                 key_code 
= (unsigned char)keysym
; 
 994             // gdk_event->string is actually deprecated 
 995             else if ( gdk_event
->length 
== 1 ) 
 997                 key_code 
= (unsigned char)gdk_event
->string
[0]; 
1003             wxLogTrace(TRACE_KEYS
, wxT("Char event: %ld"), key_code
); 
1005             event
.m_keyCode 
= key_code
; 
1007             // To conform to the docs we need to translate Ctrl-alpha 
1008             // characters to values in the range 1-26. 
1009             if ( event
.ControlDown() && 
1010                  ( wxIsLowerChar(key_code
) || wxIsUpperChar(key_code
) )) 
1012                 if ( wxIsLowerChar(key_code
) ) 
1013                     event
.m_keyCode 
= key_code 
- 'a' + 1; 
1014                 if ( wxIsUpperChar(key_code
) ) 
1015                     event
.m_keyCode 
= key_code 
- 'A' + 1; 
1017                 event
.m_uniChar 
= event
.m_keyCode
; 
1021             ret 
= SendCharHookAndCharEvents(event
, win
); 
1031 gtk_wxwindow_commit_cb (GtkIMContext 
* WXUNUSED(context
), 
1035     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
1037     // take modifiers, cursor position, timestamp etc. from the last 
1038     // key_press_event that was fed into Input Method: 
1039     if (window
->m_imData
->lastKeyEvent
) 
1041         wxFillOtherKeyEventFields(event
, 
1042                                   window
, window
->m_imData
->lastKeyEvent
); 
1046         event
.SetEventObject( window 
); 
1049     const wxString 
data(wxGTK_CONV_BACK_SYS(str
)); 
1053     for( wxString::const_iterator pstr 
= data
.begin(); pstr 
!= data
.end(); ++pstr 
) 
1056         event
.m_uniChar 
= *pstr
; 
1057         // Backward compatible for ISO-8859-1 
1058         event
.m_keyCode 
= *pstr 
< 256 ? event
.m_uniChar 
: 0; 
1059         wxLogTrace(TRACE_KEYS
, wxT("IM sent character '%c'"), event
.m_uniChar
); 
1061         event
.m_keyCode 
= (char)*pstr
; 
1062 #endif  // wxUSE_UNICODE 
1064         // To conform to the docs we need to translate Ctrl-alpha 
1065         // characters to values in the range 1-26. 
1066         if ( event
.ControlDown() && 
1067              ( wxIsLowerChar(*pstr
) || wxIsUpperChar(*pstr
) )) 
1069             if ( wxIsLowerChar(*pstr
) ) 
1070                 event
.m_keyCode 
= *pstr 
- 'a' + 1; 
1071             if ( wxIsUpperChar(*pstr
) ) 
1072                 event
.m_keyCode 
= *pstr 
- 'A' + 1; 
1074             event
.m_keyCode 
= *pstr 
- 'a' + 1; 
1076             event
.m_uniChar 
= event
.m_keyCode
; 
1080         SendCharHookAndCharEvents(event
, window
); 
1086 //----------------------------------------------------------------------------- 
1087 // "key_release_event" from any window 
1088 //----------------------------------------------------------------------------- 
1092 gtk_window_key_release_callback( GtkWidget 
* WXUNUSED(widget
), 
1093                                  GdkEventKey 
*gdk_event
, 
1099     if (g_blockEventsOnDrag
) 
1102     wxKeyEvent 
event( wxEVT_KEY_UP 
); 
1103     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1105         // unknown key pressed, ignore (the event would be useless anyhow) 
1109     return win
->GTKProcessEvent(event
); 
1113 // ============================================================================ 
1115 // ============================================================================ 
1117 // ---------------------------------------------------------------------------- 
1118 // mouse event processing helpers 
1119 // ---------------------------------------------------------------------------- 
1121 // init wxMouseEvent with the info from GdkEventXXX struct 
1122 template<typename T
> void InitMouseEvent(wxWindowGTK 
*win
, 
1123                                          wxMouseEvent
& event
, 
1126     event
.SetTimestamp( gdk_event
->time 
); 
1127     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
) != 0; 
1128     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
) != 0; 
1129     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
) != 0; 
1130     event
.m_metaDown 
= (gdk_event
->state 
& GDK_META_MASK
) != 0; 
1131     event
.m_leftDown 
= (gdk_event
->state 
& GDK_BUTTON1_MASK
) != 0; 
1132     event
.m_middleDown 
= (gdk_event
->state 
& GDK_BUTTON2_MASK
) != 0; 
1133     event
.m_rightDown 
= (gdk_event
->state 
& GDK_BUTTON3_MASK
) != 0; 
1134     event
.m_aux1Down 
= (gdk_event
->state 
& GDK_BUTTON4_MASK
) != 0; 
1135     event
.m_aux2Down 
= (gdk_event
->state 
& GDK_BUTTON5_MASK
) != 0; 
1137     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1138     event
.m_x 
= (wxCoord
)gdk_event
->x 
- pt
.x
; 
1139     event
.m_y 
= (wxCoord
)gdk_event
->y 
- pt
.y
; 
1141     if ((win
->m_wxwindow
) && (win
->GetLayoutDirection() == wxLayout_RightToLeft
)) 
1143         // origin in the upper right corner 
1144         int window_width 
= win
->m_wxwindow
->allocation
.width
; 
1145         event
.m_x 
= window_width 
- event
.m_x
; 
1148     event
.SetEventObject( win 
); 
1149     event
.SetId( win
->GetId() ); 
1150     event
.SetTimestamp( gdk_event
->time 
); 
1153 static void AdjustEventButtonState(wxMouseEvent
& event
) 
1155     // GDK reports the old state of the button for a button press event, but 
1156     // for compatibility with MSW and common sense we want m_leftDown be TRUE 
1157     // for a LEFT_DOWN event, not FALSE, so we will invert 
1158     // left/right/middleDown for the corresponding click events 
1160     if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) || 
1161         (event
.GetEventType() == wxEVT_LEFT_DCLICK
) || 
1162         (event
.GetEventType() == wxEVT_LEFT_UP
)) 
1164         event
.m_leftDown 
= !event
.m_leftDown
; 
1168     if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) || 
1169         (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) || 
1170         (event
.GetEventType() == wxEVT_MIDDLE_UP
)) 
1172         event
.m_middleDown 
= !event
.m_middleDown
; 
1176     if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) || 
1177         (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) || 
1178         (event
.GetEventType() == wxEVT_RIGHT_UP
)) 
1180         event
.m_rightDown 
= !event
.m_rightDown
; 
1185 // find the window to send the mouse event too 
1187 wxWindowGTK 
*FindWindowForMouseEvent(wxWindowGTK 
*win
, wxCoord
& x
, wxCoord
& y
) 
1192     if (win
->m_wxwindow
) 
1194         wxPizza
* pizza 
= WX_PIZZA(win
->m_wxwindow
); 
1195         xx 
+= pizza
->m_scroll_x
; 
1196         yy 
+= pizza
->m_scroll_y
; 
1199     wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
1202         wxWindowGTK 
*child 
= node
->GetData(); 
1204         node 
= node
->GetNext(); 
1205         if (!child
->IsShown()) 
1208         if (child
->GTKIsTransparentForMouse()) 
1210             // wxStaticBox is transparent in the box itself 
1211             int xx1 
= child
->m_x
; 
1212             int yy1 
= child
->m_y
; 
1213             int xx2 
= child
->m_x 
+ child
->m_width
; 
1214             int yy2 
= child
->m_y 
+ child
->m_height
; 
1217             if (((xx 
>= xx1
) && (xx 
<= xx1
+10) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1219                 ((xx 
>= xx2
-10) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1221                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy1
+10)) || 
1223                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy2
-1) && (yy 
<= yy2
))) 
1234             if ((child
->m_wxwindow 
== NULL
) && 
1235                 (child
->m_x 
<= xx
) && 
1236                 (child
->m_y 
<= yy
) && 
1237                 (child
->m_x
+child
->m_width  
>= xx
) && 
1238                 (child
->m_y
+child
->m_height 
>= yy
)) 
1251 // ---------------------------------------------------------------------------- 
1252 // common event handlers helpers 
1253 // ---------------------------------------------------------------------------- 
1255 bool wxWindowGTK::GTKProcessEvent(wxEvent
& event
) const 
1257     // nothing special at this level 
1258     return HandleWindowEvent(event
); 
1261 bool wxWindowGTK::GTKShouldIgnoreEvent() const 
1263     return !m_hasVMT 
|| g_blockEventsOnDrag
; 
1266 int wxWindowGTK::GTKCallbackCommonPrologue(GdkEventAny 
*event
) const 
1270     if (g_blockEventsOnDrag
) 
1272     if (g_blockEventsOnScroll
) 
1275     if (!GTKIsOwnWindow(event
->window
)) 
1281 // overloads for all GDK event types we use here: we need to have this as 
1282 // GdkEventXXX can't be implicitly cast to GdkEventAny even if it, in fact, 
1283 // derives from it in the sense that the structs have the same layout 
1284 #define wxDEFINE_COMMON_PROLOGUE_OVERLOAD(T)                                  \ 
1285     static int wxGtkCallbackCommonPrologue(T *event, wxWindowGTK *win)        \ 
1287         return win->GTKCallbackCommonPrologue((GdkEventAny *)event);          \ 
1290 wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventButton
) 
1291 wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventMotion
) 
1292 wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventCrossing
) 
1294 #undef wxDEFINE_COMMON_PROLOGUE_OVERLOAD 
1296 #define wxCOMMON_CALLBACK_PROLOGUE(event, win)                                \ 
1297     const int rc = wxGtkCallbackCommonPrologue(event, win);                   \ 
1301 // all event handlers must have C linkage as they're called from GTK+ C code 
1305 //----------------------------------------------------------------------------- 
1306 // "button_press_event" 
1307 //----------------------------------------------------------------------------- 
1310 gtk_window_button_press_callback( GtkWidget 
*widget
, 
1311                                   GdkEventButton 
*gdk_event
, 
1314     wxCOMMON_CALLBACK_PROLOGUE(gdk_event
, win
); 
1316     g_lastButtonNumber 
= gdk_event
->button
; 
1318     // GDK sends surplus button down events 
1319     // before a double click event. We 
1320     // need to filter these out. 
1321     if ((gdk_event
->type 
== GDK_BUTTON_PRESS
) && (win
->m_wxwindow
)) 
1323         GdkEvent 
*peek_event 
= gdk_event_peek(); 
1326             if ((peek_event
->type 
== GDK_2BUTTON_PRESS
) || 
1327                 (peek_event
->type 
== GDK_3BUTTON_PRESS
)) 
1329                 gdk_event_free( peek_event 
); 
1334                 gdk_event_free( peek_event 
); 
1339     wxEventType event_type 
= wxEVT_NULL
; 
1341     if ( gdk_event
->type 
== GDK_2BUTTON_PRESS 
&& 
1342             gdk_event
->button 
>= 1 && gdk_event
->button 
<= 3 ) 
1344         // Reset GDK internal timestamp variables in order to disable GDK 
1345         // triple click events. GDK will then next time believe no button has 
1346         // been clicked just before, and send a normal button click event. 
1347         GdkDisplay
* display 
= gtk_widget_get_display (widget
); 
1348         display
->button_click_time
[1] = 0; 
1349         display
->button_click_time
[0] = 0; 
1352     if (gdk_event
->button 
== 1) 
1354         // note that GDK generates triple click events which are not supported 
1355         // by wxWidgets but still have to be passed to the app as otherwise 
1356         // clicks would simply go missing 
1357         switch (gdk_event
->type
) 
1359             // we shouldn't get triple clicks at all for GTK2 because we 
1360             // suppress them artificially using the code above but we still 
1361             // should map them to something for GTK1 and not just ignore them 
1362             // as this would lose clicks 
1363             case GDK_3BUTTON_PRESS
:     // we could also map this to DCLICK... 
1364             case GDK_BUTTON_PRESS
: 
1365                 event_type 
= wxEVT_LEFT_DOWN
; 
1368             case GDK_2BUTTON_PRESS
: 
1369                 event_type 
= wxEVT_LEFT_DCLICK
; 
1373                 // just to silence gcc warnings 
1377     else if (gdk_event
->button 
== 2) 
1379         switch (gdk_event
->type
) 
1381             case GDK_3BUTTON_PRESS
: 
1382             case GDK_BUTTON_PRESS
: 
1383                 event_type 
= wxEVT_MIDDLE_DOWN
; 
1386             case GDK_2BUTTON_PRESS
: 
1387                 event_type 
= wxEVT_MIDDLE_DCLICK
; 
1394     else if (gdk_event
->button 
== 3) 
1396         switch (gdk_event
->type
) 
1398             case GDK_3BUTTON_PRESS
: 
1399             case GDK_BUTTON_PRESS
: 
1400                 event_type 
= wxEVT_RIGHT_DOWN
; 
1403             case GDK_2BUTTON_PRESS
: 
1404                 event_type 
= wxEVT_RIGHT_DCLICK
; 
1412     if ( event_type 
== wxEVT_NULL 
) 
1414         // unknown mouse button or click type 
1418     g_lastMouseEvent 
= (GdkEvent
*) gdk_event
; 
1420     wxMouseEvent 
event( event_type 
); 
1421     InitMouseEvent( win
, event
, gdk_event 
); 
1423     AdjustEventButtonState(event
); 
1425     // find the correct window to send the event to: it may be a different one 
1426     // from the one which got it at GTK+ level because some controls don't have 
1427     // their own X window and thus cannot get any events. 
1428     if ( !g_captureWindow 
) 
1429         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1431     // reset the event object and id in case win changed. 
1432     event
.SetEventObject( win 
); 
1433     event
.SetId( win
->GetId() ); 
1435     bool ret 
= win
->GTKProcessEvent( event 
); 
1436     g_lastMouseEvent 
= NULL
; 
1440     if ((event_type 
== wxEVT_LEFT_DOWN
) && !win
->IsOfStandardClass() && 
1441         (gs_currentFocus 
!= win
) /* && win->IsFocusable() */) 
1446     if (event_type 
== wxEVT_RIGHT_DOWN
) 
1448         // generate a "context menu" event: this is similar to right mouse 
1449         // click under many GUIs except that it is generated differently 
1450         // (right up under MSW, ctrl-click under Mac, right down here) and 
1452         // (a) it's a command event and so is propagated to the parent 
1453         // (b) under some ports it can be generated from kbd too 
1454         // (c) it uses screen coords (because of (a)) 
1455         wxContextMenuEvent 
evtCtx( 
1458             win
->ClientToScreen(event
.GetPosition())); 
1459         evtCtx
.SetEventObject(win
); 
1460         return win
->GTKProcessEvent(evtCtx
); 
1466 //----------------------------------------------------------------------------- 
1467 // "button_release_event" 
1468 //----------------------------------------------------------------------------- 
1471 gtk_window_button_release_callback( GtkWidget 
*WXUNUSED(widget
), 
1472                                     GdkEventButton 
*gdk_event
, 
1475     wxCOMMON_CALLBACK_PROLOGUE(gdk_event
, win
); 
1477     g_lastButtonNumber 
= 0; 
1479     wxEventType event_type 
= wxEVT_NULL
; 
1481     switch (gdk_event
->button
) 
1484             event_type 
= wxEVT_LEFT_UP
; 
1488             event_type 
= wxEVT_MIDDLE_UP
; 
1492             event_type 
= wxEVT_RIGHT_UP
; 
1496             // unknown button, don't process 
1500     g_lastMouseEvent 
= (GdkEvent
*) gdk_event
; 
1502     wxMouseEvent 
event( event_type 
); 
1503     InitMouseEvent( win
, event
, gdk_event 
); 
1505     AdjustEventButtonState(event
); 
1507     if ( !g_captureWindow 
) 
1508         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1510     // reset the event object and id in case win changed. 
1511     event
.SetEventObject( win 
); 
1512     event
.SetId( win
->GetId() ); 
1514     bool ret 
= win
->GTKProcessEvent(event
); 
1516     g_lastMouseEvent 
= NULL
; 
1521 //----------------------------------------------------------------------------- 
1522 // "motion_notify_event" 
1523 //----------------------------------------------------------------------------- 
1526 gtk_window_motion_notify_callback( GtkWidget 
* WXUNUSED(widget
), 
1527                                    GdkEventMotion 
*gdk_event
, 
1530     wxCOMMON_CALLBACK_PROLOGUE(gdk_event
, win
); 
1532     if (gdk_event
->is_hint
) 
1536         GdkModifierType state
; 
1537         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1542     g_lastMouseEvent 
= (GdkEvent
*) gdk_event
; 
1544     wxMouseEvent 
event( wxEVT_MOTION 
); 
1545     InitMouseEvent(win
, event
, gdk_event
); 
1547     if ( g_captureWindow 
) 
1549         // synthesise a mouse enter or leave event if needed 
1550         GdkWindow 
*winUnderMouse 
= gdk_window_at_pointer(NULL
, NULL
); 
1551         // This seems to be necessary and actually been added to 
1552         // GDK itself in version 2.0.X 
1555         bool hasMouse 
= winUnderMouse 
== gdk_event
->window
; 
1556         if ( hasMouse 
!= g_captureWindowHasMouse 
) 
1558             // the mouse changed window 
1559             g_captureWindowHasMouse 
= hasMouse
; 
1561             wxMouseEvent 
eventM(g_captureWindowHasMouse 
? wxEVT_ENTER_WINDOW
 
1562                                                         : wxEVT_LEAVE_WINDOW
); 
1563             InitMouseEvent(win
, eventM
, gdk_event
); 
1564             eventM
.SetEventObject(win
); 
1565             win
->GTKProcessEvent(eventM
); 
1570         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1572         // reset the event object and id in case win changed. 
1573         event
.SetEventObject( win 
); 
1574         event
.SetId( win
->GetId() ); 
1577     if ( !g_captureWindow 
) 
1579         wxSetCursorEvent 
cevent( event
.m_x
, event
.m_y 
); 
1580         if (win
->GTKProcessEvent( cevent 
)) 
1582             win
->SetCursor( cevent
.GetCursor() ); 
1586     bool ret 
= win
->GTKProcessEvent(event
); 
1588     g_lastMouseEvent 
= NULL
; 
1593 //----------------------------------------------------------------------------- 
1594 // "scroll_event" (mouse wheel event) 
1595 //----------------------------------------------------------------------------- 
1598 window_scroll_event_hscrollbar(GtkWidget
*, GdkEventScroll
* gdk_event
, wxWindow
* win
) 
1600     if (gdk_event
->direction 
!= GDK_SCROLL_LEFT 
&& 
1601         gdk_event
->direction 
!= GDK_SCROLL_RIGHT
) 
1606     wxMouseEvent 
event(wxEVT_MOUSEWHEEL
); 
1607     InitMouseEvent(win
, event
, gdk_event
); 
1609     GtkRange 
*range 
= win
->m_scrollBar
[wxWindow::ScrollDir_Horz
]; 
1610     if (!range
) return FALSE
; 
1612     if (range 
&& GTK_WIDGET_VISIBLE (range
)) 
1614         GtkAdjustment 
*adj 
= range
->adjustment
; 
1615         gdouble delta 
= adj
->step_increment 
* 3; 
1616         if (gdk_event
->direction 
== GDK_SCROLL_LEFT
) 
1619         gdouble new_value 
= CLAMP (adj
->value 
+ delta
, adj
->lower
, adj
->upper 
- adj
->page_size
); 
1621         gtk_adjustment_set_value (adj
, new_value
); 
1630 window_scroll_event(GtkWidget
*, GdkEventScroll
* gdk_event
, wxWindow
* win
) 
1632     if (gdk_event
->direction 
!= GDK_SCROLL_UP 
&& 
1633         gdk_event
->direction 
!= GDK_SCROLL_DOWN
) 
1638     wxMouseEvent 
event(wxEVT_MOUSEWHEEL
); 
1639     InitMouseEvent(win
, event
, gdk_event
); 
1641     // FIXME: Get these values from GTK or GDK 
1642     event
.m_linesPerAction 
= 3; 
1643     event
.m_wheelDelta 
= 120; 
1644     if (gdk_event
->direction 
== GDK_SCROLL_UP
) 
1645         event
.m_wheelRotation 
= 120; 
1647         event
.m_wheelRotation 
= -120; 
1649     if (win
->GTKProcessEvent(event
)) 
1652     GtkRange 
*range 
= win
->m_scrollBar
[wxWindow::ScrollDir_Vert
]; 
1653     if (!range
) return FALSE
; 
1655     if (range 
&& GTK_WIDGET_VISIBLE (range
)) 
1657         GtkAdjustment 
*adj 
= range
->adjustment
; 
1658         gdouble delta 
= adj
->step_increment 
* 3; 
1659         if (gdk_event
->direction 
== GDK_SCROLL_UP
) 
1662         gdouble new_value 
= CLAMP (adj
->value 
+ delta
, adj
->lower
, adj
->upper 
- adj
->page_size
); 
1664         gtk_adjustment_set_value (adj
, new_value
); 
1672 //----------------------------------------------------------------------------- 
1674 //----------------------------------------------------------------------------- 
1676 static gboolean 
wxgtk_window_popup_menu_callback(GtkWidget
*, wxWindowGTK
* win
) 
1678     wxContextMenuEvent 
event(wxEVT_CONTEXT_MENU
, win
->GetId(), wxPoint(-1, -1)); 
1679     event
.SetEventObject(win
); 
1680     return win
->GTKProcessEvent(event
); 
1683 //----------------------------------------------------------------------------- 
1685 //----------------------------------------------------------------------------- 
1688 gtk_window_focus_in_callback( GtkWidget 
* WXUNUSED(widget
), 
1689                               GdkEventFocus 
*WXUNUSED(event
), 
1692     return win
->GTKHandleFocusIn(); 
1695 //----------------------------------------------------------------------------- 
1696 // "focus_out_event" 
1697 //----------------------------------------------------------------------------- 
1700 gtk_window_focus_out_callback( GtkWidget 
* WXUNUSED(widget
), 
1701                                GdkEventFocus 
* WXUNUSED(gdk_event
), 
1704     return win
->GTKHandleFocusOut(); 
1707 //----------------------------------------------------------------------------- 
1709 //----------------------------------------------------------------------------- 
1712 wx_window_focus_callback(GtkWidget 
*widget
, 
1713                          GtkDirectionType 
WXUNUSED(direction
), 
1716     // the default handler for focus signal in GtkScrolledWindow sets 
1717     // focus to the window itself even if it doesn't accept focus, i.e. has no 
1718     // GTK_CAN_FOCUS in its style -- work around this by forcibly preventing 
1719     // the signal from reaching gtk_scrolled_window_focus() if we don't have 
1720     // any children which might accept focus (we know we don't accept the focus 
1721     // ourselves as this signal is only connected in this case) 
1722     if ( win
->GetChildren().empty() ) 
1723         g_signal_stop_emission_by_name(widget
, "focus"); 
1725     // we didn't change the focus 
1729 //----------------------------------------------------------------------------- 
1730 // "enter_notify_event" 
1731 //----------------------------------------------------------------------------- 
1734 gtk_window_enter_callback( GtkWidget 
*widget
, 
1735                            GdkEventCrossing 
*gdk_event
, 
1738     wxCOMMON_CALLBACK_PROLOGUE(gdk_event
, win
); 
1740     // Event was emitted after a grab 
1741     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
1745     GdkModifierType state 
= (GdkModifierType
)0; 
1747     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
1749     wxMouseEvent 
event( wxEVT_ENTER_WINDOW 
); 
1750     InitMouseEvent(win
, event
, gdk_event
); 
1751     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1752     event
.m_x 
= x 
+ pt
.x
; 
1753     event
.m_y 
= y 
+ pt
.y
; 
1755     if ( !g_captureWindow 
) 
1757         wxSetCursorEvent 
cevent( event
.m_x
, event
.m_y 
); 
1758         if (win
->GTKProcessEvent( cevent 
)) 
1760             win
->SetCursor( cevent
.GetCursor() ); 
1764     return win
->GTKProcessEvent(event
); 
1767 //----------------------------------------------------------------------------- 
1768 // "leave_notify_event" 
1769 //----------------------------------------------------------------------------- 
1772 gtk_window_leave_callback( GtkWidget 
*widget
, 
1773                            GdkEventCrossing 
*gdk_event
, 
1776     wxCOMMON_CALLBACK_PROLOGUE(gdk_event
, win
); 
1778     // Event was emitted after an ungrab 
1779     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
1781     wxMouseEvent 
event( wxEVT_LEAVE_WINDOW 
); 
1785     GdkModifierType state 
= (GdkModifierType
)0; 
1787     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
1789     InitMouseEvent(win
, event
, gdk_event
); 
1791     return win
->GTKProcessEvent(event
); 
1794 //----------------------------------------------------------------------------- 
1795 // "value_changed" from scrollbar 
1796 //----------------------------------------------------------------------------- 
1799 gtk_scrollbar_value_changed(GtkRange
* range
, wxWindow
* win
) 
1801     wxEventType eventType 
= win
->GTKGetScrollEventType(range
); 
1802     if (eventType 
!= wxEVT_NULL
) 
1804         // Convert scroll event type to scrollwin event type 
1805         eventType 
+= wxEVT_SCROLLWIN_TOP 
- wxEVT_SCROLL_TOP
; 
1807         // find the scrollbar which generated the event 
1808         wxWindowGTK::ScrollDir dir 
= win
->ScrollDirFromRange(range
); 
1810         // generate the corresponding wx event 
1811         const int orient 
= wxWindow::OrientFromScrollDir(dir
); 
1812         wxScrollWinEvent 
event(eventType
, win
->GetScrollPos(orient
), orient
); 
1813         event
.SetEventObject(win
); 
1815         win
->GTKProcessEvent(event
); 
1819 //----------------------------------------------------------------------------- 
1820 // "button_press_event" from scrollbar 
1821 //----------------------------------------------------------------------------- 
1824 gtk_scrollbar_button_press_event(GtkRange
*, GdkEventButton
*, wxWindow
* win
) 
1826     g_blockEventsOnScroll 
= true; 
1827     win
->m_mouseButtonDown 
= true; 
1832 //----------------------------------------------------------------------------- 
1833 // "event_after" from scrollbar 
1834 //----------------------------------------------------------------------------- 
1837 gtk_scrollbar_event_after(GtkRange
* range
, GdkEvent
* event
, wxWindow
* win
) 
1839     if (event
->type 
== GDK_BUTTON_RELEASE
) 
1841         g_signal_handlers_block_by_func(range
, (void*)gtk_scrollbar_event_after
, win
); 
1843         const int orient 
= wxWindow::OrientFromScrollDir( 
1844                                         win
->ScrollDirFromRange(range
)); 
1845         wxScrollWinEvent 
evt(wxEVT_SCROLLWIN_THUMBRELEASE
, 
1846                                 win
->GetScrollPos(orient
), orient
); 
1847         evt
.SetEventObject(win
); 
1848         win
->GTKProcessEvent(evt
); 
1852 //----------------------------------------------------------------------------- 
1853 // "button_release_event" from scrollbar 
1854 //----------------------------------------------------------------------------- 
1857 gtk_scrollbar_button_release_event(GtkRange
* range
, GdkEventButton
*, wxWindow
* win
) 
1859     g_blockEventsOnScroll 
= false; 
1860     win
->m_mouseButtonDown 
= false; 
1861     // If thumb tracking 
1862     if (win
->m_isScrolling
) 
1864         win
->m_isScrolling 
= false; 
1865         // Hook up handler to send thumb release event after this emission is finished. 
1866         // To allow setting scroll position from event handler, sending event must 
1867         // be deferred until after the GtkRange handler for this signal has run 
1868         g_signal_handlers_unblock_by_func(range
, (void*)gtk_scrollbar_event_after
, win
); 
1874 //----------------------------------------------------------------------------- 
1875 // "realize" from m_widget 
1876 //----------------------------------------------------------------------------- 
1879 gtk_window_realized_callback(GtkWidget
* widget
, wxWindow
* win
) 
1883         gtk_im_context_set_client_window( win
->m_imData
->context
, 
1884             win
->m_wxwindow 
? win
->GTKGetDrawingWindow() : widget
->window
); 
1887     // We cannot set colours and fonts before the widget 
1888     // been realized, so we do this directly after realization 
1889     // or otherwise in idle time 
1891     if (win
->m_needsStyleChange
) 
1893         win
->SetBackgroundStyle(win
->GetBackgroundStyle()); 
1894         win
->m_needsStyleChange 
= false; 
1897     wxWindowCreateEvent 
event( win 
); 
1898     event
.SetEventObject( win 
); 
1899     win
->GTKProcessEvent( event 
); 
1901     win
->GTKUpdateCursor(true, false); 
1904 //----------------------------------------------------------------------------- 
1905 // "size_allocate" from m_wxwindow or m_widget 
1906 //----------------------------------------------------------------------------- 
1909 size_allocate(GtkWidget
*, GtkAllocation
* alloc
, wxWindow
* win
) 
1911     int w 
= alloc
->width
; 
1912     int h 
= alloc
->height
; 
1913     if (win
->m_wxwindow
) 
1915         int border_x
, border_y
; 
1916         WX_PIZZA(win
->m_wxwindow
)->get_border_widths(border_x
, border_y
); 
1922     if (win
->m_oldClientWidth 
!= w 
|| win
->m_oldClientHeight 
!= h
) 
1924         win
->m_oldClientWidth  
= w
; 
1925         win
->m_oldClientHeight 
= h
; 
1926         // this callback can be connected to m_wxwindow, 
1927         // so always get size from m_widget->allocation 
1928         win
->m_width  
= win
->m_widget
->allocation
.width
; 
1929         win
->m_height 
= win
->m_widget
->allocation
.height
; 
1930         if (!win
->m_nativeSizeEvent
) 
1932             wxSizeEvent 
event(win
->GetSize(), win
->GetId()); 
1933             event
.SetEventObject(win
); 
1934             win
->GTKProcessEvent(event
); 
1939 //----------------------------------------------------------------------------- 
1941 //----------------------------------------------------------------------------- 
1943 #if GTK_CHECK_VERSION(2, 8, 0) 
1945 gtk_window_grab_broken( GtkWidget
*, 
1946                         GdkEventGrabBroken 
*event
, 
1949     // Mouse capture has been lost involuntarily, notify the application 
1950     if(!event
->keyboard 
&& wxWindow::GetCapture() == win
) 
1952         wxMouseCaptureLostEvent 
evt( win
->GetId() ); 
1953         evt
.SetEventObject( win 
); 
1954         win
->HandleWindowEvent( evt 
); 
1960 //----------------------------------------------------------------------------- 
1962 //----------------------------------------------------------------------------- 
1965 void gtk_window_style_set_callback( GtkWidget 
*WXUNUSED(widget
), 
1966                                GtkStyle 
*previous_style
, 
1969     if (win 
&& previous_style
) 
1971         wxSysColourChangedEvent event
; 
1972         event
.SetEventObject(win
); 
1974         win
->GTKProcessEvent( event 
); 
1980 // ---------------------------------------------------------------------------- 
1981 // this wxWindowBase function is implemented here (in platform-specific file) 
1982 // because it is static and so couldn't be made virtual 
1983 // ---------------------------------------------------------------------------- 
1985 wxWindow 
*wxWindowBase::DoFindFocus() 
1987     wxWindowGTK 
*focus 
= gs_pendingFocus 
? gs_pendingFocus 
: gs_currentFocus
; 
1988     // the cast is necessary when we compile in wxUniversal mode 
1989     return static_cast<wxWindow
*>(focus
); 
1992 void wxWindowGTK::AddChildGTK(wxWindowGTK
* child
) 
1994     wxASSERT_MSG(m_wxwindow
, "Cannot add a child to a window without a client area"); 
1996     // the window might have been scrolled already, we 
1997     // have to adapt the position 
1998     wxPizza
* pizza 
= WX_PIZZA(m_wxwindow
); 
1999     child
->m_x 
+= pizza
->m_scroll_x
; 
2000     child
->m_y 
+= pizza
->m_scroll_y
; 
2002     gtk_widget_set_size_request( 
2003         child
->m_widget
, child
->m_width
, child
->m_height
); 
2004     pizza
->put(child
->m_widget
, child
->m_x
, child
->m_y
); 
2007 //----------------------------------------------------------------------------- 
2009 //----------------------------------------------------------------------------- 
2011 wxWindow 
*wxGetActiveWindow() 
2013     return wxWindow::FindFocus(); 
2017 wxMouseState 
wxGetMouseState() 
2023     GdkModifierType mask
; 
2025     gdk_window_get_pointer(NULL
, &x
, &y
, &mask
); 
2029     ms
.SetLeftDown((mask 
& GDK_BUTTON1_MASK
) != 0); 
2030     ms
.SetMiddleDown((mask 
& GDK_BUTTON2_MASK
) != 0); 
2031     ms
.SetRightDown((mask 
& GDK_BUTTON3_MASK
) != 0); 
2032     ms
.SetAux1Down((mask 
& GDK_BUTTON4_MASK
) != 0); 
2033     ms
.SetAux2Down((mask 
& GDK_BUTTON5_MASK
) != 0); 
2035     ms
.SetControlDown((mask 
& GDK_CONTROL_MASK
) != 0); 
2036     ms
.SetShiftDown((mask 
& GDK_SHIFT_MASK
) != 0); 
2037     ms
.SetAltDown((mask 
& GDK_MOD1_MASK
) != 0); 
2038     ms
.SetMetaDown((mask 
& GDK_META_MASK
) != 0); 
2043 //----------------------------------------------------------------------------- 
2045 //----------------------------------------------------------------------------- 
2047 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
2049 #ifdef __WXUNIVERSAL__ 
2050     IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
) 
2052     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
2053 #endif // __WXUNIVERSAL__/__WXGTK__ 
2055 void wxWindowGTK::Init() 
2060     m_focusWidget 
= NULL
; 
2070     m_showOnIdle 
= false; 
2073     m_nativeSizeEvent 
= false; 
2075     m_isScrolling 
= false; 
2076     m_mouseButtonDown 
= false; 
2078     // initialize scrolling stuff 
2079     for ( int dir 
= 0; dir 
< ScrollDir_Max
; dir
++ ) 
2081         m_scrollBar
[dir
] = NULL
; 
2082         m_scrollPos
[dir
] = 0; 
2086     m_oldClientHeight 
= 0; 
2088     m_clipPaintRegion 
= false; 
2090     m_needsStyleChange 
= false; 
2092     m_cursor 
= *wxSTANDARD_CURSOR
; 
2095     m_dirtyTabOrder 
= false; 
2098 wxWindowGTK::wxWindowGTK() 
2103 wxWindowGTK::wxWindowGTK( wxWindow 
*parent
, 
2108                           const wxString 
&name  
) 
2112     Create( parent
, id
, pos
, size
, style
, name 
); 
2115 bool wxWindowGTK::Create( wxWindow 
*parent
, 
2120                           const wxString 
&name  
) 
2122     // Get default border 
2123     wxBorder border 
= GetBorder(style
); 
2125     style 
&= ~wxBORDER_MASK
; 
2128     if (!PreCreation( parent
, pos
, size 
) || 
2129         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
2131         wxFAIL_MSG( wxT("wxWindowGTK creation failed") ); 
2135         // We should accept the native look 
2137         GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2138         scroll_class
->scrollbar_spacing 
= 0; 
2142     m_wxwindow 
= wxPizza::New(m_windowStyle
); 
2143 #ifndef __WXUNIVERSAL__ 
2144     if (HasFlag(wxPizza::BORDER_STYLES
)) 
2146         g_signal_connect(m_wxwindow
, "parent_set", 
2147             G_CALLBACK(parent_set
), this); 
2150     if (!HasFlag(wxHSCROLL
) && !HasFlag(wxVSCROLL
)) 
2151         m_widget 
= m_wxwindow
; 
2154         m_widget 
= gtk_scrolled_window_new( NULL
, NULL 
); 
2156         GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
2158         // There is a conflict with default bindings at GTK+ 
2159         // level between scrolled windows and notebooks both of which want to use 
2160         // Ctrl-PageUp/Down: scrolled windows for scrolling in the horizontal 
2161         // direction and notebooks for changing pages -- we decide that if we don't 
2162         // have wxHSCROLL style we can safely sacrifice horizontal scrolling if it 
2163         // means we can get working keyboard navigation in notebooks 
2164         if ( !HasFlag(wxHSCROLL
) ) 
2167                 bindings 
= gtk_binding_set_by_class(G_OBJECT_GET_CLASS(m_widget
)); 
2170                 gtk_binding_entry_remove(bindings
, GDK_Page_Up
, GDK_CONTROL_MASK
); 
2171                 gtk_binding_entry_remove(bindings
, GDK_Page_Down
, GDK_CONTROL_MASK
); 
2175         if (HasFlag(wxALWAYS_SHOW_SB
)) 
2177             gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_ALWAYS
, GTK_POLICY_ALWAYS 
); 
2179             scrolledWindow
->hscrollbar_visible 
= TRUE
; 
2180             scrolledWindow
->vscrollbar_visible 
= TRUE
; 
2184             gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
2187         m_scrollBar
[ScrollDir_Horz
] = GTK_RANGE(scrolledWindow
->hscrollbar
); 
2188         m_scrollBar
[ScrollDir_Vert
] = GTK_RANGE(scrolledWindow
->vscrollbar
); 
2189         if (GetLayoutDirection() == wxLayout_RightToLeft
) 
2190             gtk_range_set_inverted( m_scrollBar
[ScrollDir_Horz
], TRUE 
); 
2192         gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
2194         // connect various scroll-related events 
2195         for ( int dir 
= 0; dir 
< ScrollDir_Max
; dir
++ ) 
2197             // these handlers block mouse events to any window during scrolling 
2198             // such as motion events and prevent GTK and wxWidgets from fighting 
2199             // over where the slider should be 
2200             g_signal_connect(m_scrollBar
[dir
], "button_press_event", 
2201                          G_CALLBACK(gtk_scrollbar_button_press_event
), this); 
2202             g_signal_connect(m_scrollBar
[dir
], "button_release_event", 
2203                          G_CALLBACK(gtk_scrollbar_button_release_event
), this); 
2205             gulong handler_id 
= g_signal_connect(m_scrollBar
[dir
], "event_after", 
2206                                 G_CALLBACK(gtk_scrollbar_event_after
), this); 
2207             g_signal_handler_block(m_scrollBar
[dir
], handler_id
); 
2209             // these handlers get notified when scrollbar slider moves 
2210             g_signal_connect_after(m_scrollBar
[dir
], "value_changed", 
2211                          G_CALLBACK(gtk_scrollbar_value_changed
), this); 
2214         gtk_widget_show( m_wxwindow 
); 
2216     g_object_ref(m_widget
); 
2219         m_parent
->DoAddChild( this ); 
2221     m_focusWidget 
= m_wxwindow
; 
2223     SetCanFocus(AcceptsFocus()); 
2230 wxWindowGTK::~wxWindowGTK() 
2234     if (gs_currentFocus 
== this) 
2235         gs_currentFocus 
= NULL
; 
2236     if (gs_pendingFocus 
== this) 
2237         gs_pendingFocus 
= NULL
; 
2239     if ( gs_deferredFocusOut 
== this ) 
2240         gs_deferredFocusOut 
= NULL
; 
2244     // destroy children before destroying this window itself 
2247     // unhook focus handlers to prevent stray events being 
2248     // propagated to this (soon to be) dead object 
2249     if (m_focusWidget 
!= NULL
) 
2251         g_signal_handlers_disconnect_by_func (m_focusWidget
, 
2252                                               (gpointer
) gtk_window_focus_in_callback
, 
2254         g_signal_handlers_disconnect_by_func (m_focusWidget
, 
2255                                               (gpointer
) gtk_window_focus_out_callback
, 
2262     // delete before the widgets to avoid a crash on solaris 
2265     // avoid problem with GTK+ 2.18 where a frozen window causes the whole 
2266     // TLW to be frozen, and if the window is then destroyed, nothing ever 
2267     // gets painted again 
2273         // Note that gtk_widget_destroy() does not destroy the widget, it just 
2274         // emits the "destroy" signal. The widget is not actually destroyed 
2275         // until its reference count drops to zero. 
2276         gtk_widget_destroy(m_widget
); 
2277         // Release our reference, should be the last one 
2278         g_object_unref(m_widget
); 
2284 bool wxWindowGTK::PreCreation( wxWindowGTK 
*parent
, const wxPoint 
&pos
,  const wxSize 
&size 
) 
2286     if ( GTKNeedsParent() ) 
2288         wxCHECK_MSG( parent
, false, wxT("Must have non-NULL parent") ); 
2291     // Use either the given size, or the default if -1 is given. 
2292     // See wxWindowBase for these functions. 
2293     m_width 
= WidthDefault(size
.x
) ; 
2294     m_height 
= HeightDefault(size
.y
); 
2302 void wxWindowGTK::PostCreation() 
2304     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2310             // these get reported to wxWidgets -> wxPaintEvent 
2312             g_signal_connect (m_wxwindow
, "expose_event", 
2313                               G_CALLBACK (gtk_window_expose_callback
), this); 
2315             if (GetLayoutDirection() == wxLayout_LeftToRight
) 
2316                 gtk_widget_set_redraw_on_allocate(m_wxwindow
, HasFlag(wxFULL_REPAINT_ON_RESIZE
)); 
2319         // Create input method handler 
2320         m_imData 
= new wxGtkIMData
; 
2322         // Cannot handle drawing preedited text yet 
2323         gtk_im_context_set_use_preedit( m_imData
->context
, FALSE 
); 
2325         g_signal_connect (m_imData
->context
, "commit", 
2326                           G_CALLBACK (gtk_wxwindow_commit_cb
), this); 
2331     if (!GTK_IS_WINDOW(m_widget
)) 
2333         if (m_focusWidget 
== NULL
) 
2334             m_focusWidget 
= m_widget
; 
2338             g_signal_connect (m_focusWidget
, "focus_in_event", 
2339                           G_CALLBACK (gtk_window_focus_in_callback
), this); 
2340             g_signal_connect (m_focusWidget
, "focus_out_event", 
2341                                 G_CALLBACK (gtk_window_focus_out_callback
), this); 
2345             g_signal_connect_after (m_focusWidget
, "focus_in_event", 
2346                           G_CALLBACK (gtk_window_focus_in_callback
), this); 
2347             g_signal_connect_after (m_focusWidget
, "focus_out_event", 
2348                                 G_CALLBACK (gtk_window_focus_out_callback
), this); 
2352     if ( !AcceptsFocusFromKeyboard() ) 
2356         g_signal_connect(m_widget
, "focus", 
2357                             G_CALLBACK(wx_window_focus_callback
), this); 
2360     // connect to the various key and mouse handlers 
2362     GtkWidget 
*connect_widget 
= GetConnectWidget(); 
2364     ConnectWidget( connect_widget 
); 
2366     /* We cannot set colours, fonts and cursors before the widget has 
2367        been realized, so we do this directly after realization */ 
2368     g_signal_connect (connect_widget
, "realize", 
2369                       G_CALLBACK (gtk_window_realized_callback
), this); 
2373         g_signal_connect(m_wxwindow 
? m_wxwindow 
: m_widget
, "size_allocate", 
2374             G_CALLBACK(size_allocate
), this); 
2377 #if GTK_CHECK_VERSION(2, 8, 0) 
2378     if ( gtk_check_version(2,8,0) == NULL 
) 
2380         // Make sure we can notify the app when mouse capture is lost 
2383             g_signal_connect (m_wxwindow
, "grab_broken_event", 
2384                           G_CALLBACK (gtk_window_grab_broken
), this); 
2387         if ( connect_widget 
!= m_wxwindow 
) 
2389             g_signal_connect (connect_widget
, "grab_broken_event", 
2390                         G_CALLBACK (gtk_window_grab_broken
), this); 
2393 #endif // GTK+ >= 2.8 
2395     if ( GTKShouldConnectSizeRequest() ) 
2397         // This is needed if we want to add our windows into native 
2398         // GTK controls, such as the toolbar. With this callback, the 
2399         // toolbar gets to know the correct size (the one set by the 
2400         // programmer). Sadly, it misbehaves for wxComboBox. 
2401         g_signal_connect (m_widget
, "size_request", 
2402                           G_CALLBACK (wxgtk_window_size_request_callback
), 
2406     InheritAttributes(); 
2410     SetLayoutDirection(wxLayout_Default
); 
2412     // unless the window was created initially hidden (i.e. Hide() had been 
2413     // called before Create()), we should show it at GTK+ level as well 
2415         gtk_widget_show( m_widget 
); 
2418 gulong 
wxWindowGTK::GTKConnectWidget(const char *signal
, void (*callback
)()) 
2420     return g_signal_connect(m_widget
, signal
, callback
, this); 
2423 void wxWindowGTK::ConnectWidget( GtkWidget 
*widget 
) 
2425     g_signal_connect (widget
, "key_press_event", 
2426                       G_CALLBACK (gtk_window_key_press_callback
), this); 
2427     g_signal_connect (widget
, "key_release_event", 
2428                       G_CALLBACK (gtk_window_key_release_callback
), this); 
2429     g_signal_connect (widget
, "button_press_event", 
2430                       G_CALLBACK (gtk_window_button_press_callback
), this); 
2431     g_signal_connect (widget
, "button_release_event", 
2432                       G_CALLBACK (gtk_window_button_release_callback
), this); 
2433     g_signal_connect (widget
, "motion_notify_event", 
2434                       G_CALLBACK (gtk_window_motion_notify_callback
), this); 
2436     g_signal_connect (widget
, "scroll_event", 
2437                       G_CALLBACK (window_scroll_event
), this); 
2438     if (m_scrollBar
[ScrollDir_Horz
]) 
2439         g_signal_connect (m_scrollBar
[ScrollDir_Horz
], "scroll_event", 
2440                       G_CALLBACK (window_scroll_event_hscrollbar
), this); 
2441     if (m_scrollBar
[ScrollDir_Vert
]) 
2442         g_signal_connect (m_scrollBar
[ScrollDir_Vert
], "scroll_event", 
2443                       G_CALLBACK (window_scroll_event
), this); 
2445     g_signal_connect (widget
, "popup_menu", 
2446                      G_CALLBACK (wxgtk_window_popup_menu_callback
), this); 
2447     g_signal_connect (widget
, "enter_notify_event", 
2448                       G_CALLBACK (gtk_window_enter_callback
), this); 
2449     g_signal_connect (widget
, "leave_notify_event", 
2450                       G_CALLBACK (gtk_window_leave_callback
), this); 
2452     if (IsTopLevel() && m_wxwindow
) 
2453         g_signal_connect (m_wxwindow
, "style_set", 
2454                               G_CALLBACK (gtk_window_style_set_callback
), this); 
2457 bool wxWindowGTK::Destroy() 
2459     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2463     return wxWindowBase::Destroy(); 
2466 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
) 
2468     gtk_widget_set_size_request(m_widget
, width
, height
); 
2470     // inform the parent to perform the move 
2471     wxASSERT_MSG(m_parent 
&& m_parent
->m_wxwindow
, 
2472                  "the parent window has no client area?"); 
2473     WX_PIZZA(m_parent
->m_wxwindow
)->move(m_widget
, x
, y
); 
2476 void wxWindowGTK::ConstrainSize() 
2479     // GPE's window manager doesn't like size hints at all, esp. when the user 
2480     // has to use the virtual keyboard, so don't constrain size there 
2484         const wxSize minSize 
= GetMinSize(); 
2485         const wxSize maxSize 
= GetMaxSize(); 
2486         if (minSize
.x 
> 0 && m_width  
< minSize
.x
) m_width  
= minSize
.x
; 
2487         if (minSize
.y 
> 0 && m_height 
< minSize
.y
) m_height 
= minSize
.y
; 
2488         if (maxSize
.x 
> 0 && m_width  
> maxSize
.x
) m_width  
= maxSize
.x
; 
2489         if (maxSize
.y 
> 0 && m_height 
> maxSize
.y
) m_height 
= maxSize
.y
; 
2493 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
2495     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2496     wxASSERT_MSG( (m_parent 
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") ); 
2498     int currentX
, currentY
; 
2499     GetPosition(¤tX
, ¤tY
); 
2500     if (x 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
2502     if (y 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
2504     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
2506     // calculate the best size if we should auto size the window 
2507     if ( ((sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1) || 
2508          ((sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1) ) 
2510         const wxSize sizeBest 
= GetBestSize(); 
2511         if ( (sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1 ) 
2513         if ( (sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1 ) 
2514             height 
= sizeBest
.y
; 
2517     const wxSize 
oldSize(m_width
, m_height
); 
2523     if (m_parent
->m_wxwindow
) 
2525         wxPizza
* pizza 
= WX_PIZZA(m_parent
->m_wxwindow
); 
2526         m_x 
= x 
+ pizza
->m_scroll_x
; 
2527         m_y 
= y 
+ pizza
->m_scroll_y
; 
2529         int left_border 
= 0; 
2530         int right_border 
= 0; 
2532         int bottom_border 
= 0; 
2534         /* the default button has a border around it */ 
2535         if (GTK_WIDGET_CAN_DEFAULT(m_widget
)) 
2537             GtkBorder 
*default_border 
= NULL
; 
2538             gtk_widget_style_get( m_widget
, "default_border", &default_border
, NULL 
); 
2541                 left_border 
+= default_border
->left
; 
2542                 right_border 
+= default_border
->right
; 
2543                 top_border 
+= default_border
->top
; 
2544                 bottom_border 
+= default_border
->bottom
; 
2545                 gtk_border_free( default_border 
); 
2549         DoMoveWindow( m_x 
- left_border
, 
2551                       m_width
+left_border
+right_border
, 
2552                       m_height
+top_border
+bottom_border 
); 
2555     if (m_width 
!= oldSize
.x 
|| m_height 
!= oldSize
.y
) 
2557         // update these variables to keep size_allocate handler 
2558         // from sending another size event for this change 
2559         GetClientSize( &m_oldClientWidth
, &m_oldClientHeight 
); 
2561         gtk_widget_queue_resize(m_widget
); 
2562         if (!m_nativeSizeEvent
) 
2564             wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
2565             event
.SetEventObject( this ); 
2566             HandleWindowEvent( event 
); 
2569     if (sizeFlags 
& wxSIZE_FORCE_EVENT
) 
2571         wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
2572         event
.SetEventObject( this ); 
2573         HandleWindowEvent( event 
); 
2577 bool wxWindowGTK::GTKShowFromOnIdle() 
2579     if (IsShown() && m_showOnIdle 
&& !GTK_WIDGET_VISIBLE (m_widget
)) 
2581         GtkAllocation alloc
; 
2584         alloc
.width 
= m_width
; 
2585         alloc
.height 
= m_height
; 
2586         gtk_widget_size_allocate( m_widget
, &alloc 
); 
2587         gtk_widget_show( m_widget 
); 
2588         wxShowEvent 
eventShow(GetId(), true); 
2589         eventShow
.SetEventObject(this); 
2590         HandleWindowEvent(eventShow
); 
2591         m_showOnIdle 
= false; 
2598 void wxWindowGTK::OnInternalIdle() 
2600     if ( gs_deferredFocusOut 
) 
2601         GTKHandleDeferredFocusOut(); 
2603     // Check if we have to show window now 
2604     if (GTKShowFromOnIdle()) return; 
2606     if ( m_dirtyTabOrder 
) 
2608         m_dirtyTabOrder 
= false; 
2612     // Update style if the window was not yet realized when 
2613     // SetBackgroundStyle() was called 
2614     if (m_needsStyleChange
) 
2616         SetBackgroundStyle(GetBackgroundStyle()); 
2617         m_needsStyleChange 
= false; 
2620     if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen()) 
2621         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
2624 void wxWindowGTK::DoGetSize( int *width
, int *height 
) const 
2626     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2628     if (width
) (*width
) = m_width
; 
2629     if (height
) (*height
) = m_height
; 
2632 void wxWindowGTK::DoSetClientSize( int width
, int height 
) 
2634     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2636     const wxSize size 
= GetSize(); 
2637     const wxSize clientSize 
= GetClientSize(); 
2638     SetSize(width 
+ (size
.x 
- clientSize
.x
), height 
+ (size
.y 
- clientSize
.y
)); 
2641 void wxWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
2643     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2650         // if window is scrollable, account for scrollbars 
2651         if ( GTK_IS_SCROLLED_WINDOW(m_widget
) ) 
2653             GtkPolicyType policy
[ScrollDir_Max
]; 
2654             gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(m_widget
), 
2655                                            &policy
[ScrollDir_Horz
], 
2656                                            &policy
[ScrollDir_Vert
]); 
2658             for ( int i 
= 0; i 
< ScrollDir_Max
; i
++ ) 
2660                 // don't account for the scrollbars we don't have 
2661                 GtkRange 
* const range 
= m_scrollBar
[i
]; 
2665                 // nor for the ones we have but don't current show 
2666                 switch ( policy
[i
] ) 
2668                     case GTK_POLICY_NEVER
: 
2669                         // never shown so doesn't take any place 
2672                     case GTK_POLICY_ALWAYS
: 
2673                         // no checks necessary 
2676                     case GTK_POLICY_AUTOMATIC
: 
2677                         // may be shown or not, check 
2678                         GtkAdjustment 
*adj 
= gtk_range_get_adjustment(range
); 
2679                         if ( adj
->upper 
<= adj
->page_size 
) 
2683                 GtkScrolledWindowClass 
*scroll_class 
= 
2684                     GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2687                 gtk_widget_size_request(GTK_WIDGET(range
), &req
); 
2688                 if (i 
== ScrollDir_Horz
) 
2689                     h 
-= req
.height 
+ scroll_class
->scrollbar_spacing
; 
2691                     w 
-= req
.width 
+ scroll_class
->scrollbar_spacing
; 
2695         const wxSize sizeBorders 
= DoGetBorderSize(); 
2705     if (width
) *width 
= w
; 
2706     if (height
) *height 
= h
; 
2709 wxSize 
wxWindowGTK::DoGetBorderSize() const 
2712         return wxWindowBase::DoGetBorderSize(); 
2715     WX_PIZZA(m_wxwindow
)->get_border_widths(x
, y
); 
2717     return 2*wxSize(x
, y
); 
2720 void wxWindowGTK::DoGetPosition( int *x
, int *y 
) const 
2722     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2726     if (!IsTopLevel() && m_parent 
&& m_parent
->m_wxwindow
) 
2728         wxPizza
* pizza 
= WX_PIZZA(m_parent
->m_wxwindow
); 
2729         dx 
= pizza
->m_scroll_x
; 
2730         dy 
= pizza
->m_scroll_y
; 
2733     if (m_x 
== -1 && m_y 
== -1) 
2735         GdkWindow 
*source 
= NULL
; 
2737             source 
= m_wxwindow
->window
; 
2739             source 
= m_widget
->window
; 
2745             gdk_window_get_origin( source
, &org_x
, &org_y 
); 
2748                 m_parent
->ScreenToClient(&org_x
, &org_y
); 
2750             const_cast<wxWindowGTK
*>(this)->m_x 
= org_x
; 
2751             const_cast<wxWindowGTK
*>(this)->m_y 
= org_y
; 
2755     if (x
) (*x
) = m_x 
- dx
; 
2756     if (y
) (*y
) = m_y 
- dy
; 
2759 void wxWindowGTK::DoClientToScreen( int *x
, int *y 
) const 
2761     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2763     if (!m_widget
->window
) return; 
2765     GdkWindow 
*source 
= NULL
; 
2767         source 
= m_wxwindow
->window
; 
2769         source 
= m_widget
->window
; 
2773     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
2777         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
2779             org_x 
+= m_widget
->allocation
.x
; 
2780             org_y 
+= m_widget
->allocation
.y
; 
2787         if (GetLayoutDirection() == wxLayout_RightToLeft
) 
2788             *x 
= (GetClientSize().x 
- *x
) + org_x
; 
2796 void wxWindowGTK::DoScreenToClient( int *x
, int *y 
) const 
2798     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2800     if (!m_widget
->window
) return; 
2802     GdkWindow 
*source 
= NULL
; 
2804         source 
= m_wxwindow
->window
; 
2806         source 
= m_widget
->window
; 
2810     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
2814         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
2816             org_x 
+= m_widget
->allocation
.x
; 
2817             org_y 
+= m_widget
->allocation
.y
; 
2823         if (GetLayoutDirection() == wxLayout_RightToLeft
) 
2824             *x 
= (GetClientSize().x 
- *x
) - org_x
; 
2831 bool wxWindowGTK::Show( bool show 
) 
2833     if ( !wxWindowBase::Show(show
) ) 
2839     // notice that we may call Hide() before the window is created and this is 
2840     // actually useful to create it hidden initially -- but we can't call 
2841     // Show() before it is created 
2844         wxASSERT_MSG( !show
, "can't show invalid window" ); 
2852             // defer until later 
2856         gtk_widget_show(m_widget
); 
2860         gtk_widget_hide(m_widget
); 
2863     wxShowEvent 
eventShow(GetId(), show
); 
2864     eventShow
.SetEventObject(this); 
2865     HandleWindowEvent(eventShow
); 
2870 void wxWindowGTK::DoEnable( bool enable 
) 
2872     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2874     gtk_widget_set_sensitive( m_widget
, enable 
); 
2875     if (m_wxwindow 
&& (m_wxwindow 
!= m_widget
)) 
2876         gtk_widget_set_sensitive( m_wxwindow
, enable 
); 
2879 int wxWindowGTK::GetCharHeight() const 
2881     wxCHECK_MSG( (m_widget 
!= NULL
), 12, wxT("invalid window") ); 
2883     wxFont font 
= GetFont(); 
2884     wxCHECK_MSG( font
.Ok(), 12, wxT("invalid font") ); 
2886     PangoContext
* context 
= gtk_widget_get_pango_context(m_widget
); 
2891     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
2892     PangoLayout 
*layout 
= pango_layout_new(context
); 
2893     pango_layout_set_font_description(layout
, desc
); 
2894     pango_layout_set_text(layout
, "H", 1); 
2895     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
2897     PangoRectangle rect
; 
2898     pango_layout_line_get_extents(line
, NULL
, &rect
); 
2900     g_object_unref (layout
); 
2902     return (int) PANGO_PIXELS(rect
.height
); 
2905 int wxWindowGTK::GetCharWidth() const 
2907     wxCHECK_MSG( (m_widget 
!= NULL
), 8, wxT("invalid window") ); 
2909     wxFont font 
= GetFont(); 
2910     wxCHECK_MSG( font
.Ok(), 8, wxT("invalid font") ); 
2912     PangoContext
* context 
= gtk_widget_get_pango_context(m_widget
); 
2917     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
2918     PangoLayout 
*layout 
= pango_layout_new(context
); 
2919     pango_layout_set_font_description(layout
, desc
); 
2920     pango_layout_set_text(layout
, "g", 1); 
2921     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
2923     PangoRectangle rect
; 
2924     pango_layout_line_get_extents(line
, NULL
, &rect
); 
2926     g_object_unref (layout
); 
2928     return (int) PANGO_PIXELS(rect
.width
); 
2931 void wxWindowGTK::DoGetTextExtent( const wxString
& string
, 
2935                                    int *externalLeading
, 
2936                                    const wxFont 
*theFont 
) const 
2938     wxFont fontToUse 
= theFont 
? *theFont 
: GetFont(); 
2940     wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") ); 
2949     PangoContext 
*context 
= NULL
; 
2951         context 
= gtk_widget_get_pango_context( m_widget 
); 
2960     PangoFontDescription 
*desc 
= fontToUse
.GetNativeFontInfo()->description
; 
2961     PangoLayout 
*layout 
= pango_layout_new(context
); 
2962     pango_layout_set_font_description(layout
, desc
); 
2964         const wxCharBuffer data 
= wxGTK_CONV( string 
); 
2966             pango_layout_set_text(layout
, data
, strlen(data
)); 
2969     PangoRectangle rect
; 
2970     pango_layout_get_extents(layout
, NULL
, &rect
); 
2972     if (x
) (*x
) = (wxCoord
) PANGO_PIXELS(rect
.width
); 
2973     if (y
) (*y
) = (wxCoord
) PANGO_PIXELS(rect
.height
); 
2976         PangoLayoutIter 
*iter 
= pango_layout_get_iter(layout
); 
2977         int baseline 
= pango_layout_iter_get_baseline(iter
); 
2978         pango_layout_iter_free(iter
); 
2979         *descent 
= *y 
- PANGO_PIXELS(baseline
); 
2981     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
2983     g_object_unref (layout
); 
2986 void wxWindowGTK::GTKDisableFocusOutEvent() 
2988     g_signal_handlers_block_by_func( m_focusWidget
, 
2989                                 (gpointer
) gtk_window_focus_out_callback
, this); 
2992 void wxWindowGTK::GTKEnableFocusOutEvent() 
2994     g_signal_handlers_unblock_by_func( m_focusWidget
, 
2995                                 (gpointer
) gtk_window_focus_out_callback
, this); 
2998 bool wxWindowGTK::GTKHandleFocusIn() 
3000     // Disable default focus handling for custom windows since the default GTK+ 
3001     // handler issues a repaint 
3002     const bool retval 
= m_wxwindow 
? true : false; 
3005     // NB: if there's still unprocessed deferred focus-out event (see 
3006     //     GTKHandleFocusOut() for explanation), we need to process it first so 
3007     //     that the order of focus events -- focus-out first, then focus-in 
3008     //     elsewhere -- is preserved 
3009     if ( gs_deferredFocusOut 
) 
3011         if ( GTKNeedsToFilterSameWindowFocus() && 
3012              gs_deferredFocusOut 
== this ) 
3014             // GTK+ focus changed from this wxWindow back to itself, so don't 
3015             // emit any events at all 
3016             wxLogTrace(TRACE_FOCUS
, 
3017                        "filtered out spurious focus change within %s(%p, %s)", 
3018                        GetClassInfo()->GetClassName(), this, GetLabel()); 
3019             gs_deferredFocusOut 
= NULL
; 
3023         // otherwise we need to send focus-out first 
3024         wxASSERT_MSG ( gs_deferredFocusOut 
!= this, 
3025                        "GTKHandleFocusIn(GTKFocus_Normal) called even though focus changed back to itself - derived class should handle this" ); 
3026         GTKHandleDeferredFocusOut(); 
3030     wxLogTrace(TRACE_FOCUS
, 
3031                "handling focus_in event for %s(%p, %s)", 
3032                GetClassInfo()->GetClassName(), this, GetLabel()); 
3035         gtk_im_context_focus_in(m_imData
->context
); 
3037     gs_currentFocus 
= this; 
3038     gs_pendingFocus 
= NULL
; 
3041     // caret needs to be informed about focus change 
3042     wxCaret 
*caret 
= GetCaret(); 
3045         caret
->OnSetFocus(); 
3047 #endif // wxUSE_CARET 
3049     // Notify the parent keeping track of focus for the kbd navigation 
3050     // purposes that we got it. 
3051     wxChildFocusEvent 
eventChildFocus(static_cast<wxWindow
*>(this)); 
3052     GTKProcessEvent(eventChildFocus
); 
3054     wxFocusEvent 
eventFocus(wxEVT_SET_FOCUS
, GetId()); 
3055     eventFocus
.SetEventObject(this); 
3056     GTKProcessEvent(eventFocus
); 
3061 bool wxWindowGTK::GTKHandleFocusOut() 
3063     // Disable default focus handling for custom windows since the default GTK+ 
3064     // handler issues a repaint 
3065     const bool retval 
= m_wxwindow 
? true : false; 
3068     // NB: If a control is composed of several GtkWidgets and when focus 
3069     //     changes from one of them to another within the same wxWindow, we get 
3070     //     a focus-out event followed by focus-in for another GtkWidget owned 
3071     //     by the same wx control. We don't want to generate two spurious 
3072     //     wxEVT_SET_FOCUS events in this case, so we defer sending wx events 
3073     //     from GTKHandleFocusOut() until we know for sure it's not coming back 
3074     //     (i.e. in GTKHandleFocusIn() or at idle time). 
3075     if ( GTKNeedsToFilterSameWindowFocus() ) 
3077         wxASSERT_MSG( gs_deferredFocusOut 
== NULL
, 
3078                       "deferred focus out event already pending" ); 
3079         wxLogTrace(TRACE_FOCUS
, 
3080                    "deferring focus_out event for %s(%p, %s)", 
3081                    GetClassInfo()->GetClassName(), this, GetLabel()); 
3082         gs_deferredFocusOut 
= this; 
3086     GTKHandleFocusOutNoDeferring(); 
3091 void wxWindowGTK::GTKHandleFocusOutNoDeferring() 
3093     wxLogTrace(TRACE_FOCUS
, 
3094                "handling focus_out event for %s(%p, %s)", 
3095                GetClassInfo()->GetClassName(), this, GetLabel()); 
3098         gtk_im_context_focus_out(m_imData
->context
); 
3100     if ( gs_currentFocus 
!= this ) 
3102         // Something is terribly wrong, gs_currentFocus is out of sync with the 
3103         // real focus. We will reset it to NULL anyway, because after this 
3104         // focus-out event is handled, one of the following with happen: 
3106         // * either focus will go out of the app altogether, in which case 
3107         //   gs_currentFocus _should_ be NULL 
3109         // * or it goes to another control, in which case focus-in event will 
3110         //   follow immediately and it will set gs_currentFocus to the right 
3112         wxLogDebug("window %s(%p, %s) lost focus even though it didn't have it", 
3113                    GetClassInfo()->GetClassName(), this, GetLabel()); 
3115     gs_currentFocus 
= NULL
; 
3118     // caret needs to be informed about focus change 
3119     wxCaret 
*caret 
= GetCaret(); 
3122         caret
->OnKillFocus(); 
3124 #endif // wxUSE_CARET 
3126     wxFocusEvent 
event( wxEVT_KILL_FOCUS
, GetId() ); 
3127     event
.SetEventObject( this ); 
3128     GTKProcessEvent( event 
); 
3132 void wxWindowGTK::GTKHandleDeferredFocusOut() 
3134     // NB: See GTKHandleFocusOut() for explanation. This function is called 
3135     //     from either GTKHandleFocusIn() or OnInternalIdle() to process 
3137     if ( gs_deferredFocusOut 
) 
3139         wxWindowGTK 
*win 
= gs_deferredFocusOut
; 
3140         gs_deferredFocusOut 
= NULL
; 
3142         wxLogTrace(TRACE_FOCUS
, 
3143                    "processing deferred focus_out event for %s(%p, %s)", 
3144                    win
->GetClassInfo()->GetClassName(), win
, win
->GetLabel()); 
3146         win
->GTKHandleFocusOutNoDeferring(); 
3150 void wxWindowGTK::SetFocus() 
3152     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3154     // Setting "physical" focus is not immediate in GTK+ and while 
3155     // gtk_widget_is_focus ("determines if the widget is the focus widget 
3156     // within its toplevel", i.e. returns true for one widget per TLW, not 
3157     // globally) returns true immediately after grabbing focus, 
3158     // GTK_WIDGET_HAS_FOCUS (which returns true only for the one widget that 
3159     // has focus at the moment) takes affect only after the window is shown 
3160     // (if it was hidden at the moment of the call) or at the next event loop 
3163     // Because we want to FindFocus() call immediately following 
3164     // foo->SetFocus() to return foo, we have to keep track of "pending" focus 
3166     gs_pendingFocus 
= this; 
3168     GtkWidget 
*widget 
= m_wxwindow 
? m_wxwindow 
: m_focusWidget
; 
3170     if ( GTK_IS_CONTAINER(widget
) && 
3171          !GTK_WIDGET_CAN_FOCUS(widget
) ) 
3173         wxLogTrace(TRACE_FOCUS
, 
3174                    wxT("Setting focus to a child of %s(%p, %s)"), 
3175                    GetClassInfo()->GetClassName(), this, GetLabel().c_str()); 
3176         gtk_widget_child_focus(widget
, GTK_DIR_TAB_FORWARD
); 
3180         wxLogTrace(TRACE_FOCUS
, 
3181                    wxT("Setting focus to %s(%p, %s)"), 
3182                    GetClassInfo()->GetClassName(), this, GetLabel().c_str()); 
3183         gtk_widget_grab_focus(widget
); 
3187 void wxWindowGTK::SetCanFocus(bool canFocus
) 
3190         GTK_WIDGET_SET_FLAGS(m_widget
, GTK_CAN_FOCUS
); 
3192         GTK_WIDGET_UNSET_FLAGS(m_widget
, GTK_CAN_FOCUS
); 
3194     if ( m_wxwindow 
&& (m_widget 
!= m_wxwindow
) ) 
3197             GTK_WIDGET_SET_FLAGS(m_wxwindow
, GTK_CAN_FOCUS
); 
3199             GTK_WIDGET_UNSET_FLAGS(m_wxwindow
, GTK_CAN_FOCUS
); 
3203 bool wxWindowGTK::Reparent( wxWindowBase 
*newParentBase 
) 
3205     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3207     wxWindowGTK 
*oldParent 
= m_parent
, 
3208              *newParent 
= (wxWindowGTK 
*)newParentBase
; 
3210     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3212     if ( !wxWindowBase::Reparent(newParent
) ) 
3215     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3218         gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget 
); 
3220     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3224         if (GTK_WIDGET_VISIBLE (newParent
->m_widget
)) 
3226             m_showOnIdle 
= true; 
3227             gtk_widget_hide( m_widget 
); 
3229         /* insert GTK representation */ 
3230         newParent
->AddChildGTK(this); 
3233     SetLayoutDirection(wxLayout_Default
); 
3238 void wxWindowGTK::DoAddChild(wxWindowGTK 
*child
) 
3240     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3241     wxASSERT_MSG( (child 
!= NULL
), wxT("invalid child window") ); 
3246     /* insert GTK representation */ 
3250 void wxWindowGTK::AddChild(wxWindowBase 
*child
) 
3252     wxWindowBase::AddChild(child
); 
3253     m_dirtyTabOrder 
= true; 
3254     wxTheApp
->WakeUpIdle(); 
3257 void wxWindowGTK::RemoveChild(wxWindowBase 
*child
) 
3259     wxWindowBase::RemoveChild(child
); 
3260     m_dirtyTabOrder 
= true; 
3261     wxTheApp
->WakeUpIdle(); 
3265 wxLayoutDirection 
wxWindowGTK::GTKGetLayout(GtkWidget 
*widget
) 
3267     return gtk_widget_get_direction(widget
) == GTK_TEXT_DIR_RTL
 
3268                 ? wxLayout_RightToLeft
 
3269                 : wxLayout_LeftToRight
; 
3273 void wxWindowGTK::GTKSetLayout(GtkWidget 
*widget
, wxLayoutDirection dir
) 
3275     wxASSERT_MSG( dir 
!= wxLayout_Default
, wxT("invalid layout direction") ); 
3277     gtk_widget_set_direction(widget
, 
3278                              dir 
== wxLayout_RightToLeft 
? GTK_TEXT_DIR_RTL
 
3279                                                          : GTK_TEXT_DIR_LTR
); 
3282 wxLayoutDirection 
wxWindowGTK::GetLayoutDirection() const 
3284     return GTKGetLayout(m_widget
); 
3287 void wxWindowGTK::SetLayoutDirection(wxLayoutDirection dir
) 
3289     if ( dir 
== wxLayout_Default 
) 
3291         const wxWindow 
*const parent 
= GetParent(); 
3294             // inherit layout from parent. 
3295             dir 
= parent
->GetLayoutDirection(); 
3297         else // no parent, use global default layout 
3299             dir 
= wxTheApp
->GetLayoutDirection(); 
3303     if ( dir 
== wxLayout_Default 
) 
3306     GTKSetLayout(m_widget
, dir
); 
3308     if (m_wxwindow 
&& (m_wxwindow 
!= m_widget
)) 
3309         GTKSetLayout(m_wxwindow
, dir
); 
3313 wxWindowGTK::AdjustForLayoutDirection(wxCoord x
, 
3314                                       wxCoord 
WXUNUSED(width
), 
3315                                       wxCoord 
WXUNUSED(widthTotal
)) const 
3317     // We now mirror the coordinates of RTL windows in wxPizza 
3321 void wxWindowGTK::DoMoveInTabOrder(wxWindow 
*win
, WindowOrder move
) 
3323     wxWindowBase::DoMoveInTabOrder(win
, move
); 
3324     m_dirtyTabOrder 
= true; 
3325     wxTheApp
->WakeUpIdle(); 
3328 bool wxWindowGTK::DoNavigateIn(int flags
) 
3330     if ( flags 
& wxNavigationKeyEvent::WinChange 
) 
3332         wxFAIL_MSG( wxT("not implemented") ); 
3336     else // navigate inside the container 
3338         wxWindow 
*parent 
= wxGetTopLevelParent((wxWindow 
*)this); 
3339         wxCHECK_MSG( parent
, false, wxT("every window must have a TLW parent") ); 
3341         GtkDirectionType dir
; 
3342         dir 
= flags 
& wxNavigationKeyEvent::IsForward 
? GTK_DIR_TAB_FORWARD
 
3343                                                       : GTK_DIR_TAB_BACKWARD
; 
3346         g_signal_emit_by_name(parent
->m_widget
, "focus", dir
, &rc
); 
3352 bool wxWindowGTK::GTKWidgetNeedsMnemonic() const 
3354     // none needed by default 
3358 void wxWindowGTK::GTKWidgetDoSetMnemonic(GtkWidget
* WXUNUSED(w
)) 
3360     // nothing to do by default since none is needed 
3363 void wxWindowGTK::RealizeTabOrder() 
3367         if ( !m_children
.empty() ) 
3369             // we don't only construct the correct focus chain but also use 
3370             // this opportunity to update the mnemonic widgets for the widgets 
3373             GList 
*chain 
= NULL
; 
3374             wxWindowGTK
* mnemonicWindow 
= NULL
; 
3376             for ( wxWindowList::const_iterator i 
= m_children
.begin(); 
3377                   i 
!= m_children
.end(); 
3380                 wxWindowGTK 
*win 
= *i
; 
3382                 if ( mnemonicWindow 
) 
3384                     if ( win
->AcceptsFocusFromKeyboard() ) 
3386                         // wxComboBox et al. needs to focus on on a different 
3387                         // widget than m_widget, so if the main widget isn't 
3388                         // focusable try the connect widget 
3389                         GtkWidget
* w 
= win
->m_widget
; 
3390                         if ( !GTK_WIDGET_CAN_FOCUS(w
) ) 
3392                             w 
= win
->GetConnectWidget(); 
3393                             if ( !GTK_WIDGET_CAN_FOCUS(w
) ) 
3399                             mnemonicWindow
->GTKWidgetDoSetMnemonic(w
); 
3400                             mnemonicWindow 
= NULL
; 
3404                 else if ( win
->GTKWidgetNeedsMnemonic() ) 
3406                     mnemonicWindow 
= win
; 
3409                 chain 
= g_list_prepend(chain
, win
->m_widget
); 
3412             chain 
= g_list_reverse(chain
); 
3414             gtk_container_set_focus_chain(GTK_CONTAINER(m_wxwindow
), chain
); 
3419             gtk_container_unset_focus_chain(GTK_CONTAINER(m_wxwindow
)); 
3424 void wxWindowGTK::Raise() 
3426     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3428     if (m_wxwindow 
&& m_wxwindow
->window
) 
3430         gdk_window_raise( m_wxwindow
->window 
); 
3432     else if (m_widget
->window
) 
3434         gdk_window_raise( m_widget
->window 
); 
3438 void wxWindowGTK::Lower() 
3440     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3442     if (m_wxwindow 
&& m_wxwindow
->window
) 
3444         gdk_window_lower( m_wxwindow
->window 
); 
3446     else if (m_widget
->window
) 
3448         gdk_window_lower( m_widget
->window 
); 
3452 bool wxWindowGTK::SetCursor( const wxCursor 
&cursor 
) 
3454     if ( !wxWindowBase::SetCursor(cursor
.Ok() ? cursor 
: *wxSTANDARD_CURSOR
) ) 
3462 void wxWindowGTK::GTKUpdateCursor(bool update_self 
/*=true*/, bool recurse 
/*=true*/) 
3466         wxCursor 
cursor(g_globalCursor
.Ok() ? g_globalCursor 
: GetCursor()); 
3469             wxArrayGdkWindows windowsThis
; 
3470             GdkWindow
* window 
= GTKGetWindow(windowsThis
); 
3472                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3475                 const size_t count 
= windowsThis
.size(); 
3476                 for ( size_t n 
= 0; n 
< count
; n
++ ) 
3478                     GdkWindow 
*win 
= windowsThis
[n
]; 
3479                     // It can be zero if the window has not been realized yet. 
3482                         gdk_window_set_cursor(win
, cursor
.GetCursor()); 
3491         for (wxWindowList::iterator it 
= GetChildren().begin(); it 
!= GetChildren().end(); ++it
) 
3493             (*it
)->GTKUpdateCursor( true ); 
3498 void wxWindowGTK::WarpPointer( int x
, int y 
) 
3500     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3502     // We provide this function ourselves as it is 
3503     // missing in GDK (top of this file). 
3505     GdkWindow 
*window 
= NULL
; 
3507         window 
= m_wxwindow
->window
; 
3509         window 
= GetConnectWidget()->window
; 
3512         gdk_window_warp_pointer( window
, x
, y 
); 
3515 wxWindowGTK::ScrollDir 
wxWindowGTK::ScrollDirFromRange(GtkRange 
*range
) const 
3517     // find the scrollbar which generated the event 
3518     for ( int dir 
= 0; dir 
< ScrollDir_Max
; dir
++ ) 
3520         if ( range 
== m_scrollBar
[dir
] ) 
3521             return (ScrollDir
)dir
; 
3524     wxFAIL_MSG( wxT("event from unknown scrollbar received") ); 
3526     return ScrollDir_Max
; 
3529 bool wxWindowGTK::DoScrollByUnits(ScrollDir dir
, ScrollUnit unit
, int units
) 
3531     bool changed 
= false; 
3532     GtkRange
* range 
= m_scrollBar
[dir
]; 
3533     if ( range 
&& units 
) 
3535         GtkAdjustment
* adj 
= range
->adjustment
; 
3536         gdouble inc 
= unit 
== ScrollUnit_Line 
? adj
->step_increment
 
3537                                               : adj
->page_increment
; 
3539         const int posOld 
= int(adj
->value 
+ 0.5); 
3540         gtk_range_set_value(range
, posOld 
+ units
*inc
); 
3542         changed 
= int(adj
->value 
+ 0.5) != posOld
; 
3548 bool wxWindowGTK::ScrollLines(int lines
) 
3550     return DoScrollByUnits(ScrollDir_Vert
, ScrollUnit_Line
, lines
); 
3553 bool wxWindowGTK::ScrollPages(int pages
) 
3555     return DoScrollByUnits(ScrollDir_Vert
, ScrollUnit_Page
, pages
); 
3558 void wxWindowGTK::Refresh(bool WXUNUSED(eraseBackground
), 
3563         // it is valid to call Refresh() for a window which hasn't been created 
3564         // yet, it simply doesn't do anything in this case 
3571             gtk_widget_queue_draw_area( m_widget
, rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3573             gtk_widget_queue_draw( m_widget 
); 
3577         // Just return if the widget or one of its ancestors isn't mapped 
3579         for (w 
= m_wxwindow
; w 
!= NULL
; w 
= w
->parent
) 
3580             if (!GTK_WIDGET_MAPPED (w
)) 
3583         GdkWindow
* window 
= GTKGetDrawingWindow(); 
3587             if (GetLayoutDirection() == wxLayout_RightToLeft
) 
3588                 x 
= GetClientSize().x 
- x 
- rect
->width
; 
3592             r
.width 
= rect
->width
; 
3593             r
.height 
= rect
->height
; 
3594             gdk_window_invalidate_rect(window
, &r
, true); 
3597             gdk_window_invalidate_rect(window
, NULL
, true); 
3601 void wxWindowGTK::Update() 
3603     if (m_widget 
&& GTK_WIDGET_MAPPED(m_widget
)) 
3605         GdkDisplay
* display 
= gtk_widget_get_display(m_widget
); 
3606         // Flush everything out to the server, and wait for it to finish. 
3607         // This ensures nothing will overwrite the drawing we are about to do. 
3608         gdk_display_sync(display
); 
3610         GdkWindow
* window 
= GTKGetDrawingWindow(); 
3612             window 
= m_widget
->window
; 
3613         gdk_window_process_updates(window
, true); 
3615         // Flush again, but no need to wait for it to finish 
3616         gdk_display_flush(display
); 
3620 bool wxWindowGTK::DoIsExposed( int x
, int y 
) const 
3622     return m_updateRegion
.Contains(x
, y
) != wxOutRegion
; 
3625 bool wxWindowGTK::DoIsExposed( int x
, int y
, int w
, int h 
) const 
3627     if (GetLayoutDirection() == wxLayout_RightToLeft
) 
3628         return m_updateRegion
.Contains(x
-w
, y
, w
, h
) != wxOutRegion
; 
3630         return m_updateRegion
.Contains(x
, y
, w
, h
) != wxOutRegion
; 
3633 void wxWindowGTK::GtkSendPaintEvents() 
3637         m_updateRegion
.Clear(); 
3641     // Clip to paint region in wxClientDC 
3642     m_clipPaintRegion 
= true; 
3644     m_nativeUpdateRegion 
= m_updateRegion
; 
3646     if (GetLayoutDirection() == wxLayout_RightToLeft
) 
3648         // Transform m_updateRegion under RTL 
3649         m_updateRegion
.Clear(); 
3652         gdk_drawable_get_size(m_wxwindow
->window
, &width
, NULL
); 
3654         wxRegionIterator 
upd( m_nativeUpdateRegion 
); 
3658             rect
.x 
= upd
.GetX(); 
3659             rect
.y 
= upd
.GetY(); 
3660             rect
.width 
= upd
.GetWidth(); 
3661             rect
.height 
= upd
.GetHeight(); 
3663             rect
.x 
= width 
- rect
.x 
- rect
.width
; 
3664             m_updateRegion
.Union( rect 
); 
3670     switch ( GetBackgroundStyle() ) 
3672         case wxBG_STYLE_ERASE
: 
3674                 wxWindowDC 
dc( (wxWindow
*)this ); 
3675                 dc
.SetDeviceClippingRegion( m_updateRegion 
); 
3677                 // Work around gtk-qt <= 0.60 bug whereby the window colour 
3681                             GetOptionInt("gtk.window.force-background-colour") ) 
3683                     dc
.SetBackground(GetBackgroundColour()); 
3687                 wxEraseEvent 
erase_event( GetId(), &dc 
); 
3688                 erase_event
.SetEventObject( this ); 
3690                 if ( HandleWindowEvent(erase_event
) ) 
3692                     // background erased, don't do it again 
3698         case wxBG_STYLE_SYSTEM
: 
3699             if ( GetThemeEnabled() ) 
3701                 // find ancestor from which to steal background 
3702                 wxWindow 
*parent 
= wxGetTopLevelParent((wxWindow 
*)this); 
3704                     parent 
= (wxWindow
*)this; 
3706                 if (GTK_WIDGET_MAPPED(parent
->m_widget
)) 
3708                     wxRegionIterator 
upd( m_nativeUpdateRegion 
); 
3712                         rect
.x 
= upd
.GetX(); 
3713                         rect
.y 
= upd
.GetY(); 
3714                         rect
.width 
= upd
.GetWidth(); 
3715                         rect
.height 
= upd
.GetHeight(); 
3717                         gtk_paint_flat_box( parent
->m_widget
->style
, 
3718                                     GTKGetDrawingWindow(), 
3719                                     (GtkStateType
)GTK_WIDGET_STATE(m_wxwindow
), 
3732         case wxBG_STYLE_PAINT
: 
3733             // nothing to do: window will be painted over in EVT_PAINT 
3737             wxFAIL_MSG( "unsupported background style" ); 
3740     wxNcPaintEvent 
nc_paint_event( GetId() ); 
3741     nc_paint_event
.SetEventObject( this ); 
3742     HandleWindowEvent( nc_paint_event 
); 
3744     wxPaintEvent 
paint_event( GetId() ); 
3745     paint_event
.SetEventObject( this ); 
3746     HandleWindowEvent( paint_event 
); 
3748     m_clipPaintRegion 
= false; 
3750     m_updateRegion
.Clear(); 
3751     m_nativeUpdateRegion
.Clear(); 
3754 void wxWindowGTK::SetDoubleBuffered( bool on 
) 
3756     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3759         gtk_widget_set_double_buffered( m_wxwindow
, on 
); 
3762 bool wxWindowGTK::IsDoubleBuffered() const 
3764     return GTK_WIDGET_DOUBLE_BUFFERED( m_wxwindow 
); 
3767 void wxWindowGTK::ClearBackground() 
3769     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3773 void wxWindowGTK::DoSetToolTip( wxToolTip 
*tip 
) 
3775     wxWindowBase::DoSetToolTip(tip
); 
3779         m_tooltip
->GTKApply( (wxWindow 
*)this ); 
3783         GtkWidget 
*w 
= GetConnectWidget(); 
3784         wxToolTip::GTKApply(w
, NULL
); 
3785 #if GTK_CHECK_VERSION(2, 12, 0) 
3786         // Just applying NULL doesn't work on 2.12.0, so also use 
3787         // gtk_widget_set_has_tooltip. It is part of the new GtkTooltip API 
3788         // but seems also to work with the old GtkTooltips. 
3789         if (gtk_check_version(2, 12, 0) == NULL
) 
3790             gtk_widget_set_has_tooltip(w
, FALSE
); 
3795 void wxWindowGTK::GTKApplyToolTip( GtkTooltips 
*tips
, const gchar 
*tip 
) 
3797     GtkWidget 
*w 
= GetConnectWidget(); 
3798     gtk_tooltips_set_tip(tips
, w
, tip
, NULL
); 
3800 #if GTK_CHECK_VERSION(2, 12, 0) 
3801     if ( !tip 
|| tip
[0] == '\0' ) 
3803         // Just applying empty tool tip doesn't work on 2.12.0, so also use 
3804         // gtk_widget_set_has_tooltip. 
3805         if (gtk_check_version(2, 12, 0) == NULL
) 
3806             gtk_widget_set_has_tooltip(w
, FALSE
); 
3810 #endif // wxUSE_TOOLTIPS 
3812 bool wxWindowGTK::SetBackgroundColour( const wxColour 
&colour 
) 
3814     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3816     if (!wxWindowBase::SetBackgroundColour(colour
)) 
3821         // We need the pixel value e.g. for background clearing. 
3822         m_backgroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
3825     // apply style change (forceStyle=true so that new style is applied 
3826     // even if the bg colour changed from valid to wxNullColour) 
3827     GTKApplyWidgetStyle(true); 
3832 bool wxWindowGTK::SetForegroundColour( const wxColour 
&colour 
) 
3834     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3836     if (!wxWindowBase::SetForegroundColour(colour
)) 
3843         // We need the pixel value e.g. for background clearing. 
3844         m_foregroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
3847     // apply style change (forceStyle=true so that new style is applied 
3848     // even if the bg colour changed from valid to wxNullColour): 
3849     GTKApplyWidgetStyle(true); 
3854 PangoContext 
*wxWindowGTK::GTKGetPangoDefaultContext() 
3856     return gtk_widget_get_pango_context( m_widget 
); 
3859 GtkRcStyle 
*wxWindowGTK::GTKCreateWidgetStyle(bool forceStyle
) 
3861     // do we need to apply any changes at all? 
3864          !m_foregroundColour
.Ok() && !m_backgroundColour
.Ok() ) 
3869     GtkRcStyle 
*style 
= gtk_rc_style_new(); 
3874             pango_font_description_copy( m_font
.GetNativeFontInfo()->description 
); 
3877     int flagsNormal 
= 0, 
3880         flagsInsensitive 
= 0; 
3882     if ( m_foregroundColour
.Ok() ) 
3884         const GdkColor 
*fg 
= m_foregroundColour
.GetColor(); 
3886         style
->fg
[GTK_STATE_NORMAL
] = 
3887         style
->text
[GTK_STATE_NORMAL
] = *fg
; 
3888         flagsNormal 
|= GTK_RC_FG 
| GTK_RC_TEXT
; 
3890         style
->fg
[GTK_STATE_PRELIGHT
] = 
3891         style
->text
[GTK_STATE_PRELIGHT
] = *fg
; 
3892         flagsPrelight 
|= GTK_RC_FG 
| GTK_RC_TEXT
; 
3894         style
->fg
[GTK_STATE_ACTIVE
] = 
3895         style
->text
[GTK_STATE_ACTIVE
] = *fg
; 
3896         flagsActive 
|= GTK_RC_FG 
| GTK_RC_TEXT
; 
3899     if ( m_backgroundColour
.Ok() ) 
3901         const GdkColor 
*bg 
= m_backgroundColour
.GetColor(); 
3903         style
->bg
[GTK_STATE_NORMAL
] = 
3904         style
->base
[GTK_STATE_NORMAL
] = *bg
; 
3905         flagsNormal 
|= GTK_RC_BG 
| GTK_RC_BASE
; 
3907         style
->bg
[GTK_STATE_PRELIGHT
] = 
3908         style
->base
[GTK_STATE_PRELIGHT
] = *bg
; 
3909         flagsPrelight 
|= GTK_RC_BG 
| GTK_RC_BASE
; 
3911         style
->bg
[GTK_STATE_ACTIVE
] = 
3912         style
->base
[GTK_STATE_ACTIVE
] = *bg
; 
3913         flagsActive 
|= GTK_RC_BG 
| GTK_RC_BASE
; 
3915         style
->bg
[GTK_STATE_INSENSITIVE
] = 
3916         style
->base
[GTK_STATE_INSENSITIVE
] = *bg
; 
3917         flagsInsensitive 
|= GTK_RC_BG 
| GTK_RC_BASE
; 
3920     style
->color_flags
[GTK_STATE_NORMAL
] = (GtkRcFlags
)flagsNormal
; 
3921     style
->color_flags
[GTK_STATE_PRELIGHT
] = (GtkRcFlags
)flagsPrelight
; 
3922     style
->color_flags
[GTK_STATE_ACTIVE
] = (GtkRcFlags
)flagsActive
; 
3923     style
->color_flags
[GTK_STATE_INSENSITIVE
] = (GtkRcFlags
)flagsInsensitive
; 
3928 void wxWindowGTK::GTKApplyWidgetStyle(bool forceStyle
) 
3930     GtkRcStyle 
*style 
= GTKCreateWidgetStyle(forceStyle
); 
3933         DoApplyWidgetStyle(style
); 
3934         gtk_rc_style_unref(style
); 
3937     // Style change may affect GTK+'s size calculation: 
3938     InvalidateBestSize(); 
3941 void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
3945         // block the signal temporarily to avoid sending 
3946         // wxSysColourChangedEvents when we change the colours ourselves 
3947         bool unblock 
= false; 
3951             g_signal_handlers_block_by_func( 
3952                 m_wxwindow
, (void *)gtk_window_style_set_callback
, this); 
3955         gtk_widget_modify_style(m_wxwindow
, style
); 
3959             g_signal_handlers_unblock_by_func( 
3960                 m_wxwindow
, (void *)gtk_window_style_set_callback
, this); 
3965         gtk_widget_modify_style(m_widget
, style
); 
3969 bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style
) 
3971     wxWindowBase::SetBackgroundStyle(style
); 
3973     if ( style 
== wxBG_STYLE_PAINT 
) 
3978             window 
= GTKGetDrawingWindow(); 
3982             GtkWidget 
* const w 
= GetConnectWidget(); 
3983             window 
= w 
? w
->window 
: NULL
; 
3988             // Make sure GDK/X11 doesn't refresh the window 
3990             gdk_window_set_back_pixmap( window
, None
, False 
); 
3992             Display
* display 
= GDK_WINDOW_DISPLAY(window
); 
3995             m_needsStyleChange 
= false; 
3997         else // window not realized yet 
3999             // Do in OnIdle, because the window is not yet available 
4000             m_needsStyleChange 
= true; 
4003         // Don't apply widget style, or we get a grey background 
4007         // apply style change (forceStyle=true so that new style is applied 
4008         // even if the bg colour changed from valid to wxNullColour): 
4009         GTKApplyWidgetStyle(true); 
4015 // ---------------------------------------------------------------------------- 
4016 // Pop-up menu stuff 
4017 // ---------------------------------------------------------------------------- 
4019 #if wxUSE_MENUS_NATIVE 
4023 void wxPopupMenuPositionCallback( GtkMenu 
*menu
, 
4025                                   gboolean 
* WXUNUSED(whatever
), 
4026                                   gpointer user_data 
) 
4028     // ensure that the menu appears entirely on screen 
4030     gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
); 
4032     wxSize sizeScreen 
= wxGetDisplaySize(); 
4033     wxPoint 
*pos 
= (wxPoint
*)user_data
; 
4035     gint xmax 
= sizeScreen
.x 
- req
.width
, 
4036          ymax 
= sizeScreen
.y 
- req
.height
; 
4038     *x 
= pos
->x 
< xmax 
? pos
->x 
: xmax
; 
4039     *y 
= pos
->y 
< ymax 
? pos
->y 
: ymax
; 
4043 bool wxWindowGTK::DoPopupMenu( wxMenu 
*menu
, int x
, int y 
) 
4045     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
4051     GtkMenuPositionFunc posfunc
; 
4052     if ( x 
== -1 && y 
== -1 ) 
4054         // use GTK's default positioning algorithm 
4060         pos 
= ClientToScreen(wxPoint(x
, y
)); 
4062         posfunc 
= wxPopupMenuPositionCallback
; 
4065     menu
->m_popupShown 
= true; 
4067                   GTK_MENU(menu
->m_menu
), 
4068                   NULL
,           // parent menu shell 
4069                   NULL
,           // parent menu item 
4070                   posfunc
,                      // function to position it 
4071                   userdata
,                     // client data 
4072                   0,                            // button used to activate it 
4073                   gtk_get_current_event_time() 
4076     while (menu
->m_popupShown
) 
4078         gtk_main_iteration(); 
4084 #endif // wxUSE_MENUS_NATIVE 
4086 #if wxUSE_DRAG_AND_DROP 
4088 void wxWindowGTK::SetDropTarget( wxDropTarget 
*dropTarget 
) 
4090     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4092     GtkWidget 
*dnd_widget 
= GetConnectWidget(); 
4094     if (m_dropTarget
) m_dropTarget
->GtkUnregisterWidget( dnd_widget 
); 
4096     if (m_dropTarget
) delete m_dropTarget
; 
4097     m_dropTarget 
= dropTarget
; 
4099     if (m_dropTarget
) m_dropTarget
->GtkRegisterWidget( dnd_widget 
); 
4102 #endif // wxUSE_DRAG_AND_DROP 
4104 GtkWidget
* wxWindowGTK::GetConnectWidget() 
4106     GtkWidget 
*connect_widget 
= m_widget
; 
4107     if (m_wxwindow
) connect_widget 
= m_wxwindow
; 
4109     return connect_widget
; 
4112 bool wxWindowGTK::GTKIsOwnWindow(GdkWindow 
*window
) const 
4114     wxArrayGdkWindows windowsThis
; 
4115     GdkWindow 
* const winThis 
= GTKGetWindow(windowsThis
); 
4117     return winThis 
? window 
== winThis
 
4118                    : windowsThis
.Index(window
) != wxNOT_FOUND
; 
4121 GdkWindow 
*wxWindowGTK::GTKGetWindow(wxArrayGdkWindows
& WXUNUSED(windows
)) const 
4123     return m_wxwindow 
? GTKGetDrawingWindow() : m_widget
->window
; 
4126 bool wxWindowGTK::SetFont( const wxFont 
&font 
) 
4128     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
4130     if (!wxWindowBase::SetFont(font
)) 
4133     // apply style change (forceStyle=true so that new style is applied 
4134     // even if the font changed from valid to wxNullFont): 
4135     GTKApplyWidgetStyle(true); 
4140 void wxWindowGTK::DoCaptureMouse() 
4142     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4144     GdkWindow 
*window 
= NULL
; 
4146         window 
= GTKGetDrawingWindow(); 
4148         window 
= GetConnectWidget()->window
; 
4150     wxCHECK_RET( window
, wxT("CaptureMouse() failed") ); 
4152     const wxCursor
* cursor 
= &m_cursor
; 
4154         cursor 
= wxSTANDARD_CURSOR
; 
4156     gdk_pointer_grab( window
, FALSE
, 
4158                          (GDK_BUTTON_PRESS_MASK 
| 
4159                           GDK_BUTTON_RELEASE_MASK 
| 
4160                           GDK_POINTER_MOTION_HINT_MASK 
| 
4161                           GDK_POINTER_MOTION_MASK
), 
4163                       cursor
->GetCursor(), 
4164                       (guint32
)GDK_CURRENT_TIME 
); 
4165     g_captureWindow 
= this; 
4166     g_captureWindowHasMouse 
= true; 
4169 void wxWindowGTK::DoReleaseMouse() 
4171     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4173     wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") ); 
4175     g_captureWindow 
= NULL
; 
4177     GdkWindow 
*window 
= NULL
; 
4179         window 
= GTKGetDrawingWindow(); 
4181         window 
= GetConnectWidget()->window
; 
4186     gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME 
); 
4189 void wxWindowGTK::GTKReleaseMouseAndNotify() 
4192     wxMouseCaptureLostEvent 
evt(GetId()); 
4193     evt
.SetEventObject( this ); 
4194     HandleWindowEvent( evt 
); 
4198 wxWindow 
*wxWindowBase::GetCapture() 
4200     return (wxWindow 
*)g_captureWindow
; 
4203 bool wxWindowGTK::IsRetained() const 
4208 void wxWindowGTK::SetScrollbar(int orient
, 
4212                                bool WXUNUSED(update
)) 
4214     const int dir 
= ScrollDirFromOrient(orient
); 
4215     GtkRange
* const sb 
= m_scrollBar
[dir
]; 
4216     wxCHECK_RET( sb
, wxT("this window is not scrollable") ); 
4220         // GtkRange requires upper > lower 
4225     GtkAdjustment 
* const adj 
= sb
->adjustment
; 
4226     adj
->step_increment 
= 1; 
4227     adj
->page_increment 
= 
4228     adj
->page_size 
= thumbVisible
; 
4231     g_signal_handlers_block_by_func( 
4232         sb
, (void*)gtk_scrollbar_value_changed
, this); 
4234     gtk_range_set_range(sb
, 0, range
); 
4235     m_scrollPos
[dir
] = sb
->adjustment
->value
; 
4237     g_signal_handlers_unblock_by_func( 
4238         sb
, (void*)gtk_scrollbar_value_changed
, this); 
4241 void wxWindowGTK::SetScrollPos(int orient
, int pos
, bool WXUNUSED(refresh
)) 
4243     const int dir 
= ScrollDirFromOrient(orient
); 
4244     GtkRange 
* const sb 
= m_scrollBar
[dir
]; 
4245     wxCHECK_RET( sb
, wxT("this window is not scrollable") ); 
4247     // This check is more than an optimization. Without it, the slider 
4248     //   will not move smoothly while tracking when using wxScrollHelper. 
4249     if (GetScrollPos(orient
) != pos
) 
4251         g_signal_handlers_block_by_func( 
4252             sb
, (void*)gtk_scrollbar_value_changed
, this); 
4254         gtk_range_set_value(sb
, pos
); 
4255         m_scrollPos
[dir
] = sb
->adjustment
->value
; 
4257         g_signal_handlers_unblock_by_func( 
4258             sb
, (void*)gtk_scrollbar_value_changed
, this); 
4262 int wxWindowGTK::GetScrollThumb(int orient
) const 
4264     GtkRange 
* const sb 
= m_scrollBar
[ScrollDirFromOrient(orient
)]; 
4265     wxCHECK_MSG( sb
, 0, wxT("this window is not scrollable") ); 
4267     return wxRound(sb
->adjustment
->page_size
); 
4270 int wxWindowGTK::GetScrollPos( int orient 
) const 
4272     GtkRange 
* const sb 
= m_scrollBar
[ScrollDirFromOrient(orient
)]; 
4273     wxCHECK_MSG( sb
, 0, wxT("this window is not scrollable") ); 
4275     return wxRound(sb
->adjustment
->value
); 
4278 int wxWindowGTK::GetScrollRange( int orient 
) const 
4280     GtkRange 
* const sb 
= m_scrollBar
[ScrollDirFromOrient(orient
)]; 
4281     wxCHECK_MSG( sb
, 0, wxT("this window is not scrollable") ); 
4283     return wxRound(sb
->adjustment
->upper
); 
4286 // Determine if increment is the same as +/-x, allowing for some small 
4287 //   difference due to possible inexactness in floating point arithmetic 
4288 static inline bool IsScrollIncrement(double increment
, double x
) 
4290     wxASSERT(increment 
> 0); 
4291     const double tolerance 
= 1.0 / 1024; 
4292     return fabs(increment 
- fabs(x
)) < tolerance
; 
4295 wxEventType 
wxWindowGTK::GTKGetScrollEventType(GtkRange
* range
) 
4297     wxASSERT(range 
== m_scrollBar
[0] || range 
== m_scrollBar
[1]); 
4299     const int barIndex 
= range 
== m_scrollBar
[1]; 
4300     GtkAdjustment
* adj 
= range
->adjustment
; 
4302     const int value 
= wxRound(adj
->value
); 
4304     // save previous position 
4305     const double oldPos 
= m_scrollPos
[barIndex
]; 
4306     // update current position 
4307     m_scrollPos
[barIndex
] = adj
->value
; 
4308     // If event should be ignored, or integral position has not changed 
4309     if (!m_hasVMT 
|| g_blockEventsOnDrag 
|| value 
== wxRound(oldPos
)) 
4314     wxEventType eventType 
= wxEVT_SCROLL_THUMBTRACK
; 
4317         // Difference from last change event 
4318         const double diff 
= adj
->value 
- oldPos
; 
4319         const bool isDown 
= diff 
> 0; 
4321         if (IsScrollIncrement(adj
->step_increment
, diff
)) 
4323             eventType 
= isDown 
? wxEVT_SCROLL_LINEDOWN 
: wxEVT_SCROLL_LINEUP
; 
4325         else if (IsScrollIncrement(adj
->page_increment
, diff
)) 
4327             eventType 
= isDown 
? wxEVT_SCROLL_PAGEDOWN 
: wxEVT_SCROLL_PAGEUP
; 
4329         else if (m_mouseButtonDown
) 
4331             // Assume track event 
4332             m_isScrolling 
= true; 
4338 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) ) 
4340     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4342     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4344     // No scrolling requested. 
4345     if ((dx 
== 0) && (dy 
== 0)) return; 
4347     m_clipPaintRegion 
= true; 
4349     WX_PIZZA(m_wxwindow
)->scroll(dx
, dy
); 
4351     m_clipPaintRegion 
= false; 
4354     bool restoreCaret 
= (GetCaret() != NULL 
&& GetCaret()->IsVisible()); 
4357         wxRect 
caretRect(GetCaret()->GetPosition(), GetCaret()->GetSize()); 
4359             caretRect
.width 
+= dx
; 
4362             caretRect
.x 
+= dx
; caretRect
.width 
-= dx
; 
4365             caretRect
.height 
+= dy
; 
4368             caretRect
.y 
+= dy
; caretRect
.height 
-= dy
; 
4371         RefreshRect(caretRect
); 
4373 #endif // wxUSE_CARET 
4376 void wxWindowGTK::GTKScrolledWindowSetBorder(GtkWidget
* w
, int wxstyle
) 
4378     //RN: Note that static controls usually have no border on gtk, so maybe 
4379     //it makes sense to treat that as simply no border at the wx level 
4381     if (!(wxstyle 
& wxNO_BORDER
) && !(wxstyle 
& wxBORDER_STATIC
)) 
4383         GtkShadowType gtkstyle
; 
4385         if(wxstyle 
& wxBORDER_RAISED
) 
4386             gtkstyle 
= GTK_SHADOW_OUT
; 
4387         else if ((wxstyle 
& wxBORDER_SUNKEN
) || (wxstyle 
& wxBORDER_THEME
)) 
4388             gtkstyle 
= GTK_SHADOW_IN
; 
4391         else if (wxstyle 
& wxBORDER_DOUBLE
) 
4392             gtkstyle 
= GTK_SHADOW_ETCHED_IN
; 
4395             gtkstyle 
= GTK_SHADOW_IN
; 
4397         gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(w
), 
4402 void wxWindowGTK::SetWindowStyleFlag( long style 
) 
4404     // Updates the internal variable. NB: Now m_windowStyle bits carry the _new_ style values already 
4405     wxWindowBase::SetWindowStyleFlag(style
); 
4408 // Find the wxWindow at the current mouse position, also returning the mouse 
4410 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
4412     pt 
= wxGetMousePosition(); 
4413     wxWindow
* found 
= wxFindWindowAtPoint(pt
); 
4417 // Get the current mouse position. 
4418 wxPoint 
wxGetMousePosition() 
4420   /* This crashes when used within wxHelpContext, 
4421      so we have to use the X-specific implementation below. 
4423     GdkModifierType *mask; 
4424     (void) gdk_window_get_pointer(NULL, &x, &y, mask); 
4426     return wxPoint(x, y); 
4430     GdkWindow
* windowAtPtr 
= gdk_window_at_pointer(& x
, & y
); 
4432     Display 
*display 
= windowAtPtr 
? GDK_WINDOW_XDISPLAY(windowAtPtr
) : GDK_DISPLAY(); 
4433     Window rootWindow 
= RootWindowOfScreen (DefaultScreenOfDisplay(display
)); 
4434     Window rootReturn
, childReturn
; 
4435     int rootX
, rootY
, winX
, winY
; 
4436     unsigned int maskReturn
; 
4438     XQueryPointer (display
, 
4442                    &rootX
, &rootY
, &winX
, &winY
, &maskReturn
); 
4443     return wxPoint(rootX
, rootY
); 
4447 GdkWindow
* wxWindowGTK::GTKGetDrawingWindow() const 
4449     GdkWindow
* window 
= NULL
; 
4451         window 
= m_wxwindow
->window
; 
4455 // ---------------------------------------------------------------------------- 
4457 // ---------------------------------------------------------------------------- 
4462 // this is called if we attempted to freeze unrealized widget when it finally 
4463 // is realized (and so can be frozen): 
4464 static void wx_frozen_widget_realize(GtkWidget
* w
, wxWindowGTK
* win
) 
4466     wxASSERT( w 
&& !GTK_WIDGET_NO_WINDOW(w
) ); 
4467     wxASSERT( GTK_WIDGET_REALIZED(w
) ); 
4469     g_signal_handlers_disconnect_by_func
 
4472         (void*)wx_frozen_widget_realize
, 
4476     GdkWindow
* window 
= w
->window
; 
4477     if (w 
== win
->m_wxwindow
) 
4478         window 
= win
->GTKGetDrawingWindow(); 
4479     gdk_window_freeze_updates(window
); 
4484 void wxWindowGTK::GTKFreezeWidget(GtkWidget 
*w
) 
4486     if ( !w 
|| GTK_WIDGET_NO_WINDOW(w
) ) 
4487         return; // window-less widget, cannot be frozen 
4489     if ( !GTK_WIDGET_REALIZED(w
) ) 
4491         // we can't thaw unrealized widgets because they don't have GdkWindow, 
4492         // so set it up to be done immediately after realization: 
4493         g_signal_connect_after
 
4497             G_CALLBACK(wx_frozen_widget_realize
), 
4503     GdkWindow
* window 
= w
->window
; 
4504     if (w 
== m_wxwindow
) 
4505         window 
= GTKGetDrawingWindow(); 
4506     gdk_window_freeze_updates(window
); 
4509 void wxWindowGTK::GTKThawWidget(GtkWidget 
*w
) 
4511     if ( !w 
|| GTK_WIDGET_NO_WINDOW(w
) ) 
4512         return; // window-less widget, cannot be frozen 
4514     if ( !GTK_WIDGET_REALIZED(w
) ) 
4516         // the widget wasn't realized yet, no need to thaw 
4517         g_signal_handlers_disconnect_by_func
 
4520             (void*)wx_frozen_widget_realize
, 
4526     GdkWindow
* window 
= w
->window
; 
4527     if (w 
== m_wxwindow
) 
4528         window 
= GTKGetDrawingWindow(); 
4529     gdk_window_thaw_updates(window
); 
4532 void wxWindowGTK::DoFreeze() 
4534     GTKFreezeWidget(m_widget
); 
4535     if ( m_wxwindow 
&& m_widget 
!= m_wxwindow 
) 
4536         GTKFreezeWidget(m_wxwindow
); 
4539 void wxWindowGTK::DoThaw() 
4541     GTKThawWidget(m_widget
); 
4542     if ( m_wxwindow 
&& m_widget 
!= m_wxwindow 
) 
4543         GTKThawWidget(m_wxwindow
);