1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/window.cpp 
   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/win_gtk.h" 
  40 #include <gdk/gdkkeysyms.h> 
  43 //----------------------------------------------------------------------------- 
  44 // documentation on internals 
  45 //----------------------------------------------------------------------------- 
  48    I have been asked several times about writing some documentation about 
  49    the GTK port of wxWidgets, especially its internal structures. Obviously, 
  50    you cannot understand wxGTK without knowing a little about the GTK, but 
  51    some more information about what the wxWindow, which is the base class 
  52    for all other window classes, does seems required as well. 
  56    What does wxWindow do? It contains the common interface for the following 
  57    jobs of its descendants: 
  59    1) Define the rudimentary behaviour common to all window classes, such as 
  60    resizing, intercepting user input (so as to make it possible to use these 
  61    events for special purposes in a derived class), window names etc. 
  63    2) Provide the possibility to contain and manage children, if the derived 
  64    class is allowed to contain children, which holds true for those window 
  65    classes which do not display a native GTK widget. To name them, these 
  66    classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame- 
  67    work classes are a special case and are handled a bit differently from 
  68    the rest. The same holds true for the wxNotebook class. 
  70    3) Provide the possibility to draw into a client area of a window. This, 
  71    too, only holds true for classes that do not display a native GTK widget 
  74    4) Provide the entire mechanism for scrolling widgets. This actual inter- 
  75    face for this is usually in wxScrolledWindow, but the GTK implementation 
  78    5) A multitude of helper or extra methods for special purposes, such as 
  79    Drag'n'Drop, managing validators etc. 
  81    6) Display a border (sunken, raised, simple or none). 
  83    Normally one might expect, that one wxWidgets window would always correspond 
  84    to one GTK widget. Under GTK, there is no such all-round widget that has all 
  85    the functionality. Moreover, the GTK defines a client area as a different 
  86    widget from the actual widget you are handling. Last but not least some 
  87    special classes (e.g. wxFrame) handle different categories of widgets and 
  88    still have the possibility to draw something in the client area. 
  89    It was therefore required to write a special purpose GTK widget, that would 
  90    represent a client area in the sense of wxWidgets capable to do the jobs 
  91    2), 3) and 4). I have written this class and it resides in win_gtk.c of 
  94    All windows must have a widget, with which they interact with other under- 
  95    lying GTK widgets. It is this widget, e.g. that has to be resized etc and 
  96    the wxWindow class has a member variable called m_widget which holds a 
  97    pointer to this widget. When the window class represents a GTK native widget, 
  98    this is (in most cases) the only GTK widget the class manages. E.g. the 
  99    wxStaticText class handles only a GtkLabel widget a pointer to which you 
 100    can find in m_widget (defined in wxWindow) 
 102    When the class has a client area for drawing into and for containing children 
 103    it has to handle the client area widget (of the type wxPizza, defined in 
 104    win_gtk.cpp), but there could be any number of widgets, handled by a class. 
 105    The common rule for all windows is only, that the widget that interacts with 
 106    the rest of GTK must be referenced in m_widget and all other widgets must be 
 107    children of this widget on the GTK level. The top-most widget, which also 
 108    represents the client area, must be in the m_wxwindow field and must be of 
 111    As I said, the window classes that display a GTK native widget only have 
 112    one widget, so in the case of e.g. the wxButton class m_widget holds a 
 113    pointer to a GtkButton widget. But windows with client areas (for drawing 
 114    and children) have a m_widget field that is a pointer to a GtkScrolled- 
 115    Window and a m_wxwindow field that is pointer to a wxPizza and this 
 116    one is (in the GTK sense) a child of the GtkScrolledWindow. 
 118    If the m_wxwindow field is set, then all input to this widget is inter- 
 119    cepted and sent to the wxWidgets class. If not, all input to the widget 
 120    that gets pointed to by m_widget gets intercepted and sent to the class. 
 124    The design of scrolling in wxWidgets is markedly different from that offered 
 125    by the GTK itself and therefore we cannot simply take it as it is. In GTK, 
 126    clicking on a scrollbar belonging to scrolled window will inevitably move 
 127    the window. In wxWidgets, the scrollbar will only emit an event, send this 
 128    to (normally) a wxScrolledWindow and that class will call ScrollWindow() 
 129    which actually moves the window and its sub-windows. Note that wxPizza 
 130    memorizes how much it has been scrolled but that wxWidgets forgets this 
 131    so that the two coordinates systems have to be kept in synch. This is done 
 132    in various places using the pizza->m_scroll_x and pizza->m_scroll_y values. 
 136    Singularly the most broken code in GTK is the code that is supposed to 
 137    inform subwindows (child windows) about new positions. Very often, duplicate 
 138    events are sent without changes in size or position, equally often no 
 139    events are sent at all (All this is due to a bug in the GtkContainer code 
 140    which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores 
 141    GTK's own system and it simply waits for size events for toplevel windows 
 142    and then iterates down the respective size events to all window. This has 
 143    the disadvantage that windows might get size events before the GTK widget 
 144    actually has the reported size. This doesn't normally pose any problem, but 
 145    the OpenGL drawing routines rely on correct behaviour. Therefore, I have 
 146    added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas, 
 147    i.e. the wxGLCanvas will emit a size event, when (and not before) the X11 
 148    window that is used for OpenGL output really has that size (as reported by 
 153    If someone at some point of time feels the immense desire to have a look at, 
 154    change or attempt to optimise the Refresh() logic, this person will need an 
 155    intimate understanding of what "draw" and "expose" events are and what 
 156    they are used for, in particular when used in connection with GTK's 
 157    own windowless widgets. Beware. 
 161    Cursors, too, have been a constant source of pleasure. The main difficulty 
 162    is that a GdkWindow inherits a cursor if the programmer sets a new cursor 
 163    for the parent. To prevent this from doing too much harm, I use idle time 
 164    to set the cursor over and over again, starting from the toplevel windows 
 165    and ending with the youngest generation (speaking of parent and child windows). 
 166    Also don't forget that cursors (like much else) are connected to GdkWindows, 
 167    not GtkWidgets and that the "window" field of a GtkWidget might very well 
 168    point to the GdkWindow of the parent widget (-> "window-less widget") and 
 169    that the two obviously have very different meanings. 
 173 //----------------------------------------------------------------------------- 
 175 //----------------------------------------------------------------------------- 
 177 // Don't allow event propagation during drag 
 178 bool g_blockEventsOnDrag
; 
 179 // Don't allow mouse event propagation during scroll 
 180 bool g_blockEventsOnScroll
; 
 181 extern wxCursor   g_globalCursor
; 
 183 // mouse capture state: the window which has it and if the mouse is currently 
 185 static wxWindowGTK  
*g_captureWindow 
= (wxWindowGTK
*) NULL
; 
 186 static bool g_captureWindowHasMouse 
= false; 
 188 wxWindowGTK  
*g_focusWindow 
= (wxWindowGTK
*) NULL
; 
 190 // If a window get the focus set but has not been realized 
 191 // yet, defer setting the focus to idle time. 
 192 wxWindowGTK 
*g_delayedFocus 
= (wxWindowGTK
*) NULL
; 
 194 // global variables because GTK+ DnD want to have the 
 195 // mouse event that caused it 
 196 GdkEvent    
*g_lastMouseEvent 
= (GdkEvent
*) NULL
; 
 197 int          g_lastButtonNumber 
= 0; 
 199 //----------------------------------------------------------------------------- 
 201 //----------------------------------------------------------------------------- 
 203 // the trace mask used for the focus debugging messages 
 204 #define TRACE_FOCUS _T("focus") 
 206 //----------------------------------------------------------------------------- 
 207 // missing gdk functions 
 208 //----------------------------------------------------------------------------- 
 211 gdk_window_warp_pointer (GdkWindow      
*window
, 
 216     window 
= gdk_get_default_root_window(); 
 218   if (!GDK_WINDOW_DESTROYED(window
)) 
 220       XWarpPointer (GDK_WINDOW_XDISPLAY(window
), 
 221                     None
,              /* not source window -> move from anywhere */ 
 222                     GDK_WINDOW_XID(window
),  /* dest window */ 
 223                     0, 0, 0, 0,        /* not source window -> move from anywhere */ 
 228 //----------------------------------------------------------------------------- 
 229 // local code (see below) 
 230 //----------------------------------------------------------------------------- 
 232 // returns the child of win which currently has focus or NULL if not found 
 234 // Note: can't be static, needed by textctrl.cpp. 
 235 wxWindow 
*wxFindFocusedChild(wxWindowGTK 
*win
) 
 237     wxWindow 
*winFocus 
= wxWindowGTK::FindFocus(); 
 239         return (wxWindow 
*)NULL
; 
 241     if ( winFocus 
== win 
) 
 242         return (wxWindow 
*)win
; 
 244     for ( wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
 246           node 
= node
->GetNext() ) 
 248         wxWindow 
*child 
= wxFindFocusedChild(node
->GetData()); 
 253     return (wxWindow 
*)NULL
; 
 256 //----------------------------------------------------------------------------- 
 257 // "size_request" of m_widget 
 258 //----------------------------------------------------------------------------- 
 260 // make it extern because wxStaticText needs to disconnect this one 
 262 void 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
*, 
 285                             GdkEventExpose 
*gdk_event
, 
 291         wxPrintf( wxT("OnExpose from ") ); 
 292         if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName()) 
 293             wxPrintf( win
->GetClassInfo()->GetClassName() ); 
 294         wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event
->area
.x
, 
 295                                          (int)gdk_event
->area
.y
, 
 296                                          (int)gdk_event
->area
.width
, 
 297                                          (int)gdk_event
->area
.height 
); 
 302         win
->m_wxwindow
->style
, 
 306         (GdkRectangle
*) NULL
, 
 308         (char *)"button", // const_cast 
 313     win
->GetUpdateRegion() = wxRegion( gdk_event
->region 
); 
 315     win
->GtkSendPaintEvents(); 
 317     // Let parent window draw window-less widgets 
 322 //----------------------------------------------------------------------------- 
 323 // "expose_event" from m_widget, for drawing border 
 324 //----------------------------------------------------------------------------- 
 326 #ifndef __WXUNIVERSAL__ 
 328 GtkWidget
* GetEntryWidget(); 
 332 expose_event_border(GtkWidget
* widget
, GdkEventExpose
* gdk_event
, wxWindow
* win
) 
 334     // if this event is not for the GdkWindow the border is drawn on 
 335     if (win
->m_wxwindow 
== win
->m_widget 
&& gdk_event
->window 
== widget
->window
) 
 340     // GtkScrolledWindow is GTK_NO_WINDOW 
 341     if (GTK_WIDGET_NO_WINDOW(widget
)) 
 343         x 
= widget
->allocation
.x
; 
 344         y 
= widget
->allocation
.y
; 
 346     int w 
= win
->m_wxwindow
->allocation
.width
; 
 347     int h 
= win
->m_wxwindow
->allocation
.height
; 
 348     if (win
->HasFlag(wxBORDER_SIMPLE
)) 
 350         GdkGC
* gc 
= gdk_gc_new(gdk_event
->window
); 
 351         gdk_gc_set_foreground(gc
, &widget
->style
->black
); 
 352         gdk_draw_rectangle(gdk_event
->window
, gc
, false, x
, y
, w 
- 1, h 
- 1); 
 357         GtkShadowType shadow 
= GTK_SHADOW_IN
; 
 358         if (win
->HasFlag(wxBORDER_RAISED
)) 
 359             shadow 
= GTK_SHADOW_OUT
; 
 361         // Style detail to use 
 363         if (widget 
== win
->m_wxwindow
) 
 364             // for non-scrollable wxWindows 
 367             // for scrollable ones 
 370         GtkWidget
* styleWidget 
= GetEntryWidget(); 
 372            styleWidget
->style
, gdk_event
->window
, GTK_STATE_NORMAL
, 
 373            shadow
, NULL
, styleWidget
, detail
, x
, y
, w
, h
); 
 376     // no further painting is needed for border-only GdkWindow 
 377     return win
->m_wxwindow 
== win
->m_widget
; 
 380 #endif // !__WXUNIVERSAL__ 
 382 //----------------------------------------------------------------------------- 
 383 // "key_press_event" from any window 
 384 //----------------------------------------------------------------------------- 
 386 // These are used when transforming Ctrl-alpha to ascii values 1-26 
 387 inline bool wxIsLowerChar(int code
) 
 389     return (code 
>= 'a' && code 
<= 'z' ); 
 392 inline bool wxIsUpperChar(int code
) 
 394     return (code 
>= 'A' && code 
<= 'Z' ); 
 398 // set WXTRACE to this to see the key event codes on the console 
 399 #define TRACE_KEYS  _T("keyevent") 
 401 // translates an X key symbol to WXK_XXX value 
 403 // if isChar is true it means that the value returned will be used for EVT_CHAR 
 404 // event and then we choose the logical WXK_XXX, i.e. '/' for GDK_KP_Divide, 
 405 // for example, while if it is false it means that the value is going to be 
 406 // used for KEY_DOWN/UP events and then we translate GDK_KP_Divide to 
 408 static long wxTranslateKeySymToWXKey(KeySym keysym
, bool isChar
) 
 414         // Shift, Control and Alt don't generate the CHAR events at all 
 417             key_code 
= isChar 
? 0 : WXK_SHIFT
; 
 421             key_code 
= isChar 
? 0 : WXK_CONTROL
; 
 429             key_code 
= isChar 
? 0 : WXK_ALT
; 
 432         // neither do the toggle modifies 
 433         case GDK_Scroll_Lock
: 
 434             key_code 
= isChar 
? 0 : WXK_SCROLL
; 
 438             key_code 
= isChar 
? 0 : WXK_CAPITAL
; 
 442             key_code 
= isChar 
? 0 : WXK_NUMLOCK
; 
 446         // various other special keys 
 459         case GDK_ISO_Left_Tab
: 
 466             key_code 
= WXK_RETURN
; 
 470             key_code 
= WXK_CLEAR
; 
 474             key_code 
= WXK_PAUSE
; 
 478             key_code 
= WXK_SELECT
; 
 482             key_code 
= WXK_PRINT
; 
 486             key_code 
= WXK_EXECUTE
; 
 490             key_code 
= WXK_ESCAPE
; 
 493         // cursor and other extended keyboard keys 
 495             key_code 
= WXK_DELETE
; 
 511             key_code 
= WXK_RIGHT
; 
 518         case GDK_Prior
:     // == GDK_Page_Up 
 519             key_code 
= WXK_PAGEUP
; 
 522         case GDK_Next
:      // == GDK_Page_Down 
 523             key_code 
= WXK_PAGEDOWN
; 
 535             key_code 
= WXK_INSERT
; 
 550             key_code 
= (isChar 
? '0' : WXK_NUMPAD0
) + keysym 
- GDK_KP_0
; 
 554             key_code 
= isChar 
? ' ' : WXK_NUMPAD_SPACE
; 
 558             key_code 
= isChar 
? WXK_TAB 
: WXK_NUMPAD_TAB
; 
 562             key_code 
= isChar 
? WXK_RETURN 
: WXK_NUMPAD_ENTER
; 
 566             key_code 
= isChar 
? WXK_F1 
: WXK_NUMPAD_F1
; 
 570             key_code 
= isChar 
? WXK_F2 
: WXK_NUMPAD_F2
; 
 574             key_code 
= isChar 
? WXK_F3 
: WXK_NUMPAD_F3
; 
 578             key_code 
= isChar 
? WXK_F4 
: WXK_NUMPAD_F4
; 
 582             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_HOME
; 
 586             key_code 
= isChar 
? WXK_LEFT 
: WXK_NUMPAD_LEFT
; 
 590             key_code 
= isChar 
? WXK_UP 
: WXK_NUMPAD_UP
; 
 594             key_code 
= isChar 
? WXK_RIGHT 
: WXK_NUMPAD_RIGHT
; 
 598             key_code 
= isChar 
? WXK_DOWN 
: WXK_NUMPAD_DOWN
; 
 601         case GDK_KP_Prior
: // == GDK_KP_Page_Up 
 602             key_code 
= isChar 
? WXK_PAGEUP 
: WXK_NUMPAD_PAGEUP
; 
 605         case GDK_KP_Next
: // == GDK_KP_Page_Down 
 606             key_code 
= isChar 
? WXK_PAGEDOWN 
: WXK_NUMPAD_PAGEDOWN
; 
 610             key_code 
= isChar 
? WXK_END 
: WXK_NUMPAD_END
; 
 614             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_BEGIN
; 
 618             key_code 
= isChar 
? WXK_INSERT 
: WXK_NUMPAD_INSERT
; 
 622             key_code 
= isChar 
? WXK_DELETE 
: WXK_NUMPAD_DELETE
; 
 626             key_code 
= isChar 
? '=' : WXK_NUMPAD_EQUAL
; 
 629         case GDK_KP_Multiply
: 
 630             key_code 
= isChar 
? '*' : WXK_NUMPAD_MULTIPLY
; 
 634             key_code 
= isChar 
? '+' : WXK_NUMPAD_ADD
; 
 637         case GDK_KP_Separator
: 
 638             // FIXME: what is this? 
 639             key_code 
= isChar 
? '.' : WXK_NUMPAD_SEPARATOR
; 
 642         case GDK_KP_Subtract
: 
 643             key_code 
= isChar 
? '-' : WXK_NUMPAD_SUBTRACT
; 
 647             key_code 
= isChar 
? '.' : WXK_NUMPAD_DECIMAL
; 
 651             key_code 
= isChar 
? '/' : WXK_NUMPAD_DIVIDE
; 
 668             key_code 
= WXK_F1 
+ keysym 
- GDK_F1
; 
 678 static inline bool wxIsAsciiKeysym(KeySym ks
) 
 683 static void wxFillOtherKeyEventFields(wxKeyEvent
& event
, 
 685                                       GdkEventKey 
*gdk_event
) 
 689     GdkModifierType state
; 
 690     if (gdk_event
->window
) 
 691         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
 693     event
.SetTimestamp( gdk_event
->time 
); 
 694     event
.SetId(win
->GetId()); 
 695     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
) != 0; 
 696     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
) != 0; 
 697     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
) != 0; 
 698     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
) != 0; 
 699     event
