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, I use idle time 
 187    to set the cursor over and over again, starting from the toplevel windows 
 188    and ending with the youngest generation (speaking of parent and child windows). 
 189    Also don't forget that cursors (like much else) are connected to GdkWindows, 
 190    not GtkWidgets and that the "window" field of a GtkWidget might very well 
 191    point to the GdkWindow of the parent widget (-> "window-less widget") and 
 192    that the two obviously have very different meanings. 
 196 //----------------------------------------------------------------------------- 
 198 //----------------------------------------------------------------------------- 
 200 // Don't allow event propagation during drag 
 201 bool g_blockEventsOnDrag
; 
 202 // Don't allow mouse event propagation during scroll 
 203 bool g_blockEventsOnScroll
; 
 204 extern wxCursor   g_globalCursor
; 
 206 // mouse capture state: the window which has it and if the mouse is currently 
 208 static wxWindowGTK  
*g_captureWindow 
= NULL
; 
 209 static bool g_captureWindowHasMouse 
= false; 
 211 // The window that currently has focus: 
 212 static wxWindowGTK 
*gs_currentFocus 
= NULL
; 
 213 // The window that is scheduled to get focus in the next event loop iteration 
 214 // or NULL if there's no pending focus change: 
 215 static wxWindowGTK 
*gs_pendingFocus 
= NULL
; 
 217 // the window that has deferred focus-out event pending, if any (see 
 218 // GTKAddDeferredFocusOut() for details) 
 219 static wxWindowGTK 
*gs_deferredFocusOut 
= NULL
; 
 221 // global variables because GTK+ DnD want to have the 
 222 // mouse event that caused it 
 223 GdkEvent    
*g_lastMouseEvent 
= NULL
; 
 224 int          g_lastButtonNumber 
= 0; 
 226 //----------------------------------------------------------------------------- 
 228 //----------------------------------------------------------------------------- 
 230 // the trace mask used for the focus debugging messages 
 231 #define TRACE_FOCUS wxT("focus") 
 233 //----------------------------------------------------------------------------- 
 234 // missing gdk functions 
 235 //----------------------------------------------------------------------------- 
 238 gdk_window_warp_pointer (GdkWindow      
*window
, 
 243     window 
= gdk_get_default_root_window(); 
 245   if (!GDK_WINDOW_DESTROYED(window
)) 
 247       XWarpPointer (GDK_WINDOW_XDISPLAY(window
), 
 248                     None
,              /* not source window -> move from anywhere */ 
 249                     GDK_WINDOW_XID(window
),  /* dest window */ 
 250                     0, 0, 0, 0,        /* not source window -> move from anywhere */ 
 256 //----------------------------------------------------------------------------- 
 257 // "size_request" of m_widget 
 258 //----------------------------------------------------------------------------- 
 262 wxgtk_window_size_request_callback(GtkWidget 
* WXUNUSED(widget
), 
 263                                    GtkRequisition 
*requisition
, 
 267     win
->GetSize( &w
, &h 
); 
 273     requisition
->height 
= h
; 
 274     requisition
->width 
= w
; 
 278 //----------------------------------------------------------------------------- 
 279 // "expose_event" of m_wxwindow 
 280 //----------------------------------------------------------------------------- 
 284 gtk_window_expose_callback( GtkWidget
* widget
, 
 285                             GdkEventExpose 
*gdk_event
, 
 288     if (gdk_event
->window 
== widget
->window
) 
 290         win
->GetUpdateRegion() = wxRegion( gdk_event
->region 
); 
 291         win
->GtkSendPaintEvents(); 
 293     // Let parent window draw window-less widgets 
 298 #ifndef __WXUNIVERSAL__ 
 299 //----------------------------------------------------------------------------- 
 300 // "expose_event" from m_wxwindow->parent, for drawing border 
 301 //----------------------------------------------------------------------------- 
 305 expose_event_border(GtkWidget
* widget
, GdkEventExpose
* gdk_event
, wxWindow
* win
) 
 307     if (gdk_event
->window 
!= widget
->window
) 
 310     const GtkAllocation
& alloc 
= win
->m_wxwindow
->allocation
; 
 311     const int x 
= alloc
.x
; 
 312     const int y 
= alloc
.y
; 
 313     const int w 
= alloc
.width
; 
 314     const int h 
= alloc
.height
; 
 316     if (w 
<= 0 || h 
<= 0) 
 319     if (win
->HasFlag(wxBORDER_SIMPLE
)) 
 321         gdk_draw_rectangle(gdk_event
->window
, 
 322             widget
->style
->black_gc
, false, x
, y
, w 
- 1, h 
- 1); 
 326         GtkShadowType shadow 
= GTK_SHADOW_IN
; 
 327         if (win
->HasFlag(wxBORDER_RAISED
)) 
 328             shadow 
= GTK_SHADOW_OUT
; 
 330         // Style detail to use 
 332         if (win
->m_widget 
== win
->m_wxwindow
) 
 333             // for non-scrollable wxWindows 
 336             // for scrollable ones 
 340            win
->m_wxwindow
->style
, gdk_event
->window
, GTK_STATE_NORMAL
, 
 341            shadow
, NULL
, wxGTKPrivate::GetEntryWidget(), detail
, x
, y
, w
, h
); 
 347 //----------------------------------------------------------------------------- 
 348 // "parent_set" from m_wxwindow 
 349 //----------------------------------------------------------------------------- 
 353 parent_set(GtkWidget
* widget
, GtkObject
* old_parent
, wxWindow
* win
) 
 357         g_signal_handlers_disconnect_by_func( 
 358             old_parent
, (void*)expose_event_border
, win
); 
 362         g_signal_connect_after(widget
->parent
, "expose_event", 
 363             G_CALLBACK(expose_event_border
), win
); 
 367 #endif // !__WXUNIVERSAL__ 
 369 //----------------------------------------------------------------------------- 
 370 // "key_press_event" from any window 
 371 //----------------------------------------------------------------------------- 
 373 // These are used when transforming Ctrl-alpha to ascii values 1-26 
 374 inline bool wxIsLowerChar(int code
) 
 376     return (code 
>= 'a' && code 
<= 'z' ); 
 379 inline bool wxIsUpperChar(int code
) 
 381     return (code 
>= 'A' && code 
<= 'Z' ); 
 385 // set WXTRACE to this to see the key event codes on the console 
 386 #define TRACE_KEYS  wxT("keyevent") 
 388 // translates an X key symbol to WXK_XXX value 
 390 // if isChar is true it means that the value returned will be used for EVT_CHAR 
 391 // event and then we choose the logical WXK_XXX, i.e. '/' for GDK_KP_Divide, 
 392 // for example, while if it is false it means that the value is going to be 
 393 // used for KEY_DOWN/UP events and then we translate GDK_KP_Divide to 
 395 static long wxTranslateKeySymToWXKey(KeySym keysym
, bool isChar
) 
 401         // Shift, Control and Alt don't generate the CHAR events at all 
 404             key_code 
= isChar 
? 0 : WXK_SHIFT
; 
 408             key_code 
= isChar 
? 0 : WXK_CONTROL
; 
 416             key_code 
= isChar 
? 0 : WXK_ALT
; 
 419         // neither do the toggle modifies 
 420         case GDK_Scroll_Lock
: 
 421             key_code 
= isChar 
? 0 : WXK_SCROLL
; 
 425             key_code 
= isChar 
? 0 : WXK_CAPITAL
; 
 429             key_code 
= isChar 
? 0 : WXK_NUMLOCK
; 
 433         // various other special keys 
 446         case GDK_ISO_Left_Tab
: 
 453             key_code 
= WXK_RETURN
; 
 457             key_code 
= WXK_CLEAR
; 
 461             key_code 
= WXK_PAUSE
; 
 465             key_code 
= WXK_SELECT
; 
 469             key_code 
= WXK_PRINT
; 
 473             key_code 
= WXK_EXECUTE
; 
 477             key_code 
= WXK_ESCAPE
; 
 480         // cursor and other extended keyboard keys 
 482             key_code 
= WXK_DELETE
; 
 498             key_code 
= WXK_RIGHT
; 
 505         case GDK_Prior
:     // == GDK_Page_Up 
 506             key_code 
= WXK_PAGEUP
; 
 509         case GDK_Next
:      // == GDK_Page_Down 
 510             key_code 
= WXK_PAGEDOWN
; 
 522             key_code 
= WXK_INSERT
; 
 537             key_code 
= (isChar 
? '0' : int(WXK_NUMPAD0
)) + keysym 
- GDK_KP_0
; 
 541             key_code 
= isChar 
? ' ' : int(WXK_NUMPAD_SPACE
); 
 545             key_code 
= isChar 
? WXK_TAB 
: WXK_NUMPAD_TAB
; 
 549             key_code 
= isChar 
? WXK_RETURN 
: WXK_NUMPAD_ENTER
; 
 553             key_code 
= isChar 
? WXK_F1 
: WXK_NUMPAD_F1
; 
 557             key_code 
= isChar 
? WXK_F2 
: WXK_NUMPAD_F2
; 
 561             key_code 
= isChar 
? WXK_F3 
: WXK_NUMPAD_F3
; 
 565             key_code 
= isChar 
? WXK_F4 
: WXK_NUMPAD_F4
; 
 569             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_HOME
; 
 573             key_code 
= isChar 
? WXK_LEFT 
: WXK_NUMPAD_LEFT
; 
 577             key_code 
= isChar 
? WXK_UP 
: WXK_NUMPAD_UP
; 
 581             key_code 
= isChar 
? WXK_RIGHT 
: WXK_NUMPAD_RIGHT
; 
 585             key_code 
= isChar 
? WXK_DOWN 
: WXK_NUMPAD_DOWN
; 
 588         case GDK_KP_Prior
: // == GDK_KP_Page_Up 
 589             key_code 
= isChar 
? WXK_PAGEUP 
: WXK_NUMPAD_PAGEUP
; 
 592         case GDK_KP_Next
: // == GDK_KP_Page_Down 
 593             key_code 
= isChar 
? WXK_PAGEDOWN 
: WXK_NUMPAD_PAGEDOWN
; 
 597             key_code 
= isChar 
? WXK_END 
: WXK_NUMPAD_END
; 
 601             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_BEGIN
; 
 605             key_code 
= isChar 
? WXK_INSERT 
: WXK_NUMPAD_INSERT
; 
 609             key_code 
= isChar 
? WXK_DELETE 
: WXK_NUMPAD_DELETE
; 
 613             key_code 
= isChar 
? '=' : int(WXK_NUMPAD_EQUAL
); 
 616         case GDK_KP_Multiply
: 
 617             key_code 
= isChar 
? '*' : int(WXK_NUMPAD_MULTIPLY
); 
 621             key_code 
= isChar 
? '+' : int(WXK_NUMPAD_ADD
); 
 624         case GDK_KP_Separator
: 
 625             // FIXME: what is this? 
 626             key_code 
= isChar 
? '.' : int(WXK_NUMPAD_SEPARATOR
); 
 629         case GDK_KP_Subtract
: 
 630             key_code 
= isChar 
? '-' : int(WXK_NUMPAD_SUBTRACT
); 
 634             key_code 
= isChar 
? '.' : int(WXK_NUMPAD_DECIMAL
); 
 638             key_code 
= isChar 
? '/' : int(WXK_NUMPAD_DIVIDE
); 
 655             key_code 
= WXK_F1 
+ keysym 
- GDK_F1
; 
 665 static inline bool wxIsAsciiKeysym(KeySym ks
) 
 670 static void wxFillOtherKeyEventFields(wxKeyEvent
& event
, 
 672                                       GdkEventKey 
*gdk_event
) 
 676     GdkModifierType state
; 
 677     if (gdk_event
->window
) 
 678         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
 680     event
.SetTimestamp( gdk_event
->time 
); 
 681     event
.SetId(win
->GetId()); 
 682     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
) != 0; 
 683     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
) != 0; 
 684     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
) != 0; 
 685     event
.m_metaDown 
= (gdk_event
->state 
& GDK_META_MASK
) != 0; 
 686     event
.m_rawCode 
= (wxUint32
) gdk_event
->keyval
; 
 687     event
.m_rawFlags 
= 0; 
 689     event
.m_uniChar 
= gdk_keyval_to_unicode(gdk_event
->keyval
); 
 691     wxGetMousePosition( &x
, &y 
); 
 692     win
->ScreenToClient( &x
, &y 
); 
 695     event
.SetEventObject( win 
); 
 700 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
, 
 702                            GdkEventKey 
*gdk_event
) 
 704     // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string 
 705     //     but only event->keyval which is quite useless to us, so remember 
 706     //     the last character from GDK_KEY_PRESS and reuse it as last resort 
 708     // NB: should be MT-safe as we're always called from the main thread only 
 713     } s_lastKeyPress 
= { 0, 0 }; 
 715     KeySym keysym 
