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" 
  23 #include "wx/dcclient.h" 
  26 #include "wx/layout.h" 
  28 #include "wx/dialog.h" 
  29 #include "wx/msgdlg.h" 
  30 #include "wx/module.h" 
  31 #include "wx/combobox.h" 
  32 #if wxUSE_TOOLBAR_NATIVE 
  33 #include "wx/toolbar.h" 
  36 #if wxUSE_DRAG_AND_DROP 
  41     #include "wx/tooltip.h" 
  49     #include "wx/textctrl.h" 
  53 #include "wx/statusbr.h" 
  54 #include "wx/settings.h" 
  56 #include "wx/fontutil.h" 
  59     #include "wx/thread.h" 
  65 // FIXME: Due to a hack we use GtkCombo in here, which is deprecated since gtk2.3.0 
  66 #include <gtk/gtkversion.h> 
  67 #if defined(GTK_DISABLE_DEPRECATED) && GTK_CHECK_VERSION(2,3,0) 
  68 #undef GTK_DISABLE_DEPRECATED 
  71 #include "wx/gtk/private.h" 
  72 #include <gdk/gdkprivate.h> 
  73 #include <gdk/gdkkeysyms.h> 
  77 #include <gtk/gtkprivate.h> 
  79 #include "wx/gtk/win_gtk.h" 
  81 #include <pango/pangox.h> 
  87 extern GtkContainerClass 
