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" 
  25     #include "wx/dcclient.h" 
  27     #include "wx/dialog.h" 
  28     #include "wx/settings.h" 
  29     #include "wx/msgdlg.h" 
  32 #include "wx/layout.h" 
  33 #include "wx/module.h" 
  34 #include "wx/combobox.h" 
  36 #if wxUSE_TOOLBAR_NATIVE 
  37     #include "wx/toolbar.h" 
  40 #if wxUSE_DRAG_AND_DROP 
  45     #include "wx/tooltip.h" 
  53     #include "wx/textctrl.h" 
  56 #include "wx/statusbr.h" 
  57 #include "wx/fontutil.h" 
  60     #include "wx/thread.h" 
  66 // FIXME: Due to a hack we use GtkCombo in here, which is deprecated since gtk2.3.0 
  67 #include <gtk/gtkversion.h> 
  68 #if defined(GTK_DISABLE_DEPRECATED) && GTK_CHECK_VERSION(2,3,0) 
  69 #undef GTK_DISABLE_DEPRECATED 
  72 #include "wx/gtk/private.h" 
  73 #include <gdk/gdkprivate.h> 
  74 #include <gdk/gdkkeysyms.h> 
  78 #include <gtk/gtkprivate.h> 
  80 #include "wx/gtk/win_gtk.h" 
  82 #include <pango/pangox.h> 
  88 extern GtkContainerClass 