= gdk_event
->keyval
; 
 717     wxLogTrace(TRACE_KEYS
, wxT("Key %s event: keysym = %ld"), 
 718                event
.GetEventType() == wxEVT_KEY_UP 
? wxT("release") 
 722     long key_code 
= wxTranslateKeySymToWXKey(keysym
, false /* !isChar */); 
 726         // do we have the translation or is it a plain ASCII character? 
 727         if ( (gdk_event
->length 
== 1) || wxIsAsciiKeysym(keysym
) ) 
 729             // we should use keysym if it is ASCII as X does some translations 
 730             // like "I pressed while Control is down" => "Ctrl-I" == "TAB" 
 731             // which we don't want here (but which we do use for OnChar()) 
 732             if ( !wxIsAsciiKeysym(keysym
) ) 
 734                 keysym 
= (KeySym
)gdk_event
->string
[0]; 
 737             // we want to always get the same key code when the same key is 
 738             // pressed regardless of the state of the modifiers, i.e. on a 
 739             // standard US keyboard pressing '5' or '%' ('5' key with 
 740             // Shift) should result in the same key code in OnKeyDown(): 
 741             // '5' (although OnChar() will get either '5' or '%'). 
 743             // to do it we first translate keysym to keycode (== scan code) 
 744             // and then back but always using the lower register 
 745             Display 
*dpy 
= (Display 
*)wxGetDisplay(); 
 746             KeyCode keycode 
= XKeysymToKeycode(dpy
, keysym
); 
 748             wxLogTrace(TRACE_KEYS
, wxT("\t-> keycode %d"), keycode
); 
 750             KeySym keysymNormalized 
= XKeycodeToKeysym(dpy
, keycode
, 0); 
 752             // use the normalized, i.e. lower register, keysym if we've 
 754             key_code 
= keysymNormalized 
? keysymNormalized 
: keysym
; 
 756             // as explained above, we want to have lower register key codes 
 757             // normally but for the letter keys we want to have the upper ones 
 759             // NB: don't use XConvertCase() here, we want to do it for letters 
 761             key_code 
= toupper(key_code
); 
 763         else // non ASCII key, what to do? 
 765             // by default, ignore it 
 768             // but if we have cached information from the last KEY_PRESS 
 769             if ( gdk_event
->type 
== GDK_KEY_RELEASE 
) 
 772                 if ( keysym 
== s_lastKeyPress
.keysym 
) 
 774                     key_code 
= s_lastKeyPress
.keycode
; 
 779         if ( gdk_event
->type 
== GDK_KEY_PRESS 
) 
 781             // remember it to be reused for KEY_UP event later 
 782             s_lastKeyPress
.keysym 
= keysym
; 
 783             s_lastKeyPress
.keycode 
= key_code
; 
 787     wxLogTrace(TRACE_KEYS
, wxT("\t-> wxKeyCode %ld"), key_code
); 
 789     // sending unknown key events doesn't really make sense 
 793     // now fill all the other fields 
 794     wxFillOtherKeyEventFields(event
, win
, gdk_event
); 
 796     event
.m_keyCode 
= key_code
; 
 798     if ( gdk_event
->type 
== GDK_KEY_PRESS 
||  gdk_event
->type 
== GDK_KEY_RELEASE 
) 
 800         event
.m_uniChar 
= key_code
; 
 810     GtkIMContext 
*context
; 
 811     GdkEventKey  
*lastKeyEvent
; 
 815         context 
= gtk_im_multicontext_new(); 
 820         g_object_unref (context
); 
 826 gtk_window_key_press_callback( GtkWidget 
*WXUNUSED(widget
), 
 827                                GdkEventKey 
*gdk_event
, 
 832     if (g_blockEventsOnDrag
) 
 835     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
 837     bool return_after_IM 
= false; 
 839     if( wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
 841         // Emit KEY_DOWN event 
 842         ret 
= win
->HandleWindowEvent( event 
); 
 846         // Return after IM processing as we cannot do 
 847         // anything with it anyhow. 
 848         return_after_IM 
= true; 
 851     if ((!ret
) && (win
->m_imData 
!= NULL
)) 
 853         // We should let GTK+ IM filter key event first. According to GTK+ 2.0 API 
 854         // docs, if IM filter returns true, no further processing should be done. 
 855         // we should send the key_down event anyway. 
 856         bool intercepted_by_IM 
= gtk_im_context_filter_keypress(win
->m_imData
->context
, gdk_event
); 
 857         win
->m_imData
->lastKeyEvent 
= NULL
; 
 858         if (intercepted_by_IM
) 
 860             wxLogTrace(TRACE_KEYS
, wxT("Key event intercepted by IM")); 
 871         wxWindowGTK 
*ancestor 
= win
; 
 874             int command 
= ancestor
->GetAcceleratorTable()->GetCommand( event 
); 
 877                 wxCommandEvent 
menu_event( wxEVT_COMMAND_MENU_SELECTED
, command 
); 
 878                 ret 
= ancestor
->HandleWindowEvent( menu_event 
); 
 882                     // if the accelerator wasn't handled as menu event, try 
 883                     // it as button click (for compatibility with other 
 885                     wxCommandEvent 
button_event( wxEVT_COMMAND_BUTTON_CLICKED
, command 
); 
 886                     ret 
= ancestor
->HandleWindowEvent( button_event 
); 
 891             if (ancestor
->IsTopLevel()) 
 893             ancestor 
= ancestor
->GetParent(); 
 896 #endif // wxUSE_ACCEL 
 898     // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x 
 899     // will only be sent if it is not in an accelerator table. 
 903         KeySym keysym 
= gdk_event
->keyval
; 
 904         // Find key code for EVT_CHAR and EVT_CHAR_HOOK events 
 905         key_code 
= wxTranslateKeySymToWXKey(keysym
, true /* isChar */); 
 908             if ( wxIsAsciiKeysym(keysym
) ) 
 911                 key_code 
= (unsigned char)keysym
; 
 913             // gdk_event->string is actually deprecated 
 914             else if ( gdk_event
->length 
== 1 ) 
 916                 key_code 
= (unsigned char)gdk_event
->string
[0]; 
 922             wxLogTrace(TRACE_KEYS
, wxT("Char event: %ld"), key_code
); 
 924             event
.m_keyCode 
= key_code
; 
 926             // To conform to the docs we need to translate Ctrl-alpha 
 927             // characters to values in the range 1-26. 
 928             if ( event
.ControlDown() && 
 929                  ( wxIsLowerChar(key_code
) || wxIsUpperChar(key_code
) )) 
 931                 if ( wxIsLowerChar(key_code
) ) 
 932                     event
.m_keyCode 
= key_code 
- 'a' + 1; 
 933                 if ( wxIsUpperChar(key_code
) ) 
 934                     event
.m_keyCode 
= key_code 
- 'A' + 1; 
 936                 event
.m_uniChar 
= event
.m_keyCode
; 
 940             // Implement OnCharHook by checking ancestor top level windows 
 941             wxWindow 
*parent 
= win
; 
 942             while (parent 
&& !parent
->IsTopLevel()) 
 943                 parent 
= parent
->GetParent(); 
 946                 event
.SetEventType( wxEVT_CHAR_HOOK 
); 
 947                 ret 
= parent
->HandleWindowEvent( event 
); 
 952                 event
.SetEventType(wxEVT_CHAR
); 
 953                 ret 
= win
->HandleWindowEvent( event 
); 
 964 gtk_wxwindow_commit_cb (GtkIMContext 
* WXUNUSED(context
), 
 968     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
 970     // take modifiers, cursor position, timestamp etc. from the last 
 971     // key_press_event that was fed into Input Method: 
 972     if (window
->m_imData
->lastKeyEvent
) 
 974         wxFillOtherKeyEventFields(event
, 
 975                                   window
, window
->m_imData
->lastKeyEvent
); 
 979         event
.SetEventObject( window 
); 
 982     const wxString 
data(wxGTK_CONV_BACK_SYS(str
)); 
 988     // Implement OnCharHook by checking ancestor top level windows 
 989     wxWindow 
*parent 
= window
; 
 990     while (parent 
&& !parent
->IsTopLevel()) 
 991         parent 
= parent
->GetParent(); 
 993     for( wxString::const_iterator pstr 
= data
.begin(); pstr 
!= data
.end(); ++pstr 
) 
 996         event
.m_uniChar 
= *pstr
; 
 997         // Backward compatible for ISO-8859-1 
 998         event
.m_keyCode 
= *pstr 
< 256 ? event
.m_uniChar 
: 0; 
 999         wxLogTrace(TRACE_KEYS
, wxT("IM sent character '%c'"), event
.m_uniChar
); 
1001         event
.m_keyCode 
= (char)*pstr
; 
1002 #endif  // wxUSE_UNICODE 
1004         // To conform to the docs we need to translate Ctrl-alpha 
1005         // characters to values in the range 1-26. 
1006         if ( event
.ControlDown() && 
1007              ( wxIsLowerChar(*pstr
) || wxIsUpperChar(*pstr
) )) 
1009             if ( wxIsLowerChar(*pstr
) ) 
1010                 event
.m_keyCode 
= *pstr 
- 'a' + 1; 
1011             if ( wxIsUpperChar(*pstr
) ) 
1012                 event
.m_keyCode 
= *pstr 
- 'A' + 1; 
1014             event
.m_keyCode 
= *pstr 
- 'a' + 1; 
1016             event
.m_uniChar 
= event
.m_keyCode
; 
1022             event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1023             ret 
= parent
->HandleWindowEvent( event 
); 
1028             event
.SetEventType(wxEVT_CHAR
); 
1029             ret 
= window
->HandleWindowEvent( event 
); 
1036 //----------------------------------------------------------------------------- 
1037 // "key_release_event" from any window 
1038 //----------------------------------------------------------------------------- 
1042 gtk_window_key_release_callback( GtkWidget 
* WXUNUSED(widget
), 
1043                                  GdkEventKey 
*gdk_event
, 
1049     if (g_blockEventsOnDrag
) 
1052     wxKeyEvent 
event( wxEVT_KEY_UP 
); 
1053     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1055         // unknown key pressed, ignore (the event would be useless anyhow) 
1059     return win
->GTKProcessEvent(event
); 
1063 // ============================================================================ 
1065 // ============================================================================ 
1067 // ---------------------------------------------------------------------------- 
1068 // mouse event processing helpers 
1069 // ---------------------------------------------------------------------------- 
1071 // init wxMouseEvent with the info from GdkEventXXX struct 
1072 template<typename T
> void InitMouseEvent(wxWindowGTK 
*win
, 
1073                                          wxMouseEvent
& event
, 
1076     event
.SetTimestamp( gdk_event
->time 
); 
1077     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
) != 0; 
1078     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
) != 0; 
1079     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
) != 0; 
1080     event
.m_metaDown 
= (gdk_event
->state 
& GDK_META_MASK
) != 0; 
1081     event
.m_leftDown 
= (gdk_event
->state 
& GDK_BUTTON1_MASK
) != 0; 
1082     event
.m_middleDown 
= (gdk_event
->state 
& GDK_BUTTON2_MASK
) != 0; 
1083     event
.m_rightDown 
= (gdk_event
->state 
& GDK_BUTTON3_MASK
) != 0; 
1084     event
.m_aux1Down 
= (gdk_event
->state 
& GDK_BUTTON4_MASK
) != 0; 
1085     event
.m_aux2Down 
= (gdk_event
->state 
& GDK_BUTTON5_MASK
) != 0; 
1087     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1088     event
.m_x 
= (wxCoord
)gdk_event
->x 
- pt
.x
; 
1089     event
.m_y 
= (wxCoord
)gdk_event
->y 
- pt
.y
; 
1091     if ((win
->m_wxwindow
) && (win
->GetLayoutDirection() == wxLayout_RightToLeft
)) 
1093         // origin in the upper right corner 
1094         int window_width 
= win
->m_wxwindow
->allocation
.width
; 
1095         event
.m_x 
= window_width 
- event
.m_x
; 
1098     event
.SetEventObject( win 
); 
1099     event
.SetId( win
->GetId() ); 
1100     event
.SetTimestamp( gdk_event
->time 
); 
1103 static void AdjustEventButtonState(wxMouseEvent
& event
) 
1105     // GDK reports the old state of the button for a button press event, but 
1106     // for compatibility with MSW and common sense we want m_leftDown be TRUE 
1107     // for a LEFT_DOWN event, not FALSE, so we will invert 
1108     // left/right/middleDown for the corresponding click events 
1110     if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) || 
1111         (event
.GetEventType() == wxEVT_LEFT_DCLICK
) || 
1112         (event
.GetEventType() == wxEVT_LEFT_UP
)) 
1114         event
.m_leftDown 
= !event
.m_leftDown
; 
1118     if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) || 
1119         (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) || 
1120         (event
.GetEventType() == wxEVT_MIDDLE_UP
)) 
1122         event
.m_middleDown 
= !event
.m_middleDown
; 
1126     if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) || 
1127         (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) || 
1128         (event
.GetEventType() == wxEVT_RIGHT_UP
)) 
1130         event
.m_rightDown 
= !event
.m_rightDown
; 
1135 // find the window to send the mouse event too 
1137 wxWindowGTK 
*FindWindowForMouseEvent(wxWindowGTK 
*win
, wxCoord
& x
, wxCoord
& y
) 
1142     if (win
->m_wxwindow
) 
1144         wxPizza
* pizza 
= WX_PIZZA(win
->m_wxwindow
); 
1145         xx 
+= pizza
->m_scroll_x
; 
1146         yy 
+= pizza
->m_scroll_y
; 
1149     wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
1152         wxWindowGTK 
*child 
= node
->GetData(); 
1154         node 
= node
->GetNext(); 
1155         if (!child
->IsShown()) 
1158         if (child
->GTKIsTransparentForMouse()) 
1160             // wxStaticBox is transparent in the box itself 
1161             int xx1 
= child
->m_x
; 
1162             int yy1 
= child
->m_y
; 
1163             int xx2 
= child
->m_x 
+ child
->m_width
; 
1164             int yy2 
= child
->m_y 
+ child
->m_height
; 
1167             if (((xx 
>= xx1
) && (xx 
<= xx1
+10) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1169                 ((xx 
>= xx2
-10) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1171                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy1
+10)) || 
1173                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy2
-1) && (yy 
<= yy2
))) 
1184             if ((child
->m_wxwindow 
== NULL
) && 
1185                 (child
->m_x 
<= xx
) && 
1186                 (child
->m_y 
<= yy
) && 
1187                 (child
->m_x
+child
->m_width  
>= xx
) && 
1188                 (child
->m_y
+child
->m_height 
>= yy
)) 
1201 // ---------------------------------------------------------------------------- 
1202 // common event handlers helpers 
1203 // ---------------------------------------------------------------------------- 
1205 bool wxWindowGTK::GTKProcessEvent(wxEvent
& event
) const 
1207     // nothing special at this level 
1208     return HandleWindowEvent(event
); 
1211 bool wxWindowGTK::GTKShouldIgnoreEvent() const 
1213     return !m_hasVMT 
|| g_blockEventsOnDrag
; 
1216 int wxWindowGTK::GTKCallbackCommonPrologue(GdkEventAny 
*event
) const 
1220     if (g_blockEventsOnDrag
) 
1222     if (g_blockEventsOnScroll
) 
1225     if (!GTKIsOwnWindow(event
->window
)) 
1231 // overloads for all GDK event types we use here: we need to have this as 
1232 // GdkEventXXX can't be implicitly cast to GdkEventAny even if it, in fact, 
1233 // derives from it in the sense that the structs have the same layout 
1234 #define wxDEFINE_COMMON_PROLOGUE_OVERLOAD(T)                                  \ 
1235     static int wxGtkCallbackCommonPrologue(T *event, wxWindowGTK *win)        \ 
1237         return win->GTKCallbackCommonPrologue((GdkEventAny *)event);          \ 
1240 wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventButton
) 
1241 wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventMotion
) 
1242 wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventCrossing
) 
1244 #undef wxDEFINE_COMMON_PROLOGUE_OVERLOAD 
1246 #define wxCOMMON_CALLBACK_PROLOGUE(event, win)                                \ 
1247     const int rc = wxGtkCallbackCommonPrologue(event, win);                   \ 
1251 // all event handlers must have C linkage as they're called from GTK+ C code 
1255 //----------------------------------------------------------------------------- 
1256 // "button_press_event" 
1257 //----------------------------------------------------------------------------- 
1260 gtk_window_button_press_callback( GtkWidget 
*widget
, 
1261                                   GdkEventButton 
*gdk_event
, 
1264     wxCOMMON_CALLBACK_PROLOGUE(gdk_event
, win
); 
1266     g_lastButtonNumber 
= gdk_event
->button
; 
1268     // GDK sends surplus button down events 
1269     // before a double click event. We 
1270     // need to filter these out. 
1271     if ((gdk_event
->type 
== GDK_BUTTON_PRESS
) && (win
->m_wxwindow
)) 
1273         GdkEvent 
*peek_event 
= gdk_event_peek(); 
1276             if ((peek_event
->type 
== GDK_2BUTTON_PRESS
) || 
1277                 (peek_event
->type 
== GDK_3BUTTON_PRESS
)) 
1279                 gdk_event_free( peek_event 
); 
1284                 gdk_event_free( peek_event 
); 
1289     wxEventType event_type 
= wxEVT_NULL
; 
1291     if ( gdk_event
->type 
== GDK_2BUTTON_PRESS 
&& 
1292             gdk_event
->button 
>= 1 && gdk_event
->button 
<= 3 ) 
1294         // Reset GDK internal timestamp variables in order to disable GDK 
1295         // triple click events. GDK will then next time believe no button has 
1296         // been clicked just before, and send a normal button click event. 
1297         GdkDisplay
* display 
= gtk_widget_get_display (widget
); 
1298         display
->button_click_time
[1] = 0; 
1299         display
->button_click_time
[0] = 0; 
1302     if (gdk_event
->button 
== 1) 
1304         // note that GDK generates triple click events which are not supported 
1305         // by wxWidgets but still have to be passed to the app as otherwise 
1306         // clicks would simply go missing 
1307         switch (gdk_event
->type
) 
1309             // we shouldn't get triple clicks at all for GTK2 because we 
1310             // suppress them artificially using the code above but we still 
1311             // should map them to something for GTK1 and not just ignore them 
1312             // as this would lose clicks 
1313             case GDK_3BUTTON_PRESS
:     // we could also map this to DCLICK... 
1314             case GDK_BUTTON_PRESS
: 
1315                 event_type 
= wxEVT_LEFT_DOWN
; 
1318             case GDK_2BUTTON_PRESS
: 
1319                 event_type 
= wxEVT_LEFT_DCLICK
; 
1323                 // just to silence gcc warnings 
1327     else if (gdk_event
->button 
== 2) 
1329         switch (gdk_event
->type
) 
1331             case GDK_3BUTTON_PRESS
: 
1332             case GDK_BUTTON_PRESS
: 
1333                 event_type 
= wxEVT_MIDDLE_DOWN
; 
1336             case GDK_2BUTTON_PRESS
: 
1337                 event_type 
= wxEVT_MIDDLE_DCLICK
; 
1344     else if (gdk_event
->button 
== 3) 
1346         switch (gdk_event
->type
) 
1348             case GDK_3BUTTON_PRESS
: 
1349             case GDK_BUTTON_PRESS
: 
1350                 event_type 
= wxEVT_RIGHT_DOWN
; 
1353             case GDK_2BUTTON_PRESS
: 
1354                 event_type 
= wxEVT_RIGHT_DCLICK
; 
1362     if ( event_type 
== wxEVT_NULL 
) 
1364         // unknown mouse button or click type 
1368     g_lastMouseEvent 
= (GdkEvent
*) gdk_event
; 
1370     wxMouseEvent 
event( event_type 
); 
1371     InitMouseEvent( win
, event
, gdk_event 
); 
1373     AdjustEventButtonState(event
); 
1375     // find the correct window to send the event to: it may be a different one 
1376     // from the one which got it at GTK+ level because some controls don't have 
1377     // their own X window and thus cannot get any events. 
1378     if ( !g_captureWindow 
) 
1379         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1381     // reset the event object and id in case win changed. 
1382     event
.SetEventObject( win 
); 
1383     event
.SetId( win
->GetId() ); 
1385     bool ret 
= win
->GTKProcessEvent( event 
); 
1386     g_lastMouseEvent 
= NULL
; 
1390     if ((event_type 
== wxEVT_LEFT_DOWN
) && !win
->IsOfStandardClass() && 
1391         (gs_currentFocus 
!= win
) /* && win->IsFocusable() */) 
1396     if (event_type 
== wxEVT_RIGHT_DOWN
) 
1398         // generate a "context menu" event: this is similar to right mouse 
1399         // click under many GUIs except that it is generated differently 
1400         // (right up under MSW, ctrl-click under Mac, right down here) and 
1402         // (a) it's a command event and so is propagated to the parent 
1403         // (b) under some ports it can be generated from kbd too 
1404         // (c) it uses screen coords (because of (a)) 
1405         wxContextMenuEvent 
evtCtx( 
1408             win
->ClientToScreen(event
.GetPosition())); 
1409         evtCtx
.SetEventObject(win
); 
1410         return win
->GTKProcessEvent(evtCtx
); 
1416 //----------------------------------------------------------------------------- 
1417 // "button_release_event" 
1418 //----------------------------------------------------------------------------- 
1421 gtk_window_button_release_callback( GtkWidget 
*WXUNUSED(widget
), 
1422                                     GdkEventButton 
*gdk_event
, 
1425     wxCOMMON_CALLBACK_PROLOGUE(gdk_event
, win
); 
1427     g_lastButtonNumber 
= 0; 
1429     wxEventType event_type 
= wxEVT_NULL
; 
1431     switch (gdk_event
->button
) 
1434             event_type 
= wxEVT_LEFT_UP
; 
1438             event_type 
= wxEVT_MIDDLE_UP
; 
1442             event_type 
= wxEVT_RIGHT_UP
; 
1446             // unknown button, don't process 
1450     g_lastMouseEvent 
= (GdkEvent
*) gdk_event
; 
1452     wxMouseEvent 
event( event_type 
); 
1453     InitMouseEvent( win
, event
, gdk_event 
); 
1455     AdjustEventButtonState(event
); 
1457     if ( !g_captureWindow 
) 
1458         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1460     // reset the event object and id in case win changed. 
1461     event
.SetEventObject( win 
); 
1462     event
.SetId( win
->GetId() ); 
1464     bool ret 
= win
->GTKProcessEvent(event
); 
1466     g_lastMouseEvent 
= NULL
; 
1471 //----------------------------------------------------------------------------- 
1472 // "motion_notify_event" 
1473 //----------------------------------------------------------------------------- 
1476 gtk_window_motion_notify_callback( GtkWidget 
* WXUNUSED(widget
), 
1477                                    GdkEventMotion 
*gdk_event
, 
1480     wxCOMMON_CALLBACK_PROLOGUE(gdk_event
, win
); 
1482     if (gdk_event
->is_hint
) 
1486         GdkModifierType state
; 
1487         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1492     g_lastMouseEvent 
= (GdkEvent
*) gdk_event
; 
1494     wxMouseEvent 
event( wxEVT_MOTION 
); 
1495     InitMouseEvent(win
, event
, gdk_event
); 
1497     if ( g_captureWindow 
) 
1499         // synthesise a mouse enter or leave event if needed 
1500         GdkWindow 
*winUnderMouse 
= gdk_window_at_pointer(NULL
, NULL
); 
1501         // This seems to be necessary and actually been added to 
1502         // GDK itself in version 2.0.X 
1505         bool hasMouse 
= winUnderMouse 
== gdk_event
->window
; 
1506         if ( hasMouse 
!= g_captureWindowHasMouse 
) 
1508             // the mouse changed window 
1509             g_captureWindowHasMouse 
= hasMouse
; 
1511             wxMouseEvent 
eventM(g_captureWindowHasMouse 
? wxEVT_ENTER_WINDOW
 
1512                                                         : wxEVT_LEAVE_WINDOW
); 
1513             InitMouseEvent(win
, eventM
, gdk_event
); 
1514             eventM
.SetEventObject(win
); 
1515             win
->GTKProcessEvent(eventM
); 
1520         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1522         // reset the event object and id in case win changed. 
1523         event
.SetEventObject( win 
); 
1524         event
.SetId( win
->GetId() ); 
1527     if ( !g_captureWindow 
) 
1529         wxSetCursorEvent 
cevent( event
.m_x
, event
.m_y 
); 
1530         if (win
->GTKProcessEvent( cevent 
)) 
1532             win
->SetCursor( cevent
.GetCursor() ); 
1536     bool ret 
= win
->GTKProcessEvent(event
); 
1538     g_lastMouseEvent 
= NULL
; 
1543 //----------------------------------------------------------------------------- 
1544 // "scroll_event" (mouse wheel event) 
1545 //----------------------------------------------------------------------------- 
1548 window_scroll_event_hscrollbar(GtkWidget
*, GdkEventScroll
* gdk_event
, wxWindow
* win
) 
1550     if (gdk_event
->direction 
!= GDK_SCROLL_LEFT 
&& 
1551         gdk_event
->direction 
!= GDK_SCROLL_RIGHT
) 
1556     wxMouseEvent 
event(wxEVT_MOUSEWHEEL
); 
1557     InitMouseEvent(win
, event
, gdk_event
); 
1559     GtkRange 
*range 
= win
->m_scrollBar
[wxWindow::ScrollDir_Horz
]; 
1560     if (!range
) return FALSE
; 
1562     if (range 
&& GTK_WIDGET_VISIBLE (range
)) 
1564         GtkAdjustment 
*adj 
= range
->adjustment
; 
1565         gdouble delta 
= adj
->step_increment 
* 3; 
1566         if (gdk_event
->direction 
== GDK_SCROLL_LEFT
) 
1569         gdouble new_value 
= CLAMP (adj
->value 
+ delta
, adj
->lower
, adj
->upper 
- adj
->page_size
); 
1571         gtk_adjustment_set_value (adj
, new_value
); 
1580 window_scroll_event(GtkWidget
*, GdkEventScroll
* gdk_event
, wxWindow
* win
) 
1582     if (gdk_event
->direction 
!= GDK_SCROLL_UP 
&& 
1583         gdk_event
->direction 
!= GDK_SCROLL_DOWN
) 
1588     wxMouseEvent 
event(wxEVT_MOUSEWHEEL
); 
1589     InitMouseEvent(win
, event
, gdk_event
); 
1591     // FIXME: Get these values from GTK or GDK 
1592     event
.m_linesPerAction 
= 3; 
1593     event
.m_wheelDelta 
= 120; 
1594     if (gdk_event
->direction 
== GDK_SCROLL_UP
) 
1595         event
.m_wheelRotation 
= 120; 
1597         event
.m_wheelRotation 
= -120; 
1599     if (win
->GTKProcessEvent(event
)) 
1602     GtkRange 
*range 
= win
->m_scrollBar
[wxWindow::ScrollDir_Vert
]; 
1603     if (!range
) return FALSE
; 
1605     if (range 
&& GTK_WIDGET_VISIBLE (range
)) 
1607         GtkAdjustment 
*adj 
= range
->adjustment
; 
1608         gdouble delta 
= adj
->step_increment 
* 3; 
1609         if (gdk_event
->direction 
== GDK_SCROLL_UP
) 
1612         gdouble new_value 
= CLAMP (adj
->value 
+ delta
, adj
->lower
, adj
->upper 
- adj
->page_size
); 
1614         gtk_adjustment_set_value (adj
, new_value
); 
1622 //----------------------------------------------------------------------------- 
1624 //----------------------------------------------------------------------------- 
1626 static gboolean 
wxgtk_window_popup_menu_callback(GtkWidget
*, wxWindowGTK
* win
) 
1628     wxContextMenuEvent 
event(wxEVT_CONTEXT_MENU
, win
->GetId(), wxPoint(-1, -1)); 
1629     event
.SetEventObject(win
); 
1630     return win
->GTKProcessEvent(event
); 
1633 //----------------------------------------------------------------------------- 
1635 //----------------------------------------------------------------------------- 
1638 gtk_window_focus_in_callback( GtkWidget 
* WXUNUSED(widget
), 
1639                               GdkEventFocus 
*WXUNUSED(event
), 
1642     return win
->GTKHandleFocusIn(); 
1645 //----------------------------------------------------------------------------- 
1646 // "focus_out_event" 
1647 //----------------------------------------------------------------------------- 
1650 gtk_window_focus_out_callback( GtkWidget 
* WXUNUSED(widget
), 
1651                                GdkEventFocus 
* WXUNUSED(gdk_event
), 
1654     return win
->GTKHandleFocusOut(); 
1657 //----------------------------------------------------------------------------- 
1659 //----------------------------------------------------------------------------- 
1662 wx_window_focus_callback(GtkWidget 
*widget
, 
1663                          GtkDirectionType 
WXUNUSED(direction
), 
1666     // the default handler for focus signal in GtkScrolledWindow sets 
1667     // focus to the window itself even if it doesn't accept focus, i.e. has no 
1668     // GTK_CAN_FOCUS in its style -- work around this by forcibly preventing 
1669     // the signal from reaching gtk_scrolled_window_focus() if we don't have 
1670     // any children which might accept focus (we know we don't accept the focus 
1671     // ourselves as this signal is only connected in this case) 
1672     if ( win
->GetChildren().empty() ) 
1673         g_signal_stop_emission_by_name(widget
, "focus"); 
1675     // we didn't change the focus 
1679 //----------------------------------------------------------------------------- 
1680 // "enter_notify_event" 
1681 //----------------------------------------------------------------------------- 
1684 gtk_window_enter_callback( GtkWidget 
*widget
, 
1685                            GdkEventCrossing 
*gdk_event
, 
1688     wxCOMMON_CALLBACK_PROLOGUE(gdk_event
, win
); 
1690     // Event was emitted after a grab 
1691     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
1695     GdkModifierType state 
= (GdkModifierType
)0; 
1697     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
1699     wxMouseEvent 
event( wxEVT_ENTER_WINDOW 
); 
1700     InitMouseEvent(win
, event
, gdk_event
); 
1701     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1702     event
.m_x 
= x 
+ pt
.x
; 
1703     event
.m_y 
= y 
+ pt
.y
; 
1705     if ( !g_captureWindow 
) 
1707         wxSetCursorEvent 
cevent( event
.m_x
, event
.m_y 
); 
1708         if (win
->GTKProcessEvent( cevent 
)) 
1710             win
->SetCursor( cevent
.GetCursor() ); 
1714     return win
->GTKProcessEvent(event
); 
1717 //----------------------------------------------------------------------------- 
1718 // "leave_notify_event" 
1719 //----------------------------------------------------------------------------- 
1722 gtk_window_leave_callback( GtkWidget 
*widget
, 
1723                            GdkEventCrossing 
*gdk_event
, 
1726     wxCOMMON_CALLBACK_PROLOGUE(gdk_event
, win
); 
1728     // Event was emitted after an ungrab 
1729     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
1731     wxMouseEvent 
event( wxEVT_LEAVE_WINDOW 
); 
1735     GdkModifierType state 
= (GdkModifierType
)0; 
1737     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
1739     InitMouseEvent(win
, event
, gdk_event
); 
1741     return win
->GTKProcessEvent(event
); 
1744 //----------------------------------------------------------------------------- 
1745 // "value_changed" from scrollbar 
1746 //----------------------------------------------------------------------------- 
1749 gtk_scrollbar_value_changed(GtkRange
* range
, wxWindow
* win
) 
1751     wxEventType eventType 
= win
->GTKGetScrollEventType(range
); 
1752     if (eventType 
!= wxEVT_NULL
) 
1754         // Convert scroll event type to scrollwin event type 
1755         eventType 
+= wxEVT_SCROLLWIN_TOP 
- wxEVT_SCROLL_TOP
; 
1757         // find the scrollbar which generated the event 
1758         wxWindowGTK::ScrollDir dir 
= win
->ScrollDirFromRange(range
); 
1760         // generate the corresponding wx event 
1761         const int orient 
= wxWindow::OrientFromScrollDir(dir
); 
1762         wxScrollWinEvent 
event(eventType
, win
->GetScrollPos(orient
), orient
); 
1763         event
.SetEventObject(win
); 
1765         win
->GTKProcessEvent(event
); 
1769 //----------------------------------------------------------------------------- 
1770 // "button_press_event" from scrollbar 
1771 //----------------------------------------------------------------------------- 
1774 gtk_scrollbar_button_press_event(GtkRange
*, GdkEventButton
*, wxWindow
* win
) 
1776     g_blockEventsOnScroll 
= true; 
1777     win
->m_mouseButtonDown 
= true; 
1782 //----------------------------------------------------------------------------- 
1783 // "event_after" from scrollbar 
1784 //----------------------------------------------------------------------------- 
1787 gtk_scrollbar_event_after(GtkRange
* range
, GdkEvent
* event
, wxWindow
* win
) 
1789     if (event
->type 
== GDK_BUTTON_RELEASE
) 
1791         g_signal_handlers_block_by_func(range
, (void*)gtk_scrollbar_event_after
, win
); 
1793         const int orient 
= wxWindow::OrientFromScrollDir( 
1794                                         win
->ScrollDirFromRange(range
)); 
1795         wxScrollWinEvent 
evt(wxEVT_SCROLLWIN_THUMBRELEASE
, 
1796                                 win
->GetScrollPos(orient
), orient
); 
1797         evt
.SetEventObject(win
); 
1798         win
->GTKProcessEvent(evt
); 
1802 //----------------------------------------------------------------------------- 
1803 // "button_release_event" from scrollbar 
1804 //----------------------------------------------------------------------------- 
1807 gtk_scrollbar_button_release_event(GtkRange
* range
, GdkEventButton
*, wxWindow
* win
) 
1809     g_blockEventsOnScroll 
= false; 
1810     win
->m_mouseButtonDown 
= false; 
1811     // If thumb tracking 
1812     if (win
->m_isScrolling
) 
1814         win
->m_isScrolling 
= false; 
1815         // Hook up handler to send thumb release event after this emission is finished. 
1816         // To allow setting scroll position from event handler, sending event must 
1817         // be deferred until after the GtkRange handler for this signal has run 
1818         g_signal_handlers_unblock_by_func(range
, (void*)gtk_scrollbar_event_after
, win
); 
1824 //----------------------------------------------------------------------------- 
1825 // "realize" from m_widget 
1826 //----------------------------------------------------------------------------- 
1829 gtk_window_realized_callback(GtkWidget
* widget
, wxWindow
* win
) 
1833         gtk_im_context_set_client_window( win
->m_imData
->context
, 
1837     // We cannot set colours and fonts before the widget 
1838     // been realized, so we do this directly after realization 
1839     // or otherwise in idle time 
1841     if (win
->m_needsStyleChange
) 
1843         win
->SetBackgroundStyle(win
->GetBackgroundStyle()); 
1844         win
->m_needsStyleChange 
= false; 
1847     wxWindowCreateEvent 
event( win 
); 
1848     event
.SetEventObject( win 
); 
1849     win
->GTKProcessEvent( event 
); 
1852 //----------------------------------------------------------------------------- 
1853 // "size_allocate" from m_wxwindow or m_widget 
1854 //----------------------------------------------------------------------------- 
1857 size_allocate(GtkWidget
*, GtkAllocation
* alloc
, wxWindow
* win
) 
1859     int w 
= alloc
->width
; 
1860     int h 
= alloc
->height
; 
1861     if (win
->m_wxwindow
) 
1863         int border_x
, border_y
; 
1864         WX_PIZZA(win
->m_wxwindow
)->get_border_widths(border_x
, border_y
); 
1870     if (win
->m_oldClientWidth 
!= w 
|| win
->m_oldClientHeight 
!= h
) 
1872         win
->m_oldClientWidth  
= w
; 
1873         win
->m_oldClientHeight 
= h
; 
1874         // this callback can be connected to m_wxwindow, 
1875         // so always get size from m_widget->allocation 
1876         win
->m_width  
= win
->m_widget
->allocation
.width
; 
1877         win
->m_height 
= win
->m_widget
->allocation
.height
; 
1878         if (!win
->m_nativeSizeEvent
) 
1880             wxSizeEvent 
event(win
->GetSize(), win
->GetId()); 
1881             event
.SetEventObject(win
); 
1882             win
->GTKProcessEvent(event
); 
1887 //----------------------------------------------------------------------------- 
1889 //----------------------------------------------------------------------------- 
1891 #if GTK_CHECK_VERSION(2, 8, 0) 
1893 gtk_window_grab_broken( GtkWidget
*, 
1894                         GdkEventGrabBroken 
*event
, 
1897     // Mouse capture has been lost involuntarily, notify the application 
1898     if(!event
->keyboard 
&& wxWindow::GetCapture() == win
) 
1900         wxMouseCaptureLostEvent 
evt( win
->GetId() ); 
1901         evt
.SetEventObject( win 
); 
1902         win
->HandleWindowEvent( evt 
); 
1908 //----------------------------------------------------------------------------- 
1910 //----------------------------------------------------------------------------- 
1913 void gtk_window_style_set_callback( GtkWidget 
*WXUNUSED(widget
), 
1914                                GtkStyle 
*previous_style
, 
1917     if (win 
&& previous_style
) 
1919         wxSysColourChangedEvent event
; 
1920         event
.SetEventObject(win
); 
1922         win
->GTKProcessEvent( event 
); 
1928 // ---------------------------------------------------------------------------- 
1929 // this wxWindowBase function is implemented here (in platform-specific file) 
1930 // because it is static and so couldn't be made virtual 
1931 // ---------------------------------------------------------------------------- 
1933 wxWindow 
*wxWindowBase::DoFindFocus() 
1935     wxWindowGTK 
*focus 
= gs_pendingFocus 
? gs_pendingFocus 
: gs_currentFocus
; 
1936     // the cast is necessary when we compile in wxUniversal mode 
1937     return static_cast<wxWindow
*>(focus
); 
1940 void wxWindowGTK::AddChildGTK(wxWindowGTK
* child
) 
1942     wxASSERT_MSG(m_wxwindow
, "Cannot add a child to a window without a client area"); 
1944     // the window might have been scrolled already, we 
1945     // have to adapt the position 
1946     wxPizza
* pizza 
= WX_PIZZA(m_wxwindow
); 
1947     child
->m_x 
+= pizza
->m_scroll_x
; 
1948     child
->m_y 
+= pizza
->m_scroll_y
; 
1950     gtk_widget_set_size_request( 
1951         child
->m_widget
, child
->m_width
, child
->m_height
); 
1953         GTK_FIXED(m_wxwindow
), child
->m_widget
, child
->m_x
, child
->m_y
); 
1956 //----------------------------------------------------------------------------- 
1958 //----------------------------------------------------------------------------- 
1960 wxWindow 
*wxGetActiveWindow() 
1962     return wxWindow::FindFocus(); 
1966 wxMouseState 
wxGetMouseState() 
1972     GdkModifierType mask
; 
1974     gdk_window_get_pointer(NULL
, &x
, &y
, &mask
); 
1978     ms
.SetLeftDown((mask 
& GDK_BUTTON1_MASK
) != 0); 
1979     ms
.SetMiddleDown((mask 
& GDK_BUTTON2_MASK
) != 0); 
1980     ms
.SetRightDown((mask 
& GDK_BUTTON3_MASK
) != 0); 
1981     ms
.SetAux1Down((mask 
& GDK_BUTTON4_MASK
) != 0); 
1982     ms
.SetAux2Down((mask 
& GDK_BUTTON5_MASK
) != 0); 
1984     ms
.SetControlDown((mask 
& GDK_CONTROL_MASK
) != 0); 
1985     ms
.SetShiftDown((mask 
& GDK_SHIFT_MASK
) != 0); 
1986     ms
.SetAltDown((mask 
& GDK_MOD1_MASK
) != 0); 
1987     ms
.SetMetaDown((mask 
& GDK_META_MASK
) != 0); 
1992 //----------------------------------------------------------------------------- 
1994 //----------------------------------------------------------------------------- 
1996 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
1998 #ifdef __WXUNIVERSAL__ 
1999     IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
) 
2001     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
2002 #endif // __WXUNIVERSAL__/__WXGTK__ 
2004 void wxWindowGTK::Init() 
2009     m_focusWidget 
= NULL
; 
2019     m_showOnIdle 
= false; 
2022     m_nativeSizeEvent 
= false; 
2024     m_isScrolling 
= false; 
2025     m_mouseButtonDown 
= false; 
2027     // initialize scrolling stuff 
2028     for ( int dir 
= 0; dir 
< ScrollDir_Max
; dir
++ ) 
2030         m_scrollBar
[dir
] = NULL
; 
2031         m_scrollPos
[dir
] = 0; 
2035     m_oldClientHeight 
= 0; 
2037     m_clipPaintRegion 
= false; 
2039     m_needsStyleChange 
= false; 
2041     m_cursor 
= *wxSTANDARD_CURSOR
; 
2044     m_dirtyTabOrder 
= false; 
2047 wxWindowGTK::wxWindowGTK() 
2052 wxWindowGTK::wxWindowGTK( wxWindow 
*parent
, 
2057                           const wxString 
&name  
) 
2061     Create( parent
, id
, pos
, size
, style
, name 
); 
2064 bool wxWindowGTK::Create( wxWindow 
*parent
, 
2069                           const wxString 
&name  
) 
2071     // Get default border 
2072     wxBorder border 
= GetBorder(style
); 
2074     style 
&= ~wxBORDER_MASK
; 
2077     if (!PreCreation( parent
, pos
, size 
) || 
2078         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
2080         wxFAIL_MSG( wxT("wxWindowGTK creation failed") ); 
2084         // We should accept the native look 
2086         GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2087         scroll_class
->scrollbar_spacing 
= 0; 
2091     m_wxwindow 
= wxPizza::New(m_windowStyle
); 
2092 #ifndef __WXUNIVERSAL__ 
2093     if (HasFlag(wxPizza::BORDER_STYLES
)) 
2095         g_signal_connect(m_wxwindow
, "parent_set", 
2096             G_CALLBACK(parent_set
), this); 
2099     if (!HasFlag(wxHSCROLL
) && !HasFlag(wxVSCROLL
)) 
2100         m_widget 
= m_wxwindow
; 
2103         m_widget 
= gtk_scrolled_window_new( NULL
, NULL 
); 
2105         GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
2107         // There is a conflict with default bindings at GTK+ 
2108         // level between scrolled windows and notebooks both of which want to use 
2109         // Ctrl-PageUp/Down: scrolled windows for scrolling in the horizontal 
2110         // direction and notebooks for changing pages -- we decide that if we don't 
2111         // have wxHSCROLL style we can safely sacrifice horizontal scrolling if it 
2112         // means we can get working keyboard navigation in notebooks 
2113         if ( !HasFlag(wxHSCROLL
) ) 
2116                 bindings 
= gtk_binding_set_by_class(G_OBJECT_GET_CLASS(m_widget
)); 
2119                 gtk_binding_entry_remove(bindings
, GDK_Page_Up
, GDK_CONTROL_MASK
); 
2120                 gtk_binding_entry_remove(bindings
, GDK_Page_Down
, GDK_CONTROL_MASK
); 
2124         if (HasFlag(wxALWAYS_SHOW_SB
)) 
2126             gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_ALWAYS
, GTK_POLICY_ALWAYS 
); 
2128             scrolledWindow
->hscrollbar_visible 
= TRUE
; 
2129             scrolledWindow
->vscrollbar_visible 
= TRUE
; 
2133             gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
2136         m_scrollBar
[ScrollDir_Horz
] = GTK_RANGE(scrolledWindow
->hscrollbar
); 
2137         m_scrollBar
[ScrollDir_Vert
] = GTK_RANGE(scrolledWindow
->vscrollbar
); 
2138         if (GetLayoutDirection() == wxLayout_RightToLeft
) 
2139             gtk_range_set_inverted( m_scrollBar
[ScrollDir_Horz
], TRUE 
); 
2141         gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
2143         // connect various scroll-related events 
2144         for ( int dir 
= 0; dir 
< ScrollDir_Max
; dir
++ ) 
2146             // these handlers block mouse events to any window during scrolling 
2147             // such as motion events and prevent GTK and wxWidgets from fighting 
2148             // over where the slider should be 
2149             g_signal_connect(m_scrollBar
[dir
], "button_press_event", 
2150                          G_CALLBACK(gtk_scrollbar_button_press_event
), this); 
2151             g_signal_connect(m_scrollBar
[dir
], "button_release_event", 
2152                          G_CALLBACK(gtk_scrollbar_button_release_event
), this); 
2154             gulong handler_id 
= g_signal_connect(m_scrollBar
[dir
], "event_after", 
2155                                 G_CALLBACK(gtk_scrollbar_event_after
), this); 
2156             g_signal_handler_block(m_scrollBar
[dir
], handler_id
); 
2158             // these handlers get notified when scrollbar slider moves 
2159             g_signal_connect_after(m_scrollBar
[dir
], "value_changed", 
2160                          G_CALLBACK(gtk_scrollbar_value_changed
), this); 
2163         gtk_widget_show( m_wxwindow 
); 
2165     g_object_ref(m_widget
); 
2168         m_parent
->DoAddChild( this ); 
2170     m_focusWidget 
= m_wxwindow
; 
2172     SetCanFocus(AcceptsFocus()); 
2179 wxWindowGTK::~wxWindowGTK() 
2183     if (gs_currentFocus 
== this) 
2184         gs_currentFocus 
= NULL
; 
2185     if (gs_pendingFocus 
== this) 
2186         gs_pendingFocus 
= NULL
; 
2188     if ( gs_deferredFocusOut 
== this ) 
2189         gs_deferredFocusOut 
= NULL
; 
2193     // destroy children before destroying this window itself 
2196     // unhook focus handlers to prevent stray events being 
2197     // propagated to this (soon to be) dead object 
2198     if (m_focusWidget 
!= NULL
) 
2200         g_signal_handlers_disconnect_by_func (m_focusWidget
, 
2201                                               (gpointer
) gtk_window_focus_in_callback
, 
2203         g_signal_handlers_disconnect_by_func (m_focusWidget
, 
2204                                               (gpointer
) gtk_window_focus_out_callback
, 
2211     // delete before the widgets to avoid a crash on solaris 
2216         // Note that gtk_widget_destroy() does not destroy the widget, it just 
2217         // emits the "destroy" signal. The widget is not actually destroyed 
2218         // until its reference count drops to zero. 
2219         gtk_widget_destroy(m_widget
); 
2220         // Release our reference, should be the last one 
2221         g_object_unref(m_widget
); 
2227 bool wxWindowGTK::PreCreation( wxWindowGTK 
*parent
, const wxPoint 
&pos
,  const wxSize 
&size 
) 
2229     if ( GTKNeedsParent() ) 
2231         wxCHECK_MSG( parent
, false, wxT("Must have non-NULL parent") ); 
2234     // Use either the given size, or the default if -1 is given. 
2235     // See wxWindowBase for these functions. 
2236     m_width 
= WidthDefault(size
.x
) ; 
2237     m_height 
= HeightDefault(size
.y
); 
2245 void wxWindowGTK::PostCreation() 
2247     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2253             // these get reported to wxWidgets -> wxPaintEvent 
2255             g_signal_connect (m_wxwindow
, "expose_event", 
2256                               G_CALLBACK (gtk_window_expose_callback
), this); 
2258             if (GetLayoutDirection() == wxLayout_LeftToRight
) 
2259                 gtk_widget_set_redraw_on_allocate(m_wxwindow
, HasFlag(wxFULL_REPAINT_ON_RESIZE
)); 
2262         // Create input method handler 
2263         m_imData 
= new wxGtkIMData
; 
2265         // Cannot handle drawing preedited text yet 
2266         gtk_im_context_set_use_preedit( m_imData
->context
, FALSE 
); 
2268         g_signal_connect (m_imData
->context
, "commit", 
2269                           G_CALLBACK (gtk_wxwindow_commit_cb
), this); 
2274     if (!GTK_IS_WINDOW(m_widget
)) 
2276         if (m_focusWidget 
== NULL
) 
2277             m_focusWidget 
= m_widget
; 
2281             g_signal_connect (m_focusWidget
, "focus_in_event", 
2282                           G_CALLBACK (gtk_window_focus_in_callback
), this); 
2283             g_signal_connect (m_focusWidget
, "focus_out_event", 
2284                                 G_CALLBACK (gtk_window_focus_out_callback
), this); 
2288             g_signal_connect_after (m_focusWidget
, "focus_in_event", 
2289                           G_CALLBACK (gtk_window_focus_in_callback
), this); 
2290             g_signal_connect_after (m_focusWidget
, "focus_out_event", 
2291                                 G_CALLBACK (gtk_window_focus_out_callback
), this); 
2295     if ( !AcceptsFocusFromKeyboard() ) 
2299         g_signal_connect(m_widget
, "focus", 
2300                             G_CALLBACK(wx_window_focus_callback
), this); 
2303     // connect to the various key and mouse handlers 
2305     GtkWidget 
*connect_widget 
= GetConnectWidget(); 
2307     ConnectWidget( connect_widget 
); 
2309     /* We cannot set colours, fonts and cursors before the widget has 
2310        been realized, so we do this directly after realization */ 
2311     g_signal_connect (connect_widget
, "realize", 
2312                       G_CALLBACK (gtk_window_realized_callback
), this); 
2316         g_signal_connect(m_wxwindow 
? m_wxwindow 
: m_widget
, "size_allocate", 
2317             G_CALLBACK(size_allocate
), this); 
2320 #if GTK_CHECK_VERSION(2, 8, 0) 
2321     if ( gtk_check_version(2,8,0) == NULL 
) 
2323         // Make sure we can notify the app when mouse capture is lost 
2326             g_signal_connect (m_wxwindow
, "grab_broken_event", 
2327                           G_CALLBACK (gtk_window_grab_broken
), this); 
2330         if ( connect_widget 
!= m_wxwindow 
) 
2332             g_signal_connect (connect_widget
, "grab_broken_event", 
2333                         G_CALLBACK (gtk_window_grab_broken
), this); 
2336 #endif // GTK+ >= 2.8 
2338     if ( GTKShouldConnectSizeRequest() ) 
2340         // This is needed if we want to add our windows into native 
2341         // GTK controls, such as the toolbar. With this callback, the 
2342         // toolbar gets to know the correct size (the one set by the 
2343         // programmer). Sadly, it misbehaves for wxComboBox. 
2344         g_signal_connect (m_widget
, "size_request", 
2345                           G_CALLBACK (wxgtk_window_size_request_callback
), 
2349     InheritAttributes(); 
2353     SetLayoutDirection(wxLayout_Default
); 
2355     // unless the window was created initially hidden (i.e. Hide() had been 
2356     // called before Create()), we should show it at GTK+ level as well 
2358         gtk_widget_show( m_widget 
); 
2361 gulong 
wxWindowGTK::GTKConnectWidget(const char *signal
, void (*callback
)()) 
2363     return g_signal_connect(m_widget
, signal
, callback
, this); 
2366 void wxWindowGTK::ConnectWidget( GtkWidget 
*widget 
) 
2368     g_signal_connect (widget
, "key_press_event", 
2369                       G_CALLBACK (gtk_window_key_press_callback
), this); 
2370     g_signal_connect (widget
, "key_release_event", 
2371                       G_CALLBACK (gtk_window_key_release_callback
), this); 
2372     g_signal_connect (widget
, "button_press_event", 
2373                       G_CALLBACK (gtk_window_button_press_callback
), this); 
2374     g_signal_connect (widget
, "button_release_event", 
2375                       G_CALLBACK (gtk_window_button_release_callback
), this); 
2376     g_signal_connect (widget
, "motion_notify_event", 
2377                       G_CALLBACK (gtk_window_motion_notify_callback
), this); 
2379     g_signal_connect (widget
, "scroll_event", 
2380                       G_CALLBACK (window_scroll_event
), this); 
2381     if (m_scrollBar
[ScrollDir_Horz
]) 
2382         g_signal_connect (m_scrollBar
[ScrollDir_Horz
], "scroll_event", 
2383                       G_CALLBACK (window_scroll_event_hscrollbar
), this); 
2384     if (m_scrollBar
[ScrollDir_Vert
]) 
2385         g_signal_connect (m_scrollBar
[ScrollDir_Vert
], "scroll_event", 
2386                       G_CALLBACK (window_scroll_event
), this); 
2388     g_signal_connect (widget
, "popup_menu", 
2389                      G_CALLBACK (wxgtk_window_popup_menu_callback
), this); 
2390     g_signal_connect (widget
, "enter_notify_event", 
2391                       G_CALLBACK (gtk_window_enter_callback
), this); 
2392     g_signal_connect (widget
, "leave_notify_event", 
2393                       G_CALLBACK (gtk_window_leave_callback
), this); 
2395     if (IsTopLevel() && m_wxwindow
) 
2396         g_signal_connect (m_wxwindow
, "style_set", 
2397                               G_CALLBACK (gtk_window_style_set_callback
), this); 
2400 bool wxWindowGTK::Destroy() 
2402     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2406     return wxWindowBase::Destroy(); 
2409 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
) 
2411     gtk_widget_set_size_request(m_widget
, width
, height
); 
2413     // inform the parent to perform the move 
2414     wxASSERT_MSG(m_parent 
&& m_parent
->m_wxwindow
, 
2415                  "the parent window has no client area?"); 
2416     WX_PIZZA(m_parent
->m_wxwindow
)->move(m_widget
, x
, y
); 
2419 void wxWindowGTK::ConstrainSize() 
2422     // GPE's window manager doesn't like size hints at all, esp. when the user 
2423     // has to use the virtual keyboard, so don't constrain size there 
2427         const wxSize minSize 
= GetMinSize(); 
2428         const wxSize maxSize 
= GetMaxSize(); 
2429         if (minSize
.x 
> 0 && m_width  
< minSize
.x
) m_width  
= minSize
.x
; 
2430         if (minSize
.y 
> 0 && m_height 
< minSize
.y
) m_height 
= minSize
.y
; 
2431         if (maxSize
.x 
> 0 && m_width  
> maxSize
.x
) m_width  
= maxSize
.x
; 
2432         if (maxSize
.y 
> 0 && m_height 
> maxSize
.y
) m_height 
= maxSize
.y
; 
2436 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
2438     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2439     wxASSERT_MSG( (m_parent 
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") ); 
2441     int currentX
, currentY
; 
2442     GetPosition(¤tX
, ¤tY
); 
2443     if (x 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
2445     if (y 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
2447     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
2449     // calculate the best size if we should auto size the window 
2450     if ( ((sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1) || 
2451          ((sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1) ) 
2453         const wxSize sizeBest 
= GetBestSize(); 
2454         if ( (sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1 ) 
2456         if ( (sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1 ) 
2457             height 
= sizeBest
.y
; 
2460     const wxSize 
oldSize(m_width
, m_height
); 
2466     if (m_parent
->m_wxwindow
) 
2468         wxPizza
* pizza 
= WX_PIZZA(m_parent
->m_wxwindow
); 
2469         m_x 
= x 
+ pizza
->m_scroll_x
; 
2470         m_y 
= y 
+ pizza
->m_scroll_y
; 
2472         int left_border 
= 0; 
2473         int right_border 
= 0; 
2475         int bottom_border 
= 0; 
2477         /* the default button has a border around it */ 
2478         if (GTK_WIDGET_CAN_DEFAULT(m_widget
)) 
2480             GtkBorder 
*default_border 
= NULL
; 
2481             gtk_widget_style_get( m_widget
, "default_border", &default_border
, NULL 
); 
2484                 left_border 
+= default_border
->left
; 
2485                 right_border 
+= default_border
->right
; 
2486                 top_border 
+= default_border
->top
; 
2487                 bottom_border 
+= default_border
->bottom
; 
2488                 gtk_border_free( default_border 
); 
2492         DoMoveWindow( m_x 
- left_border
, 
2494                       m_width
+left_border
+right_border
, 
2495                       m_height
+top_border
+bottom_border 
); 
2498     if (m_width 
!= oldSize
.x 
|| m_height 
!= oldSize
.y
) 
2500         // update these variables to keep size_allocate handler 
2501         // from sending another size event for this change 
2502         GetClientSize( &m_oldClientWidth
, &m_oldClientHeight 
); 
2504         gtk_widget_queue_resize(m_widget
); 
2505         if (!m_nativeSizeEvent
) 
2507             wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
2508             event
.SetEventObject( this ); 
2509             HandleWindowEvent( event 
); 
2512     if (sizeFlags 
& wxSIZE_FORCE_EVENT
) 
2514         wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
2515         event
.SetEventObject( this ); 
2516         HandleWindowEvent( event 
); 
2520 bool wxWindowGTK::GTKShowFromOnIdle() 
2522     if (IsShown() && m_showOnIdle 
&& !GTK_WIDGET_VISIBLE (m_widget
)) 
2524         GtkAllocation alloc
; 
2527         alloc
.width 
= m_width
; 
2528         alloc
.height 
= m_height
; 
2529         gtk_widget_size_allocate( m_widget
, &alloc 
); 
2530         gtk_widget_show( m_widget 
); 
2531         wxShowEvent 
eventShow(GetId(), true); 
2532         eventShow
.SetEventObject(this); 
2533         HandleWindowEvent(eventShow
); 
2534         m_showOnIdle 
= false; 
2541 void wxWindowGTK::OnInternalIdle() 
2543     if ( gs_deferredFocusOut 
) 
2544         GTKHandleDeferredFocusOut(); 
2546     // Check if we have to show window now 
2547     if (GTKShowFromOnIdle()) return; 
2549     if ( m_dirtyTabOrder 
) 
2551         m_dirtyTabOrder 
= false; 
2555     // Update style if the window was not yet realized when 
2556     // SetBackgroundStyle() was called 
2557     if (m_needsStyleChange
) 
2559         SetBackgroundStyle(GetBackgroundStyle()); 
2560         m_needsStyleChange 
= false; 
2563     wxCursor cursor 
= m_cursor
; 
2564     if (g_globalCursor
.Ok()) cursor 
= g_globalCursor
; 
2568         /* I now set the cursor anew in every OnInternalIdle call 
2569            as setting the cursor in a parent window also effects the 
2570            windows above so that checking for the current cursor is 
2573         if (m_wxwindow 
&& (m_wxwindow 
!= m_widget
)) 
2575             GdkWindow 
*window 
= m_wxwindow
->window
; 
2577                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2579             if (!g_globalCursor
.Ok()) 
2580                 cursor 
= *wxSTANDARD_CURSOR
; 
2582             window 
= m_widget
->window
; 
2583             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
2584                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2587         else if ( m_widget 
) 
2589             GdkWindow 
*window 
= m_widget
->window
; 
2590             if ( window 
&& !GTK_WIDGET_NO_WINDOW(m_widget
) ) 
2591                gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2595     if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen()) 
2596         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
2599 void wxWindowGTK::DoGetSize( int *width
, int *height 
) const 
2601     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2603     if (width
) (*width
) = m_width
; 
2604     if (height
) (*height
) = m_height
; 
2607 void wxWindowGTK::DoSetClientSize( int width
, int height 
) 
2609     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2611     const wxSize size 
= GetSize(); 
2612     const wxSize clientSize 
= GetClientSize(); 
2613     SetSize(width 
+ (size
.x 
- clientSize
.x
), height 
+ (size
.y 
- clientSize
.y
)); 
2616 void wxWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
2618     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2625         // if window is scrollable, account for scrollbars 
2626         if ( GTK_IS_SCROLLED_WINDOW(m_widget
) ) 
2628             GtkPolicyType policy
[ScrollDir_Max
]; 
2629             gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(m_widget
), 
2630                                            &policy
[ScrollDir_Horz
], 
2631                                            &policy
[ScrollDir_Vert
]); 
2633             for ( int i 
= 0; i 
< ScrollDir_Max
; i
++ ) 
2635                 // don't account for the scrollbars we don't have 
2636                 GtkRange 
* const range 
= m_scrollBar
[i
]; 
2640                 // nor for the ones we have but don't current show 
2641                 switch ( policy
[i
] ) 
2643                     case GTK_POLICY_NEVER
: 
2644                         // never shown so doesn't take any place 
2647                     case GTK_POLICY_ALWAYS
: 
2648                         // no checks necessary 
2651                     case GTK_POLICY_AUTOMATIC
: 
2652                         // may be shown or not, check 
2653                         GtkAdjustment 
*adj 
= gtk_range_get_adjustment(range
); 
2654                         if ( adj
->upper 
<= adj
->page_size 
) 
2658                 GtkScrolledWindowClass 
*scroll_class 
= 
2659                     GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2662                 gtk_widget_size_request(GTK_WIDGET(range
), &req
); 
2663                 if (i 
== ScrollDir_Horz
) 
2664                     h 
-= req
.height 
+ scroll_class
->scrollbar_spacing
; 
2666                     w 
-= req
.width 
+ scroll_class
->scrollbar_spacing
; 
2670         int border_x
, border_y
; 
2671         WX_PIZZA(m_wxwindow
)->get_border_widths(border_x
, border_y
); 
2681     if (width
) *width 
= w
; 
2682     if (height
) *height 
= h
; 
2685 void wxWindowGTK::DoGetPosition( int *x
, int *y 
) const 
2687     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2691     if (!IsTopLevel() && m_parent 
&& m_parent
->m_wxwindow
) 
2693         wxPizza
* pizza 
= WX_PIZZA(m_parent
->m_wxwindow
); 
2694         dx 
= pizza
->m_scroll_x
; 
2695         dy 
= pizza
->m_scroll_y
; 
2698     if (m_x 
== -1 && m_y 
== -1) 
2700         GdkWindow 
*source 
= NULL
; 
2702             source 
= m_wxwindow
->window
; 
2704             source 
= m_widget
->window
; 
2710             gdk_window_get_origin( source
, &org_x
, &org_y 
); 
2713                 m_parent
->ScreenToClient(&org_x
, &org_y
); 
2715             const_cast<wxWindowGTK
*>(this)->m_x 
= org_x
; 
2716             const_cast<wxWindowGTK
*>(this)->m_y 
= org_y
; 
2720     if (x
) (*x
) = m_x 
- dx
; 
2721     if (y
) (*y
) = m_y 
- dy
; 
2724 void wxWindowGTK::DoClientToScreen( int *x
, int *y 
) const 
2726     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2728     if (!m_widget
->window
) return; 
2730     GdkWindow 
*source 
= NULL
; 
2732         source 
= m_wxwindow
->window
; 
2734         source 
= m_widget
->window
; 
2738     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
2742         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
2744             org_x 
+= m_widget
->allocation
.x
; 
2745             org_y 
+= m_widget
->allocation
.y
; 
2752         if (GetLayoutDirection() == wxLayout_RightToLeft
) 
2753             *x 
= (GetClientSize().x 
- *x
) + org_x
; 
2761 void wxWindowGTK::DoScreenToClient( int *x
, int *y 
) const 
2763     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2765     if (!m_widget
->window
) return; 
2767     GdkWindow 
*source 
= NULL
; 
2769         source 
= m_wxwindow
->window
; 
2771         source 
= m_widget
->window
; 
2775     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
2779         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
2781             org_x 
+= m_widget
->allocation
.x
; 
2782             org_y 
+= m_widget
->allocation
.y
; 
2788         if (GetLayoutDirection() == wxLayout_RightToLeft
) 
2789             *x 
= (GetClientSize().x 
- *x
) - org_x
; 
2796 bool wxWindowGTK::Show( bool show 
) 
2798     if ( !wxWindowBase::Show(show
) ) 
2804     // notice that we may call Hide() before the window is created and this is 
2805     // actually useful to create it hidden initially -- but we can't call 
2806     // Show() before it is created 
2809         wxASSERT_MSG( !show
, "can't show invalid window" ); 
2817             // defer until later 
2821         gtk_widget_show(m_widget
); 
2825         gtk_widget_hide(m_widget
); 
2828     wxShowEvent 
eventShow(GetId(), show
); 
2829     eventShow
.SetEventObject(this); 
2830     HandleWindowEvent(eventShow
); 
2835 void wxWindowGTK::DoEnable( bool enable 
) 
2837     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2839     gtk_widget_set_sensitive( m_widget
, enable 
); 
2840     if (m_wxwindow 
&& (m_wxwindow 
!= m_widget
)) 
2841         gtk_widget_set_sensitive( m_wxwindow
, enable 
); 
2844 int wxWindowGTK::GetCharHeight() const 
2846     wxCHECK_MSG( (m_widget 
!= NULL
), 12, wxT("invalid window") ); 
2848     wxFont font 
= GetFont(); 
2849     wxCHECK_MSG( font
.Ok(), 12, wxT("invalid font") ); 
2851     PangoContext
* context 
= gtk_widget_get_pango_context(m_widget
); 
2856     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
2857     PangoLayout 
*layout 
= pango_layout_new(context
); 
2858     pango_layout_set_font_description(layout
, desc
); 
2859     pango_layout_set_text(layout
, "H", 1); 
2860     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
2862     PangoRectangle rect
; 
2863     pango_layout_line_get_extents(line
, NULL
, &rect
); 
2865     g_object_unref (layout
); 
2867     return (int) PANGO_PIXELS(rect
.height
); 
2870 int wxWindowGTK::GetCharWidth() const 
2872     wxCHECK_MSG( (m_widget 
!= NULL
), 8, wxT("invalid window") ); 
2874     wxFont font 
= GetFont(); 
2875     wxCHECK_MSG( font
.Ok(), 8, wxT("invalid font") ); 
2877     PangoContext
* context 
= gtk_widget_get_pango_context(m_widget
); 
2882     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
2883     PangoLayout 
*layout 
= pango_layout_new(context
); 
2884     pango_layout_set_font_description(layout
, desc
); 
2885     pango_layout_set_text(layout
, "g", 1); 
2886     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
2888     PangoRectangle rect
; 
2889     pango_layout_line_get_extents(line
, NULL
, &rect
); 
2891     g_object_unref (layout
); 
2893     return (int) PANGO_PIXELS(rect
.width
); 
2896 void wxWindowGTK::DoGetTextExtent( const wxString
& string
, 
2900                                    int *externalLeading
, 
2901                                    const wxFont 
*theFont 
) const 
2903     wxFont fontToUse 
= theFont 
? *theFont 
: GetFont(); 
2905     wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") ); 
2914     PangoContext 
*context 
= NULL
; 
2916         context 
= gtk_widget_get_pango_context( m_widget 
); 
2925     PangoFontDescription 
*desc 
= fontToUse
.GetNativeFontInfo()->description
; 
2926     PangoLayout 
*layout 
= pango_layout_new(context
); 
2927     pango_layout_set_font_description(layout
, desc
); 
2929         const wxCharBuffer data 
= wxGTK_CONV( string 
); 
2931             pango_layout_set_text(layout
, data
, strlen(data
)); 
2934     PangoRectangle rect
; 
2935     pango_layout_get_extents(layout
, NULL
, &rect
); 
2937     if (x
) (*x
) = (wxCoord
) PANGO_PIXELS(rect
.width
); 
2938     if (y
) (*y
) = (wxCoord
) PANGO_PIXELS(rect
.height
); 
2941         PangoLayoutIter 
*iter 
= pango_layout_get_iter(layout
); 
2942         int baseline 
= pango_layout_iter_get_baseline(iter
); 
2943         pango_layout_iter_free(iter
); 
2944         *descent 
= *y 
- PANGO_PIXELS(baseline
); 
2946     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
2948     g_object_unref (layout
); 
2951 void wxWindowGTK::GTKDisableFocusOutEvent() 
2953     g_signal_handlers_block_by_func( m_focusWidget
, 
2954                                 (gpointer
) gtk_window_focus_out_callback
, this); 
2957 void wxWindowGTK::GTKEnableFocusOutEvent() 
2959     g_signal_handlers_unblock_by_func( m_focusWidget
, 
2960                                 (gpointer
) gtk_window_focus_out_callback
, this); 
2963 bool wxWindowGTK::GTKHandleFocusIn() 
2965     // Disable default focus handling for custom windows since the default GTK+ 
2966     // handler issues a repaint 
2967     const bool retval 
= m_wxwindow 
? true : false; 
2970     // NB: if there's still unprocessed deferred focus-out event (see 
2971     //     GTKHandleFocusOut() for explanation), we need to process it first so 
2972     //     that the order of focus events -- focus-out first, then focus-in 
2973     //     elsewhere -- is preserved 
2974     if ( gs_deferredFocusOut 
) 
2976         if ( GTKNeedsToFilterSameWindowFocus() && 
2977              gs_deferredFocusOut 
== this ) 
2979             // GTK+ focus changed from this wxWindow back to itself, so don't 
2980             // emit any events at all 
2981             wxLogTrace(TRACE_FOCUS
, 
2982                        "filtered out spurious focus change within %s(%p, %s)", 
2983                        GetClassInfo()->GetClassName(), this, GetLabel()); 
2984             gs_deferredFocusOut 
= NULL
; 
2988         // otherwise we need to send focus-out first 
2989         wxASSERT_MSG ( gs_deferredFocusOut 
!= this, 
2990                        "GTKHandleFocusIn(GTKFocus_Normal) called even though focus changed back to itself - derived class should handle this" ); 
2991         GTKHandleDeferredFocusOut(); 
2995     wxLogTrace(TRACE_FOCUS
, 
2996                "handling focus_in event for %s(%p, %s)", 
2997                GetClassInfo()->GetClassName(), this, GetLabel()); 
3000         gtk_im_context_focus_in(m_imData
->context
); 
3002     gs_currentFocus 
= this; 
3003     gs_pendingFocus 
= NULL
; 
3006     // caret needs to be informed about focus change 
3007     wxCaret 
*caret 
= GetCaret(); 
3010         caret
->OnSetFocus(); 
3012 #endif // wxUSE_CARET 
3014     // Notify the parent keeping track of focus for the kbd navigation 
3015     // purposes that we got it. 
3016     wxChildFocusEvent 
eventChildFocus(static_cast<wxWindow
*>(this)); 
3017     GTKProcessEvent(eventChildFocus
); 
3019     wxFocusEvent 
eventFocus(wxEVT_SET_FOCUS
, GetId()); 
3020     eventFocus
.SetEventObject(this); 
3021     GTKProcessEvent(eventFocus
); 
3026 bool wxWindowGTK::GTKHandleFocusOut() 
3028     // Disable default focus handling for custom windows since the default GTK+ 
3029     // handler issues a repaint 
3030     const bool retval 
= m_wxwindow 
? true : false; 
3033     // NB: If a control is composed of several GtkWidgets and when focus 
3034     //     changes from one of them to another within the same wxWindow, we get 
3035     //     a focus-out event followed by focus-in for another GtkWidget owned 
3036     //     by the same wx control. We don't want to generate two spurious 
3037     //     wxEVT_SET_FOCUS events in this case, so we defer sending wx events 
3038     //     from GTKHandleFocusOut() until we know for sure it's not coming back 
3039     //     (i.e. in GTKHandleFocusIn() or at idle time). 
3040     if ( GTKNeedsToFilterSameWindowFocus() ) 
3042         wxASSERT_MSG( gs_deferredFocusOut 
== NULL
, 
3043                       "deferred focus out event already pending" ); 
3044         wxLogTrace(TRACE_FOCUS
, 
3045                    "deferring focus_out event for %s(%p, %s)", 
3046                    GetClassInfo()->GetClassName(), this, GetLabel()); 
3047         gs_deferredFocusOut 
= this; 
3051     GTKHandleFocusOutNoDeferring(); 
3056 void wxWindowGTK::GTKHandleFocusOutNoDeferring() 
3058     wxLogTrace(TRACE_FOCUS
, 
3059                "handling focus_out event for %s(%p, %s)", 
3060                GetClassInfo()->GetClassName(), this, GetLabel()); 
3063         gtk_im_context_focus_out(m_imData
->context
); 
3065     if ( gs_currentFocus 
!= this ) 
3067         // Something is terribly wrong, gs_currentFocus is out of sync with the 
3068         // real focus. We will reset it to NULL anyway, because after this 
3069         // focus-out event is handled, one of the following with happen: 
3071         // * either focus will go out of the app altogether, in which case 
3072         //   gs_currentFocus _should_ be NULL 
3074         // * or it goes to another control, in which case focus-in event will 
3075         //   follow immediately and it will set gs_currentFocus to the right 
3077         wxLogDebug("window %s(%p, %s) lost focus even though it didn't have it", 
3078                    GetClassInfo()->GetClassName(), this, GetLabel()); 
3080     gs_currentFocus 
= NULL
; 
3083     // caret needs to be informed about focus change 
3084     wxCaret 
*caret 
= GetCaret(); 
3087         caret
->OnKillFocus(); 
3089 #endif // wxUSE_CARET 
3091     wxFocusEvent 
event( wxEVT_KILL_FOCUS
, GetId() ); 
3092     event
.SetEventObject( this ); 
3093     GTKProcessEvent( event 
); 
3097 void wxWindowGTK::GTKHandleDeferredFocusOut() 
3099     // NB: See GTKHandleFocusOut() for explanation. This function is called 
3100     //     from either GTKHandleFocusIn() or OnInternalIdle() to process 
3102     if ( gs_deferredFocusOut 
) 
3104         wxWindowGTK 
*win 
= gs_deferredFocusOut
; 
3105         gs_deferredFocusOut 
= NULL
; 
3107         wxLogTrace(TRACE_FOCUS
, 
3108                    "processing deferred focus_out event for %s(%p, %s)", 
3109                    win
->GetClassInfo()->GetClassName(), win
, win
->GetLabel()); 
3111         win
->GTKHandleFocusOutNoDeferring(); 
3115 void wxWindowGTK::SetFocus() 
3117     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3119     // Setting "physical" focus is not immediate in GTK+ and while 
3120     // gtk_widget_is_focus ("determines if the widget is the focus widget 
3121     // within its toplevel", i.e. returns true for one widget per TLW, not 
3122     // globally) returns true immediately after grabbing focus, 
3123     // GTK_WIDGET_HAS_FOCUS (which returns true only for the one widget that 
3124     // has focus at the moment) takes affect only after the window is shown 
3125     // (if it was hidden at the moment of the call) or at the next event loop 
3128     // Because we want to FindFocus() call immediately following 
3129     // foo->SetFocus() to return foo, we have to keep track of "pending" focus 
3131     gs_pendingFocus 
= this; 
3133     GtkWidget 
*widget 
= m_wxwindow 
? m_wxwindow 
: m_focusWidget
; 
3135     if ( GTK_IS_CONTAINER(widget
) && 
3136          !GTK_WIDGET_CAN_FOCUS(widget
) ) 
3138         wxLogTrace(TRACE_FOCUS
, 
3139                    wxT("Setting focus to a child of %s(%p, %s)"), 
3140                    GetClassInfo()->GetClassName(), this, GetLabel().c_str()); 
3141         gtk_widget_child_focus(widget
, GTK_DIR_TAB_FORWARD
); 
3145         wxLogTrace(TRACE_FOCUS
, 
3146                    wxT("Setting focus to %s(%p, %s)"), 
3147                    GetClassInfo()->GetClassName(), this, GetLabel().c_str()); 
3148         gtk_widget_grab_focus(widget
); 
3152 void wxWindowGTK::SetCanFocus(bool canFocus
) 
3155         GTK_WIDGET_SET_FLAGS(m_widget
, GTK_CAN_FOCUS
); 
3157         GTK_WIDGET_UNSET_FLAGS(m_widget
, GTK_CAN_FOCUS
); 
3159     if ( m_wxwindow 
&& (m_widget 
!= m_wxwindow
) ) 
3162             GTK_WIDGET_SET_FLAGS(m_wxwindow
, GTK_CAN_FOCUS
); 
3164             GTK_WIDGET_UNSET_FLAGS(m_wxwindow
, GTK_CAN_FOCUS
); 
3168 bool wxWindowGTK::Reparent( wxWindowBase 
*newParentBase 
) 
3170     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3172     wxWindowGTK 
*oldParent 
= m_parent
, 
3173              *newParent 
= (wxWindowGTK 
*)newParentBase
; 
3175     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3177     if ( !wxWindowBase::Reparent(newParent
) ) 
3180     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3183         gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget 
); 
3185     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3189         if (GTK_WIDGET_VISIBLE (newParent
->m_widget
)) 
3191             m_showOnIdle 
= true; 
3192             gtk_widget_hide( m_widget 
); 
3194         /* insert GTK representation */ 
3195         newParent
->AddChildGTK(this); 
3198     SetLayoutDirection(wxLayout_Default
); 
3203 void wxWindowGTK::DoAddChild(wxWindowGTK 
*child
) 
3205     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3206     wxASSERT_MSG( (child 
!= NULL
), wxT("invalid child window") ); 
3211     /* insert GTK representation */ 
3215 void wxWindowGTK::AddChild(wxWindowBase 
*child
) 
3217     wxWindowBase::AddChild(child
); 
3218     m_dirtyTabOrder 
= true; 
3219     wxTheApp
->WakeUpIdle(); 
3222 void wxWindowGTK::RemoveChild(wxWindowBase 
*child
) 
3224     wxWindowBase::RemoveChild(child
); 
3225     m_dirtyTabOrder 
= true; 
3226     wxTheApp
->WakeUpIdle(); 
3230 wxLayoutDirection 
wxWindowGTK::GTKGetLayout(GtkWidget 
*widget
) 
3232     return gtk_widget_get_direction(widget
) == GTK_TEXT_DIR_RTL
 
3233                 ? wxLayout_RightToLeft
 
3234                 : wxLayout_LeftToRight
; 
3238 void wxWindowGTK::GTKSetLayout(GtkWidget 
*widget
, wxLayoutDirection dir
) 
3240     wxASSERT_MSG( dir 
!= wxLayout_Default
, wxT("invalid layout direction") ); 
3242     gtk_widget_set_direction(widget
, 
3243                              dir 
== wxLayout_RightToLeft 
? GTK_TEXT_DIR_RTL
 
3244                                                          : GTK_TEXT_DIR_LTR
); 
3247 wxLayoutDirection 
wxWindowGTK::GetLayoutDirection() const 
3249     return GTKGetLayout(m_widget
); 
3252 void wxWindowGTK::SetLayoutDirection(wxLayoutDirection dir
) 
3254     if ( dir 
== wxLayout_Default 
) 
3256         const wxWindow 
*const parent 
= GetParent(); 
3259             // inherit layout from parent. 
3260             dir 
= parent
->GetLayoutDirection(); 
3262         else // no parent, use global default layout 
3264             dir 
= wxTheApp
->GetLayoutDirection(); 
3268     if ( dir 
== wxLayout_Default 
) 
3271     GTKSetLayout(m_widget
, dir
); 
3273     if (m_wxwindow 
&& (m_wxwindow 
!= m_widget
)) 
3274         GTKSetLayout(m_wxwindow
, dir
); 
3278 wxWindowGTK::AdjustForLayoutDirection(wxCoord x
, 
3279                                       wxCoord 
WXUNUSED(width
), 
3280                                       wxCoord 
WXUNUSED(widthTotal
)) const 
3282     // We now mirror the coordinates of RTL windows in wxPizza 
3286 void wxWindowGTK::DoMoveInTabOrder(wxWindow 
*win
, WindowOrder move
) 
3288     wxWindowBase::DoMoveInTabOrder(win
, move
); 
3289     m_dirtyTabOrder 
= true; 
3290     wxTheApp
->WakeUpIdle(); 
3293 bool wxWindowGTK::DoNavigateIn(int flags
) 
3295     if ( flags 
& wxNavigationKeyEvent::WinChange 
) 
3297         wxFAIL_MSG( wxT("not implemented") ); 
3301     else // navigate inside the container 
3303         wxWindow 
*parent 
= wxGetTopLevelParent((wxWindow 
*)this); 
3304         wxCHECK_MSG( parent
, false, wxT("every window must have a TLW parent") ); 
3306         GtkDirectionType dir
; 
3307         dir 
= flags 
& wxNavigationKeyEvent::IsForward 
? GTK_DIR_TAB_FORWARD
 
3308                                                       : GTK_DIR_TAB_BACKWARD
; 
3311         g_signal_emit_by_name(parent
->m_widget
, "focus", dir
, &rc
); 
3317 bool wxWindowGTK::GTKWidgetNeedsMnemonic() const 
3319     // none needed by default 
3323 void wxWindowGTK::GTKWidgetDoSetMnemonic(GtkWidget
* WXUNUSED(w
)) 
3325     // nothing to do by default since none is needed 
3328 void wxWindowGTK::RealizeTabOrder() 
3332         if ( !m_children
.empty() ) 
3334             // we don't only construct the correct focus chain but also use 
3335             // this opportunity to update the mnemonic widgets for the widgets 
3338             GList 
*chain 
= NULL
; 
3339             wxWindowGTK
* mnemonicWindow 
= NULL
; 
3341             for ( wxWindowList::const_iterator i 
= m_children
.begin(); 
3342                   i 
!= m_children
.end(); 
3345                 wxWindowGTK 
*win 
= *i
; 
3347                 if ( mnemonicWindow 
) 
3349                     if ( win
->AcceptsFocusFromKeyboard() ) 
3351                         // wxComboBox et al. needs to focus on on a different 
3352                         // widget than m_widget, so if the main widget isn't 
3353                         // focusable try the connect widget 
3354                         GtkWidget
* w 
= win
->m_widget
; 
3355                         if ( !GTK_WIDGET_CAN_FOCUS(w
) ) 
3357                             w 
= win
->GetConnectWidget(); 
3358                             if ( !GTK_WIDGET_CAN_FOCUS(w
) ) 
3364                             mnemonicWindow
->GTKWidgetDoSetMnemonic(w
); 
3365                             mnemonicWindow 
= NULL
; 
3369                 else if ( win
->GTKWidgetNeedsMnemonic() ) 
3371                     mnemonicWindow 
= win
; 
3374                 chain 
= g_list_prepend(chain
, win
->m_widget
); 
3377             chain 
= g_list_reverse(chain
); 
3379             gtk_container_set_focus_chain(GTK_CONTAINER(m_wxwindow
), chain
); 
3384             gtk_container_unset_focus_chain(GTK_CONTAINER(m_wxwindow
)); 
3389 void wxWindowGTK::Raise() 
3391     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3393     if (m_wxwindow 
&& m_wxwindow
->window
) 
3395         gdk_window_raise( m_wxwindow
->window 
); 
3397     else if (m_widget
->window
) 
3399         gdk_window_raise( m_widget
->window 
); 
3403 void wxWindowGTK::Lower() 
3405     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3407     if (m_wxwindow 
&& m_wxwindow
->window
) 
3409         gdk_window_lower( m_wxwindow
->window 
); 
3411     else if (m_widget
->window
) 
3413         gdk_window_lower( m_widget
->window 
); 
3417 bool wxWindowGTK::SetCursor( const wxCursor 
&cursor 
) 
3419     if ( !wxWindowBase::SetCursor(cursor
.Ok() ? cursor 
: *wxSTANDARD_CURSOR
) ) 
3427 void wxWindowGTK::GTKUpdateCursor() 
3429     wxCursor 
cursor(g_globalCursor
.Ok() ? g_globalCursor 
: GetCursor()); 
3432         wxArrayGdkWindows windowsThis
; 
3433         GdkWindow 
* const winThis 
= GTKGetWindow(windowsThis
); 
3436             gdk_window_set_cursor(winThis
, cursor
.GetCursor()); 
3440             const size_t count 
= windowsThis
.size(); 
3441             for ( size_t n 
= 0; n 
< count
; n
++ ) 
3443                 GdkWindow 
*win 
= windowsThis
[n
]; 
3446                     wxFAIL_MSG(wxT("NULL window returned by GTKGetWindow()?")); 
3450                 gdk_window_set_cursor(win
, cursor
.GetCursor()); 
3456 void wxWindowGTK::WarpPointer( int x
, int y 
) 
3458     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3460     // We provide this function ourselves as it is 
3461     // missing in GDK (top of this file). 
3463     GdkWindow 
*window 
= NULL
; 
3465         window 
= m_wxwindow
->window
; 
3467         window 
= GetConnectWidget()->window
; 
3470         gdk_window_warp_pointer( window
, x
, y 
); 
3473 wxWindowGTK::ScrollDir 
wxWindowGTK::ScrollDirFromRange(GtkRange 
*range
) const 
3475     // find the scrollbar which generated the event 
3476     for ( int dir 
= 0; dir 
< ScrollDir_Max
; dir
++ ) 
3478         if ( range 
== m_scrollBar
[dir
] ) 
3479             return (ScrollDir
)dir
; 
3482     wxFAIL_MSG( wxT("event from unknown scrollbar received") ); 
3484     return ScrollDir_Max
; 
3487 bool wxWindowGTK::DoScrollByUnits(ScrollDir dir
, ScrollUnit unit
, int units
) 
3489     bool changed 
= false; 
3490     GtkRange
* range 
= m_scrollBar
[dir
]; 
3491     if ( range 
&& units 
) 
3493         GtkAdjustment
* adj 
= range
->adjustment
; 
3494         gdouble inc 
= unit 
== ScrollUnit_Line 
? adj
->step_increment
 
3495                                               : adj
->page_increment
; 
3497         const int posOld 
= int(adj
->value 
+ 0.5); 
3498         gtk_range_set_value(range
, posOld 
+ units
*inc
); 
3500         changed 
= int(adj
->value 
+ 0.5) != posOld
; 
3506 bool wxWindowGTK::ScrollLines(int lines
) 
3508     return DoScrollByUnits(ScrollDir_Vert
, ScrollUnit_Line
, lines
); 
3511 bool wxWindowGTK::ScrollPages(int pages
) 
3513     return DoScrollByUnits(ScrollDir_Vert
, ScrollUnit_Page
, pages
); 
3516 void wxWindowGTK::Refresh(bool WXUNUSED(eraseBackground
), 
3521         // it is valid to call Refresh() for a window which hasn't been created 
3522         // yet, it simply doesn't do anything in this case 
3529             gtk_widget_queue_draw_area( m_widget
, rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3531             gtk_widget_queue_draw( m_widget 
); 
3535         // Just return if the widget or one of its ancestors isn't mapped 
3537         for (w 
= m_wxwindow
; w 
!= NULL
; w 
= w
->parent
) 
3538             if (!GTK_WIDGET_MAPPED (w
)) 
3544             if (GetLayoutDirection() == wxLayout_RightToLeft
) 
3545                 x 
= GetClientSize().x 
- x 
- rect
->width
; 
3549             r
.width 
= rect
->width
; 
3550             r
.height 
= rect
->height
; 
3551             gdk_window_invalidate_rect( m_wxwindow
->window
, &r
, TRUE 
); 
3554             gdk_window_invalidate_rect( m_wxwindow
->window
, NULL
, TRUE 
); 
3558 void wxWindowGTK::Update() 
3560     if (m_widget 
&& m_widget
->window
) 
3562         GdkDisplay
* display 
= gtk_widget_get_display(m_widget
); 
3563         // Flush everything out to the server, and wait for it to finish. 
3564         // This ensures nothing will overwrite the drawing we are about to do. 
3565         gdk_display_sync(display
); 
3567         gdk_window_process_updates(m_widget
->window
, TRUE
); 
3569         // Flush again, but no need to wait for it to finish 
3570         gdk_display_flush(display
); 
3574 bool wxWindowGTK::DoIsExposed( int x
, int y 
) const 
3576     return m_updateRegion
.Contains(x
, y
) != wxOutRegion
; 
3579 bool wxWindowGTK::DoIsExposed( int x
, int y
, int w
, int h 
) const 
3581     if (GetLayoutDirection() == wxLayout_RightToLeft
) 
3582         return m_updateRegion
.Contains(x
-w
, y
, w
, h
) != wxOutRegion
; 
3584         return m_updateRegion
.Contains(x
, y
, w
, h
) != wxOutRegion
; 
3587 void wxWindowGTK::GtkSendPaintEvents() 
3591         m_updateRegion
.Clear(); 
3595     // Clip to paint region in wxClientDC 
3596     m_clipPaintRegion 
= true; 
3598     m_nativeUpdateRegion 
= m_updateRegion
; 
3600     if (GetLayoutDirection() == wxLayout_RightToLeft
) 
3602         // Transform m_updateRegion under RTL 
3603         m_updateRegion
.Clear(); 
3606         gdk_drawable_get_size(m_wxwindow
->window
, &width
, NULL
); 
3608         wxRegionIterator 
upd( m_nativeUpdateRegion 
); 
3612             rect
.x 
= upd
.GetX(); 
3613             rect
.y 
= upd
.GetY(); 
3614             rect
.width 
= upd
.GetWidth(); 
3615             rect
.height 
= upd
.GetHeight(); 
3617             rect
.x 
= width 
- rect
.x 
- rect
.width
; 
3618             m_updateRegion
.Union( rect 
); 
3624     switch ( GetBackgroundStyle() ) 
3626         case wxBG_STYLE_ERASE
: 
3628                 wxWindowDC 
dc( (wxWindow
*)this ); 
3629                 dc
.SetDeviceClippingRegion( m_updateRegion 
); 
3631                 // Work around gtk-qt <= 0.60 bug whereby the window colour 
3635                             GetOptionInt("gtk.window.force-background-colour") ) 
3637                     dc
.SetBackground(GetBackgroundColour()); 
3641                 wxEraseEvent 
erase_event( GetId(), &dc 
); 
3642                 erase_event
.SetEventObject( this ); 
3644                 if ( HandleWindowEvent(erase_event
) ) 
3646                     // background erased, don't do it again 
3652         case wxBG_STYLE_SYSTEM
: 
3653             if ( GetThemeEnabled() ) 
3655                 // find ancestor from which to steal background 
3656                 wxWindow 
*parent 
= wxGetTopLevelParent((wxWindow 
*)this); 
3658                     parent 
= (wxWindow
*)this; 
3660                 if (GTK_WIDGET_MAPPED(parent
->m_widget
)) 
3662                     wxRegionIterator 
upd( m_nativeUpdateRegion 
); 
3666                         rect
.x 
= upd
.GetX(); 
3667                         rect
.y 
= upd
.GetY(); 
3668                         rect
.width 
= upd
.GetWidth(); 
3669                         rect
.height 
= upd
.GetHeight(); 
3671                         gtk_paint_flat_box( parent
->m_widget
->style
, 
3673                                     (GtkStateType
)GTK_WIDGET_STATE(m_wxwindow
), 
3686         case wxBG_STYLE_PAINT
: 
3687             // nothing to do: window will be painted over in EVT_PAINT 
3691             wxFAIL_MSG( "unsupported background style" ); 
3694     wxNcPaintEvent 
nc_paint_event( GetId() ); 
3695     nc_paint_event
.SetEventObject( this ); 
3696     HandleWindowEvent( nc_paint_event 
); 
3698     wxPaintEvent 
paint_event( GetId() ); 
3699     paint_event
.SetEventObject( this ); 
3700     HandleWindowEvent( paint_event 
); 
3702     m_clipPaintRegion 
= false; 
3704     m_updateRegion
.Clear(); 
3705     m_nativeUpdateRegion
.Clear(); 
3708 void wxWindowGTK::SetDoubleBuffered( bool on 
) 
3710     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3713         gtk_widget_set_double_buffered( m_wxwindow
, on 
); 
3716 bool wxWindowGTK::IsDoubleBuffered() const 
3718     return GTK_WIDGET_DOUBLE_BUFFERED( m_wxwindow 
); 
3721 void wxWindowGTK::ClearBackground() 
3723     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3727 void wxWindowGTK::DoSetToolTip( wxToolTip 
*tip 
) 
3729     wxWindowBase::DoSetToolTip(tip
); 
3733         m_tooltip
->GTKApply( (wxWindow 
*)this ); 
3737         GtkWidget 
*w 
= GetConnectWidget(); 
3738         wxToolTip::GTKApply(w
, NULL
); 
3739 #if GTK_CHECK_VERSION(2, 12, 0) 
3740         // Just applying NULL doesn't work on 2.12.0, so also use 
3741         // gtk_widget_set_has_tooltip. It is part of the new GtkTooltip API 
3742         // but seems also to work with the old GtkTooltips. 
3743         if (gtk_check_version(2, 12, 0) == NULL
) 
3744             gtk_widget_set_has_tooltip(w
, FALSE
); 
3749 void wxWindowGTK::GTKApplyToolTip( GtkTooltips 
*tips
, const gchar 
*tip 
) 
3751     gtk_tooltips_set_tip(tips
, GetConnectWidget(), tip
, NULL
); 
3753 #endif // wxUSE_TOOLTIPS 
3755 bool wxWindowGTK::SetBackgroundColour( const wxColour 
&colour 
) 
3757     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3759     if (!wxWindowBase::SetBackgroundColour(colour
)) 
3764         // We need the pixel value e.g. for background clearing. 
3765         m_backgroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
3768     // apply style change (forceStyle=true so that new style is applied 
3769     // even if the bg colour changed from valid to wxNullColour) 
3770     GTKApplyWidgetStyle(true); 
3775 bool wxWindowGTK::SetForegroundColour( const wxColour 
&colour 
) 
3777     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3779     if (!wxWindowBase::SetForegroundColour(colour
)) 
3786         // We need the pixel value e.g. for background clearing. 
3787         m_foregroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
3790     // apply style change (forceStyle=true so that new style is applied 
3791     // even if the bg colour changed from valid to wxNullColour): 
3792     GTKApplyWidgetStyle(true); 
3797 PangoContext 
*wxWindowGTK::GTKGetPangoDefaultContext() 
3799     return gtk_widget_get_pango_context( m_widget 
); 
3802 GtkRcStyle 
*wxWindowGTK::GTKCreateWidgetStyle(bool forceStyle
) 
3804     // do we need to apply any changes at all? 
3807          !m_foregroundColour
.Ok() && !m_backgroundColour
.Ok() ) 
3812     GtkRcStyle 
*style 
= gtk_rc_style_new(); 
3817             pango_font_description_copy( m_font
.GetNativeFontInfo()->description 
); 
3820     int flagsNormal 
= 0, 
3823         flagsInsensitive 
= 0; 
3825     if ( m_foregroundColour
.Ok() ) 
3827         const GdkColor 
*fg 
= m_foregroundColour
.GetColor(); 
3829         style
->fg
[GTK_STATE_NORMAL
] = 
3830         style
->text
[GTK_STATE_NORMAL
] = *fg
; 
3831         flagsNormal 
|= GTK_RC_FG 
| GTK_RC_TEXT
; 
3833         style
->fg
[GTK_STATE_PRELIGHT
] = 
3834         style
->text
[GTK_STATE_PRELIGHT
] = *fg
; 
3835         flagsPrelight 
|= GTK_RC_FG 
| GTK_RC_TEXT
; 
3837         style
->fg
[GTK_STATE_ACTIVE
] = 
3838         style
->text
[GTK_STATE_ACTIVE
] = *fg
; 
3839         flagsActive 
|= GTK_RC_FG 
| GTK_RC_TEXT
; 
3842     if ( m_backgroundColour
.Ok() ) 
3844         const GdkColor 
*bg 
= m_backgroundColour
.GetColor(); 
3846         style
->bg
[GTK_STATE_NORMAL
] = 
3847         style
->base
[GTK_STATE_NORMAL
] = *bg
; 
3848         flagsNormal 
|= GTK_RC_BG 
| GTK_RC_BASE
; 
3850         style
->bg
[GTK_STATE_PRELIGHT
] = 
3851         style
->base
[GTK_STATE_PRELIGHT
] = *bg
; 
3852         flagsPrelight 
|= GTK_RC_BG 
| GTK_RC_BASE
; 
3854         style
->bg
[GTK_STATE_ACTIVE
] = 
3855         style
->base
[GTK_STATE_ACTIVE
] = *bg
; 
3856         flagsActive 
|= GTK_RC_BG 
| GTK_RC_BASE
; 
3858         style
->bg
[GTK_STATE_INSENSITIVE
] = 
3859         style
->base
[GTK_STATE_INSENSITIVE
] = *bg
; 
3860         flagsInsensitive 
|= GTK_RC_BG 
| GTK_RC_BASE
; 
3863     style
->color_flags
[GTK_STATE_NORMAL
] = (GtkRcFlags
)flagsNormal
; 
3864     style
->color_flags
[GTK_STATE_PRELIGHT
] = (GtkRcFlags
)flagsPrelight
; 
3865     style
->color_flags
[GTK_STATE_ACTIVE
] = (GtkRcFlags
)flagsActive
; 
3866     style
->color_flags
[GTK_STATE_INSENSITIVE
] = (GtkRcFlags
)flagsInsensitive
; 
3871 void wxWindowGTK::GTKApplyWidgetStyle(bool forceStyle
) 
3873     GtkRcStyle 
*style 
= GTKCreateWidgetStyle(forceStyle
); 
3876         DoApplyWidgetStyle(style
); 
3877         gtk_rc_style_unref(style
); 
3880     // Style change may affect GTK+'s size calculation: 
3881     InvalidateBestSize(); 
3884 void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
3888         // block the signal temporarily to avoid sending 
3889         // wxSysColourChangedEvents when we change the colours ourselves 
3890         bool unblock 
= false; 
3894             g_signal_handlers_block_by_func( 
3895                 m_wxwindow
, (void *)gtk_window_style_set_callback
, this); 
3898         gtk_widget_modify_style(m_wxwindow
, style
); 
3902             g_signal_handlers_unblock_by_func( 
3903                 m_wxwindow
, (void *)gtk_window_style_set_callback
, this); 
3908         gtk_widget_modify_style(m_widget
, style
); 
3912 bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style
) 
3914     wxWindowBase::SetBackgroundStyle(style
); 
3916     if ( style 
== wxBG_STYLE_PAINT 
) 
3921             window 
= m_wxwindow
->window
; 
3925             GtkWidget 
* const w 
= GetConnectWidget(); 
3926             window 
= w 
? w
->window 
: NULL
; 
3931             // Make sure GDK/X11 doesn't refresh the window 
3933             gdk_window_set_back_pixmap( window
, None
, False 
); 
3935             Display
* display 
= GDK_WINDOW_DISPLAY(window
); 
3938             m_needsStyleChange 
= false; 
3940         else // window not realized yet 
3942             // Do in OnIdle, because the window is not yet available 
3943             m_needsStyleChange 
= true; 
3946         // Don't apply widget style, or we get a grey background 
3950         // apply style change (forceStyle=true so that new style is applied 
3951         // even if the bg colour changed from valid to wxNullColour): 
3952         GTKApplyWidgetStyle(true); 
3958 // ---------------------------------------------------------------------------- 
3959 // Pop-up menu stuff 
3960 // ---------------------------------------------------------------------------- 
3962 #if wxUSE_MENUS_NATIVE 
3964 static void SetInvokingWindow( wxMenu 
*menu
, wxWindow
* win 
) 
3966     menu
->SetInvokingWindow( win 
); 
3968     wxMenuItemList::compatibility_iterator node 
= menu
->GetMenuItems().GetFirst(); 
3971         wxMenuItem 
*menuitem 
= node
->GetData(); 
3972         if (menuitem
->IsSubMenu()) 
3974             SetInvokingWindow( menuitem
->GetSubMenu(), win 
); 
3977         node 
= node
->GetNext(); 
3983 void wxPopupMenuPositionCallback( GtkMenu 
*menu
, 
3985                                   gboolean 
* WXUNUSED(whatever
), 
3986                                   gpointer user_data 
) 
3988     // ensure that the menu appears entirely on screen 
3990     gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
); 
3992     wxSize sizeScreen 
= wxGetDisplaySize(); 
3993     wxPoint 
*pos 
= (wxPoint
*)user_data
; 
3995     gint xmax 
= sizeScreen
.x 
- req
.width
, 
3996          ymax 
= sizeScreen
.y 
- req
.height
; 
3998     *x 
= pos
->x 
< xmax 
? pos
->x 
: xmax
; 
3999     *y 
= pos
->y 
< ymax 
? pos
->y 
: ymax
; 
4003 bool wxWindowGTK::DoPopupMenu( wxMenu 
*menu
, int x
, int y 
) 
4005     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
4007     wxCHECK_MSG( menu 
!= NULL
, false, wxT("invalid popup-menu") ); 
4009     SetInvokingWindow( menu
, this ); 
4015     GtkMenuPositionFunc posfunc
; 
4016     if ( x 
== -1 && y 
== -1 ) 
4018         // use GTK's default positioning algorithm 
4024         pos 
= ClientToScreen(wxPoint(x
, y
)); 
4026         posfunc 
= wxPopupMenuPositionCallback
; 
4029     menu
->m_popupShown 
= true; 
4031                   GTK_MENU(menu
->m_menu
), 
4032                   NULL
,           // parent menu shell 
4033                   NULL
,           // parent menu item 
4034                   posfunc
,                      // function to position it 
4035                   userdata
,                     // client data 
4036                   0,                            // button used to activate it 
4037                   gtk_get_current_event_time() 
4040     while (menu
->m_popupShown
) 
4042         gtk_main_iteration(); 
4048 #endif // wxUSE_MENUS_NATIVE 
4050 #if wxUSE_DRAG_AND_DROP 
4052 void wxWindowGTK::SetDropTarget( wxDropTarget 
*dropTarget 
) 
4054     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4056     GtkWidget 
*dnd_widget 
= GetConnectWidget(); 
4058     if (m_dropTarget
) m_dropTarget
->GtkUnregisterWidget( dnd_widget 
); 
4060     if (m_dropTarget
) delete m_dropTarget
; 
4061     m_dropTarget 
= dropTarget
; 
4063     if (m_dropTarget
) m_dropTarget
->GtkRegisterWidget( dnd_widget 
); 
4066 #endif // wxUSE_DRAG_AND_DROP 
4068 GtkWidget
* wxWindowGTK::GetConnectWidget() 
4070     GtkWidget 
*connect_widget 
= m_widget
; 
4071     if (m_wxwindow
) connect_widget 
= m_wxwindow
; 
4073     return connect_widget
; 
4076 bool wxWindowGTK::GTKIsOwnWindow(GdkWindow 
*window
) const 
4078     wxArrayGdkWindows windowsThis
; 
4079     GdkWindow 
* const winThis 
= GTKGetWindow(windowsThis
); 
4081     return winThis 
? window 
== winThis
 
4082                    : windowsThis
.Index(window
) != wxNOT_FOUND
; 
4085 GdkWindow 
*wxWindowGTK::GTKGetWindow(wxArrayGdkWindows
& WXUNUSED(windows
)) const 
4087     return m_wxwindow 
? m_wxwindow
->window 
: m_widget
->window
; 
4090 bool wxWindowGTK::SetFont( const wxFont 
&font 
) 
4092     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
4094     if (!wxWindowBase::SetFont(font
)) 
4097     // apply style change (forceStyle=true so that new style is applied 
4098     // even if the font changed from valid to wxNullFont): 
4099     GTKApplyWidgetStyle(true); 
4104 void wxWindowGTK::DoCaptureMouse() 
4106     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4108     GdkWindow 
*window 
= NULL
; 
4110         window 
= m_wxwindow
->window
; 
4112         window 
= GetConnectWidget()->window
; 
4114     wxCHECK_RET( window
, wxT("CaptureMouse() failed") ); 
4116     const wxCursor
* cursor 
= &m_cursor
; 
4118         cursor 
= wxSTANDARD_CURSOR
; 
4120     gdk_pointer_grab( window
, FALSE
, 
4122                          (GDK_BUTTON_PRESS_MASK 
| 
4123                           GDK_BUTTON_RELEASE_MASK 
| 
4124                           GDK_POINTER_MOTION_HINT_MASK 
| 
4125                           GDK_POINTER_MOTION_MASK
), 
4127                       cursor
->GetCursor(), 
4128                       (guint32
)GDK_CURRENT_TIME 
); 
4129     g_captureWindow 
= this; 
4130     g_captureWindowHasMouse 
= true; 
4133 void wxWindowGTK::DoReleaseMouse() 
4135     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4137     wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") ); 
4139     g_captureWindow 
= NULL
; 
4141     GdkWindow 
*window 
= NULL
; 
4143         window 
= m_wxwindow
->window
; 
4145         window 
= GetConnectWidget()->window
; 
4150     gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME 
); 
4153 void wxWindowGTK::GTKReleaseMouseAndNotify() 
4156     wxMouseCaptureLostEvent 
evt(GetId()); 
4157     evt
.SetEventObject( this ); 
4158     HandleWindowEvent( evt 
); 
4162 wxWindow 
*wxWindowBase::GetCapture() 
4164     return (wxWindow 
*)g_captureWindow
; 
4167 bool wxWindowGTK::IsRetained() const 
4172 void wxWindowGTK::SetScrollbar(int orient
, 
4176                                bool WXUNUSED(update
)) 
4178     const int dir 
= ScrollDirFromOrient(orient
); 
4179     GtkRange
* const sb 
= m_scrollBar
[dir
]; 
4180     wxCHECK_RET( sb
, wxT("this window is not scrollable") ); 
4184         // GtkRange requires upper > lower 
4189     GtkAdjustment 
* const adj 
= sb
->adjustment
; 
4190     adj
->step_increment 
= 1; 
4191     adj
->page_increment 
= 
4192     adj
->page_size 
= thumbVisible
; 
4195     g_signal_handlers_block_by_func( 
4196         sb
, (void*)gtk_scrollbar_value_changed
, this); 
4198     gtk_range_set_range(sb
, 0, range
); 
4199     m_scrollPos
[dir
] = sb
->adjustment
->value
; 
4201     g_signal_handlers_unblock_by_func( 
4202         sb
, (void*)gtk_scrollbar_value_changed
, this); 
4205 void wxWindowGTK::SetScrollPos(int orient
, int pos
, bool WXUNUSED(refresh
)) 
4207     const int dir 
= ScrollDirFromOrient(orient
); 
4208     GtkRange 
* const sb 
= m_scrollBar
[dir
]; 
4209     wxCHECK_RET( sb
, wxT("this window is not scrollable") ); 
4211     // This check is more than an optimization. Without it, the slider 
4212     //   will not move smoothly while tracking when using wxScrollHelper. 
4213     if (GetScrollPos(orient
) != pos
) 
4215         g_signal_handlers_block_by_func( 
4216             sb
, (void*)gtk_scrollbar_value_changed
, this); 
4218         gtk_range_set_value(sb
, pos
); 
4219         m_scrollPos
[dir
] = sb
->adjustment
->value
; 
4221         g_signal_handlers_unblock_by_func( 
4222             sb
, (void*)gtk_scrollbar_value_changed
, this); 
4226 int wxWindowGTK::GetScrollThumb(int orient
) const 
4228     GtkRange 
* const sb 
= m_scrollBar
[ScrollDirFromOrient(orient
)]; 
4229     wxCHECK_MSG( sb
, 0, wxT("this window is not scrollable") ); 
4231     return wxRound(sb
->adjustment
->page_size
); 
4234 int wxWindowGTK::GetScrollPos( int orient 
) const 
4236     GtkRange 
* const sb 
= m_scrollBar
[ScrollDirFromOrient(orient
)]; 
4237     wxCHECK_MSG( sb
, 0, wxT("this window is not scrollable") ); 
4239     return wxRound(sb
->adjustment
->value
); 
4242 int wxWindowGTK::GetScrollRange( int orient 
) const 
4244     GtkRange 
* const sb 
= m_scrollBar
[ScrollDirFromOrient(orient
)]; 
4245     wxCHECK_MSG( sb
, 0, wxT("this window is not scrollable") ); 
4247     return wxRound(sb
->adjustment
->upper
); 
4250 // Determine if increment is the same as +/-x, allowing for some small 
4251 //   difference due to possible inexactness in floating point arithmetic 
4252 static inline bool IsScrollIncrement(double increment
, double x
) 
4254     wxASSERT(increment 
> 0); 
4255     const double tolerance 
= 1.0 / 1024; 
4256     return fabs(increment 
- fabs(x
)) < tolerance
; 
4259 wxEventType 
wxWindowGTK::GTKGetScrollEventType(GtkRange
* range
) 
4261     wxASSERT(range 
== m_scrollBar
[0] || range 
== m_scrollBar
[1]); 
4263     const int barIndex 
= range 
== m_scrollBar
[1]; 
4264     GtkAdjustment
* adj 
= range
->adjustment
; 
4266     const int value 
= wxRound(adj
->value
); 
4268     // save previous position 
4269     const double oldPos 
= m_scrollPos
[barIndex
]; 
4270     // update current position 
4271     m_scrollPos
[barIndex
] = adj
->value
; 
4272     // If event should be ignored, or integral position has not changed 
4273     if (!m_hasVMT 
|| g_blockEventsOnDrag 
|| value 
== wxRound(oldPos
)) 
4278     wxEventType eventType 
= wxEVT_SCROLL_THUMBTRACK
; 
4281         // Difference from last change event 
4282         const double diff 
= adj
->value 
- oldPos
; 
4283         const bool isDown 
= diff 
> 0; 
4285         if (IsScrollIncrement(adj
->step_increment
, diff
)) 
4287             eventType 
= isDown 
? wxEVT_SCROLL_LINEDOWN 
: wxEVT_SCROLL_LINEUP
; 
4289         else if (IsScrollIncrement(adj
->page_increment
, diff
)) 
4291             eventType 
= isDown 
? wxEVT_SCROLL_PAGEDOWN 
: wxEVT_SCROLL_PAGEUP
; 
4293         else if (m_mouseButtonDown
) 
4295             // Assume track event 
4296             m_isScrolling 
= true; 
4302 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) ) 
4304     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4306     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4308     // No scrolling requested. 
4309     if ((dx 
== 0) && (dy 
== 0)) return; 
4311     m_clipPaintRegion 
= true; 
4313     WX_PIZZA(m_wxwindow
)->scroll(dx
, dy
); 
4315     m_clipPaintRegion 
= false; 
4318     bool restoreCaret 
= (GetCaret() != NULL 
&& GetCaret()->IsVisible()); 
4321         wxRect 
caretRect(GetCaret()->GetPosition(), GetCaret()->GetSize()); 
4323             caretRect
.width 
+= dx
; 
4326             caretRect
.x 
+= dx
; caretRect
.width 
-= dx
; 
4329             caretRect
.height 
+= dy
; 
4332             caretRect
.y 
+= dy
; caretRect
.height 
-= dy
; 
4335         RefreshRect(caretRect
); 
4337 #endif // wxUSE_CARET 
4340 void wxWindowGTK::GTKScrolledWindowSetBorder(GtkWidget
* w
, int wxstyle
) 
4342     //RN: Note that static controls usually have no border on gtk, so maybe 
4343     //it makes sense to treat that as simply no border at the wx level 
4345     if (!(wxstyle 
& wxNO_BORDER
) && !(wxstyle 
& wxBORDER_STATIC
)) 
4347         GtkShadowType gtkstyle
; 
4349         if(wxstyle 
& wxBORDER_RAISED
) 
4350             gtkstyle 
= GTK_SHADOW_OUT
; 
4351         else if ((wxstyle 
& wxBORDER_SUNKEN
) || (wxstyle 
& wxBORDER_THEME
)) 
4352             gtkstyle 
= GTK_SHADOW_IN
; 
4355         else if (wxstyle 
& wxBORDER_DOUBLE
) 
4356             gtkstyle 
= GTK_SHADOW_ETCHED_IN
; 
4359             gtkstyle 
= GTK_SHADOW_IN
; 
4361         gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(w
), 
4366 void wxWindowGTK::SetWindowStyleFlag( long style 
) 
4368     // Updates the internal variable. NB: Now m_windowStyle bits carry the _new_ style values already 
4369     wxWindowBase::SetWindowStyleFlag(style
); 
4372 // Find the wxWindow at the current mouse position, also returning the mouse 
4374 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
4376     pt 
= wxGetMousePosition(); 
4377     wxWindow
* found 
= wxFindWindowAtPoint(pt
); 
4381 // Get the current mouse position. 
4382 wxPoint 
wxGetMousePosition() 
4384   /* This crashes when used within wxHelpContext, 
4385      so we have to use the X-specific implementation below. 
4387     GdkModifierType *mask; 
4388     (void) gdk_window_get_pointer(NULL, &x, &y, mask); 
4390     return wxPoint(x, y); 
4394     GdkWindow
* windowAtPtr 
= gdk_window_at_pointer(& x
, & y
); 
4396     Display 
*display 
= windowAtPtr 
? GDK_WINDOW_XDISPLAY(windowAtPtr
) : GDK_DISPLAY(); 
4397     Window rootWindow 
= RootWindowOfScreen (DefaultScreenOfDisplay(display
)); 
4398     Window rootReturn
, childReturn
; 
4399     int rootX
, rootY
, winX
, winY
; 
4400     unsigned int maskReturn
; 
4402     XQueryPointer (display
, 
4406                    &rootX
, &rootY
, &winX
, &winY
, &maskReturn
); 
4407     return wxPoint(rootX
, rootY
); 
4411 GdkWindow
* wxWindowGTK::GTKGetDrawingWindow() const 
4413     GdkWindow
* window 
= NULL
; 
4415         window 
= m_wxwindow
->window
; 
4419 // ---------------------------------------------------------------------------- 
4421 // ---------------------------------------------------------------------------- 
4426 // this is called if we attempted to freeze unrealized widget when it finally 
4427 // is realized (and so can be frozen): 
4428 static void wx_frozen_widget_realize(GtkWidget
* w
, void* WXUNUSED(data
)) 
4430     wxASSERT( w 
&& !GTK_WIDGET_NO_WINDOW(w
) ); 
4431     wxASSERT( GTK_WIDGET_REALIZED(w
) ); 
4433     g_signal_handlers_disconnect_by_func
 
4436         (void*)wx_frozen_widget_realize
, 
4440     gdk_window_freeze_updates(w
->window
); 
4445 void wxWindowGTK::GTKFreezeWidget(GtkWidget 
*w
) 
4447     if ( !w 
|| GTK_WIDGET_NO_WINDOW(w
) ) 
4448         return; // window-less widget, cannot be frozen 
4450     if ( !GTK_WIDGET_REALIZED(w
) ) 
4452         // we can't thaw unrealized widgets because they don't have GdkWindow, 
4453         // so set it up to be done immediately after realization: 
4454         g_signal_connect_after
 
4458             G_CALLBACK(wx_frozen_widget_realize
), 
4464     gdk_window_freeze_updates(w
->window
); 
4467 void wxWindowGTK::GTKThawWidget(GtkWidget 
*w
) 
4469     if ( !w 
|| GTK_WIDGET_NO_WINDOW(w
) ) 
4470         return; // window-less widget, cannot be frozen 
4472     if ( !GTK_WIDGET_REALIZED(w
) ) 
4474         // the widget wasn't realized yet, no need to thaw 
4475         g_signal_handlers_disconnect_by_func
 
4478             (void*)wx_frozen_widget_realize
, 
4484     gdk_window_thaw_updates(w
->window
); 
4487 void wxWindowGTK::DoFreeze() 
4489     GTKFreezeWidget(m_widget
); 
4490     if ( m_wxwindow 
&& m_widget 
!= m_wxwindow 
) 
4491         GTKFreezeWidget(m_wxwindow
); 
4494 void wxWindowGTK::DoThaw() 
4496     GTKThawWidget(m_widget
); 
4497     if ( m_wxwindow 
&& m_widget 
!= m_wxwindow 
) 
4498         GTKThawWidget(m_wxwindow
);