*pizza_parent_class
; 
  89 //----------------------------------------------------------------------------- 
  90 // documentation on internals 
  91 //----------------------------------------------------------------------------- 
  94    I have been asked several times about writing some documentation about 
  95    the GTK port of wxWidgets, especially its internal structures. Obviously, 
  96    you cannot understand wxGTK without knowing a little about the GTK, but 
  97    some more information about what the wxWindow, which is the base class 
  98    for all other window classes, does seems required as well. 
 102    What does wxWindow do? It contains the common interface for the following 
 103    jobs of its descendants: 
 105    1) Define the rudimentary behaviour common to all window classes, such as 
 106    resizing, intercepting user input (so as to make it possible to use these 
 107    events for special purposes in a derived class), window names etc. 
 109    2) Provide the possibility to contain and manage children, if the derived 
 110    class is allowed to contain children, which holds true for those window 
 111    classes which do not display a native GTK widget. To name them, these 
 112    classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame- 
 113    work classes are a special case and are handled a bit differently from 
 114    the rest. The same holds true for the wxNotebook class. 
 116    3) Provide the possibility to draw into a client area of a window. This, 
 117    too, only holds true for classes that do not display a native GTK widget 
 120    4) Provide the entire mechanism for scrolling widgets. This actual inter- 
 121    face for this is usually in wxScrolledWindow, but the GTK implementation 
 124    5) A multitude of helper or extra methods for special purposes, such as 
 125    Drag'n'Drop, managing validators etc. 
 127    6) Display a border (sunken, raised, simple or none). 
 129    Normally one might expect, that one wxWidgets window would always correspond 
 130    to one GTK widget. Under GTK, there is no such allround widget that has all 
 131    the functionality. Moreover, the GTK defines a client area as a different 
 132    widget from the actual widget you are handling. Last but not least some 
 133    special classes (e.g. wxFrame) handle different categories of widgets and 
 134    still have the possibility to draw something in the client area. 
 135    It was therefore required to write a special purpose GTK widget, that would 
 136    represent a client area in the sense of wxWidgets capable to do the jobs 
 137    2), 3) and 4). I have written this class and it resides in win_gtk.c of 
 140    All windows must have a widget, with which they interact with other under- 
 141    lying GTK widgets. It is this widget, e.g. that has to be resized etc and 
 142    the wxWindow class has a member variable called m_widget which holds a 
 143    pointer to this widget. When the window class represents a GTK native widget, 
 144    this is (in most cases) the only GTK widget the class manages. E.g. the 
 145    wxStaticText class handles only a GtkLabel widget a pointer to which you 
 146    can find in m_widget (defined in wxWindow) 
 148    When the class has a client area for drawing into and for containing children 
 149    it has to handle the client area widget (of the type GtkPizza, defined in 
 150    win_gtk.c), but there could be any number of widgets, handled by a class 
 151    The common rule for all windows is only, that the widget that interacts with 
 152    the rest of GTK must be referenced in m_widget and all other widgets must be 
 153    children of this widget on the GTK level. The top-most widget, which also 
 154    represents the client area, must be in the m_wxwindow field and must be of 
 157    As I said, the window classes that display a GTK native widget only have 
 158    one widget, so in the case of e.g. the wxButton class m_widget holds a 
 159    pointer to a GtkButton widget. But windows with client areas (for drawing 
 160    and children) have a m_widget field that is a pointer to a GtkScrolled- 
 161    Window and a m_wxwindow field that is pointer to a GtkPizza and this 
 162    one is (in the GTK sense) a child of the GtkScrolledWindow. 
 164    If the m_wxwindow field is set, then all input to this widget is inter- 
 165    cepted and sent to the wxWidgets class. If not, all input to the widget 
 166    that gets pointed to by m_widget gets intercepted and sent to the class. 
 170    The design of scrolling in wxWidgets is markedly different from that offered 
 171    by the GTK itself and therefore we cannot simply take it as it is. In GTK, 
 172    clicking on a scrollbar belonging to scrolled window will inevitably move 
 173    the window. In wxWidgets, the scrollbar will only emit an event, send this 
 174    to (normally) a wxScrolledWindow and that class will call ScrollWindow() 
 175    which actually moves the window and its subchildren. Note that GtkPizza 
 176    memorizes how much it has been scrolled but that wxWidgets forgets this 
 177    so that the two coordinates systems have to be kept in synch. This is done 
 178    in various places using the pizza->xoffset and pizza->yoffset values. 
 182    Singularily the most broken code in GTK is the code that is supposed to 
 183    inform subwindows (child windows) about new positions. Very often, duplicate 
 184    events are sent without changes in size or position, equally often no 
 185    events are sent at all (All this is due to a bug in the GtkContainer code 
 186    which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores 
 187    GTK's own system and it simply waits for size events for toplevel windows 
 188    and then iterates down the respective size events to all window. This has 
 189    the disadvantage that windows might get size events before the GTK widget 
 190    actually has the reported size. This doesn't normally pose any problem, but 
 191    the OpenGL drawing routines rely on correct behaviour. Therefore, I have 
 192    added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas, 
 193    i.e. the wxGLCanvas will emit a size event, when (and not before) the X11 
 194    window that is used for OpenGL output really has that size (as reported by 
 199    If someone at some point of time feels the immense desire to have a look at, 
 200    change or attempt to optimise the Refresh() logic, this person will need an 
 201    intimate understanding of what "draw" and "expose" events are and what 
 202    they are used for, in particular when used in connection with GTK's 
 203    own windowless widgets. Beware. 
 207    Cursors, too, have been a constant source of pleasure. The main difficulty 
 208    is that a GdkWindow inherits a cursor if the programmer sets a new cursor 
 209    for the parent. To prevent this from doing too much harm, I use idle time 
 210    to set the cursor over and over again, starting from the toplevel windows 
 211    and ending with the youngest generation (speaking of parent and child windows). 
 212    Also don't forget that cursors (like much else) are connected to GdkWindows, 
 213    not GtkWidgets and that the "window" field of a GtkWidget might very well 
 214    point to the GdkWindow of the parent widget (-> "window-less widget") and 
 215    that the two obviously have very different meanings. 
 219 //----------------------------------------------------------------------------- 
 221 //----------------------------------------------------------------------------- 
 223 extern wxList     wxPendingDelete
; 
 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 ); 
 400         g_object_unref (G_OBJECT (gc
)); 
 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     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1596         g_signal_stop_emission_by_name (widget
, "button_press_event"); 
1600     if (event_type 
== wxEVT_RIGHT_DOWN
) 
1602         // generate a "context menu" event: this is similar to right mouse 
1603         // click under many GUIs except that it is generated differently 
1604         // (right up under MSW, ctrl-click under Mac, right down here) and 
1606         // (a) it's a command event and so is propagated to the parent 
1607         // (b) under some ports it can be generated from kbd too 
1608         // (c) it uses screen coords (because of (a)) 
1609         wxContextMenuEvent 
evtCtx( 
1612             win
->ClientToScreen(event
.GetPosition())); 
1613         evtCtx
.SetEventObject(win
); 
1614         return win
->GetEventHandler()->ProcessEvent(evtCtx
); 
1621 //----------------------------------------------------------------------------- 
1622 // "button_release_event" 
1623 //----------------------------------------------------------------------------- 
1627 gtk_window_button_release_callback( GtkWidget 
*widget
, 
1628                                     GdkEventButton 
*gdk_event
, 
1634         wxapp_install_idle_handler(); 
1636     if (!win
->m_hasVMT
) return FALSE
; 
1637     if (g_blockEventsOnDrag
) return FALSE
; 
1638     if (g_blockEventsOnScroll
) return FALSE
; 
1640     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1642     wxEventType event_type 
= wxEVT_NULL
; 
1644     switch (gdk_event
->button
) 
1647             event_type 
= wxEVT_LEFT_UP
; 
1651             event_type 
= wxEVT_MIDDLE_UP
; 
1655             event_type 
= wxEVT_RIGHT_UP
; 
1659             // unknwon button, don't process 
1663     wxMouseEvent 
event( event_type 
); 
1664     InitMouseEvent( win
, event
, gdk_event 
); 
1666     AdjustEventButtonState(event
); 
1668     // same wxListBox hack as above 
1669     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1671     if ( !g_captureWindow 
) 
1672         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1674     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1676         g_signal_stop_emission_by_name (widget
, "button_release_event"); 
1684 //----------------------------------------------------------------------------- 
1685 // "motion_notify_event" 
1686 //----------------------------------------------------------------------------- 
1690 gtk_window_motion_notify_callback( GtkWidget 
*widget
, 
1691                                    GdkEventMotion 
*gdk_event
, 
1697         wxapp_install_idle_handler(); 
1699     if (!win
->m_hasVMT
) return FALSE
; 
1700     if (g_blockEventsOnDrag
) return FALSE
; 
1701     if (g_blockEventsOnScroll
) return FALSE
; 
1703     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1705     if (gdk_event
->is_hint
) 
1709         GdkModifierType state
; 
1710         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1716     printf( "OnMotion from " ); 
1717     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1718       printf( win->GetClassInfo()->GetClassName() ); 
1722     wxMouseEvent 
event( wxEVT_MOTION 
); 
1723     InitMouseEvent(win
, event
, gdk_event
); 
1725     if ( g_captureWindow 
) 
1727         // synthetize a mouse enter or leave event if needed 
1728         GdkWindow 
*winUnderMouse 
= gdk_window_at_pointer(NULL
, NULL
); 
1729         // This seems to be necessary and actually been added to 
1730         // GDK itself in version 2.0.X 
1733         bool hasMouse 
= winUnderMouse 
== gdk_event
->window
; 
1734         if ( hasMouse 
!= g_captureWindowHasMouse 
) 
1736             // the mouse changed window 
1737             g_captureWindowHasMouse 
= hasMouse
; 
1739             wxMouseEvent 
eventM(g_captureWindowHasMouse 
? wxEVT_ENTER_WINDOW
 
1740                                                         : wxEVT_LEAVE_WINDOW
); 
1741             InitMouseEvent(win
, eventM
, gdk_event
); 
1742             eventM
.SetEventObject(win
); 
1743             win
->GetEventHandler()->ProcessEvent(eventM
); 
1748         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1751     if ( !g_captureWindow 
) 
1753         wxSetCursorEvent 
cevent( event
.m_x
, event
.m_y 
); 
1754         if (win
->GetEventHandler()->ProcessEvent( cevent 
)) 
1756             // Rewrite cursor handling here (away from idle). 
1760     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1762         g_signal_stop_emission_by_name (widget
, "motion_notify_event"); 
1770 //----------------------------------------------------------------------------- 
1771 // "mouse_wheel_event" 
1772 //----------------------------------------------------------------------------- 
1776 gtk_window_wheel_callback (GtkWidget 
* widget
, 
1777                            GdkEventScroll 
* gdk_event
, 
1783         wxapp_install_idle_handler(); 
1785     wxEventType event_type 
= wxEVT_NULL
; 
1786     if (gdk_event
->direction 
== GDK_SCROLL_UP
) 
1787         event_type 
= wxEVT_MOUSEWHEEL
; 
1788     else if (gdk_event
->direction 
== GDK_SCROLL_DOWN
) 
1789         event_type 
= wxEVT_MOUSEWHEEL
; 
1793     wxMouseEvent 
event( event_type 
); 
1794     // Can't use InitMouse macro because scroll events don't have button 
1795     event
.SetTimestamp( gdk_event
->time 
); 
1796     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
); 
1797     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
); 
1798     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
); 
1799     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
); 
1800     event
.m_leftDown 
= (gdk_event
->state 
& GDK_BUTTON1_MASK
); 
1801     event
.m_middleDown 
= (gdk_event
->state 
& GDK_BUTTON2_MASK
); 
1802     event
.m_rightDown 
= (gdk_event
->state 
& GDK_BUTTON3_MASK
); 
1803     event
.m_linesPerAction 
= 3; 
1804     event
.m_wheelDelta 
= 120; 
1805     if (gdk_event
->direction 
== GDK_SCROLL_UP
) 
1806         event
.m_wheelRotation 
= 120; 
1808         event
.m_wheelRotation 
= -120; 
1810     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1811     event
.m_x 
= (wxCoord
)gdk_event
->x 
- pt
.x
; 
1812     event
.m_y 
= (wxCoord
)gdk_event
->y 
- pt
.y
; 
1814     event
.SetEventObject( win 
); 
1815     event
.SetId( win
->GetId() ); 
1816     event
.SetTimestamp( gdk_event
->time 
); 
1818     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1820         g_signal_stop_emission_by_name (widget
, "scroll_event"); 
1828 //----------------------------------------------------------------------------- 
1830 //----------------------------------------------------------------------------- 
1832 static gboolean 
wxgtk_window_popup_menu_callback(GtkWidget
*, wxWindowGTK
* win
) 
1834     wxContextMenuEvent 
event( 
1838     event
.SetEventObject(win
); 
1839     return win
->GetEventHandler()->ProcessEvent(event
); 
1843 //----------------------------------------------------------------------------- 
1845 //----------------------------------------------------------------------------- 
1847 // send the wxChildFocusEvent and wxFocusEvent, common code of 
1848 // gtk_window_focus_in_callback() and SetFocus() 
1849 static bool DoSendFocusEvents(wxWindow 
*win
) 
1851     // Notify the parent keeping track of focus for the kbd navigation 
1852     // purposes that we got it. 
1853     wxChildFocusEvent 
eventChildFocus(win
); 
1854     (void)win
->GetEventHandler()->ProcessEvent(eventChildFocus
); 
1856     wxFocusEvent 
eventFocus(wxEVT_SET_FOCUS
, win
->GetId()); 
1857     eventFocus
.SetEventObject(win
); 
1859     return win
->GetEventHandler()->ProcessEvent(eventFocus
); 
1864 gtk_window_focus_in_callback( GtkWidget 
*widget
, 
1865                               GdkEventFocus 
*WXUNUSED(event
), 
1871         wxapp_install_idle_handler(); 
1874         gtk_im_context_focus_in(win
->m_imData
->context
); 
1877     g_focusWindow 
= win
; 
1879     wxLogTrace(TRACE_FOCUS
, 
1880                _T("%s: focus in"), win
->GetName().c_str()); 
1884         gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
); 
1888     // caret needs to be informed about focus change 
1889     wxCaret 
*caret 
= win
->GetCaret(); 
1892         caret
->OnSetFocus(); 
1894 #endif // wxUSE_CARET 
1896     gboolean ret 
= FALSE
; 
1898     // does the window itself think that it has the focus? 
1899     if ( !win
->m_hasFocus 
) 
1901         // not yet, notify it 
1902         win
->m_hasFocus 
= true; 
1904         (void)DoSendFocusEvents(win
); 
1909     // Disable default focus handling for custom windows 
1910     // since the default GTK+ handler issues a repaint 
1911     if (win
->m_wxwindow
) 
1918 //----------------------------------------------------------------------------- 
1919 // "focus_out_event" 
1920 //----------------------------------------------------------------------------- 
1924 gtk_window_focus_out_callback( GtkWidget 
*widget
, 
1925                                GdkEventFocus 
*gdk_event
, 
1931         wxapp_install_idle_handler(); 
1934         gtk_im_context_focus_out(win
->m_imData
->context
); 
1936     wxLogTrace( TRACE_FOCUS
, 
1937                 _T("%s: focus out"), win
->GetName().c_str() ); 
1940     wxWindowGTK 
*winFocus 
= wxFindFocusedChild(win
); 
1944     g_focusWindow 
= (wxWindowGTK 
*)NULL
; 
1952     // caret needs to be informed about focus change 
1953     wxCaret 
*caret 
= win
->GetCaret(); 
1956         caret
->OnKillFocus(); 
1958 #endif // wxUSE_CARET 
1960     gboolean ret 
= FALSE
; 
1962     // don't send the window a kill focus event if it thinks that it doesn't 
1963     // have focus already 
1964     if ( win
->m_hasFocus 
) 
1966         win
->m_hasFocus 
= false; 
1968         wxFocusEvent 
event( wxEVT_KILL_FOCUS
, win
->GetId() ); 
1969         event
.SetEventObject( win 
); 
1971         (void)win
->GetEventHandler()->ProcessEvent( event 
); 
1976     // Disable default focus handling for custom windows 
1977     // since the default GTK+ handler issues a repaint 
1978     if (win
->m_wxwindow
) 
1985 //----------------------------------------------------------------------------- 
1986 // "enter_notify_event" 
1987 //----------------------------------------------------------------------------- 
1991 gtk_window_enter_callback( GtkWidget 
*widget
, 
1992                            GdkEventCrossing 
*gdk_event
, 
1998         wxapp_install_idle_handler(); 
2000     if (!win
->m_hasVMT
) return FALSE
; 
2001     if (g_blockEventsOnDrag
) return FALSE
; 
2003     // Event was emitted after a grab 
2004     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
2006     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
2010     GdkModifierType state 
= (GdkModifierType
)0; 
2012     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
2014     wxMouseEvent 
event( wxEVT_ENTER_WINDOW 
); 
2015     InitMouseEvent(win
, event
, gdk_event
); 
2016     wxPoint pt 
= win
->GetClientAreaOrigin(); 
2017     event
.m_x 
= x 
+ pt
.x
; 
2018     event
.m_y 
= y 
+ pt
.y
; 
2020     if ( !g_captureWindow 
) 
2022         wxSetCursorEvent 
cevent( event
.m_x
, event
.m_y 
); 
2023         if (win
->GetEventHandler()->ProcessEvent( cevent 
)) 
2025             // Rewrite cursor handling here (away from idle). 
2029     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
2031        g_signal_stop_emission_by_name (widget
, "enter_notify_event"); 
2039 //----------------------------------------------------------------------------- 
2040 // "leave_notify_event" 
2041 //----------------------------------------------------------------------------- 
2045 gtk_window_leave_callback( GtkWidget 
*widget
, 
2046                            GdkEventCrossing 
*gdk_event
, 
2052         wxapp_install_idle_handler(); 
2054     if (!win
->m_hasVMT
) return FALSE
; 
2055     if (g_blockEventsOnDrag
) return FALSE
; 
2057     // Event was emitted after an ungrab 
2058     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
2060     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
2062     wxMouseEvent 
event( wxEVT_LEAVE_WINDOW 
); 
2063     event
.SetTimestamp( gdk_event
->time 
); 
2064     event
.SetEventObject( win 
); 
2068     GdkModifierType state 
= (GdkModifierType
)0; 
2070     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
2072     event
.m_shiftDown 
= (state 
& GDK_SHIFT_MASK
) != 0; 
2073     event
.m_controlDown 
= (state 
& GDK_CONTROL_MASK
) != 0; 
2074     event
.m_altDown 
= (state 
& GDK_MOD1_MASK
) != 0; 
2075     event
.m_metaDown 
= (state 
& GDK_MOD2_MASK
) != 0; 
2076     event
.m_leftDown 
= (state 
& GDK_BUTTON1_MASK
) != 0; 
2077     event
.m_middleDown 
= (state 
& GDK_BUTTON2_MASK
) != 0; 
2078     event
.m_rightDown 
= (state 
& GDK_BUTTON3_MASK
) != 0; 
2080     wxPoint pt 
= win
->GetClientAreaOrigin(); 
2081     event
.m_x 
= x 
+ pt
.x
; 
2082     event
.m_y 
= y 
+ pt
.y
; 
2084     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
2086         g_signal_stop_emission_by_name (widget
, "leave_notify_event"); 
2094 //----------------------------------------------------------------------------- 
2095 // "value_changed" from m_vAdjust 
2096 //----------------------------------------------------------------------------- 
2099 static void gtk_window_vscroll_callback( GtkAdjustment 
*adjust
, 
2105         wxapp_install_idle_handler(); 
2107     if (g_blockEventsOnDrag
) return; 
2109     if (!win
->m_hasVMT
) return; 
2111     float diff 
= adjust
->value 
- win
->m_oldVerticalPos
; 
2112     if (fabs(diff
) < 0.2) return; 
2114     win
->m_oldVerticalPos 
= adjust
->value
; 
2116     wxEventType command 
= GtkScrollWinTypeToWx(GTK_SCROLL_JUMP
); 
2118     int value 
= (int)(adjust
->value
+0.5); 
2120     wxScrollWinEvent 
event( command
, value
, wxVERTICAL 
); 
2121     event
.SetEventObject( win 
); 
2122     win
->GetEventHandler()->ProcessEvent( event 
); 
2126 //----------------------------------------------------------------------------- 
2127 // "value_changed" from m_hAdjust 
2128 //----------------------------------------------------------------------------- 
2131 static void gtk_window_hscroll_callback( GtkAdjustment 
*adjust
, 
2137         wxapp_install_idle_handler(); 
2139     if (g_blockEventsOnDrag
) return; 
2140     if (!win
->m_hasVMT
) return; 
2142     float diff 
= adjust
->value 
- win
->m_oldHorizontalPos
; 
2143     if (fabs(diff
) < 0.2) return; 
2145     wxEventType command 
= GtkScrollWinTypeToWx(GTK_SCROLL_JUMP
); 
2147     win
->m_oldHorizontalPos 
= adjust
->value
; 
2149     int value 
= (int)(adjust
->value
+0.5); 
2151     wxScrollWinEvent 
event( command
, value
, wxHORIZONTAL 
); 
2152     event
.SetEventObject( win 
); 
2153     win
->GetEventHandler()->ProcessEvent( event 
); 
2157 //----------------------------------------------------------------------------- 
2158 // "button_press_event" from scrollbar 
2159 //----------------------------------------------------------------------------- 
2163 gtk_scrollbar_button_press_callback( GtkWidget 
*widget
, 
2164                                      GdkEventButton 
*gdk_event
, 
2170         wxapp_install_idle_handler(); 
2173     g_blockEventsOnScroll 
= true; 
2175 // FIXME: there is no 'slider' field in GTK+ 2.0 any more 
2177     win
->m_isScrolling 
= (gdk_event
->window 
== widget
->slider
); 
2184 //----------------------------------------------------------------------------- 
2185 // "button_release_event" from scrollbar 
2186 //----------------------------------------------------------------------------- 
2190 gtk_scrollbar_button_release_callback( GtkRange 
*widget
, 
2191                                        GdkEventButton 
*WXUNUSED(gdk_event
), 
2196 //  don't test here as we can release the mouse while being over 
2197 //  a different window than the slider 
2199 //    if (gdk_event->window != widget->slider) return FALSE; 
2201     g_blockEventsOnScroll 
= false; 
2203     if (win
->m_isScrolling
) 
2205         wxEventType command 
= wxEVT_SCROLLWIN_THUMBRELEASE
; 
2209         GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
2210         if (widget 
== GTK_RANGE(scrolledWindow
->hscrollbar
)) 
2212             value 
= (int)(win
->m_hAdjust
->value
+0.5); 
2215         if (widget 
== GTK_RANGE(scrolledWindow
->vscrollbar
)) 
2217             value 
= (int)(win
->m_vAdjust
->value
+0.5); 
2221         wxScrollWinEvent 
event( command
, value
, dir 
); 
2222         event
.SetEventObject( win 
); 
2223         win
->GetEventHandler()->ProcessEvent( event 
); 
2226     win
->m_isScrolling 
= false; 
2232 // ---------------------------------------------------------------------------- 
2233 // this wxWindowBase function is implemented here (in platform-specific file) 
2234 // because it is static and so couldn't be made virtual 
2235 // ---------------------------------------------------------------------------- 
2237 wxWindow 
*wxWindowBase::DoFindFocus() 
2239     // the cast is necessary when we compile in wxUniversal mode 
2240     return (wxWindow 
*)g_focusWindow
; 
2243 //----------------------------------------------------------------------------- 
2244 // "realize" from m_widget 
2245 //----------------------------------------------------------------------------- 
2247 /* We cannot set colours and fonts before the widget has 
2248    been realized, so we do this directly after realization. */ 
2252 gtk_window_realized_callback( GtkWidget 
*m_widget
, wxWindow 
*win 
) 
2257         wxapp_install_idle_handler(); 
2261         GtkPizza 
*pizza 
= GTK_PIZZA( m_widget 
); 
2262         gtk_im_context_set_client_window( win
->m_imData
->context
, 
2263                                           pizza
->bin_window 
); 
2266     wxWindowCreateEvent 
event( win 
); 
2267     event
.SetEventObject( win 
); 
2268     win
->GetEventHandler()->ProcessEvent( event 
); 
2272 //----------------------------------------------------------------------------- 
2274 //----------------------------------------------------------------------------- 
2278 void gtk_window_size_callback( GtkWidget 
*WXUNUSED(widget
), 
2279                                GtkAllocation 
*WXUNUSED(alloc
), 
2283         wxapp_install_idle_handler(); 
2285     if (!win
->m_hasScrolling
) return; 
2287     int client_width 
= 0; 
2288     int client_height 
= 0; 
2289     win
->GetClientSize( &client_width
, &client_height 
); 
2290     if ((client_width 
== win
->m_oldClientWidth
) && (client_height 
== win
->m_oldClientHeight
)) 
2293     win
->m_oldClientWidth 
= client_width
; 
2294     win
->m_oldClientHeight 
= client_height
; 
2296     if (!win
->m_nativeSizeEvent
) 
2298         wxSizeEvent 
event( win
->GetSize(), win
->GetId() ); 
2299         event
.SetEventObject( win 
); 
2300         win
->GetEventHandler()->ProcessEvent( event 
); 
2307     #define WXUNUSED_UNLESS_XIM(param)  param 
2309     #define WXUNUSED_UNLESS_XIM(param)  WXUNUSED(param) 
2312 /* Resize XIM window */ 
2316 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
), 
2317                                  GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
), 
2318                                  wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) ) 
2321         wxapp_install_idle_handler(); 
2327     if  (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
) 
2331         gdk_drawable_get_size (widget
->window
, &width
, &height
); 
2332         win
->m_icattr
->preedit_area
.width 
= width
; 
2333         win
->m_icattr
->preedit_area
.height 
= height
; 
2334         gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
); 
2340 //----------------------------------------------------------------------------- 
2341 // "realize" from m_wxwindow 
2342 //----------------------------------------------------------------------------- 
2344 /* Initialize XIM support */ 
2348 gtk_wxwindow_realized_callback( GtkWidget 
* WXUNUSED_UNLESS_XIM(widget
), 
2349                                 wxWindowGTK 
* WXUNUSED_UNLESS_XIM(win
) ) 
2352         wxapp_install_idle_handler(); 
2355     if (win
->m_ic
) return; 
2356     if (!widget
) return; 
2357     if (!gdk_im_ready()) return; 
2359     win
->m_icattr 
= gdk_ic_attr_new(); 
2360     if (!win
->m_icattr
) return; 
2364     GdkColormap 
*colormap
; 
2365     GdkICAttr 
*attr 
= win
->m_icattr
; 
2366     unsigned attrmask 
= GDK_IC_ALL_REQ
; 
2368     GdkIMStyle supported_style 
= (GdkIMStyle
) 
2369                                   (GDK_IM_PREEDIT_NONE 
| 
2370                                    GDK_IM_PREEDIT_NOTHING 
| 
2371                                    GDK_IM_PREEDIT_POSITION 
| 
2372                                    GDK_IM_STATUS_NONE 
| 
2373                                    GDK_IM_STATUS_NOTHING
); 
2375     if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2376         supported_style 
= (GdkIMStyle
)(supported_style 
& ~GDK_IM_PREEDIT_POSITION
); 
2378     attr
->style 
= style 
= gdk_im_decide_style (supported_style
); 
2379     attr
->client_window 
= widget
->window
; 
2381     if ((colormap 
= gtk_widget_get_colormap (widget
)) != 
2382             gtk_widget_get_default_colormap ()) 
2384         attrmask 
|= GDK_IC_PREEDIT_COLORMAP
; 
2385         attr
->preedit_colormap 
= colormap
; 
2388     attrmask 
|= GDK_IC_PREEDIT_FOREGROUND
; 
2389     attrmask 
|= GDK_IC_PREEDIT_BACKGROUND
; 
2390     attr
->preedit_foreground 
= widget
->style
->fg
[GTK_STATE_NORMAL
]; 
2391     attr
->preedit_background 
= widget
->style
->base
[GTK_STATE_NORMAL
]; 
2393     switch (style 
& GDK_IM_PREEDIT_MASK
) 
2395         case GDK_IM_PREEDIT_POSITION
: 
2396             if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2398                 g_warning ("over-the-spot style requires fontset"); 
2402             gdk_drawable_get_size (widget
->window
, &width
, &height
); 
2404             attrmask 
|= GDK_IC_PREEDIT_POSITION_REQ
; 
2405             attr
->spot_location
.x 
= 0; 
2406             attr
->spot_location
.y 
= height
; 
2407             attr
->preedit_area
.x 
= 0; 
2408             attr
->preedit_area
.y 
= 0; 
2409             attr
->preedit_area
.width 
= width
; 
2410             attr
->preedit_area
.height 
= height
; 
2411             attr
->preedit_fontset 
= widget
->style
->font
; 
2416       win
->m_ic 
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
); 
2418       if (win
->m_ic 
== NULL
) 
2419           g_warning ("Can't create input context."); 
2422           mask 
= gdk_window_get_events (widget
->window
); 
2423           mask 
= (GdkEventMask
)(mask 
| gdk_ic_get_events (win
->m_ic
)); 
2424           gdk_window_set_events (widget
->window
, mask
); 
2426           if (GTK_WIDGET_HAS_FOCUS(widget
)) 
2427               gdk_im_begin (win
->m_ic
, widget
->window
); 
2433 //----------------------------------------------------------------------------- 
2434 // InsertChild for wxWindowGTK. 
2435 //----------------------------------------------------------------------------- 
2437 /* Callback for wxWindowGTK. This very strange beast has to be used because 
2438  * C++ has no virtual methods in a constructor. We have to emulate a 
2439  * virtual function here as wxNotebook requires a different way to insert 
2440  * a child in it. I had opted for creating a wxNotebookPage window class 
2441  * which would have made this superfluous (such in the MDI window system), 
2442  * but no-one was listening to me... */ 
2444 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child 
) 
2446     /* the window might have been scrolled already, do we 
2447        have to adapt the position */ 
2448     GtkPizza 
*pizza 
= GTK_PIZZA(parent
->m_wxwindow
); 
2449     child
->m_x 
+= pizza
->xoffset
; 
2450     child
->m_y 
+= pizza
->yoffset
; 
2452     gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
), 
2453                      GTK_WIDGET(child
->m_widget
), 
2460 //----------------------------------------------------------------------------- 
2462 //----------------------------------------------------------------------------- 
2464 wxWindow 
*wxGetActiveWindow() 
2466     return wxWindow::FindFocus(); 
2470 wxMouseState 
wxGetMouseState() 
2476     GdkModifierType mask
; 
2478     gdk_window_get_pointer(NULL
, &x
, &y
, &mask
); 
2482     ms
.SetLeftDown(mask 
& GDK_BUTTON1_MASK
); 
2483     ms
.SetMiddleDown(mask 
& GDK_BUTTON2_MASK
); 
2484     ms
.SetRightDown(mask 
& GDK_BUTTON3_MASK
); 
2486     ms
.SetControlDown(mask 
& GDK_CONTROL_MASK
); 
2487     ms
.SetShiftDown(mask 
& GDK_SHIFT_MASK
); 
2488     ms
.SetAltDown(mask 
& GDK_MOD1_MASK
); 
2489     ms
.SetMetaDown(mask 
& GDK_MOD2_MASK
); 
2494 //----------------------------------------------------------------------------- 
2496 //----------------------------------------------------------------------------- 
2498 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
2500 #ifdef __WXUNIVERSAL__ 
2501     IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
) 
2503     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
2504 #endif // __WXUNIVERSAL__/__WXGTK__ 
2506 void wxWindowGTK::Init() 
2509     m_widget 
= (GtkWidget 
*) NULL
; 
2510     m_wxwindow 
= (GtkWidget 
*) NULL
; 
2511     m_focusWidget 
= (GtkWidget 
*) NULL
; 
2521     m_needParent 
= true; 
2522     m_isBeingDeleted 
= false; 
2525     m_nativeSizeEvent 
= false; 
2527     m_hasScrolling 
= false; 
2528     m_isScrolling 
= false; 
2530     m_hAdjust 
= (GtkAdjustment
*) NULL
; 
2531     m_vAdjust 
= (GtkAdjustment
*) NULL
; 
2532     m_oldHorizontalPos 
= 
2533     m_oldVerticalPos 
= 0.0; 
2535     m_oldClientHeight 
= 0; 
2539     m_insertCallback 
= (wxInsertChildFunction
) NULL
; 
2541     m_acceptsFocus 
= false; 
2544     m_clipPaintRegion 
= false; 
2546     m_needsStyleChange 
= false; 
2548     m_cursor 
= *wxSTANDARD_CURSOR
; 
2551     m_dirtyTabOrder 
= false; 
2554 wxWindowGTK::wxWindowGTK() 
2559 wxWindowGTK::wxWindowGTK( wxWindow 
*parent
, 
2564                           const wxString 
&name  
) 
2568     Create( parent
, id
, pos
, size
, style
, name 
); 
2571 bool wxWindowGTK::Create( wxWindow 
*parent
, 
2576                           const wxString 
&name  
) 
2578     if (!PreCreation( parent
, pos
, size 
) || 
2579         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
2581         wxFAIL_MSG( wxT("wxWindowGTK creation failed") ); 
2585     m_insertCallback 
= wxInsertChildInWindow
; 
2587     m_widget 
= gtk_scrolled_window_new( (GtkAdjustment 
*) NULL
, (GtkAdjustment 
*) NULL 
); 
2588     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
2590     GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
2592     GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2593     scroll_class
->scrollbar_spacing 
= 0; 
2595     gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
2597     m_hAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) ); 
2598     m_vAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) ); 
2600     m_wxwindow 
= gtk_pizza_new(); 
2602 #ifndef __WXUNIVERSAL__ 
2603     GtkPizza 
*pizza 
= GTK_PIZZA(m_wxwindow
); 
2605     if (HasFlag(wxRAISED_BORDER
)) 
2607         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT 
); 
2609     else if (HasFlag(wxSUNKEN_BORDER
)) 
2611         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN 
); 
2613     else if (HasFlag(wxSIMPLE_BORDER
)) 
2615         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN 
); 
2619         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE 
); 
2621 #endif // __WXUNIVERSAL__ 
2623     gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
2625     GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
2626     m_acceptsFocus 
= true; 
2628     // I _really_ don't want scrollbars in the beginning 
2629     m_vAdjust
->lower 
= 0.0; 
2630     m_vAdjust
->upper 
= 1.0; 
2631     m_vAdjust
->value 
= 0.0; 
2632     m_vAdjust
->step_increment 
= 1.0; 
2633     m_vAdjust
->page_increment 
= 1.0; 
2634     m_vAdjust
->page_size 
= 5.0; 
2635     g_signal_emit_by_name (m_vAdjust
, "changed"); 
2636     m_hAdjust
->lower 
= 0.0; 
2637     m_hAdjust
->upper 
= 1.0; 
2638     m_hAdjust
->value 
= 0.0; 
2639     m_hAdjust
->step_increment 
= 1.0; 
2640     m_hAdjust
->page_increment 
= 1.0; 
2641     m_hAdjust
->page_size 
= 5.0; 
2642     g_signal_emit_by_name (m_hAdjust
, "changed"); 
2644     // these handlers block mouse events to any window during scrolling such as 
2645     // motion events and prevent GTK and wxWidgets from fighting over where the 
2647     g_signal_connect (scrolledWindow
->vscrollbar
, "button_press_event", 
2648                       G_CALLBACK (gtk_scrollbar_button_press_callback
), this); 
2649     g_signal_connect (scrolledWindow
->hscrollbar
, "button_press_event", 
2650                       G_CALLBACK (gtk_scrollbar_button_press_callback
), this); 
2651     g_signal_connect (scrolledWindow
->vscrollbar
, "button_release_event", 
2652                       G_CALLBACK (gtk_scrollbar_button_release_callback
), this); 
2653     g_signal_connect (scrolledWindow
->hscrollbar
, "button_release_event", 
2654                       G_CALLBACK (gtk_scrollbar_button_release_callback
), this); 
2656     // these handlers get notified when screen updates are required either when 
2657     // scrolling or when the window size (and therefore scrollbar configuration) 
2660     g_signal_connect (m_hAdjust
, "value_changed", 
2661                       G_CALLBACK (gtk_window_hscroll_callback
), this); 
2662     g_signal_connect (m_vAdjust
, "value_changed", 
2663                       G_CALLBACK (gtk_window_vscroll_callback
), this); 
2665     gtk_widget_show( m_wxwindow 
); 
2668         m_parent
->DoAddChild( this ); 
2670     m_focusWidget 
= m_wxwindow
; 
2677 wxWindowGTK::~wxWindowGTK() 
2681     if (g_focusWindow 
== this) 
2682         g_focusWindow 
= NULL
; 
2684     if ( g_delayedFocus 
== this ) 
2685         g_delayedFocus 
= NULL
; 
2687     m_isBeingDeleted 
= true; 
2690     // destroy children before destroying this window itself 
2693     // unhook focus handlers to prevent stray events being 
2694     // propagated to this (soon to be) dead object 
2695     if (m_focusWidget 
!= NULL
) 
2697         g_signal_handlers_disconnect_by_func (m_focusWidget
, 
2698                                               (gpointer
) gtk_window_focus_in_callback
, 
2700         g_signal_handlers_disconnect_by_func (m_focusWidget
, 
2701                                               (gpointer
) gtk_window_focus_out_callback
, 
2710         gdk_ic_destroy (m_ic
); 
2712         gdk_ic_attr_destroy (m_icattr
); 
2715     // delete before the widgets to avoid a crash on solaris 
2720         gtk_widget_destroy( m_wxwindow 
); 
2721         m_wxwindow 
= (GtkWidget
*) NULL
; 
2726         gtk_widget_destroy( m_widget 
); 
2727         m_widget 
= (GtkWidget
*) NULL
; 
2731 bool wxWindowGTK::PreCreation( wxWindowGTK 
*parent
, const wxPoint 
&pos
,  const wxSize 
&size 
) 
2733     wxCHECK_MSG( !m_needParent 
|| parent
, false, wxT("Need complete parent.") ); 
2735     // Use either the given size, or the default if -1 is given. 
2736     // See wxWindowBase for these functions. 
2737     m_width 
= WidthDefault(size
.x
) ; 
2738     m_height 
= HeightDefault(size
.y
); 
2746 void wxWindowGTK::PostCreation() 
2748     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2754             // these get reported to wxWidgets -> wxPaintEvent 
2756             gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE 
); 
2758             g_signal_connect (m_wxwindow
, "expose_event", 
2759                               G_CALLBACK (gtk_window_expose_callback
), this); 
2761             gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow
), HasFlag( wxFULL_REPAINT_ON_RESIZE 
) ); 
2764         // Create input method handler 
2765         m_imData 
= new wxGtkIMData
; 
2767         // Cannot handle drawing preedited text yet 
2768         gtk_im_context_set_use_preedit( m_imData
->context
, FALSE 
); 
2770         g_signal_connect (m_imData
->context
, "commit", 
2771                           G_CALLBACK (gtk_wxwindow_commit_cb
), this); 
2773         // these are called when the "sunken" or "raised" borders are drawn 
2774         g_signal_connect (m_widget
, "expose_event", 
2775                           G_CALLBACK (gtk_window_own_expose_callback
), this); 
2780     if (!GTK_IS_WINDOW(m_widget
)) 
2782         if (m_focusWidget 
== NULL
) 
2783             m_focusWidget 
= m_widget
; 
2787             g_signal_connect (m_focusWidget
, "focus_in_event", 
2788                           G_CALLBACK (gtk_window_focus_in_callback
), this); 
2789             g_signal_connect (m_focusWidget
, "focus_out_event", 
2790                                 G_CALLBACK (gtk_window_focus_out_callback
), this); 
2794             g_signal_connect_after (m_focusWidget
, "focus_in_event", 
2795                           G_CALLBACK (gtk_window_focus_in_callback
), this); 
2796             g_signal_connect_after (m_focusWidget
, "focus_out_event", 
2797                                 G_CALLBACK (gtk_window_focus_out_callback
), this); 
2801     // connect to the various key and mouse handlers 
2803     GtkWidget 
*connect_widget 
= GetConnectWidget(); 
2805     ConnectWidget( connect_widget 
); 
2807     /* We cannot set colours, fonts and cursors before the widget has 
2808        been realized, so we do this directly after realization */ 
2809     g_signal_connect (connect_widget
, "realize", 
2810                       G_CALLBACK (gtk_window_realized_callback
), this); 
2814         // Catch native resize events 
2815         g_signal_connect (m_wxwindow
, "size_allocate", 
2816                           G_CALLBACK (gtk_window_size_callback
), this); 
2818         // Initialize XIM support 
2819         g_signal_connect (m_wxwindow
, "realize", 
2820                           G_CALLBACK (gtk_wxwindow_realized_callback
), this); 
2822         // And resize XIM window 
2823         g_signal_connect (m_wxwindow
, "size_allocate", 
2824                           G_CALLBACK (gtk_wxwindow_size_callback
), this); 
2827     if (GTK_IS_COMBO(m_widget
)) 
2829         GtkCombo 
*gcombo 
= GTK_COMBO(m_widget
); 
2831         g_signal_connect (gcombo
->entry
, "size_request", 
2832                           G_CALLBACK (wxgtk_combo_size_request_callback
), 
2837         // This is needed if we want to add our windows into native 
2838         // GTK controls, such as the toolbar. With this callback, the 
2839         // toolbar gets to know the correct size (the one set by the 
2840         // programmer). Sadly, it misbehaves for wxComboBox. 
2841         g_signal_connect (m_widget
, "size_request", 
2842                           G_CALLBACK (wxgtk_window_size_request_callback
), 
2846     InheritAttributes(); 
2850     // unless the window was created initially hidden (i.e. Hide() had been 
2851     // called before Create()), we should show it at GTK+ level as well 
2853         gtk_widget_show( m_widget 
); 
2856 void wxWindowGTK::ConnectWidget( GtkWidget 
*widget 
) 
2858     g_signal_connect (widget
, "key_press_event", 
2859                       G_CALLBACK (gtk_window_key_press_callback
), this); 
2860     g_signal_connect (widget
, "key_release_event", 
2861                       G_CALLBACK (gtk_window_key_release_callback
), this); 
2862     g_signal_connect (widget
, "button_press_event", 
2863                       G_CALLBACK (gtk_window_button_press_callback
), this); 
2864     g_signal_connect (widget
, "button_release_event", 
2865                       G_CALLBACK (gtk_window_button_release_callback
), this); 
2866     g_signal_connect (widget
, "motion_notify_event", 
2867                       G_CALLBACK (gtk_window_motion_notify_callback
), this); 
2868     g_signal_connect (widget
, "scroll_event", 
2869                       G_CALLBACK (gtk_window_wheel_callback
), this); 
2870     g_signal_connect (widget
, "popup_menu", 
2871                      G_CALLBACK (wxgtk_window_popup_menu_callback
), this); 
2872     g_signal_connect (widget
, "enter_notify_event", 
2873                       G_CALLBACK (gtk_window_enter_callback
), this); 
2874     g_signal_connect (widget
, "leave_notify_event", 
2875                       G_CALLBACK (gtk_window_leave_callback
), this); 
2878 bool wxWindowGTK::Destroy() 
2880     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2884     return wxWindowBase::Destroy(); 
2887 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
) 
2889     gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height 
); 
2892 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
2894     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2895     wxASSERT_MSG( (m_parent 
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") ); 
2898     printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height ); 
2901     if (m_resizing
) return; /* I don't like recursions */ 
2904     int currentX
, currentY
; 
2905     GetPosition(¤tX
, ¤tY
); 
2906     if (x 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
2908     if (y 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
2910     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
2912     // calculate the best size if we should auto size the window 
2913     if ( ((sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1) || 
2914          ((sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1) ) 
2916         const wxSize sizeBest 
= GetBestSize(); 
2917         if ( (sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1 ) 
2919         if ( (sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1 ) 
2920             height 
= sizeBest
.y
; 
2928     int minWidth  
= GetMinWidth(), 
2929         minHeight 
= GetMinHeight(), 
2930         maxWidth  
= GetMaxWidth(), 
2931         maxHeight 
= GetMaxHeight(); 
2933     if ((minWidth  
!= -1) && (m_width  
< minWidth 
)) m_width  
= minWidth
; 
2934     if ((minHeight 
!= -1) && (m_height 
< minHeight
)) m_height 
= minHeight
; 
2935     if ((maxWidth  
!= -1) && (m_width  
> maxWidth 
)) m_width  
= maxWidth
; 
2936     if ((maxHeight 
!= -1) && (m_height 
> maxHeight
)) m_height 
= maxHeight
; 
2938 #if wxUSE_TOOLBAR_NATIVE 
2939     if (wxDynamicCast(GetParent(), wxToolBar
)) 
2941        // don't take the x,y values, they're wrong because toolbar sets them 
2942        GtkWidget  
*widget 
= GTK_WIDGET(m_widget
); 
2943        gtk_widget_set_size_request (widget
, m_width
, m_height
); 
2944        if (GTK_WIDGET_VISIBLE (widget
)) 
2945             gtk_widget_queue_resize (widget
); 
2949     if (m_parent
->m_wxwindow 
== NULL
) // i.e. wxNotebook 
2951         // don't set the size for children of wxNotebook, just take the values. 
2959         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
2960         if ((sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) == 0) 
2962             if (x 
!= -1) m_x 
= x 
+ pizza
->xoffset
; 
2963             if (y 
!= -1) m_y 
= y 
+ pizza
->yoffset
; 
2967             m_x 
= x 
+ pizza
->xoffset
; 
2968             m_y 
= y 
+ pizza
->yoffset
; 
2971         int left_border 
= 0; 
2972         int right_border 
= 0; 
2974         int bottom_border 
= 0; 
2976         /* the default button has a border around it */ 
2977         if (GTK_WIDGET_CAN_DEFAULT(m_widget
)) 
2979             GtkBorder 
*default_border 
= NULL
; 
2980             gtk_widget_style_get( m_widget
, "default_border", &default_border
, NULL 
); 
2983                 left_border 
+= default_border
->left
; 
2984                 right_border 
+= default_border
->right
; 
2985                 top_border 
+= default_border
->top
; 
2986                 bottom_border 
+= default_border
->bottom
; 
2987                 g_free( default_border 
); 
2991         DoMoveWindow( m_x
-top_border
, 
2993                       m_width
+left_border
+right_border
, 
2994                       m_height
+top_border
+bottom_border 
); 
2999         /* Sometimes the client area changes size without the 
3000            whole windows's size changing, but if the whole 
3001            windows's size doesn't change, no wxSizeEvent will 
3002            normally be sent. Here we add an extra test if 
3003            the client test has been changed and this will 
3005         GetClientSize( &m_oldClientWidth
, &m_oldClientHeight 
); 
3009     wxPrintf( "OnSize sent from " ); 
3010     if (GetClassInfo() && GetClassInfo()->GetClassName()) 
3011         wxPrintf( GetClassInfo()->GetClassName() ); 
3012     wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height ); 
3015     if (!m_nativeSizeEvent
) 
3017         wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
3018         event
.SetEventObject( this ); 
3019         GetEventHandler()->ProcessEvent( event 
); 
3025 void wxWindowGTK::OnInternalIdle() 
3027     if ( m_dirtyTabOrder 
) 
3029         m_dirtyTabOrder 
= false; 
3033     // Update style if the window was not yet realized 
3034     // and SetBackgroundStyle(wxBG_STYLE_CUSTOM) was called 
3035     if (m_needsStyleChange
) 
3037         SetBackgroundStyle(GetBackgroundStyle()); 
3038         m_needsStyleChange 
= false; 
3041     // Update invalidated regions. 
3044     wxCursor cursor 
= m_cursor
; 
3045     if (g_globalCursor
.Ok()) cursor 
= g_globalCursor
; 
3049         /* I now set the cursor anew in every OnInternalIdle call 
3050            as setting the cursor in a parent window also effects the 
3051            windows above so that checking for the current cursor is 
3056             GdkWindow 
*window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3058                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3060             if (!g_globalCursor
.Ok()) 
3061                 cursor 
= *wxSTANDARD_CURSOR
; 
3063             window 
= m_widget
->window
; 
3064             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
3065                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3071             GdkWindow 
*window 
= m_widget
->window
; 
3072             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
3073                gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3078     if (wxUpdateUIEvent::CanUpdate(this)) 
3079         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
3082 void wxWindowGTK::DoGetSize( int *width
, int *height 
) const 
3084     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3086     if (width
) (*width
) = m_width
; 
3087     if (height
) (*height
) = m_height
; 
3090 void wxWindowGTK::DoSetClientSize( int width
, int height 
) 
3092     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3101             GetScrollbarWidth(m_widget
, dw
, dh
); 
3104 #ifndef __WXUNIVERSAL__ 
3105         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
3107             // shadow border size is 2 
3111         if (HasFlag(wxSIMPLE_BORDER
)) 
3113             // simple border size is 1 
3117 #endif // __WXUNIVERSAL__ 
3123     SetSize(width
, height
); 
3126 void wxWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
3128     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3140             GetScrollbarWidth(m_widget
, dw
, dh
); 
3143 #ifndef __WXUNIVERSAL__ 
3144         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
3146             // shadow border size is 2 
3150         if (HasFlag(wxSIMPLE_BORDER
)) 
3152             // simple border size is 1 
3156 #endif // __WXUNIVERSAL__ 
3162     if (width
) *width 
= w
; 
3163     if (height
) *height 
= h
; 
3166 void wxWindowGTK::DoGetPosition( int *x
, int *y 
) const 
3168     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3172     if (m_parent 
&& m_parent
->m_wxwindow
) 
3174         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
3175         dx 
= pizza
->xoffset
; 
3176         dy 
= pizza
->yoffset
; 
3179     if (x
) (*x
) = m_x 
- dx
; 
3180     if (y
) (*y
) = m_y 
- dy
; 
3183 void wxWindowGTK::DoClientToScreen( int *x
, int *y 
) const 
3185     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3187     if (!m_widget
->window
) return; 
3189     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3191         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3193         source 
= m_widget
->window
; 
3197     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3201         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3203             org_x 
+= m_widget
->allocation
.x
; 
3204             org_y 
+= m_widget
->allocation
.y
; 
3212 void wxWindowGTK::DoScreenToClient( int *x
, int *y 
) const 
3214     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3216     if (!m_widget
->window
) return; 
3218     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3220         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3222         source 
= m_widget
->window
; 
3226     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3230         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3232             org_x 
+= m_widget
->allocation
.x
; 
3233             org_y 
+= m_widget
->allocation
.y
; 
3241 bool wxWindowGTK::Show( bool show 
) 
3243     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3245     if (!wxWindowBase::Show(show
)) 
3252         gtk_widget_show( m_widget 
); 
3254         gtk_widget_hide( m_widget 
); 
3256     wxShowEvent 
eventShow(GetId(), show
); 
3257     eventShow
.SetEventObject(this); 
3259     GetEventHandler()->ProcessEvent(eventShow
); 
3264 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
) 
3266     win
->OnParentEnable(enable
); 
3268     // Recurse, so that children have the opportunity to Do The Right Thing 
3269     // and reset colours that have been messed up by a parent's (really ancestor's) 
3271     for ( wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
3273           node 
= node
->GetNext() ) 
3275         wxWindow 
*child 
= node
->GetData(); 
3276         if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
))) 
3277             wxWindowNotifyEnable(child
, enable
); 
3281 bool wxWindowGTK::Enable( bool enable 
) 
3283     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3285     if (!wxWindowBase::Enable(enable
)) 
3291     gtk_widget_set_sensitive( m_widget
, enable 
); 
3293         gtk_widget_set_sensitive( m_wxwindow
, enable 
); 
3295     wxWindowNotifyEnable(this, enable
); 
3300 int wxWindowGTK::GetCharHeight() const 
3302     wxCHECK_MSG( (m_widget 
!= NULL
), 12, wxT("invalid window") ); 
3304     wxFont font 
= GetFont(); 
3305     wxCHECK_MSG( font
.Ok(), 12, wxT("invalid font") ); 
3307     PangoContext 
*context 
= NULL
; 
3309         context 
= gtk_widget_get_pango_context( m_widget 
); 
3314     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
3315     PangoLayout 
*layout 
= pango_layout_new(context
); 
3316     pango_layout_set_font_description(layout
, desc
); 
3317     pango_layout_set_text(layout
, "H", 1); 
3318     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
3320     PangoRectangle rect
; 
3321     pango_layout_line_get_extents(line
, NULL
, &rect
); 
3323     g_object_unref( G_OBJECT( layout 
) ); 
3325     return (int) PANGO_PIXELS(rect
.height
); 
3328 int wxWindowGTK::GetCharWidth() const 
3330     wxCHECK_MSG( (m_widget 
!= NULL
), 8, wxT("invalid window") ); 
3332     wxFont font 
= GetFont(); 
3333     wxCHECK_MSG( font
.Ok(), 8, wxT("invalid font") ); 
3335     PangoContext 
*context 
= NULL
; 
3337         context 
= gtk_widget_get_pango_context( m_widget 
); 
3342     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
3343     PangoLayout 
*layout 
= pango_layout_new(context
); 
3344     pango_layout_set_font_description(layout
, desc
); 
3345     pango_layout_set_text(layout
, "g", 1); 
3346     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
3348     PangoRectangle rect
; 
3349     pango_layout_line_get_extents(line
, NULL
, &rect
); 
3351     g_object_unref( G_OBJECT( layout 
) ); 
3353     return (int) PANGO_PIXELS(rect
.width
); 
3356 void wxWindowGTK::GetTextExtent( const wxString
& string
, 
3360                                  int *externalLeading
, 
3361                                  const wxFont 
*theFont 
) const 
3363     wxFont fontToUse 
= theFont 
? *theFont 
: GetFont(); 
3365     wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") ); 
3374     PangoContext 
*context 
= NULL
; 
3376         context 
= gtk_widget_get_pango_context( m_widget 
); 
3385     PangoFontDescription 
*desc 
= fontToUse
.GetNativeFontInfo()->description
; 
3386     PangoLayout 
*layout 
= pango_layout_new(context
); 
3387     pango_layout_set_font_description(layout
, desc
); 
3389         const wxCharBuffer data 
= wxGTK_CONV( string 
); 
3391             pango_layout_set_text(layout
, data
, strlen(data
)); 
3394     PangoRectangle rect
; 
3395     pango_layout_get_extents(layout
, NULL
, &rect
); 
3397     if (x
) (*x
) = (wxCoord
) PANGO_PIXELS(rect
.width
); 
3398     if (y
) (*y
) = (wxCoord
) PANGO_PIXELS(rect
.height
); 
3401         PangoLayoutIter 
*iter 
= pango_layout_get_iter(layout
); 
3402         int baseline 
= pango_layout_iter_get_baseline(iter
); 
3403         pango_layout_iter_free(iter
); 
3404         *descent 
= *y 
- PANGO_PIXELS(baseline
); 
3406     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3408     g_object_unref( G_OBJECT( layout 
) ); 
3411 void wxWindowGTK::SetFocus() 
3413     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3416         // don't do anything if we already have focus 
3422         if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
)) 
3424             gtk_widget_grab_focus (m_wxwindow
); 
3429         if (GTK_IS_CONTAINER(m_widget
)) 
3431             gtk_widget_child_focus( m_widget
, GTK_DIR_TAB_FORWARD 
); 
3434         if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) ) 
3437             if (!GTK_WIDGET_REALIZED(m_widget
)) 
3439                 // we can't set the focus to the widget now so we remember that 
3440                 // it should be focused and will do it later, during the idle 
3441                 // time, as soon as we can 
3442                 wxLogTrace(TRACE_FOCUS
, 
3443                            _T("Delaying setting focus to %s(%s)"), 
3444                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3446                 g_delayedFocus 
= this; 
3450                 wxLogTrace(TRACE_FOCUS
, 
3451                            _T("Setting focus to %s(%s)"), 
3452                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3454                 gtk_widget_grab_focus (m_widget
); 
3459            wxLogTrace(TRACE_FOCUS
, 
3460                       _T("Can't set focus to %s(%s)"), 
3461                       GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3466 bool wxWindowGTK::AcceptsFocus() const 
3468     return m_acceptsFocus 
&& wxWindowBase::AcceptsFocus(); 
3471 bool wxWindowGTK::Reparent( wxWindowBase 
*newParentBase 
) 
3473     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3475     wxWindowGTK 
*oldParent 
= m_parent
, 
3476              *newParent 
= (wxWindowGTK 
*)newParentBase
; 
3478     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3480     if ( !wxWindowBase::Reparent(newParent
) ) 
3483     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3485     /* prevent GTK from deleting the widget arbitrarily */ 
3486     gtk_widget_ref( m_widget 
); 
3490         gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget 
); 
3493     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3497         /* insert GTK representation */ 
3498         (*(newParent
->m_insertCallback
))(newParent
, this); 
3501     /* reverse: prevent GTK from deleting the widget arbitrarily */ 
3502     gtk_widget_unref( m_widget 
); 
3507 void wxWindowGTK::DoAddChild(wxWindowGTK 
*child
) 
3509     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3511     wxASSERT_MSG( (child 
!= NULL
), wxT("invalid child window") ); 
3513     wxASSERT_MSG( (m_insertCallback 
!= NULL
), wxT("invalid child insertion function") ); 
3518     /* insert GTK representation */ 
3519     (*m_insertCallback
)(this, child
); 
3522 void wxWindowGTK::AddChild(wxWindowBase 
*child
) 
3524     wxWindowBase::AddChild(child
); 
3525     m_dirtyTabOrder 
= true; 
3527         wxapp_install_idle_handler(); 
3530 void wxWindowGTK::RemoveChild(wxWindowBase 
*child
) 
3532     wxWindowBase::RemoveChild(child
); 
3533     m_dirtyTabOrder 
= true; 
3535         wxapp_install_idle_handler(); 
3538 void wxWindowGTK::DoMoveInTabOrder(wxWindow 
*win
, MoveKind move
) 
3540     wxWindowBase::DoMoveInTabOrder(win
, move
); 
3541     m_dirtyTabOrder 
= true; 
3543         wxapp_install_idle_handler(); 
3546 bool wxWindowGTK::GTKWidgetNeedsMnemonic() const 
3548     // none needed by default 
3552 void wxWindowGTK::GTKWidgetDoSetMnemonic(GtkWidget
* WXUNUSED(w
)) 
3554     // nothing to do by default since none is needed 
3557 void wxWindowGTK::RealizeTabOrder() 
3561         if ( !m_children
.empty() ) 
3563             // we don't only construct the correct focus chain but also use 
3564             // this opportunity to update the mnemonic widgets for the widgets 
3567             GList 
*chain 
= NULL
; 
3568             wxWindowGTK
* mnemonicWindow 
= NULL
; 
3570             for ( wxWindowList::const_iterator i 
= m_children
.begin(); 
3571                   i 
!= m_children
.end(); 
3574                 wxWindowGTK 
*win 
= *i
; 
3576                 if ( mnemonicWindow 
) 
3578                     if ( win
->AcceptsFocusFromKeyboard() ) 
3580                         // wxComboBox et al. needs to focus on on a different 
3581                         // widget than m_widget, so if the main widget isn't 
3582                         // focusable try the connect widget 
3583                         GtkWidget
* w 
= win
->m_widget
; 
3584                         if ( !GTK_WIDGET_CAN_FOCUS(w
) ) 
3586                             w 
= win
->GetConnectWidget(); 
3587                             if ( !GTK_WIDGET_CAN_FOCUS(w
) ) 
3593                             mnemonicWindow
->GTKWidgetDoSetMnemonic(w
); 
3594                             mnemonicWindow 
= NULL
; 
3598                 else if ( win
->GTKWidgetNeedsMnemonic() ) 
3600                     mnemonicWindow 
= win
; 
3603                 chain 
= g_list_prepend(chain
, win
->m_widget
); 
3606             chain 
= g_list_reverse(chain
); 
3608             gtk_container_set_focus_chain(GTK_CONTAINER(m_wxwindow
), chain
); 
3613             gtk_container_unset_focus_chain(GTK_CONTAINER(m_wxwindow
)); 
3618 void wxWindowGTK::Raise() 
3620     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3622     if (m_wxwindow 
&& m_wxwindow
->window
) 
3624         gdk_window_raise( m_wxwindow
->window 
); 
3626     else if (m_widget
->window
) 
3628         gdk_window_raise( m_widget
->window 
); 
3632 void wxWindowGTK::Lower() 
3634     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3636     if (m_wxwindow 
&& m_wxwindow
->window
) 
3638         gdk_window_lower( m_wxwindow
->window 
); 
3640     else if (m_widget
->window
) 
3642         gdk_window_lower( m_widget
->window 
); 
3646 bool wxWindowGTK::SetCursor( const wxCursor 
&cursor 
) 
3648     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3650     if (cursor 
== m_cursor
) 
3654         wxapp_install_idle_handler(); 
3656     if (cursor 
== wxNullCursor
) 
3657        return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR 
); 
3659        return wxWindowBase::SetCursor( cursor 
); 
3662 void wxWindowGTK::WarpPointer( int x
, int y 
) 
3664     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3666     // We provide this function ourselves as it is 
3667     // missing in GDK (top of this file). 
3669     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3671         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3673         window 
= GetConnectWidget()->window
; 
3676         gdk_window_warp_pointer( window
, x
, y 
); 
3679 static bool wxScrollAdjust(GtkAdjustment
* adj
, double change
) 
3681     double value_start 
= adj
->value
; 
3682     double value 
= value_start 
+ change
; 
3683     double upper 
= adj
->upper 
- adj
->page_size
; 
3688     // Lower bound will be checked by gtk_adjustment_set_value 
3689     gtk_adjustment_set_value(adj
, value
); 
3690     return adj
->value 
!= value_start
; 
3693 bool wxWindowGTK::ScrollLines(int lines
) 
3696         m_vAdjust 
!= NULL 
&& 
3697         wxScrollAdjust(m_vAdjust
, lines 
* m_vAdjust
->step_increment
); 
3700 bool wxWindowGTK::ScrollPages(int pages
) 
3703         m_vAdjust 
!= NULL 
&& 
3704         wxScrollAdjust(m_vAdjust
, pages 
* m_vAdjust
->page_increment
); 
3707 void wxWindowGTK::SetVScrollAdjustment(GtkAdjustment
* adj
) 
3709     wxASSERT(m_vAdjust 
== NULL
); 
3713 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect 
*rect 
) 
3717     if (!m_widget
->window
) 
3722         GdkRectangle gdk_rect
, 
3726             gdk_rect
.x 
= rect
->x
; 
3727             gdk_rect
.y 
= rect
->y
; 
3728             gdk_rect
.width 
= rect
->width
; 
3729             gdk_rect
.height 
= rect
->height
; 
3732         else // invalidate everything 
3737         gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, p
, TRUE 
); 
3741 void wxWindowGTK::Update() 
3745     // when we call Update() we really want to update the window immediately on 
3746     // screen, even if it means flushing the entire queue and hence slowing down 
3747     // everything -- but it should still be done, it's just that Update() should 
3748     // be called very rarely 
3752 void wxWindowGTK::GtkUpdate() 
3754     if (m_wxwindow 
&& GTK_PIZZA(m_wxwindow
)->bin_window
) 
3755         gdk_window_process_updates( GTK_PIZZA(m_wxwindow
)->bin_window
, FALSE 
); 
3757     // for consistency with other platforms (and also because it's convenient 
3758     // to be able to update an entire TLW by calling Update() only once), we 
3759     // should also update all our children here 
3760     for ( wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
3762           node 
= node
->GetNext() ) 
3764         node
->GetData()->GtkUpdate(); 
3768 void wxWindowGTK::GtkSendPaintEvents() 
3772         m_updateRegion
.Clear(); 
3776     // Clip to paint region in wxClientDC 
3777     m_clipPaintRegion 
= true; 
3779     // widget to draw on 
3780     GtkPizza 
*pizza 
= GTK_PIZZA (m_wxwindow
); 
3782     if (GetThemeEnabled() && (GetBackgroundStyle() == wxBG_STYLE_SYSTEM
)) 
3784         // find ancestor from which to steal background 
3785         wxWindow 
*parent 
= wxGetTopLevelParent((wxWindow 
*)this); 
3787             parent 
= (wxWindow
*)this; 
3789         if (GTK_WIDGET_MAPPED(parent
->m_widget
)) 
3791             wxRegionIterator 
upd( m_updateRegion 
); 
3795                 rect
.x 
= upd
.GetX(); 
3796                 rect
.y 
= upd
.GetY(); 
3797                 rect
.width 
= upd
.GetWidth(); 
3798                 rect
.height 
= upd
.GetHeight(); 
3800                 gtk_paint_flat_box( parent
->m_widget
->style
, 
3802                             (GtkStateType
)GTK_WIDGET_STATE(m_wxwindow
), 
3816         wxWindowDC 
dc( (wxWindow
*)this ); 
3817         dc
.SetClippingRegion( m_updateRegion 
); 
3819         wxEraseEvent 
erase_event( GetId(), &dc 
); 
3820         erase_event
.SetEventObject( this ); 
3822         GetEventHandler()->ProcessEvent(erase_event
); 
3825     wxNcPaintEvent 
nc_paint_event( GetId() ); 
3826     nc_paint_event
.SetEventObject( this ); 
3827     GetEventHandler()->ProcessEvent( nc_paint_event 
); 
3829     wxPaintEvent 
paint_event( GetId() ); 
3830     paint_event
.SetEventObject( this ); 
3831     GetEventHandler()->ProcessEvent( paint_event 
); 
3833     m_clipPaintRegion 
= false; 
3835     m_updateRegion
.Clear(); 
3838 void wxWindowGTK::ClearBackground() 
3840     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3844 void wxWindowGTK::DoSetToolTip( wxToolTip 
*tip 
) 
3846     wxWindowBase::DoSetToolTip(tip
); 
3849         m_tooltip
->Apply( (wxWindow 
*)this ); 
3852 void wxWindowGTK::ApplyToolTip( GtkTooltips 
*tips
, const wxChar 
*tip 
) 
3854     wxString 
tmp( tip 
); 
3855     gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxGTK_CONV(tmp
), (gchar
*) NULL 
); 
3857 #endif // wxUSE_TOOLTIPS 
3859 bool wxWindowGTK::SetBackgroundColour( const wxColour 
&colour 
) 
3861     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3863     if (!wxWindowBase::SetBackgroundColour(colour
)) 
3868         // We need the pixel value e.g. for background clearing. 
3869         m_backgroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
3872     // apply style change (forceStyle=true so that new style is applied 
3873     // even if the bg colour changed from valid to wxNullColour) 
3874     if (GetBackgroundStyle() != wxBG_STYLE_CUSTOM
) 
3875         ApplyWidgetStyle(true); 
3880 bool wxWindowGTK::SetForegroundColour( const wxColour 
&colour 
) 
3882     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3884     if (!wxWindowBase::SetForegroundColour(colour
)) 
3891         // We need the pixel value e.g. for background clearing. 
3892         m_foregroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
3895     // apply style change (forceStyle=true so that new style is applied 
3896     // even if the bg colour changed from valid to wxNullColour): 
3897     ApplyWidgetStyle(true); 
3902 PangoContext 
*wxWindowGTK::GtkGetPangoDefaultContext() 
3904     return gtk_widget_get_pango_context( m_widget 
); 
3907 GtkRcStyle 
*wxWindowGTK::CreateWidgetStyle(bool forceStyle
) 
3909     // do we need to apply any changes at all? 
3912          !m_foregroundColour
.Ok() && !m_backgroundColour
.Ok() ) 
3917     GtkRcStyle 
*style 
= gtk_rc_style_new(); 
3922             pango_font_description_copy( m_font
.GetNativeFontInfo()->description 
); 
3925     if ( m_foregroundColour
.Ok() ) 
3927         GdkColor 
*fg 
= m_foregroundColour
.GetColor(); 
3929         style
->fg
[GTK_STATE_NORMAL
] = *fg
; 
3930         style
->color_flags
[GTK_STATE_NORMAL
] = GTK_RC_FG
; 
3932         style
->fg
[GTK_STATE_PRELIGHT
] = *fg
; 
3933         style
->color_flags
[GTK_STATE_PRELIGHT
] = GTK_RC_FG
; 
3935         style
->fg
[GTK_STATE_ACTIVE
] = *fg
; 
3936         style
->color_flags
[GTK_STATE_ACTIVE
] = GTK_RC_FG
; 
3939     if ( m_backgroundColour
.Ok() ) 
3941         GdkColor 
*bg 
= m_backgroundColour
.GetColor(); 
3943         style
->bg
[GTK_STATE_NORMAL
] = *bg
; 
3944         style
->base
[GTK_STATE_NORMAL
] = *bg
; 
3945         style
->color_flags
[GTK_STATE_NORMAL
] = (GtkRcFlags
) 
3946             (style
->color_flags
[GTK_STATE_NORMAL
] | GTK_RC_BG 
| GTK_RC_BASE
); 
3948         style
->bg
[GTK_STATE_PRELIGHT
] = *bg
; 
3949         style
->base
[GTK_STATE_PRELIGHT
] = *bg
; 
3950         style
->color_flags
[GTK_STATE_PRELIGHT
] = (GtkRcFlags
) 
3951             (style
->color_flags
[GTK_STATE_PRELIGHT
] | GTK_RC_BG 
| GTK_RC_BASE
); 
3953         style
->bg
[GTK_STATE_ACTIVE
] = *bg
; 
3954         style
->base
[GTK_STATE_ACTIVE
] = *bg
; 
3955         style
->color_flags
[GTK_STATE_ACTIVE
] = (GtkRcFlags
) 
3956             (style
->color_flags
[GTK_STATE_ACTIVE
] | GTK_RC_BG 
| GTK_RC_BASE
); 
3958         style
->bg
[GTK_STATE_INSENSITIVE
] = *bg
; 
3959         style
->base
[GTK_STATE_INSENSITIVE
] = *bg
; 
3960         style
->color_flags
[GTK_STATE_INSENSITIVE
] = (GtkRcFlags
) 
3961             (style
->color_flags
[GTK_STATE_INSENSITIVE
] | GTK_RC_BG 
| GTK_RC_BASE
); 
3967 void wxWindowGTK::ApplyWidgetStyle(bool forceStyle
) 
3969     GtkRcStyle 
*style 
= CreateWidgetStyle(forceStyle
); 
3972         DoApplyWidgetStyle(style
); 
3973         gtk_rc_style_unref(style
); 
3976     // Style change may affect GTK+'s size calculation: 
3977     InvalidateBestSize(); 
3980 void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
3983         gtk_widget_modify_style(m_wxwindow
, style
); 
3985         gtk_widget_modify_style(m_widget
, style
); 
3988 bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style
) 
3990     wxWindowBase::SetBackgroundStyle(style
); 
3992     if (style 
== wxBG_STYLE_CUSTOM
) 
3994         GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3996             window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3998             window 
= GetConnectWidget()->window
; 
4002             // Make sure GDK/X11 doesn't refresh the window 
4004             gdk_window_set_back_pixmap( window
, None
, False 
); 
4006             Display
* display 
= GDK_WINDOW_DISPLAY(window
); 
4009             m_needsStyleChange 
= false; 
4012             // Do in OnIdle, because the window is not yet available 
4013             m_needsStyleChange 
= true; 
4015         // Don't apply widget style, or we get a grey background 
4019         // apply style change (forceStyle=true so that new style is applied 
4020         // even if the bg colour changed from valid to wxNullColour): 
4021         ApplyWidgetStyle(true); 
4026 #if wxUSE_DRAG_AND_DROP 
4028 void wxWindowGTK::SetDropTarget( wxDropTarget 
*dropTarget 
) 
4030     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4032     GtkWidget 
*dnd_widget 
= GetConnectWidget(); 
4034     if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget 
); 
4036     if (m_dropTarget
) delete m_dropTarget
; 
4037     m_dropTarget 
= dropTarget
; 
4039     if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget 
); 
4042 #endif // wxUSE_DRAG_AND_DROP 
4044 GtkWidget
* wxWindowGTK::GetConnectWidget() 
4046     GtkWidget 
*connect_widget 
= m_widget
; 
4047     if (m_wxwindow
) connect_widget 
= m_wxwindow
; 
4049     return connect_widget
; 
4052 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow 
*window 
) 
4055         return (window 
== GTK_PIZZA(m_wxwindow
)->bin_window
); 
4057     return (window 
== m_widget
->window
); 
4060 bool wxWindowGTK::SetFont( const wxFont 
&font 
) 
4062     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
4064     if (!wxWindowBase::SetFont(font
)) 
4067     // apply style change (forceStyle=true so that new style is applied 
4068     // even if the font changed from valid to wxNullFont): 
4069     ApplyWidgetStyle(true); 
4074 void wxWindowGTK::DoCaptureMouse() 
4076     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4078     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4080         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4082         window 
= GetConnectWidget()->window
; 
4084     wxCHECK_RET( window
, _T("CaptureMouse() failed") ); 
4086     const wxCursor
* cursor 
= &m_cursor
; 
4088         cursor 
= wxSTANDARD_CURSOR
; 
4090     gdk_pointer_grab( window
, FALSE
, 
4092                          (GDK_BUTTON_PRESS_MASK 
| 
4093                           GDK_BUTTON_RELEASE_MASK 
| 
4094                           GDK_POINTER_MOTION_HINT_MASK 
| 
4095                           GDK_POINTER_MOTION_MASK
), 
4097                       cursor
->GetCursor(), 
4098                       (guint32
)GDK_CURRENT_TIME 
); 
4099     g_captureWindow 
= this; 
4100     g_captureWindowHasMouse 
= true; 
4103 void wxWindowGTK::DoReleaseMouse() 
4105     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4107     wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") ); 
4109     g_captureWindow 
= (wxWindowGTK
*) NULL
; 
4111     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4113         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4115         window 
= GetConnectWidget()->window
; 
4120     gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME 
); 
4124 wxWindow 
*wxWindowBase::GetCapture() 
4126     return (wxWindow 
*)g_captureWindow
; 
4129 bool wxWindowGTK::IsRetained() const 
4134 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
, 
4135       int range
, bool refresh 
) 
4137     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4139     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4141     m_hasScrolling 
= true; 
4143     if (orient 
== wxHORIZONTAL
) 
4145         float fpos 
= (float)pos
; 
4146         float frange 
= (float)range
; 
4147         float fthumb 
= (float)thumbVisible
; 
4148         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4149         if (fpos 
< 0.0) fpos 
= 0.0; 
4151         if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) && 
4152             (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2)) 
4154             SetScrollPos( orient
, pos
, refresh 
); 
4158         m_oldHorizontalPos 
= fpos
; 
4160         m_hAdjust
->lower 
= 0.0; 
4161         m_hAdjust
->upper 
= frange
; 
4162         m_hAdjust
->value 
= fpos
; 
4163         m_hAdjust
->step_increment 
= 1.0; 
4164         m_hAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4165         m_hAdjust
->page_size 
= fthumb
; 
4169         float fpos 
= (float)pos
; 
4170         float frange 
= (float)range
; 
4171         float fthumb 
= (float)thumbVisible
; 
4172         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4173         if (fpos 
< 0.0) fpos 
= 0.0; 
4175         if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) && 
4176             (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2)) 
4178             SetScrollPos( orient
, pos
, refresh 
); 
4182         m_oldVerticalPos 
= fpos
; 
4184         m_vAdjust
->lower 
= 0.0; 
4185         m_vAdjust
->upper 
= frange
; 
4186         m_vAdjust
->value 
= fpos
; 
4187         m_vAdjust
->step_increment 
= 1.0; 
4188         m_vAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4189         m_vAdjust
->page_size 
= fthumb
; 
4192     if (orient 
== wxHORIZONTAL
) 
4193         g_signal_emit_by_name (m_hAdjust
, "changed"); 
4195         g_signal_emit_by_name (m_vAdjust
, "changed"); 
4198 void wxWindowGTK::GtkUpdateScrollbar(int orient
) 
4200     GtkAdjustment 
*adj 
= orient 
== wxHORIZONTAL 
? m_hAdjust 
: m_vAdjust
; 
4201     gpointer fn 
= orient 
== wxHORIZONTAL
 