*pizza_parent_class
; 
  90 //----------------------------------------------------------------------------- 
  91 // documentation on internals 
  92 //----------------------------------------------------------------------------- 
  95    I have been asked several times about writing some documentation about 
  96    the GTK port of wxWidgets, especially its internal structures. Obviously, 
  97    you cannot understand wxGTK without knowing a little about the GTK, but 
  98    some more information about what the wxWindow, which is the base class 
  99    for all other window classes, does seems required as well. 
 103    What does wxWindow do? It contains the common interface for the following 
 104    jobs of its descendants: 
 106    1) Define the rudimentary behaviour common to all window classes, such as 
 107    resizing, intercepting user input (so as to make it possible to use these 
 108    events for special purposes in a derived class), window names etc. 
 110    2) Provide the possibility to contain and manage children, if the derived 
 111    class is allowed to contain children, which holds true for those window 
 112    classes which do not display a native GTK widget. To name them, these 
 113    classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame- 
 114    work classes are a special case and are handled a bit differently from 
 115    the rest. The same holds true for the wxNotebook class. 
 117    3) Provide the possibility to draw into a client area of a window. This, 
 118    too, only holds true for classes that do not display a native GTK widget 
 121    4) Provide the entire mechanism for scrolling widgets. This actual inter- 
 122    face for this is usually in wxScrolledWindow, but the GTK implementation 
 125    5) A multitude of helper or extra methods for special purposes, such as 
 126    Drag'n'Drop, managing validators etc. 
 128    6) Display a border (sunken, raised, simple or none). 
 130    Normally one might expect, that one wxWidgets window would always correspond 
 131    to one GTK widget. Under GTK, there is no such allround widget that has all 
 132    the functionality. Moreover, the GTK defines a client area as a different 
 133    widget from the actual widget you are handling. Last but not least some 
 134    special classes (e.g. wxFrame) handle different categories of widgets and 
 135    still have the possibility to draw something in the client area. 
 136    It was therefore required to write a special purpose GTK widget, that would 
 137    represent a client area in the sense of wxWidgets capable to do the jobs 
 138    2), 3) and 4). I have written this class and it resides in win_gtk.c of 
 141    All windows must have a widget, with which they interact with other under- 
 142    lying GTK widgets. It is this widget, e.g. that has to be resized etc and 
 143    the wxWindow class has a member variable called m_widget which holds a 
 144    pointer to this widget. When the window class represents a GTK native widget, 
 145    this is (in most cases) the only GTK widget the class manages. E.g. the 
 146    wxStaticText class handles only a GtkLabel widget a pointer to which you 
 147    can find in m_widget (defined in wxWindow) 
 149    When the class has a client area for drawing into and for containing children 
 150    it has to handle the client area widget (of the type GtkPizza, defined in 
 151    win_gtk.c), but there could be any number of widgets, handled by a class 
 152    The common rule for all windows is only, that the widget that interacts with 
 153    the rest of GTK must be referenced in m_widget and all other widgets must be 
 154    children of this widget on the GTK level. The top-most widget, which also 
 155    represents the client area, must be in the m_wxwindow field and must be of 
 158    As I said, the window classes that display a GTK native widget only have 
 159    one widget, so in the case of e.g. the wxButton class m_widget holds a 
 160    pointer to a GtkButton widget. But windows with client areas (for drawing 
 161    and children) have a m_widget field that is a pointer to a GtkScrolled- 
 162    Window and a m_wxwindow field that is pointer to a GtkPizza and this 
 163    one is (in the GTK sense) a child of the GtkScrolledWindow. 
 165    If the m_wxwindow field is set, then all input to this widget is inter- 
 166    cepted and sent to the wxWidgets class. If not, all input to the widget 
 167    that gets pointed to by m_widget gets intercepted and sent to the class. 
 171    The design of scrolling in wxWidgets is markedly different from that offered 
 172    by the GTK itself and therefore we cannot simply take it as it is. In GTK, 
 173    clicking on a scrollbar belonging to scrolled window will inevitably move 
 174    the window. In wxWidgets, the scrollbar will only emit an event, send this 
 175    to (normally) a wxScrolledWindow and that class will call ScrollWindow() 
 176    which actually moves the window and its subchildren. Note that GtkPizza 
 177    memorizes how much it has been scrolled but that wxWidgets forgets this 
 178    so that the two coordinates systems have to be kept in synch. This is done 
 179    in various places using the pizza->xoffset and pizza->yoffset values. 
 183    Singularily the most broken code in GTK is the code that is supposed to 
 184    inform subwindows (child windows) about new positions. Very often, duplicate 
 185    events are sent without changes in size or position, equally often no 
 186    events are sent at all (All this is due to a bug in the GtkContainer code 
 187    which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores 
 188    GTK's own system and it simply waits for size events for toplevel windows 
 189    and then iterates down the respective size events to all window. This has 
 190    the disadvantage that windows might get size events before the GTK widget 
 191    actually has the reported size. This doesn't normally pose any problem, but 
 192    the OpenGL drawing routines rely on correct behaviour. Therefore, I have 
 193    added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas, 
 194    i.e. the wxGLCanvas will emit a size event, when (and not before) the X11 
 195    window that is used for OpenGL output really has that size (as reported by 
 200    If someone at some point of time feels the immense desire to have a look at, 
 201    change or attempt to optimise the Refresh() logic, this person will need an 
 202    intimate understanding of what "draw" and "expose" events are and what 
 203    they are used for, in particular when used in connection with GTK's 
 204    own windowless widgets. Beware. 
 208    Cursors, too, have been a constant source of pleasure. The main difficulty 
 209    is that a GdkWindow inherits a cursor if the programmer sets a new cursor 
 210    for the parent. To prevent this from doing too much harm, I use idle time 
 211    to set the cursor over and over again, starting from the toplevel windows 
 212    and ending with the youngest generation (speaking of parent and child windows). 
 213    Also don't forget that cursors (like much else) are connected to GdkWindows, 
 214    not GtkWidgets and that the "window" field of a GtkWidget might very well 
 215    point to the GdkWindow of the parent widget (-> "window-less widget") and 
 216    that the two obviously have very different meanings. 
 220 //----------------------------------------------------------------------------- 
 222 //----------------------------------------------------------------------------- 
 224 extern bool       g_blockEventsOnDrag
; 
 225 extern bool       g_blockEventsOnScroll
; 
 226 extern wxCursor   g_globalCursor
; 
 228 static GdkGC 
*g_eraseGC 
= NULL
; 
 230 // mouse capture state: the window which has it and if the mouse is currently 
 232 static wxWindowGTK  
*g_captureWindow 
= (wxWindowGTK
*) NULL
; 
 233 static bool g_captureWindowHasMouse 
= false; 
 235 wxWindowGTK  
*g_focusWindow 
= (wxWindowGTK
*) NULL
; 
 237 // the last window which had the focus - this is normally never NULL (except 
 238 // if we never had focus at all) as even when g_focusWindow is NULL it still 
 239 // keeps its previous value 
 240 wxWindowGTK 
*g_focusWindowLast 
= (wxWindowGTK
*) NULL
; 
 242 // If a window get the focus set but has not been realized 
 243 // yet, defer setting the focus to idle time. 
 244 wxWindowGTK 
*g_delayedFocus 
= (wxWindowGTK
*) NULL
; 
 246 extern bool g_mainThreadLocked
; 
 248 //----------------------------------------------------------------------------- 
 250 //----------------------------------------------------------------------------- 
 255 #   define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance"); 
 257 #   define DEBUG_MAIN_THREAD 
 260 #define DEBUG_MAIN_THREAD 
 263 // the trace mask used for the focus debugging messages 
 264 #define TRACE_FOCUS _T("focus") 
 266 //----------------------------------------------------------------------------- 
 267 // missing gdk functions 
 268 //----------------------------------------------------------------------------- 
 271 gdk_window_warp_pointer (GdkWindow      
*window
, 
 276     window 
= gdk_get_default_root_window(); 
 278   if (!GDK_WINDOW_DESTROYED(window
)) 
 280       XWarpPointer (GDK_WINDOW_XDISPLAY(window
), 
 281                     None
,              /* not source window -> move from anywhere */ 
 282                     GDK_WINDOW_XID(window
),  /* dest window */ 
 283                     0, 0, 0, 0,        /* not source window -> move from anywhere */ 
 288 //----------------------------------------------------------------------------- 
 289 // local code (see below) 
 290 //----------------------------------------------------------------------------- 
 292 // returns the child of win which currently has focus or NULL if not found 
 294 // Note: can't be static, needed by textctrl.cpp. 
 295 wxWindow 
*wxFindFocusedChild(wxWindowGTK 
*win
) 
 297     wxWindow 
*winFocus 
= wxWindowGTK::FindFocus(); 
 299         return (wxWindow 
*)NULL
; 
 301     if ( winFocus 
== win 
) 
 302         return (wxWindow 
*)win
; 
 304     for ( wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
 306           node 
= node
->GetNext() ) 
 308         wxWindow 
*child 
= wxFindFocusedChild(node
->GetData()); 
 313     return (wxWindow 
*)NULL
; 
 316 static void GetScrollbarWidth(GtkWidget
* widget
, int& w
, int& h
) 
 318     GtkScrolledWindow
* scroll_window 
= GTK_SCROLLED_WINDOW(widget
); 
 319     GtkScrolledWindowClass
* scroll_class 
= GTK_SCROLLED_WINDOW_CLASS(GTK_OBJECT_GET_CLASS(scroll_window
)); 
 320     GtkRequisition scroll_req
; 
 323     if (scroll_window
->vscrollbar_visible
) 
 325         scroll_req
.width 
= 2; 
 326         scroll_req
.height 
= 2; 
 327         (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
 328             (scroll_window
->vscrollbar
, &scroll_req 
); 
 329         w 
= scroll_req
.width 
+ 
 330             scroll_class
->scrollbar_spacing
; 
 334     if (scroll_window
->hscrollbar_visible
) 
 336         scroll_req
.width 
= 2; 
 337         scroll_req
.height 
= 2; 
 338         (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
 339             (scroll_window
->hscrollbar
, &scroll_req 
); 
 340         h 
= scroll_req
.height 
+ 
 341             scroll_class
->scrollbar_spacing
; 
 345 static void draw_frame( GtkWidget 
*widget
, wxWindowGTK 
*win 
) 
 347     // wxUniversal widgets draw the borders and scrollbars themselves 
 348 #ifndef __WXUNIVERSAL__ 
 355     if (win
->m_hasScrolling
) 
 357         GetScrollbarWidth(widget
, dw
, dh
); 
 362     if (GTK_WIDGET_NO_WINDOW (widget
)) 
 364         dx 
+= widget
->allocation
.x
; 
 365         dy 
+= widget
->allocation
.y
; 
 368     if (win
->HasFlag(wxRAISED_BORDER
)) 
 370         gtk_paint_shadow (widget
->style
, 
 374                           NULL
, NULL
, NULL
, // FIXME: No clipping? 
 376                           widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh 
); 
 380     if (win
->HasFlag(wxSUNKEN_BORDER
)) 
 382         gtk_paint_shadow (widget
->style
, 
 386                           NULL
, NULL
, NULL
, // FIXME: No clipping? 
 388                           widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh 
); 
 392     if (win
->HasFlag(wxSIMPLE_BORDER
)) 
 395         gc 
= gdk_gc_new( widget
->window 
); 
 396         gdk_gc_set_foreground( gc
, &widget
->style
->black 
); 
 397         gdk_draw_rectangle( widget
->window
, gc
, FALSE
, 
 399                          widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 ); 
 403 #endif // __WXUNIVERSAL__ 
 406 //----------------------------------------------------------------------------- 
 407 // "expose_event" of m_widget 
 408 //----------------------------------------------------------------------------- 
 412 gtk_window_own_expose_callback( GtkWidget 
*widget
, 
 413                                 GdkEventExpose 
*gdk_event
, 
 416     if (gdk_event
->count 
> 0) return FALSE
; 
 418     draw_frame( widget
, win 
); 
 420     (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
); 
 426 //----------------------------------------------------------------------------- 
 427 // "size_request" of m_widget 
 428 //----------------------------------------------------------------------------- 
 430 // make it extern because wxStaticText needs to disconnect this one 
 432 void wxgtk_window_size_request_callback(GtkWidget 
*widget
, 
 433                                         GtkRequisition 
*requisition
, 
 437     win
->GetSize( &w
, &h 
); 
 443     requisition
->height 
= h
; 
 444     requisition
->width 
= w
; 
 450 void wxgtk_combo_size_request_callback(GtkWidget 
*widget
, 
 451                                        GtkRequisition 
*requisition
, 
 454     // This callback is actually hooked into the text entry 
 455     // of the combo box, not the GtkHBox. 
 458     win
->GetSize( &w
, &h 
); 
 464     GtkCombo 
*gcombo 
= GTK_COMBO(win
->m_widget
); 
 466     GtkRequisition entry_req
; 
 468     entry_req
.height 
= 2; 
 469     (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(gcombo
->button
) )->size_request 
) 
 470         (gcombo
->button
, &entry_req 
); 
 472     requisition
->width 
= w 
- entry_req
.width
; 
 473     requisition
->height 
= entry_req
.height
; 
 477 //----------------------------------------------------------------------------- 
 478 // "expose_event" of m_wxwindow 
 479 //----------------------------------------------------------------------------- 
 483 gtk_window_expose_callback( GtkWidget 
*widget
, 
 484                             GdkEventExpose 
*gdk_event
, 
 490         wxapp_install_idle_handler(); 
 492     // This callback gets called in drawing-idle time under 
 493     // GTK 2.0, so we don't need to defer anything to idle 
 496     GtkPizza 
*pizza 
= GTK_PIZZA( widget 
); 
 497     if (gdk_event
->window 
!= pizza
->bin_window
) return FALSE
; 
 502         wxPrintf( wxT("OnExpose from ") ); 
 503         if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName()) 
 504             wxPrintf( win
->GetClassInfo()->GetClassName() ); 
 505         wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event
->area
.x
, 
 506                                          (int)gdk_event
->area
.y
, 
 507                                          (int)gdk_event
->area
.width
, 
 508                                          (int)gdk_event
->area
.height 
); 
 513         win
->m_wxwindow
->style
, 
 517         (GdkRectangle
*) NULL
, 
 519         (char *)"button", // const_cast 
 524     win
->GetUpdateRegion() = wxRegion( gdk_event
->region 
); 
 526     win
->GtkSendPaintEvents(); 
 529     // Let parent window draw window-less widgets 
 530     (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
); 
 536 //----------------------------------------------------------------------------- 
 537 // "key_press_event" from any window 
 538 //----------------------------------------------------------------------------- 
 540 // set WXTRACE to this to see the key event codes on the console 
 541 #define TRACE_KEYS  _T("keyevent") 
 543 // translates an X key symbol to WXK_XXX value 
 545 // if isChar is true it means that the value returned will be used for EVT_CHAR 
 546 // event and then we choose the logical WXK_XXX, i.e. '/' for GDK_KP_Divide, 
 547 // for example, while if it is false it means that the value is going to be 
 548 // used for KEY_DOWN/UP events and then we translate GDK_KP_Divide to 
 550 static long wxTranslateKeySymToWXKey(KeySym keysym
, bool isChar
) 
 556         // Shift, Control and Alt don't generate the CHAR events at all 
 559             key_code 
= isChar 
? 0 : WXK_SHIFT
; 
 563             key_code 
= isChar 
? 0 : WXK_CONTROL
; 
 571             key_code 
= isChar 
? 0 : WXK_ALT
; 
 574         // neither do the toggle modifies 
 575         case GDK_Scroll_Lock
: 
 576             key_code 
= isChar 
? 0 : WXK_SCROLL
; 
 580             key_code 
= isChar 
? 0 : WXK_CAPITAL
; 
 584             key_code 
= isChar 
? 0 : WXK_NUMLOCK
; 
 588         // various other special keys 
 601         case GDK_ISO_Left_Tab
: 
 608             key_code 
= WXK_RETURN
; 
 612             key_code 
= WXK_CLEAR
; 
 616             key_code 
= WXK_PAUSE
; 
 620             key_code 
= WXK_SELECT
; 
 624             key_code 
= WXK_PRINT
; 
 628             key_code 
= WXK_EXECUTE
; 
 632             key_code 
= WXK_ESCAPE
; 
 635         // cursor and other extended keyboard keys 
 637             key_code 
= WXK_DELETE
; 
 653             key_code 
= WXK_RIGHT
; 
 660         case GDK_Prior
:     // == GDK_Page_Up 
 661             key_code 
= WXK_PAGEUP
; 
 664         case GDK_Next
:      // == GDK_Page_Down 
 665             key_code 
= WXK_PAGEDOWN
; 
 677             key_code 
= WXK_INSERT
; 
 692             key_code 
= (isChar 
? '0' : WXK_NUMPAD0
) + keysym 
- GDK_KP_0
; 
 696             key_code 
= isChar 
? ' ' : WXK_NUMPAD_SPACE
; 
 700             key_code 
= isChar 
? WXK_TAB 
: WXK_NUMPAD_TAB
; 
 704             key_code 
= isChar 
? WXK_RETURN 
: WXK_NUMPAD_ENTER
; 
 708             key_code 
= isChar 
? WXK_F1 
: WXK_NUMPAD_F1
; 
 712             key_code 
= isChar 
? WXK_F2 
: WXK_NUMPAD_F2
; 
 716             key_code 
= isChar 
? WXK_F3 
: WXK_NUMPAD_F3
; 
 720             key_code 
= isChar 
? WXK_F4 
: WXK_NUMPAD_F4
; 
 724             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_HOME
; 
 728             key_code 
= isChar 
? WXK_LEFT 
: WXK_NUMPAD_LEFT
; 
 732             key_code 
= isChar 
? WXK_UP 
: WXK_NUMPAD_UP
; 
 736             key_code 
= isChar 
? WXK_RIGHT 
: WXK_NUMPAD_RIGHT
; 
 740             key_code 
= isChar 
? WXK_DOWN 
: WXK_NUMPAD_DOWN
; 
 743         case GDK_KP_Prior
: // == GDK_KP_Page_Up 
 744             key_code 
= isChar 
? WXK_PAGEUP 
: WXK_NUMPAD_PAGEUP
; 
 747         case GDK_KP_Next
: // == GDK_KP_Page_Down 
 748             key_code 
= isChar 
? WXK_PAGEDOWN 
: WXK_NUMPAD_PAGEDOWN
; 
 752             key_code 
= isChar 
? WXK_END 
: WXK_NUMPAD_END
; 
 756             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_BEGIN
; 
 760             key_code 
= isChar 
? WXK_INSERT 
: WXK_NUMPAD_INSERT
; 
 764             key_code 
= isChar 
? WXK_DELETE 
: WXK_NUMPAD_DELETE
; 
 768             key_code 
= isChar 
? '=' : WXK_NUMPAD_EQUAL
; 
 771         case GDK_KP_Multiply
: 
 772             key_code 
= isChar 
? '*' : WXK_NUMPAD_MULTIPLY
; 
 776             key_code 
= isChar 
? '+' : WXK_NUMPAD_ADD
; 
 779         case GDK_KP_Separator
: 
 780             // FIXME: what is this? 
 781             key_code 
= isChar 
? '.' : WXK_NUMPAD_SEPARATOR
; 
 784         case GDK_KP_Subtract
: 
 785             key_code 
= isChar 
? '-' : WXK_NUMPAD_SUBTRACT
; 
 789             key_code 
= isChar 
? '.' : WXK_NUMPAD_DECIMAL
; 
 793             key_code 
= isChar 
? '/' : WXK_NUMPAD_DIVIDE
; 
 810             key_code 
= WXK_F1 
+ keysym 
- GDK_F1
; 
 820 static inline bool wxIsAsciiKeysym(KeySym ks
) 
 825 static void wxFillOtherKeyEventFields(wxKeyEvent
& event
, 
 827                                       GdkEventKey 
*gdk_event
) 
 831     GdkModifierType state
; 
 832     if (gdk_event
->window
) 
 833         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
 835     event
.SetTimestamp( gdk_event
->time 
); 
 836     event
.SetId(win
->GetId()); 
 837     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
) != 0; 
 838     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
) != 0; 
 839     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
) != 0; 
 840     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
) != 0; 
 841     event
.m_scanCode 
= gdk_event
->keyval
; 
 842     event
.m_rawCode 
= (wxUint32
) gdk_event
->keyval
; 
 843     event
.m_rawFlags 
= 0; 
 845     event
.m_uniChar 
= gdk_keyval_to_unicode(gdk_event
->keyval
); 
 847     wxGetMousePosition( &x
, &y 
); 
 848     win
->ScreenToClient( &x
, &y 
); 
 851     event
.SetEventObject( win 
); 
 856 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
, 
 858                            GdkEventKey 
*gdk_event
) 
 860     // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string 
 861     //     but only event->keyval which is quite useless to us, so remember 
 862     //     the last character from GDK_KEY_PRESS and reuse it as last resort 
 864     // NB: should be MT-safe as we're always called from the main thread only 
 869     } s_lastKeyPress 
= { 0, 0 }; 
 871     KeySym keysym 
= gdk_event
->keyval
; 
 873     wxLogTrace(TRACE_KEYS
, _T("Key %s event: keysym = %ld"), 
 874                event
.GetEventType() == wxEVT_KEY_UP 
? _T("release") 
 878     long key_code 
= wxTranslateKeySymToWXKey(keysym
, false /* !isChar */); 
 882         // do we have the translation or is it a plain ASCII character? 
 883         if ( (gdk_event
->length 
== 1) || wxIsAsciiKeysym(keysym
) ) 
 885             // we should use keysym if it is ASCII as X does some translations 
 886             // like "I pressed while Control is down" => "Ctrl-I" == "TAB" 
 887             // which we don't want here (but which we do use for OnChar()) 
 888             if ( !wxIsAsciiKeysym(keysym
) ) 
 890                 keysym 
= (KeySym
)gdk_event
->string
[0]; 
 893             // we want to always get the same key code when the same key is 
 894             // pressed regardless of the state of the modifiers, i.e. on a 
 895             // standard US keyboard pressing '5' or '%' ('5' key with 
 896             // Shift) should result in the same key code in OnKeyDown(): 
 897             // '5' (although OnChar() will get either '5' or '%'). 
 899             // to do it we first translate keysym to keycode (== scan code) 
 900             // and then back but always using the lower register 
 901             Display 
*dpy 
= (Display 
*)wxGetDisplay(); 
 902             KeyCode keycode 
= XKeysymToKeycode(dpy
, keysym
); 
 904             wxLogTrace(TRACE_KEYS
, _T("\t-> keycode %d"), keycode
); 
 906             KeySym keysymNormalized 
= XKeycodeToKeysym(dpy
, keycode
, 0); 
 908             // use the normalized, i.e. lower register, keysym if we've 
 910             key_code 
= keysymNormalized 
? keysymNormalized 
: keysym
; 
 912             // as explained above, we want to have lower register key codes 
 913             // normally but for the letter keys we want to have the upper ones 
 915             // NB: don't use XConvertCase() here, we want to do it for letters 
 917             key_code 
= toupper(key_code
); 
 919         else // non ASCII key, what to do? 
 921             // by default, ignore it 
 924             // but if we have cached information from the last KEY_PRESS 
 925             if ( gdk_event
->type 
== GDK_KEY_RELEASE 
) 
 928                 if ( keysym 
== s_lastKeyPress
.keysym 
) 
 930                     key_code 
= s_lastKeyPress
.keycode
; 
 935         if ( gdk_event
->type 
== GDK_KEY_PRESS 
) 
 937             // remember it to be reused for KEY_UP event later 
 938             s_lastKeyPress
.keysym 
= keysym
; 
 939             s_lastKeyPress
.keycode 
= key_code
; 
 943     wxLogTrace(TRACE_KEYS
, _T("\t-> wxKeyCode %ld"), key_code
); 
 945     // sending unknown key events doesn't really make sense 
 949     // now fill all the other fields 
 950     wxFillOtherKeyEventFields(event
, win
, gdk_event
); 
 952     event
.m_keyCode 
= key_code
; 
 954     if ( gdk_event
->type 
== GDK_KEY_PRESS 
||  gdk_event
->type 
== GDK_KEY_RELEASE 
) 
 956         event
.m_uniChar 
= key_code
; 
 966     GtkIMContext 
*context
; 
 967     GdkEventKey  
*lastKeyEvent
; 
 971         context 
= gtk_im_multicontext_new(); 
 976         g_object_unref (context
); 
 982 gtk_window_key_press_callback( GtkWidget 
*widget
, 
 983                                GdkEventKey 
*gdk_event
, 
 989         wxapp_install_idle_handler(); 
 993     if (g_blockEventsOnDrag
) 
 997     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
 999     bool return_after_IM 
= false; 
1001     if( wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1003         // Emit KEY_DOWN event 
1004         ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1008         // Return after IM processing as we cannot do 
1009         // anything with it anyhow. 
1010         return_after_IM 
= true; 
1013     // 2005.01.26 modified by Hong Jen Yee (hzysoft@sina.com.tw): 
1014     // When we get a key_press event here, it could be originate 
1015     // from the current widget or its child widgets.  However, only the widget 
1016     // with the INPUT FOCUS can generate the INITIAL key_press event.  That is, 
1017     // if the CURRENT widget doesn't have the FOCUS at all, this event definitely 
1018     // originated from its child widgets and shouldn't be passed to IM context. 
1019     // In fact, what a GTK+ IM should do is filtering keyEvents and convert them 
1020     // into text input ONLY WHEN THE WIDGET HAS INPUT FOCUS.  Besides, when current 
1021     // widgets has both IM context and input focus, the event should be filtered 
1022     // by gtk_im_context_filter_keypress(). 
1023     // Then, we should, according to GTK+ 2.0 API doc, return whatever it returns. 
1024     if ((!ret
) && (win
->m_imData 
!= NULL
) && ( wxWindow::FindFocus() == win 
)) 
1026         // We should let GTK+ IM filter key event first. According to GTK+ 2.0 API 
1027         // docs, if IM filter returns true, no further processing should be done. 
1028         // we should send the key_down event anyway. 
1029         bool intercepted_by_IM 
= gtk_im_context_filter_keypress(win
->m_imData
->context
, gdk_event
); 
1030         win
->m_imData
->lastKeyEvent 
= NULL
; 
1031         if (intercepted_by_IM
) 
1033             wxLogTrace(TRACE_KEYS
, _T("Key event intercepted by IM")); 
1038     if (return_after_IM
) 
1044         wxWindowGTK 
*ancestor 
= win
; 
1047             int command 
= ancestor
->GetAcceleratorTable()->GetCommand( event 
); 
1050                 wxCommandEvent 
command_event( wxEVT_COMMAND_MENU_SELECTED
, command 
); 
1051                 ret 
= ancestor
->GetEventHandler()->ProcessEvent( command_event 
); 
1054             if (ancestor
->IsTopLevel()) 
1056             ancestor 
= ancestor
->GetParent(); 
1059 #endif // wxUSE_ACCEL 
1061     // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x 
1062     // will only be sent if it is not in an accelerator table. 
1066         KeySym keysym 
= gdk_event
->keyval
; 
1067         // Find key code for EVT_CHAR and EVT_CHAR_HOOK events 
1068         key_code 
= wxTranslateKeySymToWXKey(keysym
, true /* isChar */); 
1071             if ( wxIsAsciiKeysym(keysym
) ) 
1074                 key_code 
= (unsigned char)keysym
; 
1076             // gdk_event->string is actually deprecated 
1077             else if ( gdk_event
->length 
== 1 ) 
1079                 key_code 
= (unsigned char)gdk_event
->string
[0]; 
1085             wxLogTrace(TRACE_KEYS
, _T("Char event: %ld"), key_code
); 
1087             event
.m_keyCode 
= key_code
; 
1089             // To conform to the docs we need to translate Ctrl-alpha 
1090             // characters to values in the range 1-26. 
1091             if (event
.ControlDown() && key_code 
>= 'a' && key_code 
<= 'z' ) 
1093                 event
.m_keyCode 
= key_code 
- 'a' + 1; 
1095                 event
.m_uniChar 
= event
.m_keyCode
; 
1099             // Implement OnCharHook by checking ancestor top level windows 
1100             wxWindow 
*parent 
= win
; 
1101             while (parent 
&& !parent
->IsTopLevel()) 
1102                 parent 
= parent
->GetParent(); 
1105                 event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1106                 ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1111                 event
.SetEventType(wxEVT_CHAR
); 
1112                 ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1121     // win is a control: tab can be propagated up 
1123          ((gdk_event
->keyval 
== GDK_Tab
) || (gdk_event
->keyval 
== GDK_ISO_Left_Tab
)) && 
1124 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here - the control may 
1125 //     have this style, yet choose not to process this particular TAB in which 
1126 //     case TAB must still work as a navigational character 
1127 // JS: enabling again to make consistent with other platforms 
1128 //     (with wxTE_PROCESS_TAB you have to call Navigate to get default 
1129 //     navigation behaviour) 
1131          (! (win
->HasFlag(wxTE_PROCESS_TAB
) && win
->IsKindOf(CLASSINFO(wxTextCtrl
)) )) && 
1133          win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) ) 
1135         wxNavigationKeyEvent new_event
; 
1136         new_event
.SetEventObject( win
->GetParent() ); 
1137         // GDK reports GDK_ISO_Left_Tab for SHIFT-TAB 
1138         new_event
.SetDirection( (gdk_event
->keyval 
== GDK_Tab
) ); 
1139         // CTRL-TAB changes the (parent) window, i.e. switch notebook page 
1140         new_event
.SetWindowChange( (gdk_event
->state 
& GDK_CONTROL_MASK
) ); 
1141         new_event
.SetCurrentFocus( win 
); 
1142         ret 
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event 
); 
1145     // generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) 
1147          (gdk_event
->keyval 
== GDK_Escape
) ) 
1149         // however only do it if we have a Cancel button in the dialog, 
1150         // otherwise the user code may get confused by the events from a 
1151         // non-existing button and, worse, a wxButton might get button event 
1152         // from another button which is not really expected 
1153         wxWindow 
*winForCancel 
= win
, 
1155         while ( winForCancel 
) 
1157             btnCancel 
= winForCancel
->FindWindow(wxID_CANCEL
); 
1160                 // found a cancel button 
1164             if ( winForCancel
->IsTopLevel() ) 
1166                 // no need to look further 
1170             // maybe our parent has a cancel button? 
1171             winForCancel 
= winForCancel
->GetParent(); 
1176             wxCommandEvent 
eventClick(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
); 
1177             eventClick
.SetEventObject(btnCancel
); 
1178             ret 
= btnCancel
->GetEventHandler()->ProcessEvent(eventClick
); 
1184         g_signal_stop_emission_by_name (widget
, "key_press_event"); 
1194 gtk_wxwindow_commit_cb (GtkIMContext 
*context
, 
1198     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
1200     // take modifiers, cursor position, timestamp etc. from the last 
1201     // key_press_event that was fed into Input Method: 
1202     if (window
->m_imData
->lastKeyEvent
) 
1204         wxFillOtherKeyEventFields(event
, 
1205                                   window
, window
->m_imData
->lastKeyEvent
); 
1208     const wxWxCharBuffer 
data(wxGTK_CONV_BACK(str
)); 
1214     // Implement OnCharHook by checking ancestor top level windows 
1215     wxWindow 
*parent 
= window
; 
1216     while (parent 
&& !parent
->IsTopLevel()) 
1217         parent 
= parent
->GetParent(); 
1219     for( const wxChar
* pstr 
= data
; *pstr
; pstr
++ ) 
1222         event
.m_uniChar 
= *pstr
; 
1223         // Backward compatible for ISO-8859-1 
1224         event
.m_keyCode 
= *pstr 
< 256 ? event
.m_uniChar 
: 0; 
1225         wxLogTrace(TRACE_KEYS
, _T("IM sent character '%c'"), event
.m_uniChar
); 
1227         event
.m_keyCode 
= *pstr
; 
1228 #endif  // wxUSE_UNICODE 
1230         // To conform to the docs we need to translate Ctrl-alpha 
1231         // characters to values in the range 1-26. 
1232         if (event
.ControlDown() && *pstr 
>= 'a' && *pstr 
<= 'z' ) 
1234             event
.m_keyCode 
= *pstr 
- 'a' + 1; 
1236             event
.m_uniChar 
= event
.m_keyCode
; 
1242             event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1243             ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1248             event
.SetEventType(wxEVT_CHAR
); 
1249             ret 
= window
->GetEventHandler()->ProcessEvent( event 
); 
1256 //----------------------------------------------------------------------------- 
1257 // "key_release_event" from any window 
1258 //----------------------------------------------------------------------------- 
1262 gtk_window_key_release_callback( GtkWidget 
*widget
, 
1263                                  GdkEventKey 
*gdk_event
, 
1269         wxapp_install_idle_handler(); 
1274     if (g_blockEventsOnDrag
) 
1277     wxKeyEvent 
event( wxEVT_KEY_UP 
); 
1278     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1280         // unknown key pressed, ignore (the event would be useless anyhow) 
1284     if ( !win
->GetEventHandler()->ProcessEvent( event 
) ) 
1287     g_signal_stop_emission_by_name (widget
, "key_release_event"); 
1292 // ============================================================================ 
1294 // ============================================================================ 
1296 // ---------------------------------------------------------------------------- 
1297 // mouse event processing helpers 
1298 // ---------------------------------------------------------------------------- 
1300 // init wxMouseEvent with the info from GdkEventXXX struct 
1301 template<typename T
> void InitMouseEvent(wxWindowGTK 
*win
, 
1302                                          wxMouseEvent
& event
, 
1305     event
.SetTimestamp( gdk_event
->time 
); 
1306     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
); 
1307     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
); 
1308     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
); 
1309     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
); 
1310     event
.m_leftDown 
= (gdk_event
->state 
& GDK_BUTTON1_MASK
); 
1311     event
.m_middleDown 
= (gdk_event
->state 
& GDK_BUTTON2_MASK
); 
1312     event
.m_rightDown 
= (gdk_event
->state 
& GDK_BUTTON3_MASK
); 
1313     if (event
.GetEventType() == wxEVT_MOUSEWHEEL
) 
1315        event
.m_linesPerAction 
= 3; 
1316        event
.m_wheelDelta 
= 120; 
1317        if (((GdkEventButton
*)gdk_event
)->button 
== 4) 
1318            event
.m_wheelRotation 
= 120; 
1319        else if (((GdkEventButton
*)gdk_event
)->button 
== 5) 
1320            event
.m_wheelRotation 
= -120; 
1323     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1324     event
.m_x 
= (wxCoord
)gdk_event
->x 
- pt
.x
; 
1325     event
.m_y 
= (wxCoord
)gdk_event
->y 
- pt
.y
; 
1327     event
.SetEventObject( win 
); 
1328     event
.SetId( win
->GetId() ); 
1329     event
.SetTimestamp( gdk_event
->time 
); 
1332 static void AdjustEventButtonState(wxMouseEvent
& event
) 
1334     // GDK reports the old state of the button for a button press event, but 
1335     // for compatibility with MSW and common sense we want m_leftDown be TRUE 
1336     // for a LEFT_DOWN event, not FALSE, so we will invert 
1337     // left/right/middleDown for the corresponding click events 
1339     if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) || 
1340         (event
.GetEventType() == wxEVT_LEFT_DCLICK
) || 
1341         (event
.GetEventType() == wxEVT_LEFT_UP
)) 
1343         event
.m_leftDown 
= !event
.m_leftDown
; 
1347     if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) || 
1348         (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) || 
1349         (event
.GetEventType() == wxEVT_MIDDLE_UP
)) 
1351         event
.m_middleDown 
= !event
.m_middleDown
; 
1355     if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) || 
1356         (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) || 
1357         (event
.GetEventType() == wxEVT_RIGHT_UP
)) 
1359         event
.m_rightDown 
= !event
.m_rightDown
; 
1364 // find the window to send the mouse event too 
1366 wxWindowGTK 
*FindWindowForMouseEvent(wxWindowGTK 
*win
, wxCoord
& x
, wxCoord
& y
) 
1371     if (win
->m_wxwindow
) 
1373         GtkPizza 
*pizza 
= GTK_PIZZA(win
->m_wxwindow
); 
1374         xx 
+= pizza
->xoffset
; 
1375         yy 
+= pizza
->yoffset
; 
1378     wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
1381         wxWindowGTK 
*child 
= node
->GetData(); 
1383         node 
= node
->GetNext(); 
1384         if (!child
->IsShown()) 
1387         if (child
->IsTransparentForMouse()) 
1389             // wxStaticBox is transparent in the box itself 
1390             int xx1 
= child
->m_x
; 
1391             int yy1 
= child
->m_y
; 
1392             int xx2 
= child
->m_x 
+ child
->m_width
; 
1393             int yy2 
= child
->m_y 
+ child
->m_height
; 
1396             if (((xx 
>= xx1
) && (xx 
<= xx1
+10) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1398                 ((xx 
>= xx2
-10) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1400                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy1
+10)) || 
1402                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy2
-1) && (yy 
<= yy2
))) 
1413             if ((child
->m_wxwindow 
== (GtkWidget
*) NULL
) && 
1414                 (child
->m_x 
<= xx
) && 
1415                 (child
->m_y 
<= yy
) && 
1416                 (child
->m_x
+child
->m_width  
>= xx
) && 
1417                 (child
->m_y
+child
->m_height 
>= yy
)) 
1430 //----------------------------------------------------------------------------- 
1431 // "button_press_event" 
1432 //----------------------------------------------------------------------------- 
1436 gtk_window_button_press_callback( GtkWidget 
*widget
, 
1437                                   GdkEventButton 
*gdk_event
, 
1443         wxapp_install_idle_handler(); 
1446     wxPrintf( wxT("1) OnButtonPress from ") ); 
1447     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1448         wxPrintf( win->GetClassInfo()->GetClassName() ); 
1449     wxPrintf( wxT(".\n") ); 
1451     if (!win
->m_hasVMT
) return FALSE
; 
1452     if (g_blockEventsOnDrag
) return TRUE
; 
1453     if (g_blockEventsOnScroll
) return TRUE
; 
1455     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1457     if (win
->m_wxwindow 
&& (g_focusWindow 
!= win
) && win
->AcceptsFocus()) 
1459         gtk_widget_grab_focus( win
->m_wxwindow 
); 
1461         wxPrintf( wxT("GrabFocus from ") ); 
1462         if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1463             wxPrintf( win->GetClassInfo()->GetClassName() ); 
1464         wxPrintf( wxT(".\n") ); 
1468     // GDK sends surplus button down events 
1469     // before a double click event. We 
1470     // need to filter these out. 
1471     if (gdk_event
->type 
== GDK_BUTTON_PRESS
) 
1473         GdkEvent 
*peek_event 
= gdk_event_peek(); 
1476             if ((peek_event
->type 
== GDK_2BUTTON_PRESS
) || 
1477                 (peek_event
->type 
== GDK_3BUTTON_PRESS
)) 
1479                 gdk_event_free( peek_event 
); 
1484                 gdk_event_free( peek_event 
); 
1489     wxEventType event_type 
= wxEVT_NULL
; 
1491     // GdkDisplay is a GTK+ 2.2.0 thing 
1492 #if defined(__WXGTK20__) && GTK_CHECK_VERSION(2, 2, 0) 
1493     if ( gdk_event
->type 
== GDK_2BUTTON_PRESS 
&& 
1494             !gtk_check_version(2,2,0) && 
1495             gdk_event
->button 
>= 1 && gdk_event
->button 
<= 3 ) 
1497         // Reset GDK internal timestamp variables in order to disable GDK 
1498         // triple click events. GDK will then next time believe no button has 
1499         // been clicked just before, and send a normal button click event. 
1500         GdkDisplay
* display 
= gtk_widget_get_display (widget
); 
1501         display
->button_click_time
[1] = 0; 
1502         display
->button_click_time
[0] = 0; 
1506     if (gdk_event
->button 
== 1) 
1508         // note that GDK generates triple click events which are not supported 
1509         // by wxWidgets but still have to be passed to the app as otherwise 
1510         // clicks would simply go missing 
1511         switch (gdk_event
->type
) 
1513             // we shouldn't get triple clicks at all for GTK2 because we 
1514             // suppress them artificially using the code above but we still 
1515             // should map them to something for GTK1 and not just ignore them 
1516             // as this would lose clicks 
1517             case GDK_3BUTTON_PRESS
:     // we could also map this to DCLICK... 
1518             case GDK_BUTTON_PRESS
: 
1519                 event_type 
= wxEVT_LEFT_DOWN
; 
1522             case GDK_2BUTTON_PRESS
: 
1523                 event_type 
= wxEVT_LEFT_DCLICK
; 
1527                 // just to silence gcc warnings 
1531     else if (gdk_event
->button 
== 2) 
1533         switch (gdk_event
->type
) 
1535             case GDK_3BUTTON_PRESS
: 
1536             case GDK_BUTTON_PRESS
: 
1537                 event_type 
= wxEVT_MIDDLE_DOWN
; 
1540             case GDK_2BUTTON_PRESS
: 
1541                 event_type 
= wxEVT_MIDDLE_DCLICK
; 
1548     else if (gdk_event
->button 
== 3) 
1550         switch (gdk_event
->type
) 
1552             case GDK_3BUTTON_PRESS
: 
1553             case GDK_BUTTON_PRESS
: 
1554                 event_type 
= wxEVT_RIGHT_DOWN
; 
1557             case GDK_2BUTTON_PRESS
: 
1558                 event_type 
= wxEVT_RIGHT_DCLICK
; 
1565     else if (gdk_event
->button 
== 4 || gdk_event
->button 
== 5) 
1567         if (gdk_event
->type 
== GDK_BUTTON_PRESS 
) 
1569             event_type 
= wxEVT_MOUSEWHEEL
; 
1573     if ( event_type 
== wxEVT_NULL 
) 
1575         // unknown mouse button or click type 
1579     wxMouseEvent 
event( event_type 
); 
1580     InitMouseEvent( win
, event
, gdk_event 
); 
1582     AdjustEventButtonState(event
); 
1584     // wxListBox actually gets mouse events from the item, so we need to give it 
1585     // a chance to correct this 
1586     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1588     // find the correct window to send the event to: it may be a different one 
1589     // from the one which got it at GTK+ level because some controls don't have 
1590     // their own X window and thus cannot get any events. 
1591     if ( !g_captureWindow 
) 
1592         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1594     // reset the event object and id in case win changed. 
1595     event
.SetEventObject( win 
); 
1596     event
.SetId( win
->GetId() ); 
1598     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1600         g_signal_stop_emission_by_name (widget
, "button_press_event"); 
1604     if (event_type 
== wxEVT_RIGHT_DOWN
) 
1606         // generate a "context menu" event: this is similar to right mouse 
1607         // click under many GUIs except that it is generated differently 
1608         // (right up under MSW, ctrl-click under Mac, right down here) and 
1610         // (a) it's a command event and so is propagated to the parent 
1611         // (b) under some ports it can be generated from kbd too 
1612         // (c) it uses screen coords (because of (a)) 
1613         wxContextMenuEvent 
evtCtx( 
1616             win
->ClientToScreen(event
.GetPosition())); 
1617         evtCtx
.SetEventObject(win
); 
1618         return win
->GetEventHandler()->ProcessEvent(evtCtx
); 
1625 //----------------------------------------------------------------------------- 
1626 // "button_release_event" 
1627 //----------------------------------------------------------------------------- 
1631 gtk_window_button_release_callback( GtkWidget 
*widget
, 
1632                                     GdkEventButton 
*gdk_event
, 
1638         wxapp_install_idle_handler(); 
1640     if (!win
->m_hasVMT
) return FALSE
; 
1641     if (g_blockEventsOnDrag
) return FALSE
; 
1642     if (g_blockEventsOnScroll
) return FALSE
; 
1644     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1646     wxEventType event_type 
= wxEVT_NULL
; 
1648     switch (gdk_event
->button
) 
1651             event_type 
= wxEVT_LEFT_UP
; 
1655             event_type 
= wxEVT_MIDDLE_UP
; 
1659             event_type 
= wxEVT_RIGHT_UP
; 
1663             // unknwon button, don't process 
1667     wxMouseEvent 
event( event_type 
); 
1668     InitMouseEvent( win
, event
, gdk_event 
); 
1670     AdjustEventButtonState(event
); 
1672     // same wxListBox hack as above 
1673     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1675     if ( !g_captureWindow 
) 
1676         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1678     // reset the event object and id in case win changed. 
1679     event
.SetEventObject( win 
); 
1680     event
.SetId( win
->GetId() ); 
1682     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1684         g_signal_stop_emission_by_name (widget
, "button_release_event"); 
1692 //----------------------------------------------------------------------------- 
1693 // "motion_notify_event" 
1694 //----------------------------------------------------------------------------- 
1698 gtk_window_motion_notify_callback( GtkWidget 
*widget
, 
1699                                    GdkEventMotion 
*gdk_event
, 
1705         wxapp_install_idle_handler(); 
1707     if (!win
->m_hasVMT
) return FALSE
; 
1708     if (g_blockEventsOnDrag
) return FALSE
; 
1709     if (g_blockEventsOnScroll
) return FALSE
; 
1711     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1713     if (gdk_event
->is_hint
) 
1717         GdkModifierType state
; 
1718         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1724     printf( "OnMotion from " ); 
1725     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1726       printf( win->GetClassInfo()->GetClassName() ); 
1730     wxMouseEvent 
event( wxEVT_MOTION 
); 
1731     InitMouseEvent(win
, event
, gdk_event
); 
1733     if ( g_captureWindow 
) 
1735         // synthetize a mouse enter or leave event if needed 
1736         GdkWindow 
*winUnderMouse 
= gdk_window_at_pointer(NULL
, NULL
); 
1737         // This seems to be necessary and actually been added to 
1738         // GDK itself in version 2.0.X 
1741         bool hasMouse 
= winUnderMouse 
== gdk_event
->window
; 
1742         if ( hasMouse 
!= g_captureWindowHasMouse 
) 
1744             // the mouse changed window 
1745             g_captureWindowHasMouse 
= hasMouse
; 
1747             wxMouseEvent 
eventM(g_captureWindowHasMouse 
? wxEVT_ENTER_WINDOW
 
1748                                                         : wxEVT_LEAVE_WINDOW
); 
1749             InitMouseEvent(win
, eventM
, gdk_event
); 
1750             eventM
.SetEventObject(win
); 
1751             win
->GetEventHandler()->ProcessEvent(eventM
); 
1756         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1758         // reset the event object and id in case win changed. 
1759         event
.SetEventObject( win 
); 
1760         event
.SetId( win
->GetId() ); 
1763     if ( !g_captureWindow 
) 
1765         wxSetCursorEvent 
cevent( event
.m_x
, event
.m_y 
); 
1766         if (win
->GetEventHandler()->ProcessEvent( cevent 
)) 
1768             // Rewrite cursor handling here (away from idle). 
1772     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1774         g_signal_stop_emission_by_name (widget
, "motion_notify_event"); 
1782 //----------------------------------------------------------------------------- 
1783 // "scroll_event", (mouse wheel event) 
1784 //----------------------------------------------------------------------------- 
1788 window_scroll_event(GtkWidget
*, GdkEventScroll
* gdk_event
, wxWindow
* win
) 
1793         wxapp_install_idle_handler(); 
1795     if (gdk_event
->direction 
!= GDK_SCROLL_UP 
&& 
1796         gdk_event
->direction 
!= GDK_SCROLL_DOWN
) 
1801     wxMouseEvent 
event(wxEVT_MOUSEWHEEL
); 
1802     // Can't use InitMouse macro because scroll events don't have button 
1803     event
.SetTimestamp( gdk_event
->time 
); 
1804     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
); 
1805     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
); 
1806     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
); 
1807     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
); 
1808     event
.m_leftDown 
= (gdk_event
->state 
& GDK_BUTTON1_MASK
); 
1809     event
.m_middleDown 
= (gdk_event
->state 
& GDK_BUTTON2_MASK
); 
1810     event
.m_rightDown 
= (gdk_event
->state 
& GDK_BUTTON3_MASK
); 
1811     event
.m_linesPerAction 
= 3; 
1812     event
.m_wheelDelta 
= 120; 
1813     if (gdk_event
->direction 
== GDK_SCROLL_UP
) 
1814         event
.m_wheelRotation 
= 120; 
1816         event
.m_wheelRotation 
= -120; 
1818     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1819     event
.m_x 
= (wxCoord
)gdk_event
->x 
- pt
.x
; 
1820     event
.m_y 
= (wxCoord
)gdk_event
->y 
- pt
.y
; 
1822     event
.SetEventObject( win 
); 
1823     event
.SetId( win
->GetId() ); 
1824     event
.SetTimestamp( gdk_event
->time 
); 
1826     return win
->GetEventHandler()->ProcessEvent(event
); 
1830 //----------------------------------------------------------------------------- 
1832 //----------------------------------------------------------------------------- 
1834 static gboolean 
wxgtk_window_popup_menu_callback(GtkWidget
*, wxWindowGTK
* win
) 
1836     wxContextMenuEvent 
event( 
1840     event
.SetEventObject(win
); 
1841     return win
->GetEventHandler()->ProcessEvent(event
); 
1845 //----------------------------------------------------------------------------- 
1847 //----------------------------------------------------------------------------- 
1849 // send the wxChildFocusEvent and wxFocusEvent, common code of 
1850 // gtk_window_focus_in_callback() and SetFocus() 
1851 static bool DoSendFocusEvents(wxWindow 
*win
) 
1853     // Notify the parent keeping track of focus for the kbd navigation 
1854     // purposes that we got it. 
1855     wxChildFocusEvent 
eventChildFocus(win
); 
1856     (void)win
->GetEventHandler()->ProcessEvent(eventChildFocus
); 
1858     wxFocusEvent 
eventFocus(wxEVT_SET_FOCUS
, win
->GetId()); 
1859     eventFocus
.SetEventObject(win
); 
1861     return win
->GetEventHandler()->ProcessEvent(eventFocus
); 
1866 gtk_window_focus_in_callback( GtkWidget 
*widget
, 
1867                               GdkEventFocus 
*WXUNUSED(event
), 
1873         wxapp_install_idle_handler(); 
1876         gtk_im_context_focus_in(win
->m_imData
->context
); 
1879     g_focusWindow 
= win
; 
1881     wxLogTrace(TRACE_FOCUS
, 
1882                _T("%s: focus in"), win
->GetName().c_str()); 
1886         gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
); 
1890     // caret needs to be informed about focus change 
1891     wxCaret 
*caret 
= win
->GetCaret(); 
1894         caret
->OnSetFocus(); 
1896 #endif // wxUSE_CARET 
1898     gboolean ret 
= FALSE
; 
1900     // does the window itself think that it has the focus? 
1901     if ( !win
->m_hasFocus 
) 
1903         // not yet, notify it 
1904         win
->m_hasFocus 
= true; 
1906         (void)DoSendFocusEvents(win
); 
1911     // Disable default focus handling for custom windows 
1912     // since the default GTK+ handler issues a repaint 
1913     if (win
->m_wxwindow
) 
1920 //----------------------------------------------------------------------------- 
1921 // "focus_out_event" 
1922 //----------------------------------------------------------------------------- 
1926 gtk_window_focus_out_callback( GtkWidget 
*widget
, 
1927                                GdkEventFocus 
*gdk_event
, 
1933         wxapp_install_idle_handler(); 
1936         gtk_im_context_focus_out(win
->m_imData
->context
); 
1938     wxLogTrace( TRACE_FOCUS
, 
1939                 _T("%s: focus out"), win
->GetName().c_str() ); 
1942     wxWindowGTK 
*winFocus 
= wxFindFocusedChild(win
); 
1946     g_focusWindow 
= (wxWindowGTK 
*)NULL
; 
1954     // caret needs to be informed about focus change 
1955     wxCaret 
*caret 
= win
->GetCaret(); 
1958         caret
->OnKillFocus(); 
1960 #endif // wxUSE_CARET 
1962     gboolean ret 
= FALSE
; 
1964     // don't send the window a kill focus event if it thinks that it doesn't 
1965     // have focus already 
1966     if ( win
->m_hasFocus 
) 
1968         win
->m_hasFocus 
= false; 
1970         wxFocusEvent 
event( wxEVT_KILL_FOCUS
, win
->GetId() ); 
1971         event
.SetEventObject( win 
); 
1973         (void)win
->GetEventHandler()->ProcessEvent( event 
); 
1978     // Disable default focus handling for custom windows 
1979     // since the default GTK+ handler issues a repaint 
1980     if (win
->m_wxwindow
) 
1987 //----------------------------------------------------------------------------- 
1988 // "enter_notify_event" 
1989 //----------------------------------------------------------------------------- 
1993 gtk_window_enter_callback( GtkWidget 
*widget
, 
1994                            GdkEventCrossing 
*gdk_event
, 
2000         wxapp_install_idle_handler(); 
2002     if (!win
->m_hasVMT
) return FALSE
; 
2003     if (g_blockEventsOnDrag
) return FALSE
; 
2005     // Event was emitted after a grab 
2006     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
2008     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
2012     GdkModifierType state 
= (GdkModifierType
)0; 
2014     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
2016     wxMouseEvent 
event( wxEVT_ENTER_WINDOW 
); 
2017     InitMouseEvent(win
, event
, gdk_event
); 
2018     wxPoint pt 
= win
->GetClientAreaOrigin(); 
2019     event
.m_x 
= x 
+ pt
.x
; 
2020     event
.m_y 
= y 
+ pt
.y
; 
2022     if ( !g_captureWindow 
) 
2024         wxSetCursorEvent 
cevent( event
.m_x
, event
.m_y 
); 
2025         if (win
->GetEventHandler()->ProcessEvent( cevent 
)) 
2027             // Rewrite cursor handling here (away from idle). 
2031     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
2033        g_signal_stop_emission_by_name (widget
, "enter_notify_event"); 
2041 //----------------------------------------------------------------------------- 
2042 // "leave_notify_event" 
2043 //----------------------------------------------------------------------------- 
2047 gtk_window_leave_callback( GtkWidget 
*widget
, 
2048                            GdkEventCrossing 
*gdk_event
, 
2054         wxapp_install_idle_handler(); 
2056     if (!win
->m_hasVMT
) return FALSE
; 
2057     if (g_blockEventsOnDrag
) return FALSE
; 
2059     // Event was emitted after an ungrab 
2060     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
2062     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
2064     wxMouseEvent 
event( wxEVT_LEAVE_WINDOW 
); 
2065     event
.SetTimestamp( gdk_event
->time 
); 
2066     event
.SetEventObject( win 
); 
2070     GdkModifierType state 
= (GdkModifierType
)0; 
2072     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
2074     event
.m_shiftDown 
= (state 
& GDK_SHIFT_MASK
) != 0; 
2075     event
.m_controlDown 
= (state 
& GDK_CONTROL_MASK
) != 0; 
2076     event
.m_altDown 
= (state 
& GDK_MOD1_MASK
) != 0; 
2077     event
.m_metaDown 
= (state 
& GDK_MOD2_MASK
) != 0; 
2078     event
.m_leftDown 
= (state 
& GDK_BUTTON1_MASK
) != 0; 
2079     event
.m_middleDown 
= (state 
& GDK_BUTTON2_MASK
) != 0; 
2080     event
.m_rightDown 
= (state 
& GDK_BUTTON3_MASK
) != 0; 
2082     wxPoint pt 
= win
->GetClientAreaOrigin(); 
2083     event
.m_x 
= x 
+ pt
.x
; 
2084     event
.m_y 
= y 
+ pt
.y
; 
2086     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
2088         g_signal_stop_emission_by_name (widget
, "leave_notify_event"); 
2096 //----------------------------------------------------------------------------- 
2097 // "value_changed" from scrollbar 
2098 //----------------------------------------------------------------------------- 
2102 gtk_scrollbar_value_changed(GtkRange
* range
, wxWindow
* win
) 
2104     wxEventType eventType 
= win
->GetScrollEventType(range
); 
2105     if (eventType 
!= wxEVT_NULL
) 
2107         // Convert scroll event type to scrollwin event type 
2108         eventType 
+= wxEVT_SCROLLWIN_TOP 
- wxEVT_SCROLL_TOP
; 
2109         const int orient 
= range 
== win
->m_scrollBar
[0] ? wxHORIZONTAL 
: wxVERTICAL
; 
2110         wxScrollWinEvent 
event(eventType
, win
->GetScrollPos(orient
), orient
); 
2111         event
.SetEventObject(win
); 
2112         win
->GetEventHandler()->ProcessEvent(event
); 
2117 //----------------------------------------------------------------------------- 
2118 // "button_press_event" from scrollbar 
2119 //----------------------------------------------------------------------------- 
2123 gtk_scrollbar_button_press_event(GtkRange
*, GdkEventButton
*, wxWindow
* win
) 
2128         wxapp_install_idle_handler(); 
2130     g_blockEventsOnScroll 
= true; 
2131     win
->m_mouseButtonDown 
= true; 
2137 //----------------------------------------------------------------------------- 
2138 // "button_release_event" from scrollbar 
2139 //----------------------------------------------------------------------------- 
2143 gtk_scrollbar_button_release_event(GtkRange
* range
, GdkEventButton
*, wxWindow
* win
) 
2147     g_blockEventsOnScroll 
= false; 
2148     win
->m_mouseButtonDown 
= false; 
2149     // If thumb tracking 
2150     if (win
->m_isScrolling
) 
2152         win
->m_isScrolling 
= false; 
2153         const int orient 
= range 
== win
->m_scrollBar
[0] ? wxHORIZONTAL 
: wxVERTICAL
; 
2154         wxScrollWinEvent 
event(wxEVT_SCROLLWIN_THUMBRELEASE
, win
->GetScrollPos(orient
), orient
); 
2155         event
.SetEventObject(win
); 
2156         win
->GetEventHandler()->ProcessEvent(event
); 
2163 // ---------------------------------------------------------------------------- 
2164 // this wxWindowBase function is implemented here (in platform-specific file) 
2165 // because it is static and so couldn't be made virtual 
2166 // ---------------------------------------------------------------------------- 
2168 wxWindow 
*wxWindowBase::DoFindFocus() 
2170     // the cast is necessary when we compile in wxUniversal mode 
2171     return (wxWindow 
*)g_focusWindow
; 
2174 //----------------------------------------------------------------------------- 
2175 // "realize" from m_widget 
2176 //----------------------------------------------------------------------------- 
2178 /* We cannot set colours and fonts before the widget has 
2179    been realized, so we do this directly after realization. */ 
2183 gtk_window_realized_callback( GtkWidget 
*m_widget
, wxWindow 
*win 
) 
2188         wxapp_install_idle_handler(); 
2192         GtkPizza 
*pizza 
= GTK_PIZZA( m_widget 
); 
2193         gtk_im_context_set_client_window( win
->m_imData
->context
, 
2194                                           pizza
->bin_window 
); 
2197     wxWindowCreateEvent 
event( win 
); 
2198     event
.SetEventObject( win 
); 
2199     win
->GetEventHandler()->ProcessEvent( event 
); 
2203 //----------------------------------------------------------------------------- 
2205 //----------------------------------------------------------------------------- 
2209 void gtk_window_size_callback( GtkWidget 
*WXUNUSED(widget
), 
2210                                GtkAllocation 
*WXUNUSED(alloc
), 
2214         wxapp_install_idle_handler(); 
2216     int client_width 
= 0; 
2217     int client_height 
= 0; 
2218     win
->GetClientSize( &client_width
, &client_height 
); 
2219     if ((client_width 
== win
->m_oldClientWidth
) && (client_height 
== win
->m_oldClientHeight
)) 
2222     win
->m_oldClientWidth 
= client_width
; 
2223     win
->m_oldClientHeight 
= client_height
; 
2225     if (!win
->m_nativeSizeEvent
) 
2227         wxSizeEvent 
event( win
->GetSize(), win
->GetId() ); 
2228         event
.SetEventObject( win 
); 
2229         win
->GetEventHandler()->ProcessEvent( event 
); 
2236     #define WXUNUSED_UNLESS_XIM(param)  param 
2238     #define WXUNUSED_UNLESS_XIM(param)  WXUNUSED(param) 
2241 /* Resize XIM window */ 
2245 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
), 
2246                                  GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
), 
2247                                  wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) ) 
2250         wxapp_install_idle_handler(); 
2256     if  (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
) 
2260         gdk_drawable_get_size (widget
->window
, &width
, &height
); 
2261         win
->m_icattr
->preedit_area
.width 
= width
; 
2262         win
->m_icattr
->preedit_area
.height 
= height
; 
2263         gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
); 
2269 //----------------------------------------------------------------------------- 
2270 // "realize" from m_wxwindow 
2271 //----------------------------------------------------------------------------- 
2273 /* Initialize XIM support */ 
2277 gtk_wxwindow_realized_callback( GtkWidget 
* WXUNUSED_UNLESS_XIM(widget
), 
2278                                 wxWindowGTK 
* WXUNUSED_UNLESS_XIM(win
) ) 
2281         wxapp_install_idle_handler(); 
2284     if (win
->m_ic
) return; 
2285     if (!widget
) return; 
2286     if (!gdk_im_ready()) return; 
2288     win
->m_icattr 
= gdk_ic_attr_new(); 
2289     if (!win
->m_icattr
) return; 
2293     GdkColormap 
*colormap
; 
2294     GdkICAttr 
*attr 
= win
->m_icattr
; 
2295     unsigned attrmask 
= GDK_IC_ALL_REQ
; 
2297     GdkIMStyle supported_style 
= (GdkIMStyle
) 
2298                                   (GDK_IM_PREEDIT_NONE 
| 
2299                                    GDK_IM_PREEDIT_NOTHING 
| 
2300                                    GDK_IM_PREEDIT_POSITION 
| 
2301                                    GDK_IM_STATUS_NONE 
| 
2302                                    GDK_IM_STATUS_NOTHING
); 
2304     if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2305         supported_style 
= (GdkIMStyle
)(supported_style 
& ~GDK_IM_PREEDIT_POSITION
); 
2307     attr
->style 
= style 
= gdk_im_decide_style (supported_style
); 
2308     attr
->client_window 
= widget
->window
; 
2310     if ((colormap 
= gtk_widget_get_colormap (widget
)) != 
2311             gtk_widget_get_default_colormap ()) 
2313         attrmask 
|= GDK_IC_PREEDIT_COLORMAP
; 
2314         attr
->preedit_colormap 
= colormap
; 
2317     attrmask 
|= GDK_IC_PREEDIT_FOREGROUND
; 
2318     attrmask 
|= GDK_IC_PREEDIT_BACKGROUND
; 
2319     attr
->preedit_foreground 
= widget
->style
->fg
[GTK_STATE_NORMAL
]; 
2320     attr
->preedit_background 
= widget
->style
->base
[GTK_STATE_NORMAL
]; 
2322     switch (style 
& GDK_IM_PREEDIT_MASK
) 
2324         case GDK_IM_PREEDIT_POSITION
: 
2325             if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2327                 g_warning ("over-the-spot style requires fontset"); 
2331             gdk_drawable_get_size (widget
->window
, &width
, &height
); 
2333             attrmask 
|= GDK_IC_PREEDIT_POSITION_REQ
; 
2334             attr
->spot_location
.x 
= 0; 
2335             attr
->spot_location
.y 
= height
; 
2336             attr
->preedit_area
.x 
= 0; 
2337             attr
->preedit_area
.y 
= 0; 
2338             attr
->preedit_area
.width 
= width
; 
2339             attr
->preedit_area
.height 
= height
; 
2340             attr
->preedit_fontset 
= widget
->style
->font
; 
2345       win
->m_ic 
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
); 
2347       if (win
->m_ic 
== NULL
) 
2348           g_warning ("Can't create input context."); 
2351           mask 
= gdk_window_get_events (widget
->window
); 
2352           mask 
= (GdkEventMask
)(mask 
| gdk_ic_get_events (win
->m_ic
)); 
2353           gdk_window_set_events (widget
->window
, mask
); 
2355           if (GTK_WIDGET_HAS_FOCUS(widget
)) 
2356               gdk_im_begin (win
->m_ic
, widget
->window
); 
2362 //----------------------------------------------------------------------------- 
2363 // InsertChild for wxWindowGTK. 
2364 //----------------------------------------------------------------------------- 
2366 /* Callback for wxWindowGTK. This very strange beast has to be used because 
2367  * C++ has no virtual methods in a constructor. We have to emulate a 
2368  * virtual function here as wxNotebook requires a different way to insert 
2369  * a child in it. I had opted for creating a wxNotebookPage window class 
2370  * which would have made this superfluous (such in the MDI window system), 
2371  * but no-one was listening to me... */ 
2373 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child 
) 
2375     /* the window might have been scrolled already, do we 
2376        have to adapt the position */ 
2377     GtkPizza 
*pizza 
= GTK_PIZZA(parent
->m_wxwindow
); 
2378     child
->m_x 
+= pizza
->xoffset
; 
2379     child
->m_y 
+= pizza
->yoffset
; 
2381     gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
), 
2382                      GTK_WIDGET(child
->m_widget
), 
2389 //----------------------------------------------------------------------------- 
2391 //----------------------------------------------------------------------------- 
2393 wxWindow 
*wxGetActiveWindow() 
2395     return wxWindow::FindFocus(); 
2399 wxMouseState 
wxGetMouseState() 
2405     GdkModifierType mask
; 
2407     gdk_window_get_pointer(NULL
, &x
, &y
, &mask
); 
2411     ms
.SetLeftDown(mask 
& GDK_BUTTON1_MASK
); 
2412     ms
.SetMiddleDown(mask 
& GDK_BUTTON2_MASK
); 
2413     ms
.SetRightDown(mask 
& GDK_BUTTON3_MASK
); 
2415     ms
.SetControlDown(mask 
& GDK_CONTROL_MASK
); 
2416     ms
.SetShiftDown(mask 
& GDK_SHIFT_MASK
); 
2417     ms
.SetAltDown(mask 
& GDK_MOD1_MASK
); 
2418     ms
.SetMetaDown(mask 
& GDK_MOD2_MASK
); 
2423 //----------------------------------------------------------------------------- 
2425 //----------------------------------------------------------------------------- 
2427 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
2429 #ifdef __WXUNIVERSAL__ 
2430     IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
) 
2432     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
2433 #endif // __WXUNIVERSAL__/__WXGTK__ 
2435 void wxWindowGTK::Init() 
2438     m_widget 
= (GtkWidget 
*) NULL
; 
2439     m_wxwindow 
= (GtkWidget 
*) NULL
; 
2440     m_focusWidget 
= (GtkWidget 
*) NULL
; 
2450     m_needParent 
= true; 
2451     m_isBeingDeleted 
= false; 
2454     m_nativeSizeEvent 
= false; 
2456     m_hasScrolling 
= false; 
2457     m_isScrolling 
= false; 
2458     m_mouseButtonDown 
= false; 
2459     m_blockScrollEvent 
= false; 
2462     m_scrollBar
[1] = NULL
; 
2467     m_oldClientHeight 
= 0; 
2471     m_insertCallback 
= (wxInsertChildFunction
) NULL
; 
2473     m_acceptsFocus 
= false; 
2476     m_clipPaintRegion 
= false; 
2478     m_needsStyleChange 
= false; 
2480     m_cursor 
= *wxSTANDARD_CURSOR
; 
2483     m_dirtyTabOrder 
= false; 
2486 wxWindowGTK::wxWindowGTK() 
2491 wxWindowGTK::wxWindowGTK( wxWindow 
*parent
, 
2496                           const wxString 
&name  
) 
2500     Create( parent
, id
, pos
, size
, style
, name 
); 
2503 bool wxWindowGTK::Create( wxWindow 
*parent
, 
2508                           const wxString 
&name  
) 
2510     if (!PreCreation( parent
, pos
, size 
) || 
2511         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
2513         wxFAIL_MSG( wxT("wxWindowGTK creation failed") ); 
2517     m_insertCallback 
= wxInsertChildInWindow
; 
2519     m_widget 
= gtk_scrolled_window_new( (GtkAdjustment 
*) NULL
, (GtkAdjustment 
*) NULL 
); 
2520     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
2522     GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
2524     GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2525     scroll_class
->scrollbar_spacing 
= 0; 
2527     gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
2529     m_scrollBar
[0] = GTK_RANGE(scrolledWindow
->hscrollbar
); 
2530     m_scrollBar
[1] = GTK_RANGE(scrolledWindow
->vscrollbar
); 
2532     m_wxwindow 
= gtk_pizza_new(); 
2534 #ifndef __WXUNIVERSAL__ 
2535     GtkPizza 
*pizza 
= GTK_PIZZA(m_wxwindow
); 
2537     if (HasFlag(wxRAISED_BORDER
)) 
2539         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT 
); 
2541     else if (HasFlag(wxSUNKEN_BORDER
)) 
2543         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN 
); 
2545     else if (HasFlag(wxSIMPLE_BORDER
)) 
2547         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN 
); 
2551         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE 
); 
2553 #endif // __WXUNIVERSAL__ 
2555     gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
2557     GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
2558     m_acceptsFocus 
= true; 
2560     // these handlers block mouse events to any window during scrolling such as 
2561     // motion events and prevent GTK and wxWidgets from fighting over where the 
2563     g_signal_connect(m_scrollBar
[0], "button_press_event", 
2564                      G_CALLBACK(gtk_scrollbar_button_press_event
), this); 
2565     g_signal_connect(m_scrollBar
[1], "button_press_event", 
2566                      G_CALLBACK(gtk_scrollbar_button_press_event
), this); 
2567     g_signal_connect(m_scrollBar
[0], "button_release_event", 
2568                      G_CALLBACK(gtk_scrollbar_button_release_event
), this); 
2569     g_signal_connect(m_scrollBar
[1], "button_release_event", 
2570                      G_CALLBACK(gtk_scrollbar_button_release_event
), this); 
2572     // these handlers get notified when scrollbar slider moves 
2574     g_signal_connect(m_scrollBar
[0], "value_changed", 
2575                      G_CALLBACK(gtk_scrollbar_value_changed
), this); 
2576     g_signal_connect(m_scrollBar
[1], "value_changed", 
2577                      G_CALLBACK(gtk_scrollbar_value_changed
), this); 
2579     gtk_widget_show( m_wxwindow 
); 
2582         m_parent
->DoAddChild( this ); 
2584     m_focusWidget 
= m_wxwindow
; 
2591 wxWindowGTK::~wxWindowGTK() 
2595     if (g_focusWindow 
== this) 
2596         g_focusWindow 
= NULL
; 
2598     if ( g_delayedFocus 
== this ) 
2599         g_delayedFocus 
= NULL
; 
2601     m_isBeingDeleted 
= true; 
2604     // destroy children before destroying this window itself 
2607     // unhook focus handlers to prevent stray events being 
2608     // propagated to this (soon to be) dead object 
2609     if (m_focusWidget 
!= NULL
) 
2611         g_signal_handlers_disconnect_by_func (m_focusWidget
, 
2612                                               (gpointer
) gtk_window_focus_in_callback
, 
2614         g_signal_handlers_disconnect_by_func (m_focusWidget
, 
2615                                               (gpointer
) gtk_window_focus_out_callback
, 
2624         gdk_ic_destroy (m_ic
); 
2626         gdk_ic_attr_destroy (m_icattr
); 
2629     // delete before the widgets to avoid a crash on solaris 
2634         gtk_widget_destroy( m_wxwindow 
); 
2635         m_wxwindow 
= (GtkWidget
*) NULL
; 
2640         gtk_widget_destroy( m_widget 
); 
2641         m_widget 
= (GtkWidget
*) NULL
; 
2645 bool wxWindowGTK::PreCreation( wxWindowGTK 
*parent
, const wxPoint 
&pos
,  const wxSize 
&size 
) 
2647     wxCHECK_MSG( !m_needParent 
|| parent
, false, wxT("Need complete parent.") ); 
2649     // Use either the given size, or the default if -1 is given. 
2650     // See wxWindowBase for these functions. 
2651     m_width 
= WidthDefault(size
.x
) ; 
2652     m_height 
= HeightDefault(size
.y
); 
2660 void wxWindowGTK::PostCreation() 
2662     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2668             // these get reported to wxWidgets -> wxPaintEvent 
2670             gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE 
); 
2672             g_signal_connect (m_wxwindow
, "expose_event", 
2673                               G_CALLBACK (gtk_window_expose_callback
), this); 
2675             gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow
), HasFlag( wxFULL_REPAINT_ON_RESIZE 
) ); 
2678         // Create input method handler 
2679         m_imData 
= new wxGtkIMData
; 
2681         // Cannot handle drawing preedited text yet 
2682         gtk_im_context_set_use_preedit( m_imData
->context
, FALSE 
); 
2684         g_signal_connect (m_imData
->context
, "commit", 
2685                           G_CALLBACK (gtk_wxwindow_commit_cb
), this); 
2687         // these are called when the "sunken" or "raised" borders are drawn 
2688         g_signal_connect (m_widget
, "expose_event", 
2689                           G_CALLBACK (gtk_window_own_expose_callback
), this); 
2694     if (!GTK_IS_WINDOW(m_widget
)) 
2696         if (m_focusWidget 
== NULL
) 
2697             m_focusWidget 
= m_widget
; 
2701             g_signal_connect (m_focusWidget
, "focus_in_event", 
2702                           G_CALLBACK (gtk_window_focus_in_callback
), this); 
2703             g_signal_connect (m_focusWidget
, "focus_out_event", 
2704                                 G_CALLBACK (gtk_window_focus_out_callback
), this); 
2708             g_signal_connect_after (m_focusWidget
, "focus_in_event", 
2709                           G_CALLBACK (gtk_window_focus_in_callback
), this); 
2710             g_signal_connect_after (m_focusWidget
, "focus_out_event", 
2711                                 G_CALLBACK (gtk_window_focus_out_callback
), this); 
2715     // connect to the various key and mouse handlers 
2717     GtkWidget 
*connect_widget 
= GetConnectWidget(); 
2719     ConnectWidget( connect_widget 
); 
2721     /* We cannot set colours, fonts and cursors before the widget has 
2722        been realized, so we do this directly after realization */ 
2723     g_signal_connect (connect_widget
, "realize", 
2724                       G_CALLBACK (gtk_window_realized_callback
), this); 
2728         // Catch native resize events 
2729         g_signal_connect (m_wxwindow
, "size_allocate", 
2730                           G_CALLBACK (gtk_window_size_callback
), this); 
2732         // Initialize XIM support 
2733         g_signal_connect (m_wxwindow
, "realize", 
2734                           G_CALLBACK (gtk_wxwindow_realized_callback
), this); 
2736         // And resize XIM window 
2737         g_signal_connect (m_wxwindow
, "size_allocate", 
2738                           G_CALLBACK (gtk_wxwindow_size_callback
), this); 
2741     if (GTK_IS_COMBO(m_widget
)) 
2743         GtkCombo 
*gcombo 
= GTK_COMBO(m_widget
); 
2745         g_signal_connect (gcombo
->entry
, "size_request", 
2746                           G_CALLBACK (wxgtk_combo_size_request_callback
), 
2749     else if (GTK_IS_FILE_CHOOSER_BUTTON(m_widget
)) 
2751         // FIXME: what should be done here ? 
2755         // This is needed if we want to add our windows into native 
2756         // GTK controls, such as the toolbar. With this callback, the 
2757         // toolbar gets to know the correct size (the one set by the 
2758         // programmer). Sadly, it misbehaves for wxComboBox. 
2759         g_signal_connect (m_widget
, "size_request", 
2760                           G_CALLBACK (wxgtk_window_size_request_callback
), 
2764     InheritAttributes(); 
2768     // unless the window was created initially hidden (i.e. Hide() had been 
2769     // called before Create()), we should show it at GTK+ level as well 
2771         gtk_widget_show( m_widget 
); 
2774 void wxWindowGTK::ConnectWidget( GtkWidget 
*widget 
) 
2776     g_signal_connect (widget
, "key_press_event", 
2777                       G_CALLBACK (gtk_window_key_press_callback
), this); 
2778     g_signal_connect (widget
, "key_release_event", 
2779                       G_CALLBACK (gtk_window_key_release_callback
), this); 
2780     g_signal_connect (widget
, "button_press_event", 
2781                       G_CALLBACK (gtk_window_button_press_callback
), this); 
2782     g_signal_connect (widget
, "button_release_event", 
2783                       G_CALLBACK (gtk_window_button_release_callback
), this); 
2784     g_signal_connect (widget
, "motion_notify_event", 
2785                       G_CALLBACK (gtk_window_motion_notify_callback
), this); 
2786     g_signal_connect (widget
, "scroll_event", 
2787                       G_CALLBACK (window_scroll_event
), this); 
2788     g_signal_connect (widget
, "popup_menu", 
2789                      G_CALLBACK (wxgtk_window_popup_menu_callback
), this); 
2790     g_signal_connect (widget
, "enter_notify_event", 
2791                       G_CALLBACK (gtk_window_enter_callback
), this); 
2792     g_signal_connect (widget
, "leave_notify_event", 
2793                       G_CALLBACK (gtk_window_leave_callback
), this); 
2796 bool wxWindowGTK::Destroy() 
2798     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2802     return wxWindowBase::Destroy(); 
2805 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
) 
2807     gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height 
); 
2810 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
2812     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2813     wxASSERT_MSG( (m_parent 
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") ); 
2816     printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height ); 
2819     if (m_resizing
) return; /* I don't like recursions */ 
2822     int currentX
, currentY
; 
2823     GetPosition(¤tX
, ¤tY
); 
2824     if (x 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
2826     if (y 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
2828     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
2830     // calculate the best size if we should auto size the window 
2831     if ( ((sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1) || 
2832          ((sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1) ) 
2834         const wxSize sizeBest 
= GetBestSize(); 
2835         if ( (sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1 ) 
2837         if ( (sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1 ) 
2838             height 
= sizeBest
.y
; 
2846     int minWidth  
= GetMinWidth(), 
2847         minHeight 
= GetMinHeight(), 
2848         maxWidth  
= GetMaxWidth(), 
2849         maxHeight 
= GetMaxHeight(); 
2851     if ((minWidth  
!= -1) && (m_width  
< minWidth 
)) m_width  
= minWidth
; 
2852     if ((minHeight 
!= -1) && (m_height 
< minHeight
)) m_height 
= minHeight
; 
2853     if ((maxWidth  
!= -1) && (m_width  
> maxWidth 
)) m_width  
= maxWidth
; 
2854     if ((maxHeight 
!= -1) && (m_height 
> maxHeight
)) m_height 
= maxHeight
; 
2856 #if wxUSE_TOOLBAR_NATIVE 
2857     if (wxDynamicCast(GetParent(), wxToolBar
)) 
2859        // don't take the x,y values, they're wrong because toolbar sets them 
2860        GtkWidget  
*widget 
= GTK_WIDGET(m_widget
); 
2861        gtk_widget_set_size_request (widget
, m_width
, m_height
); 
2862        if (GTK_WIDGET_VISIBLE (widget
)) 
2863             gtk_widget_queue_resize (widget
); 
2867     if (m_parent
->m_wxwindow 
== NULL
) // i.e. wxNotebook 
2869         // don't set the size for children of wxNotebook, just take the values. 
2877         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
2878         if ((sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) == 0) 
2880             if (x 
!= -1) m_x 
= x 
+ pizza
->xoffset
; 
2881             if (y 
!= -1) m_y 
= y 
+ pizza
->yoffset
; 
2885             m_x 
= x 
+ pizza
->xoffset
; 
2886             m_y 
= y 
+ pizza
->yoffset
; 
2889         int left_border 
= 0; 
2890         int right_border 
= 0; 
2892         int bottom_border 
= 0; 
2894         /* the default button has a border around it */ 
2895         if (GTK_WIDGET_CAN_DEFAULT(m_widget
)) 
2897             GtkBorder 
*default_border 
= NULL
; 
2898             gtk_widget_style_get( m_widget
, "default_border", &default_border
, NULL 
); 
2901                 left_border 
+= default_border
->left
; 
2902                 right_border 
+= default_border
->right
; 
2903                 top_border 
+= default_border
->top
; 
2904                 bottom_border 
+= default_border
->bottom
; 
2905                 g_free( default_border 
); 
2909         DoMoveWindow( m_x
-top_border
, 
2911                       m_width
+left_border
+right_border
, 
2912                       m_height
+top_border
+bottom_border 
); 
2917         /* Sometimes the client area changes size without the 
2918            whole windows's size changing, but if the whole 
2919            windows's size doesn't change, no wxSizeEvent will 
2920            normally be sent. Here we add an extra test if 
2921            the client test has been changed and this will 
2923         GetClientSize( &m_oldClientWidth
, &m_oldClientHeight 
); 
2927     wxPrintf( "OnSize sent from " ); 
2928     if (GetClassInfo() && GetClassInfo()->GetClassName()) 
2929         wxPrintf( GetClassInfo()->GetClassName() ); 
2930     wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height ); 
2933     if (!m_nativeSizeEvent
) 
2935         wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
2936         event
.SetEventObject( this ); 
2937         GetEventHandler()->ProcessEvent( event 
); 
2943 void wxWindowGTK::OnInternalIdle() 
2945     if ( m_dirtyTabOrder 
) 
2947         m_dirtyTabOrder 
= false; 
2951     // Update style if the window was not yet realized 
2952     // and SetBackgroundStyle(wxBG_STYLE_CUSTOM) was called 
2953     if (m_needsStyleChange
) 
2955         SetBackgroundStyle(GetBackgroundStyle()); 
2956         m_needsStyleChange 
= false; 
2959     // Update invalidated regions. 
2962     wxCursor cursor 
= m_cursor
; 
2963     if (g_globalCursor
.Ok()) cursor 
= g_globalCursor
; 
2967         /* I now set the cursor anew in every OnInternalIdle call 
2968            as setting the cursor in a parent window also effects the 
2969            windows above so that checking for the current cursor is 
2974             GdkWindow 
*window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
2976                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2978             if (!g_globalCursor
.Ok()) 
2979                 cursor 
= *wxSTANDARD_CURSOR
; 
2981             window 
= m_widget
->window
; 
2982             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
2983                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2989             GdkWindow 
*window 
= m_widget
->window
; 
2990             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
2991                gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2996     if (wxUpdateUIEvent::CanUpdate(this)) 
2997         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
3000 void wxWindowGTK::DoGetSize( int *width
, int *height 
) const 
3002     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3004     if (width
) (*width
) = m_width
; 
3005     if (height
) (*height
) = m_height
; 
3008 void wxWindowGTK::DoSetClientSize( int width
, int height 
) 
3010     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3019             GetScrollbarWidth(m_widget
, dw
, dh
); 
3022 #ifndef __WXUNIVERSAL__ 
3023         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
3025             // shadow border size is 2 
3029         if (HasFlag(wxSIMPLE_BORDER
)) 
3031             // simple border size is 1 
3035 #endif // __WXUNIVERSAL__ 
3041     SetSize(width
, height
); 
3044 void wxWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
3046     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3058             GetScrollbarWidth(m_widget
, dw
, dh
); 
3061 #ifndef __WXUNIVERSAL__ 
3062         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
3064             // shadow border size is 2 
3068         if (HasFlag(wxSIMPLE_BORDER
)) 
3070             // simple border size is 1 
3074 #endif // __WXUNIVERSAL__ 
3080     if (width
) *width 
= w
; 
3081     if (height
) *height 
= h
; 
3084 void wxWindowGTK::DoGetPosition( int *x
, int *y 
) const 
3086     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3090     if (m_parent 
&& m_parent
->m_wxwindow
) 
3092         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
3093         dx 
= pizza
->xoffset
; 
3094         dy 
= pizza
->yoffset
; 
3097     if (x
) (*x
) = m_x 
- dx
; 
3098     if (y
) (*y
) = m_y 
- dy
; 
3101 void wxWindowGTK::DoClientToScreen( int *x
, int *y 
) const 
3103     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3105     if (!m_widget
->window
) return; 
3107     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3109         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3111         source 
= m_widget
->window
; 
3115     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3119         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3121             org_x 
+= m_widget
->allocation
.x
; 
3122             org_y 
+= m_widget
->allocation
.y
; 
3130 void wxWindowGTK::DoScreenToClient( int *x
, int *y 
) const 
3132     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3134     if (!m_widget
->window
) return; 
3136     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3138         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3140         source 
= m_widget
->window
; 
3144     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3148         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3150             org_x 
+= m_widget
->allocation
.x
; 
3151             org_y 
+= m_widget
->allocation
.y
; 
3159 bool wxWindowGTK::Show( bool show 
) 
3161     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3163     if (!wxWindowBase::Show(show
)) 
3170         gtk_widget_show( m_widget 
); 
3172         gtk_widget_hide( m_widget 
); 
3174     wxShowEvent 
eventShow(GetId(), show
); 
3175     eventShow
.SetEventObject(this); 
3177     GetEventHandler()->ProcessEvent(eventShow
); 
3182 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
) 
3184     win
->OnParentEnable(enable
); 
3186     // Recurse, so that children have the opportunity to Do The Right Thing 
3187     // and reset colours that have been messed up by a parent's (really ancestor's) 
3189     for ( wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
3191           node 
= node
->GetNext() ) 
3193         wxWindow 
*child 
= node
->GetData(); 
3194         if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
))) 
3195             wxWindowNotifyEnable(child
, enable
); 
3199 bool wxWindowGTK::Enable( bool enable 
) 
3201     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3203     if (!wxWindowBase::Enable(enable
)) 
3209     gtk_widget_set_sensitive( m_widget
, enable 
); 
3211         gtk_widget_set_sensitive( m_wxwindow
, enable 
); 
3213     wxWindowNotifyEnable(this, enable
); 
3218 int wxWindowGTK::GetCharHeight() const 
3220     wxCHECK_MSG( (m_widget 
!= NULL
), 12, wxT("invalid window") ); 
3222     wxFont font 
= GetFont(); 
3223     wxCHECK_MSG( font
.Ok(), 12, wxT("invalid font") ); 
3225     PangoContext 
*context 
= NULL
; 
3227         context 
= gtk_widget_get_pango_context( m_widget 
); 
3232     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
3233     PangoLayout 
*layout 
= pango_layout_new(context
); 
3234     pango_layout_set_font_description(layout
, desc
); 
3235     pango_layout_set_text(layout
, "H", 1); 
3236     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
3238     PangoRectangle rect
; 
3239     pango_layout_line_get_extents(line
, NULL
, &rect
); 
3241     g_object_unref (layout
); 
3243     return (int) PANGO_PIXELS(rect
.height
); 
3246 int wxWindowGTK::GetCharWidth() const 
3248     wxCHECK_MSG( (m_widget 
!= NULL
), 8, wxT("invalid window") ); 
3250     wxFont font 
= GetFont(); 
3251     wxCHECK_MSG( font
.Ok(), 8, wxT("invalid font") ); 
3253     PangoContext 
*context 
= NULL
; 
3255         context 
= gtk_widget_get_pango_context( m_widget 
); 
3260     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
3261     PangoLayout 
*layout 
= pango_layout_new(context
); 
3262     pango_layout_set_font_description(layout
, desc
); 
3263     pango_layout_set_text(layout
, "g", 1); 
3264     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
3266     PangoRectangle rect
; 
3267     pango_layout_line_get_extents(line
, NULL
, &rect
); 
3269     g_object_unref (layout
); 
3271     return (int) PANGO_PIXELS(rect
.width
); 
3274 void wxWindowGTK::GetTextExtent( const wxString
& string
, 
3278                                  int *externalLeading
, 
3279                                  const wxFont 
*theFont 
) const 
3281     wxFont fontToUse 
= theFont 
? *theFont 
: GetFont(); 
3283     wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") ); 
3292     PangoContext 
*context 
= NULL
; 
3294         context 
= gtk_widget_get_pango_context( m_widget 
); 
3303     PangoFontDescription 
*desc 
= fontToUse
.GetNativeFontInfo()->description
; 
3304     PangoLayout 
*layout 
= pango_layout_new(context
); 
3305     pango_layout_set_font_description(layout
, desc
); 
3307         const wxCharBuffer data 
= wxGTK_CONV( string 
); 
3309             pango_layout_set_text(layout
, data
, strlen(data
)); 
3312     PangoRectangle rect
; 
3313     pango_layout_get_extents(layout
, NULL
, &rect
); 
3315     if (x
) (*x
) = (wxCoord
) PANGO_PIXELS(rect
.width
); 
3316     if (y
) (*y
) = (wxCoord
) PANGO_PIXELS(rect
.height
); 
3319         PangoLayoutIter 
*iter 
= pango_layout_get_iter(layout
); 
3320         int baseline 
= pango_layout_iter_get_baseline(iter
); 
3321         pango_layout_iter_free(iter
); 
3322         *descent 
= *y 
- PANGO_PIXELS(baseline
); 
3324     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3326     g_object_unref (layout
); 
3329 void wxWindowGTK::SetFocus() 
3331     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3334         // don't do anything if we already have focus 
3340         if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
)) 
3342             gtk_widget_grab_focus (m_wxwindow
); 
3347         if (GTK_IS_CONTAINER(m_widget
)) 
3349             gtk_widget_child_focus( m_widget
, GTK_DIR_TAB_FORWARD 
); 
3352         if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) ) 
3355             if (!GTK_WIDGET_REALIZED(m_widget
)) 
3357                 // we can't set the focus to the widget now so we remember that 
3358                 // it should be focused and will do it later, during the idle 
3359                 // time, as soon as we can 
3360                 wxLogTrace(TRACE_FOCUS
, 
3361                            _T("Delaying setting focus to %s(%s)"), 
3362                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3364                 g_delayedFocus 
= this; 
3368                 wxLogTrace(TRACE_FOCUS
, 
3369                            _T("Setting focus to %s(%s)"), 
3370                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3372                 gtk_widget_grab_focus (m_widget
); 
3377            wxLogTrace(TRACE_FOCUS
, 
3378                       _T("Can't set focus to %s(%s)"), 
3379                       GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3384 bool wxWindowGTK::AcceptsFocus() const 
3386     return m_acceptsFocus 
&& wxWindowBase::AcceptsFocus(); 
3389 bool wxWindowGTK::Reparent( wxWindowBase 
*newParentBase 
) 
3391     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3393     wxWindowGTK 
*oldParent 
= m_parent
, 
3394              *newParent 
= (wxWindowGTK 
*)newParentBase
; 
3396     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3398     if ( !wxWindowBase::Reparent(newParent
) ) 
3401     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3403     /* prevent GTK from deleting the widget arbitrarily */ 
3404     gtk_widget_ref( m_widget 
); 
3408         gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget 
); 
3411     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3415         /* insert GTK representation */ 
3416         (*(newParent
->m_insertCallback
))(newParent
, this); 
3419     /* reverse: prevent GTK from deleting the widget arbitrarily */ 
3420     gtk_widget_unref( m_widget 
); 
3425 void wxWindowGTK::DoAddChild(wxWindowGTK 
*child
) 
3427     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3429     wxASSERT_MSG( (child 
!= NULL
), wxT("invalid child window") ); 
3431     wxASSERT_MSG( (m_insertCallback 
!= NULL
), wxT("invalid child insertion function") ); 
3436     /* insert GTK representation */ 
3437     (*m_insertCallback
)(this, child
); 
3440 void wxWindowGTK::AddChild(wxWindowBase 
*child
) 
3442     wxWindowBase::AddChild(child
); 
3443     m_dirtyTabOrder 
= true; 
3445         wxapp_install_idle_handler(); 
3448 void wxWindowGTK::RemoveChild(wxWindowBase 
*child
) 
3450     wxWindowBase::RemoveChild(child
); 
3451     m_dirtyTabOrder 
= true; 
3453         wxapp_install_idle_handler(); 
3456 void wxWindowGTK::DoMoveInTabOrder(wxWindow 
*win
, MoveKind move
) 
3458     wxWindowBase::DoMoveInTabOrder(win
, move
); 
3459     m_dirtyTabOrder 
= true; 
3461         wxapp_install_idle_handler(); 
3464 bool wxWindowGTK::GTKWidgetNeedsMnemonic() const 
3466     // none needed by default 
3470 void wxWindowGTK::GTKWidgetDoSetMnemonic(GtkWidget
* WXUNUSED(w
)) 
3472     // nothing to do by default since none is needed 
3475 void wxWindowGTK::RealizeTabOrder() 
3479         if ( !m_children
.empty() ) 
3481             // we don't only construct the correct focus chain but also use 
3482             // this opportunity to update the mnemonic widgets for the widgets 
3485             GList 
*chain 
= NULL
; 
3486             wxWindowGTK
* mnemonicWindow 
= NULL
; 
3488             for ( wxWindowList::const_iterator i 
= m_children
.begin(); 
3489                   i 
!= m_children
.end(); 
3492                 wxWindowGTK 
*win 
= *i
; 
3494                 if ( mnemonicWindow 
) 
3496                     if ( win
->AcceptsFocusFromKeyboard() ) 
3498                         // wxComboBox et al. needs to focus on on a different 
3499                         // widget than m_widget, so if the main widget isn't 
3500                         // focusable try the connect widget 
3501                         GtkWidget
* w 
= win
->m_widget
; 
3502                         if ( !GTK_WIDGET_CAN_FOCUS(w
) ) 
3504                             w 
= win
->GetConnectWidget(); 
3505                             if ( !GTK_WIDGET_CAN_FOCUS(w
) ) 
3511                             mnemonicWindow
->GTKWidgetDoSetMnemonic(w
); 
3512                             mnemonicWindow 
= NULL
; 
3516                 else if ( win
->GTKWidgetNeedsMnemonic() ) 
3518                     mnemonicWindow 
= win
; 
3521                 chain 
= g_list_prepend(chain
, win
->m_widget
); 
3524             chain 
= g_list_reverse(chain
); 
3526             gtk_container_set_focus_chain(GTK_CONTAINER(m_wxwindow
), chain
); 
3531             gtk_container_unset_focus_chain(GTK_CONTAINER(m_wxwindow
)); 
3536 void wxWindowGTK::Raise() 
3538     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3540     if (m_wxwindow 
&& m_wxwindow
->window
) 
3542         gdk_window_raise( m_wxwindow
->window 
); 
3544     else if (m_widget
->window
) 
3546         gdk_window_raise( m_widget
->window 
); 
3550 void wxWindowGTK::Lower() 
3552     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3554     if (m_wxwindow 
&& m_wxwindow
->window
) 
3556         gdk_window_lower( m_wxwindow
->window 
); 
3558     else if (m_widget
->window
) 
3560         gdk_window_lower( m_widget
->window 
); 
3564 bool wxWindowGTK::SetCursor( const wxCursor 
&cursor 
) 
3566     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3568     if (cursor 
== m_cursor
) 
3572         wxapp_install_idle_handler(); 
3574     if (cursor 
== wxNullCursor
) 
3575        return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR 
); 
3577        return wxWindowBase::SetCursor( cursor 
); 
3580 void wxWindowGTK::WarpPointer( int x
, int y 
) 
3582     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3584     // We provide this function ourselves as it is 
3585     // missing in GDK (top of this file). 
3587     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3589         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3591         window 
= GetConnectWidget()->window
; 
3594         gdk_window_warp_pointer( window
, x
, y 
); 
3597 bool wxWindowGTK::ScrollLines(int lines
) 
3599     bool changed 
= false; 
3600     GtkRange
* range 
= m_scrollBar
[1]; 
3603         GtkAdjustment
* adj 
= range
->adjustment
; 
3604         const int pos 
= int(adj
->value 
+ 0.5); 
3605         gtk_range_set_value(range
, pos 
+ lines
); 
3606         changed 
= pos 
!= int(adj
->value 
+ 0.5); 
3611 bool wxWindowGTK::ScrollPages(int pages
) 
3613     bool changed 
= false; 
3614     GtkRange
* range 
= m_scrollBar
[1]; 
3617         GtkAdjustment
* adj 
= range
->adjustment
; 
3618         const int pos 
= int(adj
->value 
+ 0.5); 
3619         gtk_range_set_value(range
, pos 
+ pages 
* adj
->page_size
); 
3620         changed 
= pos 
!= int(adj
->value 
+ 0.5); 
3625 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect 
*rect 
) 
3629     if (!m_widget
->window
) 
3634         GdkRectangle gdk_rect
, 
3638             gdk_rect
.x 
= rect
->x
; 
3639             gdk_rect
.y 
= rect
->y
; 
3640             gdk_rect
.width 
= rect
->width
; 
3641             gdk_rect
.height 
= rect
->height
; 
3644         else // invalidate everything 
3649         gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, p
, TRUE 
); 
3653 void wxWindowGTK::Update() 
3657     // when we call Update() we really want to update the window immediately on 
3658     // screen, even if it means flushing the entire queue and hence slowing down 
3659     // everything -- but it should still be done, it's just that Update() should 
3660     // be called very rarely 
3664 void wxWindowGTK::GtkUpdate() 
3666     if (m_wxwindow 
&& GTK_PIZZA(m_wxwindow
)->bin_window
) 
3667         gdk_window_process_updates( GTK_PIZZA(m_wxwindow
)->bin_window
, FALSE 
); 
3669     // for consistency with other platforms (and also because it's convenient 
3670     // to be able to update an entire TLW by calling Update() only once), we 
3671     // should also update all our children here 
3672     for ( wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
3674           node 
= node
->GetNext() ) 
3676         node
->GetData()->GtkUpdate(); 
3680 void wxWindowGTK::GtkSendPaintEvents() 
3684         m_updateRegion
.Clear(); 
3688     // Clip to paint region in wxClientDC 
3689     m_clipPaintRegion 
= true; 
3691     // widget to draw on 
3692     GtkPizza 
*pizza 
= GTK_PIZZA (m_wxwindow
); 
3694     if (GetThemeEnabled() && (GetBackgroundStyle() == wxBG_STYLE_SYSTEM
)) 
3696         // find ancestor from which to steal background 
3697         wxWindow 
*parent 
= wxGetTopLevelParent((wxWindow 
*)this); 
3699             parent 
= (wxWindow
*)this; 
3701         if (GTK_WIDGET_MAPPED(parent
->m_widget
)) 
3703             wxRegionIterator 
upd( m_updateRegion 
); 
3707                 rect
.x 
= upd
.GetX(); 
3708                 rect
.y 
= upd
.GetY(); 
3709                 rect
.width 
= upd
.GetWidth(); 
3710                 rect
.height 
= upd
.GetHeight(); 
3712                 gtk_paint_flat_box( parent
->m_widget
->style
, 
3714                             (GtkStateType
)GTK_WIDGET_STATE(m_wxwindow
), 
3728         wxWindowDC 
dc( (wxWindow
*)this ); 
3729         dc
.SetClippingRegion( m_updateRegion 
); 
3731         wxEraseEvent 
erase_event( GetId(), &dc 
); 
3732         erase_event
.SetEventObject( this ); 
3734         GetEventHandler()->ProcessEvent(erase_event
); 
3737     wxNcPaintEvent 
nc_paint_event( GetId() ); 
3738     nc_paint_event
.SetEventObject( this ); 
3739     GetEventHandler()->ProcessEvent( nc_paint_event 
); 
3741     wxPaintEvent 
paint_event( GetId() ); 
3742     paint_event
.SetEventObject( this ); 
3743     GetEventHandler()->ProcessEvent( paint_event 
); 
3745     m_clipPaintRegion 
= false; 
3747     m_updateRegion
.Clear(); 
3750 void wxWindowGTK::SetDoubleBuffered( bool on 
) 
3752     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3755         gtk_widget_set_double_buffered( m_wxwindow
, on 
); 
3758 void wxWindowGTK::ClearBackground() 
3760     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3764 void wxWindowGTK::DoSetToolTip( wxToolTip 
*tip 
) 
3766     wxWindowBase::DoSetToolTip(tip
); 
3769         m_tooltip
->Apply( (wxWindow 
*)this ); 
3772 void wxWindowGTK::ApplyToolTip( GtkTooltips 
*tips
, const wxChar 
*tip 
) 
3774     wxString 
tmp( tip 
); 
3775     gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxGTK_CONV(tmp
), (gchar
*) NULL 
); 
3777 #endif // wxUSE_TOOLTIPS 
3779 bool wxWindowGTK::SetBackgroundColour( const wxColour 
&colour 
) 
3781     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3783     if (!wxWindowBase::SetBackgroundColour(colour
)) 
3788         // We need the pixel value e.g. for background clearing. 
3789         m_backgroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
3792     // apply style change (forceStyle=true so that new style is applied 
3793     // even if the bg colour changed from valid to wxNullColour) 
3794     if (GetBackgroundStyle() != wxBG_STYLE_CUSTOM
) 
3795         ApplyWidgetStyle(true); 
3800 bool wxWindowGTK::SetForegroundColour( const wxColour 
&colour 
) 
3802     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3804     if (!wxWindowBase::SetForegroundColour(colour
)) 
3811         // We need the pixel value e.g. for background clearing. 
3812         m_foregroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
3815     // apply style change (forceStyle=true so that new style is applied 
3816     // even if the bg colour changed from valid to wxNullColour): 
3817     ApplyWidgetStyle(true); 
3822 PangoContext 
*wxWindowGTK::GtkGetPangoDefaultContext() 
3824     return gtk_widget_get_pango_context( m_widget 
); 
3827 GtkRcStyle 
*wxWindowGTK::CreateWidgetStyle(bool forceStyle
) 
3829     // do we need to apply any changes at all? 
3832          !m_foregroundColour
.Ok() && !m_backgroundColour
.Ok() ) 
3837     GtkRcStyle 
*style 
= gtk_rc_style_new(); 
3842             pango_font_description_copy( m_font
.GetNativeFontInfo()->description 
); 
3845     if ( m_foregroundColour
.Ok() ) 
3847         GdkColor 
*fg 
= m_foregroundColour
.GetColor(); 
3849         style
->fg
[GTK_STATE_NORMAL
] = *fg
; 
3850         style
->color_flags
[GTK_STATE_NORMAL
] = GTK_RC_FG
; 
3852         style
->fg
[GTK_STATE_PRELIGHT
] = *fg
; 
3853         style
->color_flags
[GTK_STATE_PRELIGHT
] = GTK_RC_FG
; 
3855         style
->fg
[GTK_STATE_ACTIVE
] = *fg
; 
3856         style
->color_flags
[GTK_STATE_ACTIVE
] = GTK_RC_FG
; 
3859     if ( m_backgroundColour
.Ok() ) 
3861         GdkColor 
*bg 
= m_backgroundColour
.GetColor(); 
3863         style
->bg
[GTK_STATE_NORMAL
] = *bg
; 
3864         style
->base
[GTK_STATE_NORMAL
] = *bg
; 
3865         style
->color_flags
[GTK_STATE_NORMAL
] = (GtkRcFlags
) 
3866             (style
->color_flags
[GTK_STATE_NORMAL
] | GTK_RC_BG 
| GTK_RC_BASE
); 
3868         style
->bg
[GTK_STATE_PRELIGHT
] = *bg
; 
3869         style
->base
[GTK_STATE_PRELIGHT
] = *bg
; 
3870         style
->color_flags
[GTK_STATE_PRELIGHT
] = (GtkRcFlags
) 
3871             (style
->color_flags
[GTK_STATE_PRELIGHT
] | GTK_RC_BG 
| GTK_RC_BASE
); 
3873         style
->bg
[GTK_STATE_ACTIVE
] = *bg
; 
3874         style
->base
[GTK_STATE_ACTIVE
] = *bg
; 
3875         style
->color_flags
[GTK_STATE_ACTIVE
] = (GtkRcFlags
) 
3876             (style
->color_flags
[GTK_STATE_ACTIVE
] | GTK_RC_BG 
| GTK_RC_BASE
); 
3878         style
->bg
[GTK_STATE_INSENSITIVE
] = *bg
; 
3879         style
->base
[GTK_STATE_INSENSITIVE
] = *bg
; 
3880         style
->color_flags
[GTK_STATE_INSENSITIVE
] = (GtkRcFlags
) 
3881             (style
->color_flags
[GTK_STATE_INSENSITIVE
] | GTK_RC_BG 
| GTK_RC_BASE
); 
3887 void wxWindowGTK::ApplyWidgetStyle(bool forceStyle
) 
3889     GtkRcStyle 
*style 
= CreateWidgetStyle(forceStyle
); 
3892         DoApplyWidgetStyle(style
); 
3893         gtk_rc_style_unref(style
); 
3896     // Style change may affect GTK+'s size calculation: 
3897     InvalidateBestSize(); 
3900 void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
3903         gtk_widget_modify_style(m_wxwindow
, style
); 
3905         gtk_widget_modify_style(m_widget
, style
); 
3908 bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style
) 
3910     wxWindowBase::SetBackgroundStyle(style
); 
3912     if (style 
== wxBG_STYLE_CUSTOM
) 
3914         GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3916             window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3918             window 
= GetConnectWidget()->window
; 
3922             // Make sure GDK/X11 doesn't refresh the window 
3924             gdk_window_set_back_pixmap( window
, None
, False 
); 
3926             Display
* display 
= GDK_WINDOW_DISPLAY(window
); 
3929             m_needsStyleChange 
= false; 
3932             // Do in OnIdle, because the window is not yet available 
3933             m_needsStyleChange 
= true; 
3935         // Don't apply widget style, or we get a grey background 
3939         // apply style change (forceStyle=true so that new style is applied 
3940         // even if the bg colour changed from valid to wxNullColour): 
3941         ApplyWidgetStyle(true); 
3946 #if wxUSE_DRAG_AND_DROP 
3948 void wxWindowGTK::SetDropTarget( wxDropTarget 
*dropTarget 
) 
3950     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3952     GtkWidget 
*dnd_widget 
= GetConnectWidget(); 
3954     if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget 
); 
3956     if (m_dropTarget
) delete m_dropTarget
; 
3957     m_dropTarget 
= dropTarget
; 
3959     if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget 
); 
3962 #endif // wxUSE_DRAG_AND_DROP 
3964 GtkWidget
* wxWindowGTK::GetConnectWidget() 
3966     GtkWidget 
*connect_widget 
= m_widget
; 
3967     if (m_wxwindow
) connect_widget 
= m_wxwindow
; 
3969     return connect_widget
; 
3972 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow 
*window 
) 
3975         return (window 
== GTK_PIZZA(m_wxwindow
)->bin_window
); 
3977     return (window 
== m_widget
->window
); 
3980 bool wxWindowGTK::SetFont( const wxFont 
&font 
) 
3982     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3984     if (!wxWindowBase::SetFont(font
)) 
3987     // apply style change (forceStyle=true so that new style is applied 
3988     // even if the font changed from valid to wxNullFont): 
3989     ApplyWidgetStyle(true); 
3994 void wxWindowGTK::DoCaptureMouse() 
3996     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3998     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4000         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4002         window 
= GetConnectWidget()->window
; 
4004     wxCHECK_RET( window
, _T("CaptureMouse() failed") ); 
4006     const wxCursor
* cursor 
= &m_cursor
; 
4008         cursor 
= wxSTANDARD_CURSOR
; 
4010     gdk_pointer_grab( window
, FALSE
, 
4012                          (GDK_BUTTON_PRESS_MASK 
| 
4013                           GDK_BUTTON_RELEASE_MASK 
| 
4014                           GDK_POINTER_MOTION_HINT_MASK 
| 
4015                           GDK_POINTER_MOTION_MASK
), 
4017                       cursor
->GetCursor(), 
4018                       (guint32
)GDK_CURRENT_TIME 
); 
4019     g_captureWindow 
= this; 
4020     g_captureWindowHasMouse 
= true; 
4023 void wxWindowGTK::DoReleaseMouse() 
4025     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4027     wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") ); 
4029     g_captureWindow 
= (wxWindowGTK
*) NULL
; 
4031     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4033         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4035         window 
= GetConnectWidget()->window
; 
4040     gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME 
); 
4044 wxWindow 
*wxWindowBase::GetCapture() 
4046     return (wxWindow 
*)g_captureWindow
; 
4049 bool wxWindowGTK::IsRetained() const 
4054 void wxWindowGTK::BlockScrollEvent() 
4056     wxASSERT(!m_blockScrollEvent
); 
4057     m_blockScrollEvent 
= true; 
4060 void wxWindowGTK::UnblockScrollEvent() 
4062     wxASSERT(m_blockScrollEvent
); 
4063     m_blockScrollEvent 
= false; 
4066 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
, 
4069     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4070     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4074         m_hasScrolling 
= true; 
4078         // GtkRange requires upper > lower 
4083     const int i 
= orient 
== wxVERTICAL
; 
4084     GtkAdjustment
* adj 
= m_scrollBar
[i
]->adjustment
; 
4086     adj
->step_increment 
= 1; 
4087     adj
->page_increment 
= 
4088     adj
->page_size 
= thumbVisible
; 
4091     // automatically clamps value to [0,range-page_size], and emits change events 
4092     gtk_range_set_range(m_scrollBar
[i
], 0, range
); 
4093     UnblockScrollEvent(); 
4094     m_scrollPos
[i
] = adj
->value
; 
4097 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) ) 
4099     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4100     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4102     // This check is more than an optimization. Without it, the slider 
4103     //   will not move smoothly while tracking when using wxScrollHelper. 
4104     if (GetScrollPos(orient
) != pos
) 
4106         const int i 
= orient 
== wxVERTICAL
; 
4108         gtk_range_set_value(m_scrollBar
[i
], pos
); 
4109         UnblockScrollEvent(); 
4110         m_scrollPos
[i
] = m_scrollBar
[i
]->adjustment
->value
; 
4114 int wxWindowGTK::GetScrollThumb( int orient 
) const 
4116     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4117     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4119     const int i 
= orient 
== wxVERTICAL
; 
4120     return int(m_scrollBar
[i
]->adjustment
->page_size
); 
4123 int wxWindowGTK::GetScrollPos( int orient 
) const 
4125     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4126     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4128     const int i 
= orient 
== wxVERTICAL
; 
4129     return int(m_scrollBar
[i
]->adjustment
->value 
+ 0.5); 
4132 int wxWindowGTK::GetScrollRange( int orient 
) const 
4134     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4135     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4137     const int i 
= orient 
== wxVERTICAL
; 
4138     return int(m_scrollBar
[i
]->adjustment
->upper
); 
4141 // Determine if increment is the same as +/-x, allowing for some small 
4142 //   difference due to possible inexactness in floating point arithmetic 
4143 static inline bool IsScrollIncrement(double increment
, double x
) 
4145     wxASSERT(increment 
> 0); 
4146     const double tolerance 
= 1.0 / 1024; 
4147     return fabs(increment 
- fabs(x
)) < tolerance
; 
4150 wxEventType 
wxWindowGTK::GetScrollEventType(GtkRange
* range
) 
4155         wxapp_install_idle_handler(); 
4157     wxASSERT(range 
== m_scrollBar
[0] || range 
== m_scrollBar
[1]); 
4159     const int barIndex 
= range 
== m_scrollBar
[1]; 
4160     GtkAdjustment
* adj 
= range
->adjustment
; 
4161     const int value 
= int(adj
->value 
+ 0.5); 
4162     // save previous position 
4163     const double oldPos 
= m_scrollPos
[barIndex
]; 
4164     // update current position 
4165     m_scrollPos
[barIndex
] = adj
->value
; 
4166     // If event should be ignored, or integral position has not changed 
4167     if (!m_hasVMT 
|| g_blockEventsOnDrag 
|| m_blockScrollEvent 
|| value 
== int(oldPos 
+ 0.5)) 
4172     wxEventType eventType 
= wxEVT_SCROLL_THUMBTRACK
; 
4175         // Difference from last change event 
4176         const double diff 
= adj
->value 
- oldPos
; 
4177         const bool isDown 
= diff 
> 0; 
4179         if (IsScrollIncrement(adj
->step_increment
, diff
)) 
4181             eventType 
= isDown 
? wxEVT_SCROLL_LINEDOWN 
: wxEVT_SCROLL_LINEUP
; 
4183         else if (IsScrollIncrement(adj
->page_increment
, diff
)) 
4185             eventType 
= isDown 
? wxEVT_SCROLL_PAGEDOWN 
: wxEVT_SCROLL_PAGEUP
; 
4187         else if (m_mouseButtonDown
) 
4189             // Assume track event 
4190             m_isScrolling 
= true; 
4196 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) ) 
4198     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4200     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4202     // No scrolling requested. 
4203     if ((dx 
== 0) && (dy 
== 0)) return; 
4205     m_clipPaintRegion 
= true; 
4207     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy 
); 
4209     m_clipPaintRegion 
= false; 
4212 void wxWindowGTK::GtkScrolledWindowSetBorder(GtkWidget
* w
, int wxstyle
) 
4214     //RN: Note that static controls usually have no border on gtk, so maybe 
4215     //it makes sense to treat that as simply no border at the wx level 
4217     if (!(wxstyle 
& wxNO_BORDER
) && !(wxstyle 
& wxBORDER_STATIC
)) 
4219         GtkShadowType gtkstyle
; 
4221         if(wxstyle 
& wxBORDER_RAISED
) 
4222             gtkstyle 
= GTK_SHADOW_OUT
; 
4223         else if (wxstyle 
& wxBORDER_SUNKEN
) 
4224             gtkstyle 
= GTK_SHADOW_IN
; 
4225         else if (wxstyle 
& wxBORDER_DOUBLE
) 
4226             gtkstyle 
= GTK_SHADOW_ETCHED_IN
; 
4228             gtkstyle 
= GTK_SHADOW_IN
; 
4230         gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(w
), 
4235 void wxWindowGTK::SetWindowStyleFlag( long style 
) 
4237     // Updates the internal variable. NB: Now m_windowStyle bits carry the _new_ style values already 
4238     wxWindowBase::SetWindowStyleFlag(style
); 
4241 // Find the wxWindow at the current mouse position, also returning the mouse 
4243 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
4245     pt 
= wxGetMousePosition(); 
4246     wxWindow
* found 
= wxFindWindowAtPoint(pt
); 
4250 // Get the current mouse position. 
4251 wxPoint 
wxGetMousePosition() 
4253   /* This crashes when used within wxHelpContext, 
4254      so we have to use the X-specific implementation below. 
4256     GdkModifierType *mask; 
4257     (void) gdk_window_get_pointer(NULL, &x, &y, mask); 
4259     return wxPoint(x, y); 
4263     GdkWindow
* windowAtPtr 
= gdk_window_at_pointer(& x
, & y
); 
4265     Display 
*display 
= windowAtPtr 
? GDK_WINDOW_XDISPLAY(windowAtPtr
) : GDK_DISPLAY(); 
4266     Window rootWindow 
= RootWindowOfScreen (DefaultScreenOfDisplay(display
)); 
4267     Window rootReturn
, childReturn
; 
4268     int rootX
, rootY
, winX
, winY
; 
4269     unsigned int maskReturn
; 
4271     XQueryPointer (display
, 
4275                    &rootX
, &rootY
, &winX
, &winY
, &maskReturn
); 
4276     return wxPoint(rootX
, rootY
); 
4280 // Needed for implementing e.g. combobox on wxGTK within a modal dialog. 
4281 void wxAddGrab(wxWindow
* window
) 
4283     gtk_grab_add( (GtkWidget
*) window
->GetHandle() ); 
4286 void wxRemoveGrab(wxWindow
* window
) 
4288     gtk_grab_remove( (GtkWidget
*) window
->GetHandle() ); 
4291 // ---------------------------------------------------------------------------- 
4293 // ---------------------------------------------------------------------------- 
4295 class wxWinModule 
: public wxModule
 
4302     DECLARE_DYNAMIC_CLASS(wxWinModule
) 
4305 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
) 
4307 bool wxWinModule::OnInit() 
4309     // g_eraseGC = gdk_gc_new( gdk_get_default_root_window() ); 
4310     // gdk_gc_set_fill( g_eraseGC, GDK_SOLID ); 
4315 void wxWinModule::OnExit() 
4318         g_object_unref (g_eraseGC
);