.m_scanCode 
= gdk_event
->keyval
; 
 700     event
.m_rawCode 
= (wxUint32
) gdk_event
->keyval
; 
 701     event
.m_rawFlags 
= 0; 
 703     event
.m_uniChar 
= gdk_keyval_to_unicode(gdk_event
->keyval
); 
 705     wxGetMousePosition( &x
, &y 
); 
 706     win
->ScreenToClient( &x
, &y 
); 
 709     event
.SetEventObject( win 
); 
 714 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
, 
 716                            GdkEventKey 
*gdk_event
) 
 718     // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string 
 719     //     but only event->keyval which is quite useless to us, so remember 
 720     //     the last character from GDK_KEY_PRESS and reuse it as last resort 
 722     // NB: should be MT-safe as we're always called from the main thread only 
 727     } s_lastKeyPress 
= { 0, 0 }; 
 729     KeySym keysym 
= gdk_event
->keyval
; 
 731     wxLogTrace(TRACE_KEYS
, _T("Key %s event: keysym = %ld"), 
 732                event
.GetEventType() == wxEVT_KEY_UP 
? _T("release") 
 736     long key_code 
= wxTranslateKeySymToWXKey(keysym
, false /* !isChar */); 
 740         // do we have the translation or is it a plain ASCII character? 
 741         if ( (gdk_event
->length 
== 1) || wxIsAsciiKeysym(keysym
) ) 
 743             // we should use keysym if it is ASCII as X does some translations 
 744             // like "I pressed while Control is down" => "Ctrl-I" == "TAB" 
 745             // which we don't want here (but which we do use for OnChar()) 
 746             if ( !wxIsAsciiKeysym(keysym
) ) 
 748                 keysym 
= (KeySym
)gdk_event
->string
[0]; 
 751             // we want to always get the same key code when the same key is 
 752             // pressed regardless of the state of the modifiers, i.e. on a 
 753             // standard US keyboard pressing '5' or '%' ('5' key with 
 754             // Shift) should result in the same key code in OnKeyDown(): 
 755             // '5' (although OnChar() will get either '5' or '%'). 
 757             // to do it we first translate keysym to keycode (== scan code) 
 758             // and then back but always using the lower register 
 759             Display 
*dpy 
= (Display 
*)wxGetDisplay(); 
 760             KeyCode keycode 
= XKeysymToKeycode(dpy
, keysym
); 
 762             wxLogTrace(TRACE_KEYS
, _T("\t-> keycode %d"), keycode
); 
 764             KeySym keysymNormalized 
= XKeycodeToKeysym(dpy
, keycode
, 0); 
 766             // use the normalized, i.e. lower register, keysym if we've 
 768             key_code 
= keysymNormalized 
? keysymNormalized 
: keysym
; 
 770             // as explained above, we want to have lower register key codes 
 771             // normally but for the letter keys we want to have the upper ones 
 773             // NB: don't use XConvertCase() here, we want to do it for letters 
 775             key_code 
= toupper(key_code
); 
 777         else // non ASCII key, what to do? 
 779             // by default, ignore it 
 782             // but if we have cached information from the last KEY_PRESS 
 783             if ( gdk_event
->type 
== GDK_KEY_RELEASE 
) 
 786                 if ( keysym 
== s_lastKeyPress
.keysym 
) 
 788                     key_code 
= s_lastKeyPress
.keycode
; 
 793         if ( gdk_event
->type 
== GDK_KEY_PRESS 
) 
 795             // remember it to be reused for KEY_UP event later 
 796             s_lastKeyPress
.keysym 
= keysym
; 
 797             s_lastKeyPress
.keycode 
= key_code
; 
 801     wxLogTrace(TRACE_KEYS
, _T("\t-> wxKeyCode %ld"), key_code
); 
 803     // sending unknown key events doesn't really make sense 
 807     // now fill all the other fields 
 808     wxFillOtherKeyEventFields(event
, win
, gdk_event
); 
 810     event
.m_keyCode 
= key_code
; 
 812     if ( gdk_event
->type 
== GDK_KEY_PRESS 
||  gdk_event
->type 
== GDK_KEY_RELEASE 
) 
 814         event
.m_uniChar 
= key_code
; 
 824     GtkIMContext 
*context
; 
 825     GdkEventKey  
*lastKeyEvent
; 
 829         context 
= gtk_im_multicontext_new(); 
 834         g_object_unref (context
); 
 840 gtk_window_key_press_callback( GtkWidget 
*widget
, 
 841                                GdkEventKey 
*gdk_event
, 
 846     if (g_blockEventsOnDrag
) 
 849     // GTK+ sends keypress events to the focus widget and then 
 850     // to all its parent and grandparent widget. We only want 
 851     // the key events from the focus widget. 
 852     if (!GTK_WIDGET_HAS_FOCUS(widget
)) 
 855     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
 857     bool return_after_IM 
= false; 
 859     if( wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
 861         // Emit KEY_DOWN event 
 862         ret 
= win
->HandleWindowEvent( event 
); 
 866         // Return after IM processing as we cannot do 
 867         // anything with it anyhow. 
 868         return_after_IM 
= true; 
 871     if ((!ret
) && (win
->m_imData 
!= NULL
)) 
 873         // We should let GTK+ IM filter key event first. According to GTK+ 2.0 API 
 874         // docs, if IM filter returns true, no further processing should be done. 
 875         // we should send the key_down event anyway. 
 876         bool intercepted_by_IM 
= gtk_im_context_filter_keypress(win
->m_imData
->context
, gdk_event
); 
 877         win
->m_imData
->lastKeyEvent 
= NULL
; 
 878         if (intercepted_by_IM
) 
 880             wxLogTrace(TRACE_KEYS
, _T("Key event intercepted by IM")); 
 891         wxWindowGTK 
*ancestor 
= win
; 
 894             int command 
= ancestor
->GetAcceleratorTable()->GetCommand( event 
); 
 897                 wxCommandEvent 
command_event( wxEVT_COMMAND_MENU_SELECTED
, command 
); 
 898                 ret 
= ancestor
->HandleWindowEvent( command_event 
); 
 901             if (ancestor
->IsTopLevel()) 
 903             ancestor 
= ancestor
->GetParent(); 
 906 #endif // wxUSE_ACCEL 
 908     // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x 
 909     // will only be sent if it is not in an accelerator table. 
 913         KeySym keysym 
= gdk_event
->keyval
; 
 914         // Find key code for EVT_CHAR and EVT_CHAR_HOOK events 
 915         key_code 
= wxTranslateKeySymToWXKey(keysym
, true /* isChar */); 
 918             if ( wxIsAsciiKeysym(keysym
) ) 
 921                 key_code 
= (unsigned char)keysym
; 
 923             // gdk_event->string is actually deprecated 
 924             else if ( gdk_event
->length 
== 1 ) 
 926                 key_code 
= (unsigned char)gdk_event
->string
[0]; 
 932             wxLogTrace(TRACE_KEYS
, _T("Char event: %ld"), key_code
); 
 934             event
.m_keyCode 
= key_code
; 
 936             // To conform to the docs we need to translate Ctrl-alpha 
 937             // characters to values in the range 1-26. 
 938             if ( event
.ControlDown() && 
 939                  ( wxIsLowerChar(key_code
) || wxIsUpperChar(key_code
) )) 
 941                 if ( wxIsLowerChar(key_code
) ) 
 942                     event
.m_keyCode 
= key_code 
- 'a' + 1; 
 943                 if ( wxIsUpperChar(key_code
) ) 
 944                     event
.m_keyCode 
= key_code 
- 'A' + 1; 
 946                 event
.m_uniChar 
= event
.m_keyCode
; 
 950             // Implement OnCharHook by checking ancestor top level windows 
 951             wxWindow 
*parent 
= win
; 
 952             while (parent 
&& !parent
->IsTopLevel()) 
 953                 parent 
= parent
->GetParent(); 
 956                 event
.SetEventType( wxEVT_CHAR_HOOK 
); 
 957                 ret 
= parent
->HandleWindowEvent( event 
); 
 962                 event
.SetEventType(wxEVT_CHAR
); 
 963                 ret 
= win
->HandleWindowEvent( event 
); 
 974 gtk_wxwindow_commit_cb (GtkIMContext 
* WXUNUSED(context
), 
 978     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
 980     // take modifiers, cursor position, timestamp etc. from the last 
 981     // key_press_event that was fed into Input Method: 
 982     if (window
->m_imData
->lastKeyEvent
) 
 984         wxFillOtherKeyEventFields(event
, 
 985                                   window
, window
->m_imData
->lastKeyEvent
); 
 989         event
.SetEventObject( window 
); 
 992     const wxString 
data(wxGTK_CONV_BACK_SYS(str
)); 
 998     // Implement OnCharHook by checking ancestor top level windows 
 999     wxWindow 
*parent 
= window
; 
1000     while (parent 
&& !parent
->IsTopLevel()) 
1001         parent 
= parent
->GetParent(); 
1003     for( wxString::const_iterator pstr 
= data
.begin(); pstr 
!= data
.end(); ++pstr 
) 
1006         event
.m_uniChar 
= *pstr
; 
1007         // Backward compatible for ISO-8859-1 
1008         event
.m_keyCode 
= *pstr 
< 256 ? event
.m_uniChar 
: 0; 
1009         wxLogTrace(TRACE_KEYS
, _T("IM sent character '%c'"), event
.m_uniChar
); 
1011         event
.m_keyCode 
= (char)*pstr
; 
1012 #endif  // wxUSE_UNICODE 
1014         // To conform to the docs we need to translate Ctrl-alpha 
1015         // characters to values in the range 1-26. 
1016         if ( event
.ControlDown() && 
1017              ( wxIsLowerChar(*pstr
) || wxIsUpperChar(*pstr
) )) 
1019             if ( wxIsLowerChar(*pstr
) ) 
1020                 event
.m_keyCode 
= *pstr 
- 'a' + 1; 
1021             if ( wxIsUpperChar(*pstr
) ) 
1022                 event
.m_keyCode 
= *pstr 
- 'A' + 1; 
1024             event
.m_keyCode 
= *pstr 
- 'a' + 1; 
1026             event
.m_uniChar 
= event
.m_keyCode
; 
1032             event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1033             ret 
= parent
->HandleWindowEvent( event 
); 
1038             event
.SetEventType(wxEVT_CHAR
); 
1039             ret 
= window
->HandleWindowEvent( event 
); 
1046 //----------------------------------------------------------------------------- 
1047 // "key_release_event" from any window 
1048 //----------------------------------------------------------------------------- 
1052 gtk_window_key_release_callback( GtkWidget 
* WXUNUSED(widget
), 
1053                                  GdkEventKey 
*gdk_event
, 
1059     if (g_blockEventsOnDrag
) 
1062     wxKeyEvent 
event( wxEVT_KEY_UP 
); 
1063     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1065         // unknown key pressed, ignore (the event would be useless anyhow) 
1069     return win
->GTKProcessEvent(event
); 
1073 // ============================================================================ 
1075 // ============================================================================ 
1077 // ---------------------------------------------------------------------------- 
1078 // mouse event processing helpers 
1079 // ---------------------------------------------------------------------------- 
1081 // init wxMouseEvent with the info from GdkEventXXX struct 
1082 template<typename T
> void InitMouseEvent(wxWindowGTK 
*win
, 
1083                                          wxMouseEvent
& event
, 
1086     event
.SetTimestamp( gdk_event
->time 
); 
1087     event
.m_shiftDown 
= gdk_event
->state 
& GDK_SHIFT_MASK
; 
1088     event
.m_controlDown 
= gdk_event
->state 
& GDK_CONTROL_MASK
; 
1089     event
.m_altDown 
= gdk_event
->state 
& GDK_MOD1_MASK
; 
1090     event
.m_metaDown 
= gdk_event
->state 
& GDK_MOD2_MASK
; 
1091     event
.m_leftDown 
= gdk_event
->state 
& GDK_BUTTON1_MASK
; 
1092     event
.m_middleDown 
= gdk_event
->state 
& GDK_BUTTON2_MASK
; 
1093     event
.m_rightDown 
= gdk_event
->state 
& GDK_BUTTON3_MASK
; 
1094     event
.m_aux1Down 
= gdk_event
->state 
& GDK_BUTTON4_MASK
; 
1095     event
.m_aux2Down 
= gdk_event
->state 
& GDK_BUTTON5_MASK
; 
1097     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1098     event
.m_x 
= (wxCoord
)gdk_event
->x 
- pt
.x
; 
1099     event
.m_y 
= (wxCoord
)gdk_event
->y 
- pt
.y
; 
1101     if ((win
->m_wxwindow
) && (win
->GetLayoutDirection() == wxLayout_RightToLeft
)) 
1103         // origin in the upper right corner 
1104         int window_width 
= win
->m_wxwindow
->allocation
.width
; 
1105         event
.m_x 
= window_width 
- event
.m_x
; 
1108     event
.SetEventObject( win 
); 
1109     event
.SetId( win
->GetId() ); 
1110     event
.SetTimestamp( gdk_event
->time 
); 
1113 static void AdjustEventButtonState(wxMouseEvent
& event
) 
1115     // GDK reports the old state of the button for a button press event, but 
1116     // for compatibility with MSW and common sense we want m_leftDown be TRUE 
1117     // for a LEFT_DOWN event, not FALSE, so we will invert 
1118     // left/right/middleDown for the corresponding click events 
1120     if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) || 
1121         (event
.GetEventType() == wxEVT_LEFT_DCLICK
) || 
1122         (event
.GetEventType() == wxEVT_LEFT_UP
)) 
1124         event
.m_leftDown 
= !event
.m_leftDown
; 
1128     if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) || 
1129         (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) || 
1130         (event
.GetEventType() == wxEVT_MIDDLE_UP
)) 
1132         event
.m_middleDown 
= !event
.m_middleDown
; 
1136     if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) || 
1137         (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) || 
1138         (event
.GetEventType() == wxEVT_RIGHT_UP
)) 
1140         event
.m_rightDown 
= !event
.m_rightDown
; 
1145 // find the window to send the mouse event too 
1147 wxWindowGTK 
*FindWindowForMouseEvent(wxWindowGTK 
*win
, wxCoord
& x
, wxCoord
& y
) 
1152     if (win
->m_wxwindow
) 
1154         wxPizza
* pizza 
= WX_PIZZA(win
->m_wxwindow
); 
1155         xx 
+= pizza
->m_scroll_x
; 
1156         yy 
+= pizza
->m_scroll_y
; 
1159     wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
1162         wxWindowGTK 
*child 
= node
->GetData(); 
1164         node 
= node
->GetNext(); 
1165         if (!child
->IsShown()) 
1168         if (child
->IsTransparentForMouse()) 
1170             // wxStaticBox is transparent in the box itself 
1171             int xx1 
= child
->m_x
; 
1172             int yy1 
= child
->m_y
; 
1173             int xx2 
= child
->m_x 
+ child
->m_width
; 
1174             int yy2 
= child
->m_y 
+ child
->m_height
; 
1177             if (((xx 
>= xx1
) && (xx 
<= xx1
+10) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1179                 ((xx 
>= xx2
-10) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1181                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy1
+10)) || 
1183                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy2
-1) && (yy 
<= yy2
))) 
1194             if ((child
->m_wxwindow 
== (GtkWidget
*) NULL
) && 
1195                 (child
->m_x 
<= xx
) && 
1196                 (child
->m_y 
<= yy
) && 
1197                 (child
->m_x
+child
->m_width  
>= xx
) && 
1198                 (child
->m_y
+child
->m_height 
>= yy
)) 
1211 // ---------------------------------------------------------------------------- 
1212 // common event handlers helpers 
1213 // ---------------------------------------------------------------------------- 
1215 bool wxWindowGTK::GTKProcessEvent(wxEvent
& event
) const 
1217     // nothing special at this level 
1218     return HandleWindowEvent(event
); 
1221 int wxWindowGTK::GTKCallbackCommonPrologue(GdkEventAny 
*event
) const 
1225     if (g_blockEventsOnDrag
) 
1227     if (g_blockEventsOnScroll
) 
1230     if (!GTKIsOwnWindow(event
->window
)) 
1236 // overloads for all GDK event types we use here: we need to have this as 
1237 // GdkEventXXX can't be implicitly cast to GdkEventAny even if it, in fact, 
1238 // derives from it in the sense that the structs have the same layout 
1239 #define wxDEFINE_COMMON_PROLOGUE_OVERLOAD(T)                                  \ 
1240     static int wxGtkCallbackCommonPrologue(T *event, wxWindowGTK *win)        \ 
1242         return win->GTKCallbackCommonPrologue((GdkEventAny *)event);          \ 
1245 wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventButton
) 
1246 wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventMotion
) 
1247 wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventCrossing
) 
1249 #undef wxDEFINE_COMMON_PROLOGUE_OVERLOAD 
1251 #define wxCOMMON_CALLBACK_PROLOGUE(event, win)                                \ 
1252     const int rc = wxGtkCallbackCommonPrologue(event, win);                   \ 
1256 // send the wxChildFocusEvent and wxFocusEvent, common code of 
1257 // gtk_window_focus_in_callback() and SetFocus() 
1258 static bool DoSendFocusEvents(wxWindow 
*win
) 
1260     // Notify the parent keeping track of focus for the kbd navigation 
1261     // purposes that we got it. 
1262     wxChildFocusEvent 
eventChildFocus(win
); 
1263     (void)win
->HandleWindowEvent(eventChildFocus
); 
1265     wxFocusEvent 
eventFocus(wxEVT_SET_FOCUS
, win
->GetId()); 
1266     eventFocus
.SetEventObject(win
); 
1268     return win
->HandleWindowEvent(eventFocus
); 
1271 // all event handlers must have C linkage as they're called from GTK+ C code 
1275 //----------------------------------------------------------------------------- 
1276 // "button_press_event" 
1277 //----------------------------------------------------------------------------- 
1280 gtk_window_button_press_callback( GtkWidget 
*widget
, 
1281                                   GdkEventButton 
*gdk_event
, 
1284     wxCOMMON_CALLBACK_PROLOGUE(gdk_event
, win
); 
1286     g_lastButtonNumber 
= gdk_event
->button
; 
1288     // GDK sends surplus button down events 
1289     // before a double click event. We 
1290     // need to filter these out. 
1291     if ((gdk_event
->type 
== GDK_BUTTON_PRESS
) && (win
->m_wxwindow
)) 
1293         GdkEvent 
*peek_event 
= gdk_event_peek(); 
1296             if ((peek_event
->type 
== GDK_2BUTTON_PRESS
) || 
1297                 (peek_event
->type 
== GDK_3BUTTON_PRESS
)) 
1299                 gdk_event_free( peek_event 
); 
1304                 gdk_event_free( peek_event 
); 
1309     wxEventType event_type 
= wxEVT_NULL
; 
1311     if ( gdk_event
->type 
== GDK_2BUTTON_PRESS 
&& 
1312             gdk_event
->button 
>= 1 && gdk_event
->button 
<= 3 ) 
1314         // Reset GDK internal timestamp variables in order to disable GDK 
1315         // triple click events. GDK will then next time believe no button has 
1316         // been clicked just before, and send a normal button click event. 
1317         GdkDisplay
* display 
= gtk_widget_get_display (widget
); 
1318         display
->button_click_time
[1] = 0; 
1319         display
->button_click_time
[0] = 0; 
1322     if (gdk_event
->button 
== 1) 
1324         // note that GDK generates triple click events which are not supported 
1325         // by wxWidgets but still have to be passed to the app as otherwise 
1326         // clicks would simply go missing 
1327         switch (gdk_event
->type
) 
1329             // we shouldn't get triple clicks at all for GTK2 because we 
1330             // suppress them artificially using the code above but we still 
1331             // should map them to something for GTK1 and not just ignore them 
1332             // as this would lose clicks 
1333             case GDK_3BUTTON_PRESS
:     // we could also map this to DCLICK... 
1334             case GDK_BUTTON_PRESS
: 
1335                 event_type 
= wxEVT_LEFT_DOWN
; 
1338             case GDK_2BUTTON_PRESS
: 
1339                 event_type 
= wxEVT_LEFT_DCLICK
; 
1343                 // just to silence gcc warnings 
1347     else if (gdk_event
->button 
== 2) 
1349         switch (gdk_event
->type
) 
1351             case GDK_3BUTTON_PRESS
: 
1352             case GDK_BUTTON_PRESS
: 
1353                 event_type 
= wxEVT_MIDDLE_DOWN
; 
1356             case GDK_2BUTTON_PRESS
: 
1357                 event_type 
= wxEVT_MIDDLE_DCLICK
; 
1364     else if (gdk_event
->button 
== 3) 
1366         switch (gdk_event
->type
) 
1368             case GDK_3BUTTON_PRESS
: 
1369             case GDK_BUTTON_PRESS
: 
1370                 event_type 
= wxEVT_RIGHT_DOWN
; 
1373             case GDK_2BUTTON_PRESS
: 
1374                 event_type 
= wxEVT_RIGHT_DCLICK
; 
1382     if ( event_type 
== wxEVT_NULL 
) 
1384         // unknown mouse button or click type 
1388     g_lastMouseEvent 
= (GdkEvent
*) gdk_event
; 
1390     wxMouseEvent 
event( event_type 
); 
1391     InitMouseEvent( win
, event
, gdk_event 
); 
1393     AdjustEventButtonState(event
); 
1395     // wxListBox actually gets mouse events from the item, so we need to give it 
1396     // a chance to correct this 
1397     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1399     // find the correct window to send the event to: it may be a different one 
1400     // from the one which got it at GTK+ level because some controls don't have 
1401     // their own X window and thus cannot get any events. 
1402     if ( !g_captureWindow 
) 
1403         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1405     // reset the event object and id in case win changed. 
1406     event
.SetEventObject( win 
); 
1407     event
.SetId( win
->GetId() ); 
1409     bool ret 
= win
->GTKProcessEvent( event 
); 
1410     g_lastMouseEvent 
= NULL
; 
1414     if ((event_type 
== wxEVT_LEFT_DOWN
) && !win
->IsOfStandardClass() && 
1415         (g_focusWindow 
!= win
) /* && win->IsFocusable() */) 
1420     if (event_type 
== wxEVT_RIGHT_DOWN
) 
1422         // generate a "context menu" event: this is similar to right mouse 
1423         // click under many GUIs except that it is generated differently 
1424         // (right up under MSW, ctrl-click under Mac, right down here) and 
1426         // (a) it's a command event and so is propagated to the parent 
1427         // (b) under some ports it can be generated from kbd too 
1428         // (c) it uses screen coords (because of (a)) 
1429         wxContextMenuEvent 
evtCtx( 
1432             win
->ClientToScreen(event
.GetPosition())); 
1433         evtCtx
.SetEventObject(win
); 
1434         return win
->GTKProcessEvent(evtCtx
); 
1440 //----------------------------------------------------------------------------- 
1441 // "button_release_event" 
1442 //----------------------------------------------------------------------------- 
1445 gtk_window_button_release_callback( GtkWidget 
*widget
, 
1446                                     GdkEventButton 
*gdk_event
, 
1449     wxCOMMON_CALLBACK_PROLOGUE(gdk_event
, win
); 
1451     g_lastButtonNumber 
= 0; 
1453     wxEventType event_type 
= wxEVT_NULL
; 
1455     switch (gdk_event
->button
) 
1458             event_type 
= wxEVT_LEFT_UP
; 
1462             event_type 
= wxEVT_MIDDLE_UP
; 
1466             event_type 
= wxEVT_RIGHT_UP
; 
1470             // unknown button, don't process 
1474     g_lastMouseEvent 
= (GdkEvent
*) gdk_event
; 
1476     wxMouseEvent 
event( event_type 
); 
1477     InitMouseEvent( win
, event
, gdk_event 
); 
1479     AdjustEventButtonState(event
); 
1481     // same wxListBox hack as above 
1482     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1484     if ( !g_captureWindow 
) 
1485         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1487     // reset the event object and id in case win changed. 
1488     event
.SetEventObject( win 
); 
1489     event
.SetId( win
->GetId() ); 
1491     bool ret 
= win
->GTKProcessEvent(event
); 
1493     g_lastMouseEvent 
= NULL
; 
1498 //----------------------------------------------------------------------------- 
1499 // "motion_notify_event" 
1500 //----------------------------------------------------------------------------- 
1503 gtk_window_motion_notify_callback( GtkWidget 
* WXUNUSED(widget
), 
1504                                    GdkEventMotion 
*gdk_event
, 
1507     wxCOMMON_CALLBACK_PROLOGUE(gdk_event
, win
); 
1509     if (gdk_event
->is_hint
) 
1513         GdkModifierType state
; 
1514         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1519     g_lastMouseEvent 
= (GdkEvent
*) gdk_event
; 
1521     wxMouseEvent 
event( wxEVT_MOTION 
); 
1522     InitMouseEvent(win
, event
, gdk_event
); 
1524     if ( g_captureWindow 
) 
1526         // synthesise a mouse enter or leave event if needed 
1527         GdkWindow 
*winUnderMouse 
= gdk_window_at_pointer(NULL
, NULL
); 
1528         // This seems to be necessary and actually been added to 
1529         // GDK itself in version 2.0.X 
1532         bool hasMouse 
= winUnderMouse 
== gdk_event
->window
; 
1533         if ( hasMouse 
!= g_captureWindowHasMouse 
) 
1535             // the mouse changed window 
1536             g_captureWindowHasMouse 
= hasMouse
; 
1538             wxMouseEvent 
eventM(g_captureWindowHasMouse 
? wxEVT_ENTER_WINDOW
 
1539                                                         : wxEVT_LEAVE_WINDOW
); 
1540             InitMouseEvent(win
, eventM
, gdk_event
); 
1541             eventM
.SetEventObject(win
); 
1542             win
->GTKProcessEvent(eventM
); 
1547         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1549         // reset the event object and id in case win changed. 
1550         event
.SetEventObject( win 
); 
1551         event
.SetId( win
->GetId() ); 
1554     if ( !g_captureWindow 
) 
1556         wxSetCursorEvent 
cevent( event
.m_x
, event
.m_y 
); 
1557         if (win
->GTKProcessEvent( cevent 
)) 
1559             win
->SetCursor( cevent
.GetCursor() ); 
1563     bool ret 
= win
->GTKProcessEvent(event
); 
1565     g_lastMouseEvent 
= NULL
; 
1570 //----------------------------------------------------------------------------- 
1571 // "scroll_event" (mouse wheel event) 
1572 //----------------------------------------------------------------------------- 
1575 window_scroll_event(GtkWidget
*, GdkEventScroll
* gdk_event
, wxWindow
* win
) 
1577     if (gdk_event
->direction 
!= GDK_SCROLL_UP 
&& 
1578         gdk_event
->direction 
!= GDK_SCROLL_DOWN
) 
1583     wxMouseEvent 
event(wxEVT_MOUSEWHEEL
); 
1584     InitMouseEvent(win
, event
, gdk_event
); 
1586     // FIXME: Get these values from GTK or GDK 
1587     event
.m_linesPerAction 
= 3; 
1588     event
.m_wheelDelta 
= 120; 
1589     if (gdk_event
->direction 
== GDK_SCROLL_UP
) 
1590         event
.m_wheelRotation 
= 120; 
1592         event
.m_wheelRotation 
= -120; 
1594     return win
->GTKProcessEvent(event
); 
1597 //----------------------------------------------------------------------------- 
1599 //----------------------------------------------------------------------------- 
1601 static gboolean 
wxgtk_window_popup_menu_callback(GtkWidget
*, wxWindowGTK
* win
) 
1603     wxContextMenuEvent 
event(wxEVT_CONTEXT_MENU
, win
->GetId(), wxPoint(-1, -1)); 
1604     event
.SetEventObject(win
); 
1605     return win
->GTKProcessEvent(event
); 
1608 //----------------------------------------------------------------------------- 
1610 //----------------------------------------------------------------------------- 
1613 gtk_window_focus_in_callback( GtkWidget 
* WXUNUSED(widget
), 
1614                               GdkEventFocus 
*WXUNUSED(event
), 
1618         gtk_im_context_focus_in(win
->m_imData
->context
); 
1620     g_focusWindow 
= win
; 
1622     wxLogTrace(TRACE_FOCUS
, 
1623                _T("%s: focus in"), win
->GetName().c_str()); 
1626     // caret needs to be informed about focus change 
1627     wxCaret 
*caret 
= win
->GetCaret(); 
1630         caret
->OnSetFocus(); 
1632 #endif // wxUSE_CARET 
1634     gboolean ret 
= FALSE
; 
1636     // does the window itself think that it has the focus? 
1637     if ( !win
->m_hasFocus 
) 
1639         // not yet, notify it 
1640         win
->m_hasFocus 
= true; 
1642         (void)DoSendFocusEvents(win
); 
1647     // Disable default focus handling for custom windows 
1648     // since the default GTK+ handler issues a repaint 
1649     if (win
->m_wxwindow
) 
1655 //----------------------------------------------------------------------------- 
1656 // "focus_out_event" 
1657 //----------------------------------------------------------------------------- 
1660 gtk_window_focus_out_callback( GtkWidget 
* WXUNUSED(widget
), 
1661                                GdkEventFocus 
* WXUNUSED(gdk_event
), 
1665         gtk_im_context_focus_out(win
->m_imData
->context
); 
1667     wxLogTrace( TRACE_FOCUS
, 
1668                 _T("%s: focus out"), win
->GetName().c_str() ); 
1671     wxWindowGTK 
*winFocus 
= wxFindFocusedChild(win
); 
1675     g_focusWindow 
= (wxWindowGTK 
*)NULL
; 
1678     // caret needs to be informed about focus change 
1679     wxCaret 
*caret 
= win
->GetCaret(); 
1682         caret
->OnKillFocus(); 
1684 #endif // wxUSE_CARET 
1686     // don't send the window a kill focus event if it thinks that it doesn't 
1687     // have focus already 
1688     if ( win
->m_hasFocus 
) 
1690         // the event handler might delete the window when it loses focus, so 
1691         // check whether this is a custom window before calling it 
1692         const bool has_wxwindow 
= win
->m_wxwindow 
!= NULL
; 
1694         win
->m_hasFocus 
= false; 
1696         wxFocusEvent 
event( wxEVT_KILL_FOCUS
, win
->GetId() ); 
1697         event
.SetEventObject( win 
); 
1699         (void)win
->GTKProcessEvent( event 
); 
1701         // Disable default focus handling for custom windows 
1702         // since the default GTK+ handler issues a repaint 
1707     // continue with normal processing 
1712 wx_window_focus_callback(GtkWidget 
*widget
, 
1713                          GtkDirectionType 
WXUNUSED(direction
), 
1716     // the default handler for focus signal in GtkScrolledWindow sets 
1717     // focus to the window itself even if it doesn't accept focus, i.e. has no 
1718     // GTK_CAN_FOCUS in its style -- work around this by forcibly preventing 
1719     // the signal from reaching gtk_scrolled_window_focus() if we don't have 
1720     // any children which might accept focus (we know we don't accept the focus 
1721     // ourselves as this signal is only connected in this case) 
1722     if ( win
->GetChildren().empty() ) 
1723         g_signal_stop_emission_by_name(widget
, "focus"); 
1725     // we didn't change the focus 
1729 //----------------------------------------------------------------------------- 
1730 // "enter_notify_event" 
1731 //----------------------------------------------------------------------------- 
1734 gtk_window_enter_callback( GtkWidget 
*widget
, 
1735                            GdkEventCrossing 
*gdk_event
, 
1738     wxCOMMON_CALLBACK_PROLOGUE(gdk_event
, win
); 
1740     // Event was emitted after a grab 
1741     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
1745     GdkModifierType state 
= (GdkModifierType
)0; 
1747     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
1749     wxMouseEvent 
event( wxEVT_ENTER_WINDOW 
); 
1750     InitMouseEvent(win
, event
, gdk_event
); 
1751     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1752     event
.m_x 
= x 
+ pt
.x
; 
1753     event
.m_y 
= y 
+ pt
.y
; 
1755     if ( !g_captureWindow 
) 
1757         wxSetCursorEvent 
cevent( event
.m_x
, event
.m_y 
); 
1758         if (win
->GTKProcessEvent( cevent 
)) 
1760             win
->SetCursor( cevent
.GetCursor() ); 
1764     return win
->GTKProcessEvent(event
); 
1767 //----------------------------------------------------------------------------- 
1768 // "leave_notify_event" 
1769 //----------------------------------------------------------------------------- 
1772 gtk_window_leave_callback( GtkWidget 
*widget
, 
1773                            GdkEventCrossing 
*gdk_event
, 
1776     wxCOMMON_CALLBACK_PROLOGUE(gdk_event
, win
); 
1778     // Event was emitted after an ungrab 
1779     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
1781     wxMouseEvent 
event( wxEVT_LEAVE_WINDOW 
); 
1785     GdkModifierType state 
= (GdkModifierType
)0; 
1787     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
1789     InitMouseEvent(win
, event
, gdk_event
); 
1791     return win
->GTKProcessEvent(event
); 
1794 //----------------------------------------------------------------------------- 
1795 // "value_changed" from scrollbar 
1796 //----------------------------------------------------------------------------- 
1799 gtk_scrollbar_value_changed(GtkRange
* range
, wxWindow
* win
) 
1801     wxEventType eventType 
= win
->GetScrollEventType(range
); 
1802     if (eventType 
!= wxEVT_NULL
) 
1804         // Convert scroll event type to scrollwin event type 
1805         eventType 
+= wxEVT_SCROLLWIN_TOP 
- wxEVT_SCROLL_TOP
; 
1807         // find the scrollbar which generated the event 
1808         wxWindowGTK::ScrollDir dir 
= win
->ScrollDirFromRange(range
); 
1810         // generate the corresponding wx event 
1811         const int orient 
= wxWindow::OrientFromScrollDir(dir
); 
1812         wxScrollWinEvent 
event(eventType
, win
->GetScrollPos(orient
), orient
); 
1813         event
.SetEventObject(win
); 
1815         win
->GTKProcessEvent(event
); 
1819 //----------------------------------------------------------------------------- 
1820 // "button_press_event" from scrollbar 
1821 //----------------------------------------------------------------------------- 
1824 gtk_scrollbar_button_press_event(GtkRange
*, GdkEventButton
*, wxWindow
* win
) 
1826     g_blockEventsOnScroll 
= true; 
1827     win
->m_mouseButtonDown 
= true; 
1832 //----------------------------------------------------------------------------- 
1833 // "event_after" from scrollbar 
1834 //----------------------------------------------------------------------------- 
1837 gtk_scrollbar_event_after(GtkRange
* range
, GdkEvent
* event
, wxWindow
* win
) 
1839     if (event
->type 
== GDK_BUTTON_RELEASE
) 
1841         g_signal_handlers_block_by_func(range
, (void*)gtk_scrollbar_event_after
, win
); 
1843         const int orient 
= wxWindow::OrientFromScrollDir( 
1844                                         win
->ScrollDirFromRange(range
)); 
1845         wxScrollWinEvent 
evt(wxEVT_SCROLLWIN_THUMBRELEASE
, 
1846                                 win
->GetScrollPos(orient
), orient
); 
1847         evt
.SetEventObject(win
); 
1848         win
->GTKProcessEvent(evt
); 
1852 //----------------------------------------------------------------------------- 
1853 // "button_release_event" from scrollbar 
1854 //----------------------------------------------------------------------------- 
1857 gtk_scrollbar_button_release_event(GtkRange
* range
, GdkEventButton
*, wxWindow
* win
) 
1859     g_blockEventsOnScroll 
= false; 
1860     win
->m_mouseButtonDown 
= false; 
1861     // If thumb tracking 
1862     if (win
->m_isScrolling
) 
1864         win
->m_isScrolling 
= false; 
1865         // Hook up handler to send thumb release event after this emission is finished. 
1866         // To allow setting scroll position from event handler, sending event must 
1867         // be deferred until after the GtkRange handler for this signal has run 
1868         g_signal_handlers_unblock_by_func(range
, (void*)gtk_scrollbar_event_after
, win
); 
1874 //----------------------------------------------------------------------------- 
1875 // "realize" from m_widget 
1876 //----------------------------------------------------------------------------- 
1879 gtk_window_realized_callback(GtkWidget
* widget
, wxWindow
* win
) 
1883         gtk_im_context_set_client_window( win
->m_imData
->context
, 
1887     // We cannot set colours and fonts before the widget 
1888     // been realized, so we do this directly after realization 
1889     // or otherwise in idle time 
1891     if (win
->m_needsStyleChange
) 
1893         win
->SetBackgroundStyle(win
->GetBackgroundStyle()); 
1894         win
->m_needsStyleChange 
= false; 
1897     wxWindowCreateEvent 
event( win 
); 
1898     event
.SetEventObject( win 
); 
1899     win
->GTKProcessEvent( event 
); 
1902 //----------------------------------------------------------------------------- 
1903 // "size_allocate" from m_wxwindow or m_widget 
1904 //----------------------------------------------------------------------------- 
1907 size_allocate(GtkWidget
*, GtkAllocation
* alloc
, wxWindow
* win
) 
1909     int w 
= alloc
->width
; 
1910     int h 
= alloc
->height
; 
1911     if (win
->m_wxwindow
) 
1913         int border_x
, border_y
; 
1914         WX_PIZZA(win
->m_wxwindow
)->get_border_widths(border_x
, border_y
); 
1920     if (win
->m_oldClientWidth 
!= w 
|| win
->m_oldClientHeight 
!= h
) 
1922         win
->m_oldClientWidth  
= w
; 
1923         win
->m_oldClientHeight 
= h
; 
1924         // this callback can be connected to m_wxwindow, 
1925         // so always get size from m_widget->allocation 
1926         win
->m_width  
= win
->m_widget
->allocation
.width
; 
1927         win
->m_height 
= win
->m_widget
->allocation
.height
; 
1928         if (!win
->m_nativeSizeEvent
) 
1930             wxSizeEvent 
event(win
->GetSize(), win
->GetId()); 
1931             event
.SetEventObject(win
); 
1932             win
->GTKProcessEvent(event
); 
1937 //----------------------------------------------------------------------------- 
1939 //----------------------------------------------------------------------------- 
1941 #if GTK_CHECK_VERSION(2, 8, 0) 
1943 gtk_window_grab_broken( GtkWidget
*, 
1944                         GdkEventGrabBroken 
*event
, 
1947     // Mouse capture has been lost involuntarily, notify the application 
1948     if(!event
->keyboard 
&& wxWindow::GetCapture() == win
) 
1950         wxMouseCaptureLostEvent 
evt( win
->GetId() ); 
1951         evt
.SetEventObject( win 
); 
1952         win
->HandleWindowEvent( evt 
); 
1958 //----------------------------------------------------------------------------- 
1960 //----------------------------------------------------------------------------- 
1963 void gtk_window_style_set_callback( GtkWidget 
*WXUNUSED(widget
), 
1964                                GtkStyle 
*previous_style
, 
1967     if (win 
&& previous_style
) 
1969         wxSysColourChangedEvent event
; 
1970         event
.SetEventObject(win
); 
1972         win
->GTKProcessEvent( event 
); 
1978 // Helper to suspend colour change event event processing while we change a widget's style 
1979 class wxSuspendStyleEvents
 
1982     wxSuspendStyleEvents(wxWindow
* win
) 
1985         if (win
->m_wxwindow 
&& win
->IsTopLevel()) 
1988             g_signal_handlers_block_by_func( 
1989                 m_win
->m_wxwindow
, (void*)gtk_window_style_set_callback
, m_win
); 
1992     ~wxSuspendStyleEvents() 
1995             g_signal_handlers_unblock_by_func( 
1996                 m_win
->m_wxwindow
, (void*)gtk_window_style_set_callback
, m_win
); 
2002 // ---------------------------------------------------------------------------- 
2003 // this wxWindowBase function is implemented here (in platform-specific file) 
2004 // because it is static and so couldn't be made virtual 
2005 // ---------------------------------------------------------------------------- 
2007 wxWindow 
*wxWindowBase::DoFindFocus() 
2009     // the cast is necessary when we compile in wxUniversal mode 
2010     return (wxWindow 
*)g_focusWindow
; 
2013 //----------------------------------------------------------------------------- 
2014 // InsertChild for wxWindowGTK. 
2015 //----------------------------------------------------------------------------- 
2017 /* Callback for wxWindowGTK. This very strange beast has to be used because 
2018  * C++ has no virtual methods in a constructor. We have to emulate a 
2019  * virtual function here as wxNotebook requires a different way to insert 
2020  * a child in it. I had opted for creating a wxNotebookPage window class 
2021  * which would have made this superfluous (such in the MDI window system), 
2022  * but no-one was listening to me... */ 
2024 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child 
) 
2026     /* the window might have been scrolled already, do we 
2027        have to adapt the position */ 
2028     wxPizza
* pizza 
= WX_PIZZA(parent
->m_wxwindow
); 
2029     child
->m_x 
+= pizza
->m_scroll_x
; 
2030     child
->m_y 
+= pizza
->m_scroll_y
; 
2032     gtk_widget_set_size_request( 
2033         child
->m_widget
, child
->m_width
, child
->m_height
); 
2035         GTK_FIXED(parent
->m_wxwindow
), child
->m_widget
, child
->m_x
, child
->m_y
); 
2038 //----------------------------------------------------------------------------- 
2040 //----------------------------------------------------------------------------- 
2042 wxWindow 
*wxGetActiveWindow() 
2044     return wxWindow::FindFocus(); 
2048 wxMouseState 
wxGetMouseState() 
2054     GdkModifierType mask
; 
2056     gdk_window_get_pointer(NULL
, &x
, &y
, &mask
); 
2060     ms
.SetLeftDown(mask 
& GDK_BUTTON1_MASK
); 
2061     ms
.SetMiddleDown(mask 
& GDK_BUTTON2_MASK
); 
2062     ms
.SetRightDown(mask 
& GDK_BUTTON3_MASK
); 
2063     ms
.SetAux1Down(mask 
& GDK_BUTTON4_MASK
); 
2064     ms
.SetAux2Down(mask 
& GDK_BUTTON5_MASK
); 
2066     ms
.SetControlDown(mask 
& GDK_CONTROL_MASK
); 
2067     ms
.SetShiftDown(mask 
& GDK_SHIFT_MASK
); 
2068     ms
.SetAltDown(mask 
& GDK_MOD1_MASK
); 
2069     ms
.SetMetaDown(mask 
& GDK_MOD2_MASK
); 
2074 //----------------------------------------------------------------------------- 
2076 //----------------------------------------------------------------------------- 
2078 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
2080 #ifdef __WXUNIVERSAL__ 
2081     IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
) 
2083     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
2084 #endif // __WXUNIVERSAL__/__WXGTK__ 
2086 void wxWindowGTK::Init() 
2089     m_widget 
= (GtkWidget 
*) NULL
; 
2090     m_wxwindow 
= (GtkWidget 
*) NULL
; 
2091     m_focusWidget 
= (GtkWidget 
*) NULL
; 
2100     m_isBeingDeleted 
= false; 
2102     m_showOnIdle
= false; 
2105     m_nativeSizeEvent 
= false; 
2107     m_isScrolling 
= false; 
2108     m_mouseButtonDown 
= false; 
2110     // initialize scrolling stuff 
2111     for ( int dir 
= 0; dir 
< ScrollDir_Max
; dir
++ ) 
2113         m_scrollBar
[dir
] = NULL
; 
2114         m_scrollPos
[dir
] = 0; 
2118     m_oldClientHeight 
= 0; 
2120     m_insertCallback 
= wxInsertChildInWindow
; 
2124     m_clipPaintRegion 
= false; 
2126     m_needsStyleChange 
= false; 
2128     m_cursor 
= *wxSTANDARD_CURSOR
; 
2131     m_dirtyTabOrder 
= false; 
2134 wxWindowGTK::wxWindowGTK() 
2139 wxWindowGTK::wxWindowGTK( wxWindow 
*parent
, 
2144                           const wxString 
&name  
) 
2148     Create( parent
, id
, pos
, size
, style
, name 
); 
2151 bool wxWindowGTK::Create( wxWindow 
*parent
, 
2156                           const wxString 
&name  
) 
2158     // Get default border 
2159     wxBorder border 
= GetBorder(style
); 
2160     style 
&= ~wxBORDER_MASK
; 
2163     if (!PreCreation( parent
, pos
, size 
) || 
2164         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
2166         wxFAIL_MSG( wxT("wxWindowGTK creation failed") ); 
2171     m_wxwindow 
= wxPizza::New(m_windowStyle
); 
2172     if (!HasFlag(wxHSCROLL
) && !HasFlag(wxVSCROLL
)) 
2173         m_widget 
= m_wxwindow
; 
2176         m_widget 
= gtk_scrolled_window_new( (GtkAdjustment 
*) NULL
, (GtkAdjustment 
*) NULL 
); 
2178         GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
2180         GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2181         scroll_class
->scrollbar_spacing 
= 0; 
2183         // There is a conflict with default bindings at GTK+ 
2184         // level between scrolled windows and notebooks both of which want to use 
2185         // Ctrl-PageUp/Down: scrolled windows for scrolling in the horizontal 
2186         // direction and notebooks for changing pages -- we decide that if we don't 
2187         // have wxHSCROLL style we can safely sacrifice horizontal scrolling if it 
2188         // means we can get working keyboard navigation in notebooks 
2189         if ( !HasFlag(wxHSCROLL
) ) 
2192                 bindings 
= gtk_binding_set_by_class(G_OBJECT_GET_CLASS(m_widget
)); 
2195                 gtk_binding_entry_remove(bindings
, GDK_Page_Up
, GDK_CONTROL_MASK
); 
2196                 gtk_binding_entry_remove(bindings
, GDK_Page_Down
, GDK_CONTROL_MASK
); 
2200         if (HasFlag(wxALWAYS_SHOW_SB
)) 
2202             gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_ALWAYS
, GTK_POLICY_ALWAYS 
); 
2204             scrolledWindow
->hscrollbar_visible 
= TRUE
; 
2205             scrolledWindow
->vscrollbar_visible 
= TRUE
; 
2209             gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
2212         m_scrollBar
[ScrollDir_Horz
] = GTK_RANGE(scrolledWindow
->hscrollbar
); 
2213         m_scrollBar
[ScrollDir_Vert
] = GTK_RANGE(scrolledWindow
->vscrollbar
); 
2214         if (GetLayoutDirection() == wxLayout_RightToLeft
) 
2215             gtk_range_set_inverted( m_scrollBar
[ScrollDir_Horz
], TRUE 
); 
2217         gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
2219         // connect various scroll-related events 
2220         for ( int dir 
= 0; dir 
< ScrollDir_Max
; dir
++ ) 
2222             // these handlers block mouse events to any window during scrolling 
2223             // such as motion events and prevent GTK and wxWidgets from fighting 
2224             // over where the slider should be 
2225             g_signal_connect(m_scrollBar
[dir
], "button_press_event", 
2226                          G_CALLBACK(gtk_scrollbar_button_press_event
), this); 
2227             g_signal_connect(m_scrollBar
[dir
], "button_release_event", 
2228                          G_CALLBACK(gtk_scrollbar_button_release_event
), this); 
2230             gulong handler_id 
= g_signal_connect(m_scrollBar
[dir
], "event_after", 
2231                                 G_CALLBACK(gtk_scrollbar_event_after
), this); 
2232             g_signal_handler_block(m_scrollBar
[dir
], handler_id
); 
2234             // these handlers get notified when scrollbar slider moves 
2235             g_signal_connect_after(m_scrollBar
[dir
], "value_changed", 
2236                          G_CALLBACK(gtk_scrollbar_value_changed
), this); 
2239         gtk_widget_show( m_wxwindow 
); 
2243         m_parent
->DoAddChild( this ); 
2245     m_focusWidget 
= m_wxwindow
; 
2252 wxWindowGTK::~wxWindowGTK() 
2256     if (g_focusWindow 
== this) 
2257         g_focusWindow 
= NULL
; 
2259     if ( g_delayedFocus 
== this ) 
2260         g_delayedFocus 
= NULL
; 
2262     m_isBeingDeleted 
= true; 
2265     // destroy children before destroying this window itself 
2268     // unhook focus handlers to prevent stray events being 
2269     // propagated to this (soon to be) dead object 
2270     if (m_focusWidget 
!= NULL
) 
2272         g_signal_handlers_disconnect_by_func (m_focusWidget
, 
2273                                               (gpointer
) gtk_window_focus_in_callback
, 
2275         g_signal_handlers_disconnect_by_func (m_focusWidget
, 
2276                                               (gpointer
) gtk_window_focus_out_callback
, 
2283     // delete before the widgets to avoid a crash on solaris 
2286     if (m_wxwindow 
&& (m_wxwindow 
!= m_widget
)) 
2288         gtk_widget_destroy( m_wxwindow 
); 
2289         m_wxwindow 
= (GtkWidget
*) NULL
; 
2294         gtk_widget_destroy( m_widget 
); 
2295         m_widget 
= (GtkWidget
*) NULL
; 
2299 bool wxWindowGTK::PreCreation( wxWindowGTK 
*parent
, const wxPoint 
&pos
,  const wxSize 
&size 
) 
2301     if ( GTKNeedsParent() ) 
2303         wxCHECK_MSG( parent
, false, wxT("Must have non-NULL parent") ); 
2306     // Use either the given size, or the default if -1 is given. 
2307     // See wxWindowBase for these functions. 
2308     m_width 
= WidthDefault(size
.x
) ; 
2309     m_height 
= HeightDefault(size
.y
); 
2317 void wxWindowGTK::PostCreation() 
2319     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2325             // these get reported to wxWidgets -> wxPaintEvent 
2327             g_signal_connect (m_wxwindow
, "expose_event", 
2328                               G_CALLBACK (gtk_window_expose_callback
), this); 
2330             if (GetLayoutDirection() == wxLayout_LeftToRight
) 
2331                 gtk_widget_set_redraw_on_allocate(m_wxwindow
, HasFlag(wxFULL_REPAINT_ON_RESIZE
)); 
2334         // Create input method handler 
2335         m_imData 
= new wxGtkIMData
; 
2337         // Cannot handle drawing preedited text yet 
2338         gtk_im_context_set_use_preedit( m_imData
->context
, FALSE 
); 
2340         g_signal_connect (m_imData
->context
, "commit", 
2341                           G_CALLBACK (gtk_wxwindow_commit_cb
), this); 
2344 #ifndef __WXUNIVERSAL__ 
2345         if (HasFlag(wxPizza::BORDER_STYLES
)) 
2347             g_signal_connect(m_widget
, "expose_event", 
2348                 G_CALLBACK(expose_event_border
), this); 
2355     if (!GTK_IS_WINDOW(m_widget
)) 
2357         if (m_focusWidget 
== NULL
) 
2358             m_focusWidget 
= m_widget
; 
2362             g_signal_connect (m_focusWidget
, "focus_in_event", 
2363                           G_CALLBACK (gtk_window_focus_in_callback
), this); 
2364             g_signal_connect (m_focusWidget
, "focus_out_event", 
2365                                 G_CALLBACK (gtk_window_focus_out_callback
), this); 
2369             g_signal_connect_after (m_focusWidget
, "focus_in_event", 
2370                           G_CALLBACK (gtk_window_focus_in_callback
), this); 
2371             g_signal_connect_after (m_focusWidget
, "focus_out_event", 
2372                                 G_CALLBACK (gtk_window_focus_out_callback
), this); 
2376     if ( !AcceptsFocusFromKeyboard() ) 
2380         g_signal_connect(m_widget
, "focus", 
2381                             G_CALLBACK(wx_window_focus_callback
), this); 
2384     // connect to the various key and mouse handlers 
2386     GtkWidget 
*connect_widget 
= GetConnectWidget(); 
2388     ConnectWidget( connect_widget 
); 
2390     /* We cannot set colours, fonts and cursors before the widget has 
2391        been realized, so we do this directly after realization */ 
2392     g_signal_connect (connect_widget
, "realize", 
2393                       G_CALLBACK (gtk_window_realized_callback
), this); 
2397         g_signal_connect(m_wxwindow 
? m_wxwindow 
: m_widget
, "size_allocate", 
2398             G_CALLBACK(size_allocate
), this); 
2403 #if GTK_CHECK_VERSION(2, 8, 0) 
2404         if (!gtk_check_version(2,8,0)) 
2406             // Make sure we can notify the app when mouse capture is lost 
2407             g_signal_connect (m_wxwindow
, "grab_broken_event", 
2408                           G_CALLBACK (gtk_window_grab_broken
), this); 
2413     if ( connect_widget 
!= m_wxwindow 
) 
2415 #if GTK_CHECK_VERSION(2, 8, 0) 
2416         if (!gtk_check_version(2,8,0)) 
2418             // Make sure we can notify app code when mouse capture is lost 
2419             g_signal_connect (connect_widget
, "grab_broken_event", 
2420                         G_CALLBACK (gtk_window_grab_broken
), this); 
2425 #ifdef GTK_IS_FILE_CHOOSER_BUTTON 
2426     if (!gtk_check_version(2,6,0) && GTK_IS_FILE_CHOOSER_BUTTON(m_widget
)) 
2428         // If we connect to the "size_request" signal of a GtkFileChooserButton 
2429         // then that control won't be sized properly when placed inside sizers 
2430         // (this can be tested removing this elseif and running XRC or WIDGETS samples) 
2431         // FIXME: what should be done here ? 
2434     if ( !IsTopLevel() ) // top level windows use their own callback 
2436         // This is needed if we want to add our windows into native 
2437         // GTK controls, such as the toolbar. With this callback, the 
2438         // toolbar gets to know the correct size (the one set by the 
2439         // programmer). Sadly, it misbehaves for wxComboBox. 
2440         g_signal_connect (m_widget
, "size_request", 
2441                           G_CALLBACK (wxgtk_window_size_request_callback
), 
2445     InheritAttributes(); 
2449     SetLayoutDirection(wxLayout_Default
); 
2451     // unless the window was created initially hidden (i.e. Hide() had been 
2452     // called before Create()), we should show it at GTK+ level as well 
2454         gtk_widget_show( m_widget 
); 
2457 void wxWindowGTK::ConnectWidget( GtkWidget 
*widget 
) 
2459     g_signal_connect (widget
, "key_press_event", 
2460                       G_CALLBACK (gtk_window_key_press_callback
), this); 
2461     g_signal_connect (widget
, "key_release_event", 
2462                       G_CALLBACK (gtk_window_key_release_callback
), this); 
2463     g_signal_connect (widget
, "button_press_event", 
2464                       G_CALLBACK (gtk_window_button_press_callback
), this); 
2465     g_signal_connect (widget
, "button_release_event", 
2466                       G_CALLBACK (gtk_window_button_release_callback
), this); 
2467     g_signal_connect (widget
, "motion_notify_event", 
2468                       G_CALLBACK (gtk_window_motion_notify_callback
), this); 
2469     g_signal_connect (widget
, "scroll_event", 
2470                       G_CALLBACK (window_scroll_event
), this); 
2471     g_signal_connect (widget
, "popup_menu", 
2472                      G_CALLBACK (wxgtk_window_popup_menu_callback
), this); 
2473     g_signal_connect (widget
, "enter_notify_event", 
2474                       G_CALLBACK (gtk_window_enter_callback
), this); 
2475     g_signal_connect (widget
, "leave_notify_event", 
2476                       G_CALLBACK (gtk_window_leave_callback
), this); 
2478     if (IsTopLevel() && m_wxwindow
) 
2479         g_signal_connect (m_wxwindow
, "style_set", 
2480                               G_CALLBACK (gtk_window_style_set_callback
), this); 
2483 bool wxWindowGTK::Destroy() 
2485     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2489     return wxWindowBase::Destroy(); 
2492 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
) 
2494     gtk_widget_set_size_request(m_widget
, width
, height
); 
2495     // inform the parent to perform the move 
2496     WX_PIZZA(m_parent
->m_wxwindow
)->move(m_widget
, x
, y
); 
2499 void wxWindowGTK::ConstrainSize() 
2502     // GPE's window manager doesn't like size hints at all, esp. when the user 
2503     // has to use the virtual keyboard, so don't constrain size there 
2507         const wxSize minSize 
= GetMinSize(); 
2508         const wxSize maxSize 
= GetMaxSize(); 
2509         if (minSize
.x 
> 0 && m_width  
< minSize
.x
) m_width  
= minSize
.x
; 
2510         if (minSize
.y 
> 0 && m_height 
< minSize
.y
) m_height 
= minSize
.y
; 
2511         if (maxSize
.x 
> 0 && m_width  
> maxSize
.x
) m_width  
= maxSize
.x
; 
2512         if (maxSize
.y 
> 0 && m_height 
> maxSize
.y
) m_height 
= maxSize
.y
; 
2516 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
2518     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2519     wxASSERT_MSG( (m_parent 
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") ); 
2521     int currentX
, currentY
; 
2522     GetPosition(¤tX
, ¤tY
); 
2523     if (x 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
2525     if (y 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
2527     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
2529     // calculate the best size if we should auto size the window 
2530     if ( ((sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1) || 
2531          ((sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1) ) 
2533         const wxSize sizeBest 
= GetBestSize(); 
2534         if ( (sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1 ) 
2536         if ( (sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1 ) 
2537             height 
= sizeBest
.y
; 
2540     const wxSize 
oldSize(m_width
, m_height
); 
2548     if (m_parent
->m_wxwindow
) 
2550         wxPizza
* pizza 
= WX_PIZZA(m_parent
->m_wxwindow
); 
2551         m_x 
= x 
+ pizza
->m_scroll_x
; 
2552         m_y 
= y 
+ pizza
->m_scroll_y
; 
2554         int left_border 
= 0; 
2555         int right_border 
= 0; 
2557         int bottom_border 
= 0; 
2559         /* the default button has a border around it */ 
2560         if (GTK_WIDGET_CAN_DEFAULT(m_widget
)) 
2562             GtkBorder 
*default_border 
= NULL
; 
2563             gtk_widget_style_get( m_widget
, "default_border", &default_border
, NULL 
); 
2566                 left_border 
+= default_border
->left
; 
2567                 right_border 
+= default_border
->right
; 
2568                 top_border 
+= default_border
->top
; 
2569                 bottom_border 
+= default_border
->bottom
; 
2570                 gtk_border_free( default_border 
); 
2574         DoMoveWindow( m_x 
- left_border
, 
2576                       m_width
+left_border
+right_border
, 
2577                       m_height
+top_border
+bottom_border 
); 
2580     if (m_width 
!= oldSize
.x 
|| m_height 
!= oldSize
.y
) 
2582         // update these variables to keep size_allocate handler 
2583         // from sending another size event for this change 
2584         GetClientSize( &m_oldClientWidth
, &m_oldClientHeight 
); 
2586         gtk_widget_queue_resize(m_widget
); 
2587         if (!m_nativeSizeEvent
) 
2589             wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
2590             event
.SetEventObject( this ); 
2591             HandleWindowEvent( event 
); 
2596 bool wxWindowGTK::GtkShowFromOnIdle() 
2598     if (IsShown() && m_showOnIdle 
&& !GTK_WIDGET_VISIBLE (m_widget
)) 
2600         GtkAllocation alloc
; 
2603         alloc
.width 
= m_width
; 
2604         alloc
.height 
= m_height
; 
2605         gtk_widget_size_allocate( m_widget
, &alloc 
); 
2606         gtk_widget_show( m_widget 
); 
2607         wxShowEvent 
eventShow(GetId(), true); 
2608         eventShow
.SetEventObject(this); 
2609         HandleWindowEvent(eventShow
); 
2610         m_showOnIdle 
= false; 
2617 void wxWindowGTK::OnInternalIdle() 
2619     // Check if we have to show window now 
2620     if (GtkShowFromOnIdle()) return; 
2622     if ( m_dirtyTabOrder 
) 
2624         m_dirtyTabOrder 
= false; 
2628     // Update style if the window was not yet realized 
2629     // and SetBackgroundStyle(wxBG_STYLE_CUSTOM) was called 
2630     if (m_needsStyleChange
) 
2632         SetBackgroundStyle(GetBackgroundStyle()); 
2633         m_needsStyleChange 
= false; 
2636     wxCursor cursor 
= m_cursor
; 
2637     if (g_globalCursor
.Ok()) cursor 
= g_globalCursor
; 
2641         /* I now set the cursor anew in every OnInternalIdle call 
2642            as setting the cursor in a parent window also effects the 
2643            windows above so that checking for the current cursor is 
2646         if (m_wxwindow 
&& (m_wxwindow 
!= m_widget
)) 
2648             GdkWindow 
*window 
= m_wxwindow
->window
; 
2650                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2652             if (!g_globalCursor
.Ok()) 
2653                 cursor 
= *wxSTANDARD_CURSOR
; 
2655             window 
= m_widget
->window
; 
2656             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
2657                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2660         else if ( m_widget 
) 
2662             GdkWindow 
*window 
= m_widget
->window
; 
2663             if ( window 
&& !GTK_WIDGET_NO_WINDOW(m_widget
) ) 
2664                gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2668     if (wxUpdateUIEvent::CanUpdate(this) && IsShown()) 
2669         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
2672 void wxWindowGTK::DoGetSize( int *width
, int *height 
) const 
2674     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2676     if (width
) (*width
) = m_width
; 
2677     if (height
) (*height
) = m_height
; 
2680 void wxWindowGTK::DoSetClientSize( int width
, int height 
) 
2682     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2684     const wxSize size 
= GetSize(); 
2685     const wxSize clientSize 
= GetClientSize(); 
2686     SetSize(width 
+ (size
.x 
- clientSize
.x
), height 
+ (size
.y 
- clientSize
.y
)); 
2689 void wxWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
2691     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2698         // if window is scrollable, account for scrollbars 
2699         for (int i 
= 0; i 
< 2 && m_scrollBar
[i
]; i
++) 
2702             GtkAdjustment
* adj 
= gtk_range_get_adjustment(m_scrollBar
[i
]); 
2703             // if scrollbar enabled 
2704             if (adj
->upper 
> adj
->page_size
) 
2706                 gtk_widget_size_request(GTK_WIDGET(m_scrollBar
[i
]), &req
); 
2707                 if (i 
== ScrollDir_Horz
) 
2714         int border_x
, border_y
; 
2715         WX_PIZZA(m_wxwindow
)->get_border_widths(border_x
, border_y
); 
2725     if (width
) *width 
= w
; 
2726     if (height
) *height 
= h
; 
2729 void wxWindowGTK::DoGetPosition( int *x
, int *y 
) const 
2731     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2735     if (!IsTopLevel() && m_parent 
&& m_parent
->m_wxwindow
) 
2737         wxPizza
* pizza 
= WX_PIZZA(m_parent
->m_wxwindow
); 
2738         dx 
= pizza
->m_scroll_x
; 
2739         dy 
= pizza
->m_scroll_y
; 
2742     if (m_x 
== -1 && m_y 
== -1) 
2744         GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
2746             source 
= m_wxwindow
->window
; 
2748             source 
= m_widget
->window
; 
2754             gdk_window_get_origin( source
, &org_x
, &org_y 
); 
2757                 m_parent
->ScreenToClient(&org_x
, &org_y
); 
2759             wx_const_cast(wxWindowGTK
*, this)->m_x 
= org_x
; 
2760             wx_const_cast(wxWindowGTK
*, this)->m_y 
= org_y
; 
2764     if (x
) (*x
) = m_x 
- dx
; 
2765     if (y
) (*y
) = m_y 
- dy
; 
2768 void wxWindowGTK::DoClientToScreen( int *x
, int *y 
) const 
2770     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2772     if (!m_widget
->window
) return; 
2774     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
2776         source 
= m_wxwindow
->window
; 
2778         source 
= m_widget
->window
; 
2782     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
2786         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
2788             org_x 
+= m_widget
->allocation
.x
; 
2789             org_y 
+= m_widget
->allocation
.y
; 
2796         if (GetLayoutDirection() == wxLayout_RightToLeft
) 
2797             *x 
= (GetClientSize().x 
- *x
) + org_x
; 
2805 void wxWindowGTK::DoScreenToClient( int *x
, int *y 
) const 
2807     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2809     if (!m_widget
->window
) return; 
2811     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
2813         source 
= m_wxwindow
->window
; 
2815         source 
= m_widget
->window
; 
2819     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
2823         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
2825             org_x 
+= m_widget
->allocation
.x
; 
2826             org_y 
+= m_widget
->allocation
.y
; 
2832         if (GetLayoutDirection() == wxLayout_RightToLeft
) 
2833             *x 
= (GetClientSize().x 
- *x
) - org_x
; 
2840 bool wxWindowGTK::Show( bool show 
) 
2842     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
2844     if (!wxWindowBase::Show(show
)) 
2850     if (show 
&& m_showOnIdle
) 
2857             gtk_widget_show(m_widget
); 
2859             gtk_widget_hide(m_widget
); 
2860         wxShowEvent 
eventShow(GetId(), show
); 
2861         eventShow
.SetEventObject(this); 
2862         HandleWindowEvent(eventShow
); 
2868 void wxWindowGTK::DoEnable( bool enable 
) 
2870     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2872     gtk_widget_set_sensitive( m_widget
, enable 
); 
2873     if (m_wxwindow 
&& (m_wxwindow 
!= m_widget
)) 
2874         gtk_widget_set_sensitive( m_wxwindow
, enable 
); 
2877 int wxWindowGTK::GetCharHeight() const 
2879     wxCHECK_MSG( (m_widget 
!= NULL
), 12, wxT("invalid window") ); 
2881     wxFont font 
= GetFont(); 
2882     wxCHECK_MSG( font
.Ok(), 12, wxT("invalid font") ); 
2884     PangoContext
* context 
= gtk_widget_get_pango_context(m_widget
); 
2889     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
2890     PangoLayout 
*layout 
= pango_layout_new(context
); 
2891     pango_layout_set_font_description(layout
, desc
); 
2892     pango_layout_set_text(layout
, "H", 1); 
2893     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
2895     PangoRectangle rect
; 
2896     pango_layout_line_get_extents(line
, NULL
, &rect
); 
2898     g_object_unref (layout
); 
2900     return (int) PANGO_PIXELS(rect
.height
); 
2903 int wxWindowGTK::GetCharWidth() const 
2905     wxCHECK_MSG( (m_widget 
!= NULL
), 8, wxT("invalid window") ); 
2907     wxFont font 
= GetFont(); 
2908     wxCHECK_MSG( font
.Ok(), 8, wxT("invalid font") ); 
2910     PangoContext
* context 
= gtk_widget_get_pango_context(m_widget
); 
2915     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
2916     PangoLayout 
*layout 
= pango_layout_new(context
); 
2917     pango_layout_set_font_description(layout
, desc
); 
2918     pango_layout_set_text(layout
, "g", 1); 
2919     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
2921     PangoRectangle rect
; 
2922     pango_layout_line_get_extents(line
, NULL
, &rect
); 
2924     g_object_unref (layout
); 
2926     return (int) PANGO_PIXELS(rect
.width
); 
2929 void wxWindowGTK::GetTextExtent( const wxString
& string
, 
2933                                  int *externalLeading
, 
2934                                  const wxFont 
*theFont 
) const 
2936     wxFont fontToUse 
= theFont 
? *theFont 
: GetFont(); 
2938     wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") ); 
2947     PangoContext 
*context 
= NULL
; 
2949         context 
= gtk_widget_get_pango_context( m_widget 
); 
2958     PangoFontDescription 
*desc 
= fontToUse
.GetNativeFontInfo()->description
; 
2959     PangoLayout 
*layout 
= pango_layout_new(context
); 
2960     pango_layout_set_font_description(layout
, desc
); 
2962         const wxCharBuffer data 
= wxGTK_CONV( string 
); 
2964             pango_layout_set_text(layout
, data
, strlen(data
)); 
2967     PangoRectangle rect
; 
2968     pango_layout_get_extents(layout
, NULL
, &rect
); 
2970     if (x
) (*x
) = (wxCoord
) PANGO_PIXELS(rect
.width
); 
2971     if (y
) (*y
) = (wxCoord
) PANGO_PIXELS(rect
.height
); 
2974         PangoLayoutIter 
*iter 
= pango_layout_get_iter(layout
); 
2975         int baseline 
= pango_layout_iter_get_baseline(iter
); 
2976         pango_layout_iter_free(iter
); 
2977         *descent 
= *y 
- PANGO_PIXELS(baseline
); 
2979     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
2981     g_object_unref (layout
); 
2984 bool wxWindowGTK::GTKSetDelayedFocusIfNeeded() 
2986     if ( g_delayedFocus 
== this ) 
2988         if ( GTK_WIDGET_REALIZED(m_widget
) ) 
2990             gtk_widget_grab_focus(m_widget
); 
2991             g_delayedFocus 
= NULL
; 
3000 void wxWindowGTK::SetFocus() 
3002     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3005         // don't do anything if we already have focus 
3011         // wxWindow::SetFocus() should really set the focus to 
3012         // this control, whatever the flags are 
3013         if (!GTK_WIDGET_CAN_FOCUS(m_wxwindow
)) 
3014             GTK_WIDGET_SET_FLAGS(m_wxwindow
, GTK_CAN_FOCUS
); 
3016         if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
)) 
3018             gtk_widget_grab_focus (m_wxwindow
); 
3023         // wxWindow::SetFocus() should really set the focus to 
3024         // this control, whatever the flags are 
3025         if (!GTK_WIDGET_CAN_FOCUS(m_widget
)) 
3026             GTK_WIDGET_SET_FLAGS(m_widget
, GTK_CAN_FOCUS
); 
3028         if (GTK_IS_CONTAINER(m_widget
)) 
3030             if (GTK_IS_RADIO_BUTTON(m_widget
)) 
3032                 gtk_widget_grab_focus (m_widget
); 
3036             gtk_widget_child_focus( m_widget
, GTK_DIR_TAB_FORWARD 
); 
3039         if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) ) 
3042             if (!GTK_WIDGET_REALIZED(m_widget
)) 
3044                 // we can't set the focus to the widget now so we remember that 
3045                 // it should be focused and will do it later, during the idle 
3046                 // time, as soon as we can 
3047                 wxLogTrace(TRACE_FOCUS
, 
3048                            _T("Delaying setting focus to %s(%s)"), 
3049                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3051                 g_delayedFocus 
= this; 
3055                 wxLogTrace(TRACE_FOCUS
, 
3056                            _T("Setting focus to %s(%s)"), 
3057                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3059                 gtk_widget_grab_focus (m_widget
); 
3064            wxLogTrace(TRACE_FOCUS
, 
3065                       _T("Can't set focus to %s(%s)"), 
3066                       GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3071 void wxWindowGTK::SetCanFocus(bool canFocus
) 
3074         GTK_WIDGET_SET_FLAGS(m_widget
, GTK_CAN_FOCUS
); 
3076         GTK_WIDGET_UNSET_FLAGS(m_widget
, GTK_CAN_FOCUS
); 
3078     if ( m_wxwindow 
&& (m_widget 
!= m_wxwindow
) ) 
3081             GTK_WIDGET_SET_FLAGS(m_wxwindow
, GTK_CAN_FOCUS
); 
3083             GTK_WIDGET_UNSET_FLAGS(m_wxwindow
, GTK_CAN_FOCUS
); 
3087 bool wxWindowGTK::Reparent( wxWindowBase 
*newParentBase 
) 
3089     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3091     wxWindowGTK 
*oldParent 
= m_parent
, 
3092              *newParent 
= (wxWindowGTK 
*)newParentBase
; 
3094     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3096     if ( !wxWindowBase::Reparent(newParent
) ) 
3099     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3101     /* prevent GTK from deleting the widget arbitrarily */ 
3102     gtk_widget_ref( m_widget 
); 
3106         gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget 
); 
3109     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3113         if (GTK_WIDGET_VISIBLE (newParent
->m_widget
)) 
3115             m_showOnIdle 
= true; 
3116             gtk_widget_hide( m_widget 
); 
3119         /* insert GTK representation */ 
3120         (*(newParent
->m_insertCallback
))(newParent
, this); 
3123     /* reverse: prevent GTK from deleting the widget arbitrarily */ 
3124     gtk_widget_unref( m_widget 
); 
3126     SetLayoutDirection(wxLayout_Default
); 
3131 void wxWindowGTK::DoAddChild(wxWindowGTK 
*child
) 
3133     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3134     wxASSERT_MSG( (child 
!= NULL
), wxT("invalid child window") ); 
3139     /* insert GTK representation */ 
3140     (*m_insertCallback
)(this, child
); 
3143 void wxWindowGTK::AddChild(wxWindowBase 
*child
) 
3145     wxWindowBase::AddChild(child
); 
3146     m_dirtyTabOrder 
= true; 
3147     wxTheApp
->WakeUpIdle(); 
3150 void wxWindowGTK::RemoveChild(wxWindowBase 
*child
) 
3152     wxWindowBase::RemoveChild(child
); 
3153     m_dirtyTabOrder 
= true; 
3154     wxTheApp
->WakeUpIdle(); 
3158 wxLayoutDirection 
wxWindowGTK::GTKGetLayout(GtkWidget 
*widget
) 
3160     return gtk_widget_get_direction(widget
) == GTK_TEXT_DIR_RTL
 
3161                 ? wxLayout_RightToLeft
 
3162                 : wxLayout_LeftToRight
; 
3166 void wxWindowGTK::GTKSetLayout(GtkWidget 
*widget
, wxLayoutDirection dir
) 
3168     wxASSERT_MSG( dir 
!= wxLayout_Default
, _T("invalid layout direction") ); 
3170     gtk_widget_set_direction(widget
, 
3171                              dir 
== wxLayout_RightToLeft 
? GTK_TEXT_DIR_RTL
 
3172                                                          : GTK_TEXT_DIR_LTR
); 
3175 wxLayoutDirection 
wxWindowGTK::GetLayoutDirection() const 
3177     return GTKGetLayout(m_widget
); 
3180 void wxWindowGTK::SetLayoutDirection(wxLayoutDirection dir
) 
3182     if ( dir 
== wxLayout_Default 
) 
3184         const wxWindow 
*const parent 
= GetParent(); 
3187             // inherit layout from parent. 
3188             dir 
= parent
->GetLayoutDirection(); 
3190         else // no parent, use global default layout 
3192             dir 
= wxTheApp
->GetLayoutDirection(); 
3196     if ( dir 
== wxLayout_Default 
) 
3199     GTKSetLayout(m_widget
, dir
); 
3201     if (m_wxwindow 
&& (m_wxwindow 
!= m_widget
)) 
3202         GTKSetLayout(m_wxwindow
, dir
); 
3206 wxWindowGTK::AdjustForLayoutDirection(wxCoord x
, 
3207                                       wxCoord 
WXUNUSED(width
), 
3208                                       wxCoord 
WXUNUSED(widthTotal
)) const 
3210     // We now mirror the coordinates of RTL windows in wxPizza 
3214 void wxWindowGTK::DoMoveInTabOrder(wxWindow 
*win
, WindowOrder move
) 
3216     wxWindowBase::DoMoveInTabOrder(win
, move
); 
3217     m_dirtyTabOrder 
= true; 
3218     wxTheApp
->WakeUpIdle(); 
3221 bool wxWindowGTK::DoNavigateIn(int flags
) 
3223     if ( flags 
& wxNavigationKeyEvent::WinChange 
) 
3225         wxFAIL_MSG( _T("not implemented") ); 
3229     else // navigate inside the container 
3231         wxWindow 
*parent 
= wxGetTopLevelParent((wxWindow 
*)this); 
3232         wxCHECK_MSG( parent
, false, _T("every window must have a TLW parent") ); 
3234         GtkDirectionType dir
; 
3235         dir 
= flags 
& wxNavigationKeyEvent::IsForward 
? GTK_DIR_TAB_FORWARD
 
3236                                                       : GTK_DIR_TAB_BACKWARD
; 
3239         g_signal_emit_by_name(parent
->m_widget
, "focus", dir
, &rc
); 
3245 bool wxWindowGTK::GTKWidgetNeedsMnemonic() const 
3247     // none needed by default 
3251 void wxWindowGTK::GTKWidgetDoSetMnemonic(GtkWidget
* WXUNUSED(w
)) 
3253     // nothing to do by default since none is needed 
3256 void wxWindowGTK::RealizeTabOrder() 
3260         if ( !m_children
.empty() ) 
3262             // we don't only construct the correct focus chain but also use 
3263             // this opportunity to update the mnemonic widgets for the widgets 
3266             GList 
*chain 
= NULL
; 
3267             wxWindowGTK
* mnemonicWindow 
= NULL
; 
3269             for ( wxWindowList::const_iterator i 
= m_children
.begin(); 
3270                   i 
!= m_children
.end(); 
3273                 wxWindowGTK 
*win 
= *i
; 
3275                 if ( mnemonicWindow 
) 
3277                     if ( win
->AcceptsFocusFromKeyboard() ) 
3279                         // wxComboBox et al. needs to focus on on a different 
3280                         // widget than m_widget, so if the main widget isn't 
3281                         // focusable try the connect widget 
3282                         GtkWidget
* w 
= win
->m_widget
; 
3283                         if ( !GTK_WIDGET_CAN_FOCUS(w
) ) 
3285                             w 
= win
->GetConnectWidget(); 
3286                             if ( !GTK_WIDGET_CAN_FOCUS(w
) ) 
3292                             mnemonicWindow
->GTKWidgetDoSetMnemonic(w
); 
3293                             mnemonicWindow 
= NULL
; 
3297                 else if ( win
->GTKWidgetNeedsMnemonic() ) 
3299                     mnemonicWindow 
= win
; 
3302                 chain 
= g_list_prepend(chain
, win
->m_widget
); 
3305             chain 
= g_list_reverse(chain
); 
3307             gtk_container_set_focus_chain(GTK_CONTAINER(m_wxwindow
), chain
); 
3312             gtk_container_unset_focus_chain(GTK_CONTAINER(m_wxwindow
)); 
3317 void wxWindowGTK::Raise() 
3319     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3321     if (m_wxwindow 
&& m_wxwindow
->window
) 
3323         gdk_window_raise( m_wxwindow
->window 
); 
3325     else if (m_widget
->window
) 
3327         gdk_window_raise( m_widget
->window 
); 
3331 void wxWindowGTK::Lower() 
3333     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3335     if (m_wxwindow 
&& m_wxwindow
->window
) 
3337         gdk_window_lower( m_wxwindow
->window 
); 
3339     else if (m_widget
->window
) 
3341         gdk_window_lower( m_widget
->window 
); 
3345 bool wxWindowGTK::SetCursor( const wxCursor 
&cursor 
) 
3347     if ( !wxWindowBase::SetCursor(cursor
.Ok() ? cursor 
: *wxSTANDARD_CURSOR
) ) 
3355 void wxWindowGTK::GTKUpdateCursor() 
3357     wxCursor 
cursor(g_globalCursor
.Ok() ? g_globalCursor 
: GetCursor()); 
3360         wxArrayGdkWindows windowsThis
; 
3361         GdkWindow 
* const winThis 
= GTKGetWindow(windowsThis
); 
3364             gdk_window_set_cursor(winThis
, cursor
.GetCursor()); 
3368             const size_t count 
= windowsThis
.size(); 
3369             for ( size_t n 
= 0; n 
< count
; n
++ ) 
3371                 GdkWindow 
*win 
= windowsThis
[n
]; 
3374                     wxFAIL_MSG(_T("NULL window returned by GTKGetWindow()?")); 
3378                 gdk_window_set_cursor(win
, cursor
.GetCursor()); 
3384 void wxWindowGTK::WarpPointer( int x
, int y 
) 
3386     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3388     // We provide this function ourselves as it is 
3389     // missing in GDK (top of this file). 
3391     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3393         window 
= m_wxwindow
->window
; 
3395         window 
= GetConnectWidget()->window
; 
3398         gdk_window_warp_pointer( window
, x
, y 
); 
3401 wxWindowGTK::ScrollDir 
wxWindowGTK::ScrollDirFromRange(GtkRange 
*range
) const 
3403     // find the scrollbar which generated the event 
3404     for ( int dir 
= 0; dir 
< ScrollDir_Max
; dir
++ ) 
3406         if ( range 
== m_scrollBar
[dir
] ) 
3407             return (ScrollDir
)dir
; 
3410     wxFAIL_MSG( _T("event from unknown scrollbar received") ); 
3412     return ScrollDir_Max
; 
3415 bool wxWindowGTK::DoScrollByUnits(ScrollDir dir
, ScrollUnit unit
, int units
) 
3417     bool changed 
= false; 
3418     GtkRange
* range 
= m_scrollBar
[dir
]; 
3419     if ( range 
&& units 
) 
3421         GtkAdjustment
* adj 
= range
->adjustment
; 
3422         gdouble inc 
= unit 
== ScrollUnit_Line 
? adj
->step_increment
 
3423                                               : adj
->page_increment
; 
3425         const int posOld 
= int(adj
->value 
+ 0.5); 
3426         gtk_range_set_value(range
, posOld 
+ units
*inc
); 
3428         changed 
= int(adj
->value 
+ 0.5) != posOld
; 
3434 bool wxWindowGTK::ScrollLines(int lines
) 
3436     return DoScrollByUnits(ScrollDir_Vert
, ScrollUnit_Line
, lines
); 
3439 bool wxWindowGTK::ScrollPages(int pages
) 
3441     return DoScrollByUnits(ScrollDir_Vert
, ScrollUnit_Page
, pages
); 
3444 void wxWindowGTK::Refresh(bool WXUNUSED(eraseBackground
), 
3449     if (!m_widget
->window
) 
3454         if (m_wxwindow
->window 
== NULL
) return; 
3456         GdkRectangle gdk_rect
, 
3460             gdk_rect
.x 
= rect
->x
; 
3461             gdk_rect
.y 
= rect
->y
; 
3462             gdk_rect
.width 
= rect
->width
; 
3463             gdk_rect
.height 
= rect
->height
; 
3464             if (GetLayoutDirection() == wxLayout_RightToLeft
) 
3465                 gdk_rect
.x 
= GetClientSize().x 
- gdk_rect
.x 
- gdk_rect
.width
; 
3469         else // invalidate everything 
3474         gdk_window_invalidate_rect(m_wxwindow
->window
, p
, true); 
3478 void wxWindowGTK::Update() 
3482     // when we call Update() we really want to update the window immediately on 
3483     // screen, even if it means flushing the entire queue and hence slowing down 
3484     // everything -- but it should still be done, it's just that Update() should 
3485     // be called very rarely 
3489 void wxWindowGTK::GtkUpdate() 
3491     if (m_wxwindow 
&& m_wxwindow
->window
) 
3492         gdk_window_process_updates(m_wxwindow
->window
, false); 
3493     if (m_widget 
&& m_widget
->window 
&& (m_wxwindow 
!= m_widget
)) 
3494         gdk_window_process_updates( m_widget
->window
, FALSE 
); 
3496     // for consistency with other platforms (and also because it's convenient 
3497     // to be able to update an entire TLW by calling Update() only once), we 
3498     // should also update all our children here 
3499     for ( wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
3501           node 
= node
->GetNext() ) 
3503         node
->GetData()->GtkUpdate(); 
3507 bool wxWindowGTK::DoIsExposed( int x
, int y 
) const 
3509     return m_updateRegion
.Contains(x
, y
) != wxOutRegion
; 
3513 bool wxWindowGTK::DoIsExposed( int x
, int y
, int w
, int h 
) const 
3515     if (GetLayoutDirection() == wxLayout_RightToLeft
) 
3516         return m_updateRegion
.Contains(x
-w
, y
, w
, h
) != wxOutRegion
; 
3518         return m_updateRegion
.Contains(x
, y
, w
, h
) != wxOutRegion
; 
3521 void wxWindowGTK::GtkSendPaintEvents() 
3525         m_updateRegion
.Clear(); 
3529     // Clip to paint region in wxClientDC 
3530     m_clipPaintRegion 
= true; 
3532     m_nativeUpdateRegion 
= m_updateRegion
; 
3534     if (GetLayoutDirection() == wxLayout_RightToLeft
) 
3536         // Transform m_updateRegion under RTL 
3537         m_updateRegion
.Clear(); 
3540         gdk_drawable_get_size(m_wxwindow
->window
, &width
, NULL
); 
3542         wxRegionIterator 
upd( m_nativeUpdateRegion 
); 
3546             rect
.x 
= upd
.GetX(); 
3547             rect
.y 
= upd
.GetY(); 
3548             rect
.width 
= upd
.GetWidth(); 
3549             rect
.height 
= upd
.GetHeight(); 
3551             rect
.x 
= width 
- rect
.x 
- rect
.width
; 
3552             m_updateRegion
.Union( rect 
); 
3558     if (GetThemeEnabled() && (GetBackgroundStyle() == wxBG_STYLE_SYSTEM
)) 
3560         // find ancestor from which to steal background 
3561         wxWindow 
*parent 
= wxGetTopLevelParent((wxWindow 
*)this); 
3563             parent 
= (wxWindow
*)this; 
3565         if (GTK_WIDGET_MAPPED(parent
->m_widget
)) 
3567             wxRegionIterator 
upd( m_nativeUpdateRegion 
); 
3571                 rect
.x 
= upd
.GetX(); 
3572                 rect
.y 
= upd
.GetY(); 
3573                 rect
.width 
= upd
.GetWidth(); 
3574                 rect
.height 
= upd
.GetHeight(); 
3576                 gtk_paint_flat_box( parent
->m_widget
->style
, 
3578                             (GtkStateType
)GTK_WIDGET_STATE(m_wxwindow
), 
3591         wxWindowDC 
dc( (wxWindow
*)this ); 
3592         dc
.SetClippingRegion( m_updateRegion 
); 
3594         // Work around gtk-qt <= 0.60 bug whereby the window colour 
3596         if (GetBackgroundStyle() == wxBG_STYLE_COLOUR 
&& GetBackgroundColour().Ok() && wxSystemOptions::GetOptionInt(wxT("gtk.window.force-background-colour")) == 1) 
3598             dc
.SetBackground(wxBrush(GetBackgroundColour())); 
3602         wxEraseEvent 
erase_event( GetId(), &dc 
); 
3603         erase_event
.SetEventObject( this ); 
3605         HandleWindowEvent(erase_event
); 
3608     wxNcPaintEvent 
nc_paint_event( GetId() ); 
3609     nc_paint_event
.SetEventObject( this ); 
3610     HandleWindowEvent( nc_paint_event 
); 
3612     wxPaintEvent 
paint_event( GetId() ); 
3613     paint_event
.SetEventObject( this ); 
3614     HandleWindowEvent( paint_event 
); 
3616     m_clipPaintRegion 
= false; 
3618     m_updateRegion
.Clear(); 
3619     m_nativeUpdateRegion
.Clear(); 
3622 void wxWindowGTK::SetDoubleBuffered( bool on 
) 
3624     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3627         gtk_widget_set_double_buffered( m_wxwindow
, on 
); 
3630 bool wxWindowGTK::IsDoubleBuffered() const 
3632     return GTK_WIDGET_DOUBLE_BUFFERED( m_wxwindow 
); 
3635 void wxWindowGTK::ClearBackground() 
3637     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3641 void wxWindowGTK::DoSetToolTip( wxToolTip 
*tip 
) 
3643     wxWindowBase::DoSetToolTip(tip
); 
3646         m_tooltip
->Apply( (wxWindow 
*)this ); 
3649 void wxWindowGTK::ApplyToolTip( GtkTooltips 
*tips
, const gchar 
*tip 
) 
3651     gtk_tooltips_set_tip(tips
, GetConnectWidget(), tip
, NULL
); 
3653 #endif // wxUSE_TOOLTIPS 
3655 bool wxWindowGTK::SetBackgroundColour( const wxColour 
&colour 
) 
3657     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3659     if (!wxWindowBase::SetBackgroundColour(colour
)) 
3664         // We need the pixel value e.g. for background clearing. 
3665         m_backgroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
3668     // apply style change (forceStyle=true so that new style is applied 
3669     // even if the bg colour changed from valid to wxNullColour) 
3670     if (GetBackgroundStyle() != wxBG_STYLE_CUSTOM
) 
3671         ApplyWidgetStyle(true); 
3676 bool wxWindowGTK::SetForegroundColour( const wxColour 
&colour 
) 
3678     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3680     if (!wxWindowBase::SetForegroundColour(colour
)) 
3687         // We need the pixel value e.g. for background clearing. 
3688         m_foregroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
3691     // apply style change (forceStyle=true so that new style is applied 
3692     // even if the bg colour changed from valid to wxNullColour): 
3693     ApplyWidgetStyle(true); 
3698 PangoContext 
*wxWindowGTK::GtkGetPangoDefaultContext() 
3700     return gtk_widget_get_pango_context( m_widget 
); 
3703 GtkRcStyle 
*wxWindowGTK::CreateWidgetStyle(bool forceStyle
) 
3705     // do we need to apply any changes at all? 
3708          !m_foregroundColour
.Ok() && !m_backgroundColour
.Ok() ) 
3713     GtkRcStyle 
*style 
= gtk_rc_style_new(); 
3718             pango_font_description_copy( m_font
.GetNativeFontInfo()->description 
); 
3721     int flagsNormal 
= 0, 
3724         flagsInsensitive 
= 0; 
3726     if ( m_foregroundColour
.Ok() ) 
3728         const GdkColor 
*fg 
= m_foregroundColour
.GetColor(); 
3730         style
->fg
[GTK_STATE_NORMAL
] = 
3731         style
->text
[GTK_STATE_NORMAL
] = *fg
; 
3732         flagsNormal 
|= GTK_RC_FG 
| GTK_RC_TEXT
; 
3734         style
->fg
[GTK_STATE_PRELIGHT
] = 
3735         style
->text
[GTK_STATE_PRELIGHT
] = *fg
; 
3736         flagsPrelight 
|= GTK_RC_FG 
| GTK_RC_TEXT
; 
3738         style
->fg
[GTK_STATE_ACTIVE
] = 
3739         style
->text
[GTK_STATE_ACTIVE
] = *fg
; 
3740         flagsActive 
|= GTK_RC_FG 
| GTK_RC_TEXT
; 
3743     if ( m_backgroundColour
.Ok() ) 
3745         const GdkColor 
*bg 
= m_backgroundColour
.GetColor(); 
3747         style
->bg
[GTK_STATE_NORMAL
] = 
3748         style
->base
[GTK_STATE_NORMAL
] = *bg
; 
3749         flagsNormal 
|= GTK_RC_BG 
| GTK_RC_BASE
; 
3751         style
->bg
[GTK_STATE_PRELIGHT
] = 
3752         style
->base
[GTK_STATE_PRELIGHT
] = *bg
; 
3753         flagsPrelight 
|= GTK_RC_BG 
| GTK_RC_BASE
; 
3755         style
->bg
[GTK_STATE_ACTIVE
] = 
3756         style
->base
[GTK_STATE_ACTIVE
] = *bg
; 
3757         flagsActive 
|= GTK_RC_BG 
| GTK_RC_BASE
; 
3759         style
->bg
[GTK_STATE_INSENSITIVE
] = 
3760         style
->base
[GTK_STATE_INSENSITIVE
] = *bg
; 
3761         flagsInsensitive 
|= GTK_RC_BG 
| GTK_RC_BASE
; 
3764     style
->color_flags
[GTK_STATE_NORMAL
] = (GtkRcFlags
)flagsNormal
; 
3765     style
->color_flags
[GTK_STATE_PRELIGHT
] = (GtkRcFlags
)flagsPrelight
; 
3766     style
->color_flags
[GTK_STATE_ACTIVE
] = (GtkRcFlags
)flagsActive
; 
3767     style
->color_flags
[GTK_STATE_INSENSITIVE
] = (GtkRcFlags
)flagsInsensitive
; 
3772 void wxWindowGTK::ApplyWidgetStyle(bool forceStyle
) 
3774     GtkRcStyle 
*style 
= CreateWidgetStyle(forceStyle
); 
3777         DoApplyWidgetStyle(style
); 
3778         gtk_rc_style_unref(style
); 
3781     // Style change may affect GTK+'s size calculation: 
3782     InvalidateBestSize(); 
3785 void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
3787     wxSuspendStyleEvents 
s(static_cast<wxWindow
*>(this)); 
3790         gtk_widget_modify_style(m_wxwindow
, style
); 
3792         gtk_widget_modify_style(m_widget
, style
); 
3795 bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style
) 
3797     wxWindowBase::SetBackgroundStyle(style
); 
3799     if (style 
== wxBG_STYLE_CUSTOM
) 
3804             window 
= m_wxwindow
->window
; 
3808             GtkWidget 
* const w 
= GetConnectWidget(); 
3809             window 
= w 
? w
->window 
: NULL
; 
3814             // Make sure GDK/X11 doesn't refresh the window 
3816             gdk_window_set_back_pixmap( window
, None
, False 
); 
3818             Display
* display 
= GDK_WINDOW_DISPLAY(window
); 
3821             m_needsStyleChange 
= false; 
3823         else // window not realized yet 
3825             // Do in OnIdle, because the window is not yet available 
3826             m_needsStyleChange 
= true; 
3829         // Don't apply widget style, or we get a grey background 
3833         // apply style change (forceStyle=true so that new style is applied 
3834         // even if the bg colour changed from valid to wxNullColour): 
3835         ApplyWidgetStyle(true); 
3840 #if wxUSE_DRAG_AND_DROP 
3842 void wxWindowGTK::SetDropTarget( wxDropTarget 
*dropTarget 
) 
3844     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3846     GtkWidget 
*dnd_widget 
= GetConnectWidget(); 
3848     if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget 
); 
3850     if (m_dropTarget
) delete m_dropTarget
; 
3851     m_dropTarget 
= dropTarget
; 
3853     if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget 
); 
3856 #endif // wxUSE_DRAG_AND_DROP 
3858 GtkWidget
* wxWindowGTK::GetConnectWidget() 
3860     GtkWidget 
*connect_widget 
= m_widget
; 
3861     if (m_wxwindow
) connect_widget 
= m_wxwindow
; 
3863     return connect_widget
; 
3866 bool wxWindowGTK::GTKIsOwnWindow(GdkWindow 
*window
) const 
3868     wxArrayGdkWindows windowsThis
; 
3869     GdkWindow 
* const winThis 
= GTKGetWindow(windowsThis
); 
3871     return winThis 
? window 
== winThis
 
3872                    : windowsThis
.Index(window
) != wxNOT_FOUND
; 
3875 GdkWindow 
*wxWindowGTK::GTKGetWindow(wxArrayGdkWindows
& WXUNUSED(windows
)) const 
3877     return m_wxwindow 
? m_wxwindow
->window 
: m_widget
->window
; 
3880 bool wxWindowGTK::SetFont( const wxFont 
&font 
) 
3882     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3884     if (!wxWindowBase::SetFont(font
)) 
3887     // apply style change (forceStyle=true so that new style is applied 
3888     // even if the font changed from valid to wxNullFont): 
3889     ApplyWidgetStyle(true); 
3894 void wxWindowGTK::DoCaptureMouse() 
3896     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3898     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3900         window 
= m_wxwindow
->window
; 
3902         window 
= GetConnectWidget()->window
; 
3904     wxCHECK_RET( window
, _T("CaptureMouse() failed") ); 
3906     const wxCursor
* cursor 
= &m_cursor
; 
3908         cursor 
= wxSTANDARD_CURSOR
; 
3910     gdk_pointer_grab( window
, FALSE
, 
3912                          (GDK_BUTTON_PRESS_MASK 
| 
3913                           GDK_BUTTON_RELEASE_MASK 
| 
3914                           GDK_POINTER_MOTION_HINT_MASK 
| 
3915                           GDK_POINTER_MOTION_MASK
), 
3917                       cursor
->GetCursor(), 
3918                       (guint32
)GDK_CURRENT_TIME 
); 
3919     g_captureWindow 
= this; 
3920     g_captureWindowHasMouse 
= true; 
3923 void wxWindowGTK::DoReleaseMouse() 
3925     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3927     wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") ); 
3929     g_captureWindow 
= (wxWindowGTK
*) NULL
; 
3931     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3933         window 
= m_wxwindow
->window
; 
3935         window 
= GetConnectWidget()->window
; 
3940     gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME 
); 
3943 void wxWindowGTK::GTKReleaseMouseAndNotify() 
3946     wxMouseCaptureLostEvent 
evt(GetId()); 
3947     evt
.SetEventObject( this ); 
3948     HandleWindowEvent( evt 
); 
3952 wxWindow 
*wxWindowBase::GetCapture() 
3954     return (wxWindow 
*)g_captureWindow
; 
3957 bool wxWindowGTK::IsRetained() const 
3962 void wxWindowGTK::SetScrollbar(int orient
, 
3966                                bool WXUNUSED(update
)) 
3968     const int dir 
= ScrollDirFromOrient(orient
); 
3969     GtkRange
* const sb 
= m_scrollBar
[dir
]; 
3970     wxCHECK_RET( sb
, _T("this window is not scrollable") ); 
3974         // GtkRange requires upper > lower 
3979     GtkAdjustment 
* const adj 
= sb
->adjustment
; 
3980     adj
->step_increment 
= 1; 
3981     adj
->page_increment 
= 
3982     adj
->page_size 
= thumbVisible
; 
3985     g_signal_handlers_block_by_func( 
3986         sb
, (void*)gtk_scrollbar_value_changed
, this); 
3988     gtk_range_set_range(sb
, 0, range
); 
3989     m_scrollPos
[dir
] = sb
->adjustment
->value
; 
3991     g_signal_handlers_unblock_by_func( 
3992         sb
, (void*)gtk_scrollbar_value_changed
, this); 
3995 void wxWindowGTK::SetScrollPos(int orient
, int pos
, bool WXUNUSED(refresh
)) 
3997     const int dir 
= ScrollDirFromOrient(orient
); 
3998     GtkRange 
* const sb 
= m_scrollBar
[dir
]; 
3999     wxCHECK_RET( sb
, _T("this window is not scrollable") ); 
4001     // This check is more than an optimization. Without it, the slider 
4002     //   will not move smoothly while tracking when using wxScrollHelper. 
4003     if (GetScrollPos(orient
) != pos
) 
4005         g_signal_handlers_block_by_func( 
4006             sb
, (void*)gtk_scrollbar_value_changed
, this); 
4008         gtk_range_set_value(sb
, pos
); 
4009         m_scrollPos
[dir
] = sb
->adjustment
->value
; 
4011         g_signal_handlers_unblock_by_func( 
4012             sb
, (void*)gtk_scrollbar_value_changed
, this); 
4016 int wxWindowGTK::GetScrollThumb(int orient
) const 
4018     GtkRange 
* const sb 
= m_scrollBar
[ScrollDirFromOrient(orient
)]; 
4019     wxCHECK_MSG( sb
, 0, _T("this window is not scrollable") ); 
4021     return int(sb
->adjustment
->page_size
); 
4024 int wxWindowGTK::GetScrollPos( int orient 
) const 
4026     GtkRange 
* const sb 
= m_scrollBar
[ScrollDirFromOrient(orient
)]; 
4027     wxCHECK_MSG( sb
, 0, _T("this window is not scrollable") ); 
4029     return int(sb
->adjustment
->value 
+ 0.5); 
4032 int wxWindowGTK::GetScrollRange( int orient 
) const 
4034     GtkRange 
* const sb 
= m_scrollBar
[ScrollDirFromOrient(orient
)]; 
4035     wxCHECK_MSG( sb
, 0, _T("this window is not scrollable") ); 
4037     return int(sb
->adjustment
->upper
); 
4040 // Determine if increment is the same as +/-x, allowing for some small 
4041 //   difference due to possible inexactness in floating point arithmetic 
4042 static inline bool IsScrollIncrement(double increment
, double x
) 
4044     wxASSERT(increment 
> 0); 
4045     const double tolerance 
= 1.0 / 1024; 
4046     return fabs(increment 
- fabs(x
)) < tolerance
; 
4049 wxEventType 
wxWindowGTK::GetScrollEventType(GtkRange
* range
) 
4051     wxASSERT(range 
== m_scrollBar
[0] || range 
== m_scrollBar
[1]); 
4053     const int barIndex 
= range 
== m_scrollBar
[1]; 
4054     GtkAdjustment
* adj 
= range
->adjustment
; 
4056     const int value 
= int(adj
->value 
+ 0.5); 
4058     // save previous position 
4059     const double oldPos 
= m_scrollPos
[barIndex
]; 
4060     // update current position 
4061     m_scrollPos
[barIndex
] = adj
->value
; 
4062     // If event should be ignored, or integral position has not changed 
4063     if (!m_hasVMT 
|| g_blockEventsOnDrag 
|| value 
== int(oldPos 
+ 0.5)) 
4068     wxEventType eventType 
= wxEVT_SCROLL_THUMBTRACK
; 
4071         // Difference from last change event 
4072         const double diff 
= adj
->value 
- oldPos
; 
4073         const bool isDown 
= diff 
> 0; 
4075         if (IsScrollIncrement(adj
->step_increment
, diff
)) 
4077             eventType 
= isDown 
? wxEVT_SCROLL_LINEDOWN 
: wxEVT_SCROLL_LINEUP
; 
4079         else if (IsScrollIncrement(adj
->page_increment
, diff
)) 
4081             eventType 
= isDown 
? wxEVT_SCROLL_PAGEDOWN 
: wxEVT_SCROLL_PAGEUP
; 
4083         else if (m_mouseButtonDown
) 
4085             // Assume track event 
4086             m_isScrolling 
= true; 
4092 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) ) 
4094     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4096     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4098     // No scrolling requested. 
4099     if ((dx 
== 0) && (dy 
== 0)) return; 
4101     m_clipPaintRegion 
= true; 
4103     WX_PIZZA(m_wxwindow
)->scroll(dx
, dy
); 
4105     m_clipPaintRegion 
= false; 
4108     bool restoreCaret 
= (GetCaret() != NULL 
&& GetCaret()->IsVisible()); 
4111         wxRect 
caretRect(GetCaret()->GetPosition(), GetCaret()->GetSize()); 
4113             caretRect
.width 
+= dx
; 
4116             caretRect
.x 
+= dx
; caretRect
.width 
-= dx
; 
4119             caretRect
.height 
+= dy
; 
4122             caretRect
.y 
+= dy
; caretRect
.height 
-= dy
; 
4125         RefreshRect(caretRect
); 
4127 #endif // wxUSE_CARET 
4130 void wxWindowGTK::GtkScrolledWindowSetBorder(GtkWidget
* w
, int wxstyle
) 
4132     //RN: Note that static controls usually have no border on gtk, so maybe 
4133     //it makes sense to treat that as simply no border at the wx level 
4135     if (!(wxstyle 
& wxNO_BORDER
) && !(wxstyle 
& wxBORDER_STATIC
)) 
4137         GtkShadowType gtkstyle
; 
4139         if(wxstyle 
& wxBORDER_RAISED
) 
4140             gtkstyle 
= GTK_SHADOW_OUT
; 
4141         else if (wxstyle 
& wxBORDER_SUNKEN
) 
4142             gtkstyle 
= GTK_SHADOW_IN
; 
4145         else if (wxstyle 
& wxBORDER_DOUBLE
) 
4146             gtkstyle 
= GTK_SHADOW_ETCHED_IN
; 
4149             gtkstyle 
= GTK_SHADOW_IN
; 
4151         gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(w
), 
4156 void wxWindowGTK::SetWindowStyleFlag( long style 
) 
4158     // Updates the internal variable. NB: Now m_windowStyle bits carry the _new_ style values already 
4159     wxWindowBase::SetWindowStyleFlag(style
); 
4162 // Find the wxWindow at the current mouse position, also returning the mouse 
4164 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
4166     pt 
= wxGetMousePosition(); 
4167     wxWindow
* found 
= wxFindWindowAtPoint(pt
); 
4171 // Get the current mouse position. 
4172 wxPoint 
wxGetMousePosition() 
4174   /* This crashes when used within wxHelpContext, 
4175      so we have to use the X-specific implementation below. 
4177     GdkModifierType *mask; 
4178     (void) gdk_window_get_pointer(NULL, &x, &y, mask); 
4180     return wxPoint(x, y); 
4184     GdkWindow
* windowAtPtr 
= gdk_window_at_pointer(& x
, & y
); 
4186     Display 
*display 
= windowAtPtr 
? GDK_WINDOW_XDISPLAY(windowAtPtr
) : GDK_DISPLAY(); 
4187     Window rootWindow 
= RootWindowOfScreen (DefaultScreenOfDisplay(display
)); 
4188     Window rootReturn
, childReturn
; 
4189     int rootX
, rootY
, winX
, winY
; 
4190     unsigned int maskReturn
; 
4192     XQueryPointer (display
, 
4196                    &rootX
, &rootY
, &winX
, &winY
, &maskReturn
); 
4197     return wxPoint(rootX
, rootY
); 
4201 GdkWindow
* wxWindowGTK::GTKGetDrawingWindow() const 
4203     GdkWindow
* window 
= NULL
; 
4205         window 
= m_wxwindow
->window
;