4202             ? (gpointer
) gtk_window_hscroll_callback
 
4203             : (gpointer
) gtk_window_vscroll_callback
; 
4205     g_signal_handlers_disconnect_by_func (adj
, fn
, this); 
4206     g_signal_emit_by_name (adj
, "value_changed"); 
4207     g_signal_connect (adj
, "value_changed", G_CALLBACK (fn
), this); 
4210 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) ) 
4212     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4213     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4215     GtkAdjustment 
*adj 
= orient 
== wxHORIZONTAL 
? m_hAdjust 
: m_vAdjust
; 
4217     float fpos 
= (float)pos
; 
4218     if (fpos 
> adj
->upper 
- adj
->page_size
) 
4219         fpos 
= adj
->upper 
- adj
->page_size
; 
4222     *(orient 
== wxHORIZONTAL 
? &m_oldHorizontalPos 
: &m_oldVerticalPos
) = fpos
; 
4224     if (fabs(fpos
-adj
->value
) < 0.2) 
4228     if ( m_wxwindow
->window 
) 
4233 int wxWindowGTK::GetScrollThumb( int orient 
) const 
4235     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4237     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4239     if (orient 
== wxHORIZONTAL
) 
4240         return (int)(m_hAdjust
->page_size
+0.5); 
4242         return (int)(m_vAdjust
->page_size
+0.5); 
4245 int wxWindowGTK::GetScrollPos( int orient 
) const 
4247     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4249     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4251     if (orient 
== wxHORIZONTAL
) 
4252         return (int)(m_hAdjust
->value
+0.5); 
4254         return (int)(m_vAdjust
->value
+0.5); 
4257 int wxWindowGTK::GetScrollRange( int orient 
) const 
4259     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4261     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4263     if (orient 
== wxHORIZONTAL
) 
4264         return (int)(m_hAdjust
->upper
+0.5); 
4266         return (int)(m_vAdjust
->upper
+0.5); 
4269 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) ) 
4271     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4273     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4275     // No scrolling requested. 
4276     if ((dx 
== 0) && (dy 
== 0)) return; 
4278     m_clipPaintRegion 
= true; 
4280     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy 
); 
4282     m_clipPaintRegion 
= false; 
4285 void wxWindowGTK::GtkScrolledWindowSetBorder(GtkWidget
* w
, int wxstyle
) 
4287     //RN: Note that static controls usually have no border on gtk, so maybe 
4288     //it makes sense to treat that as simply no border at the wx level 
4290     if (!(wxstyle 
& wxNO_BORDER
) && !(wxstyle 
& wxBORDER_STATIC
)) 
4292         GtkShadowType gtkstyle
; 
4294         if(wxstyle 
& wxBORDER_RAISED
) 
4295             gtkstyle 
= GTK_SHADOW_OUT
; 
4296         else if (wxstyle 
& wxBORDER_SUNKEN
) 
4297             gtkstyle 
= GTK_SHADOW_IN
; 
4298         else if (wxstyle 
& wxBORDER_DOUBLE
) 
4299             gtkstyle 
= GTK_SHADOW_ETCHED_IN
; 
4301             gtkstyle 
= GTK_SHADOW_IN
; 
4303         gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(w
), 
4308 void wxWindowGTK::SetWindowStyleFlag( long style 
) 
4310     // Updates the internal variable. NB: Now m_windowStyle bits carry the _new_ style values already 
4311     wxWindowBase::SetWindowStyleFlag(style
); 
4314 // Find the wxWindow at the current mouse position, also returning the mouse 
4316 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
4318     pt 
= wxGetMousePosition(); 
4319     wxWindow
* found 
= wxFindWindowAtPoint(pt
); 
4323 // Get the current mouse position. 
4324 wxPoint 
wxGetMousePosition() 
4326   /* This crashes when used within wxHelpContext, 
4327      so we have to use the X-specific implementation below. 
4329     GdkModifierType *mask; 
4330     (void) gdk_window_get_pointer(NULL, &x, &y, mask); 
4332     return wxPoint(x, y); 
4336     GdkWindow
* windowAtPtr 
= gdk_window_at_pointer(& x
, & y
); 
4338     Display 
*display 
= windowAtPtr 
? GDK_WINDOW_XDISPLAY(windowAtPtr
) : GDK_DISPLAY(); 
4339     Window rootWindow 
= RootWindowOfScreen (DefaultScreenOfDisplay(display
)); 
4340     Window rootReturn
, childReturn
; 
4341     int rootX
, rootY
, winX
, winY
; 
4342     unsigned int maskReturn
; 
4344     XQueryPointer (display
, 
4348                    &rootX
, &rootY
, &winX
, &winY
, &maskReturn
); 
4349     return wxPoint(rootX
, rootY
); 
4353 // Needed for implementing e.g. combobox on wxGTK within a modal dialog. 
4354 void wxAddGrab(wxWindow
* window
) 
4356     gtk_grab_add( (GtkWidget
*) window
->GetHandle() ); 
4359 void wxRemoveGrab(wxWindow
* window
) 
4361     gtk_grab_remove( (GtkWidget
*) window
->GetHandle() ); 
4364 // ---------------------------------------------------------------------------- 
4366 // ---------------------------------------------------------------------------- 
4368 class wxWinModule 
: public wxModule
 
4375     DECLARE_DYNAMIC_CLASS(wxWinModule
) 
4378 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
) 
4380 bool wxWinModule::OnInit() 
4382     // g_eraseGC = gdk_gc_new( gdk_get_default_root_window() ); 
4383     // gdk_gc_set_fill( g_eraseGC, GDK_SOLID ); 
4388 void wxWinModule::OnExit() 
4391         g_object_unref (G_OBJECT (g_eraseGC
));