1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/window.cpp 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling, Julian Smart 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 // For compilers that support precompilation, includes "wx.h". 
  11 #include "wx/wxprec.h" 
  14 #define XWarpPointer XWARPPOINTER 
  17 #include "wx/window.h" 
  25     #include "wx/dcclient.h" 
  27     #include "wx/dialog.h" 
  28     #include "wx/settings.h" 
  29     #include "wx/msgdlg.h" 
  30     #include "wx/textctrl.h" 
  31     #include "wx/toolbar.h" 
  32     #include "wx/combobox.h" 
  33     #include "wx/layout.h" 
  34     #include "wx/statusbr.h" 
  38 #include "wx/module.h" 
  40 #if wxUSE_DRAG_AND_DROP 
  45     #include "wx/tooltip.h" 
  52 #include "wx/fontutil.h" 
  55     #include "wx/thread.h" 
  60 // FIXME: Due to a hack we use GtkCombo in here, which is deprecated since gtk2.3.0 
  61 #include <gtk/gtkversion.h> 
  62 #if defined(GTK_DISABLE_DEPRECATED) && GTK_CHECK_VERSION(2,3,0) 
  63 #undef GTK_DISABLE_DEPRECATED 
  66 #include "wx/gtk/private.h" 
  67 #include <gdk/gdkprivate.h> 
  68 #include <gdk/gdkkeysyms.h> 
  72 #include <gtk/gtkprivate.h> 
  74 #include "wx/gtk/win_gtk.h" 
  76 #include <pango/pangox.h> 
  82 extern GtkContainerClass 
*pizza_parent_class
; 
  84 //----------------------------------------------------------------------------- 
  85 // documentation on internals 
  86 //----------------------------------------------------------------------------- 
  89    I have been asked several times about writing some documentation about 
  90    the GTK port of wxWidgets, especially its internal structures. Obviously, 
  91    you cannot understand wxGTK without knowing a little about the GTK, but 
  92    some more information about what the wxWindow, which is the base class 
  93    for all other window classes, does seems required as well. 
  97    What does wxWindow do? It contains the common interface for the following 
  98    jobs of its descendants: 
 100    1) Define the rudimentary behaviour common to all window classes, such as 
 101    resizing, intercepting user input (so as to make it possible to use these 
 102    events for special purposes in a derived class), window names etc. 
 104    2) Provide the possibility to contain and manage children, if the derived 
 105    class is allowed to contain children, which holds true for those window 
 106    classes which do not display a native GTK widget. To name them, these 
 107    classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame- 
 108    work classes are a special case and are handled a bit differently from 
 109    the rest. The same holds true for the wxNotebook class. 
 111    3) Provide the possibility to draw into a client area of a window. This, 
 112    too, only holds true for classes that do not display a native GTK widget 
 115    4) Provide the entire mechanism for scrolling widgets. This actual inter- 
 116    face for this is usually in wxScrolledWindow, but the GTK implementation 
 119    5) A multitude of helper or extra methods for special purposes, such as 
 120    Drag'n'Drop, managing validators etc. 
 122    6) Display a border (sunken, raised, simple or none). 
 124    Normally one might expect, that one wxWidgets window would always correspond 
 125    to one GTK widget. Under GTK, there is no such all-round widget that has all 
 126    the functionality. Moreover, the GTK defines a client area as a different 
 127    widget from the actual widget you are handling. Last but not least some 
 128    special classes (e.g. wxFrame) handle different categories of widgets and 
 129    still have the possibility to draw something in the client area. 
 130    It was therefore required to write a special purpose GTK widget, that would 
 131    represent a client area in the sense of wxWidgets capable to do the jobs 
 132    2), 3) and 4). I have written this class and it resides in win_gtk.c of 
 135    All windows must have a widget, with which they interact with other under- 
 136    lying GTK widgets. It is this widget, e.g. that has to be resized etc and 
 137    the wxWindow class has a member variable called m_widget which holds a 
 138    pointer to this widget. When the window class represents a GTK native widget, 
 139    this is (in most cases) the only GTK widget the class manages. E.g. the 
 140    wxStaticText class handles only a GtkLabel widget a pointer to which you 
 141    can find in m_widget (defined in wxWindow) 
 143    When the class has a client area for drawing into and for containing children 
 144    it has to handle the client area widget (of the type GtkPizza, defined in 
 145    win_gtk.c), but there could be any number of widgets, handled by a class 
 146    The common rule for all windows is only, that the widget that interacts with 
 147    the rest of GTK must be referenced in m_widget and all other widgets must be 
 148    children of this widget on the GTK level. The top-most widget, which also 
 149    represents the client area, must be in the m_wxwindow field and must be of 
 152    As I said, the window classes that display a GTK native widget only have 
 153    one widget, so in the case of e.g. the wxButton class m_widget holds a 
 154    pointer to a GtkButton widget. But windows with client areas (for drawing 
 155    and children) have a m_widget field that is a pointer to a GtkScrolled- 
 156    Window and a m_wxwindow field that is pointer to a GtkPizza and this 
 157    one is (in the GTK sense) a child of the GtkScrolledWindow. 
 159    If the m_wxwindow field is set, then all input to this widget is inter- 
 160    cepted and sent to the wxWidgets class. If not, all input to the widget 
 161    that gets pointed to by m_widget gets intercepted and sent to the class. 
 165    The design of scrolling in wxWidgets is markedly different from that offered 
 166    by the GTK itself and therefore we cannot simply take it as it is. In GTK, 
 167    clicking on a scrollbar belonging to scrolled window will inevitably move 
 168    the window. In wxWidgets, the scrollbar will only emit an event, send this 
 169    to (normally) a wxScrolledWindow and that class will call ScrollWindow() 
 170    which actually moves the window and its sub-windows. Note that GtkPizza 
 171    memorizes how much it has been scrolled but that wxWidgets forgets this 
 172    so that the two coordinates systems have to be kept in synch. This is done 
 173    in various places using the pizza->xoffset and pizza->yoffset values. 
 177    Singularly the most broken code in GTK is the code that is supposed to 
 178    inform subwindows (child windows) about new positions. Very often, duplicate 
 179    events are sent without changes in size or position, equally often no 
 180    events are sent at all (All this is due to a bug in the GtkContainer code 
 181    which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores 
 182    GTK's own system and it simply waits for size events for toplevel windows 
 183    and then iterates down the respective size events to all window. This has 
 184    the disadvantage that windows might get size events before the GTK widget 
 185    actually has the reported size. This doesn't normally pose any problem, but 
 186    the OpenGL drawing routines rely on correct behaviour. Therefore, I have 
 187    added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas, 
 188    i.e. the wxGLCanvas will emit a size event, when (and not before) the X11 
 189    window that is used for OpenGL output really has that size (as reported by 
 194    If someone at some point of time feels the immense desire to have a look at, 
 195    change or attempt to optimise the Refresh() logic, this person will need an 
 196    intimate understanding of what "draw" and "expose" events are and what 
 197    they are used for, in particular when used in connection with GTK's 
 198    own windowless widgets. Beware. 
 202    Cursors, too, have been a constant source of pleasure. The main difficulty 
 203    is that a GdkWindow inherits a cursor if the programmer sets a new cursor 
 204    for the parent. To prevent this from doing too much harm, I use idle time 
 205    to set the cursor over and over again, starting from the toplevel windows 
 206    and ending with the youngest generation (speaking of parent and child windows). 
 207    Also don't forget that cursors (like much else) are connected to GdkWindows, 
 208    not GtkWidgets and that the "window" field of a GtkWidget might very well 
 209    point to the GdkWindow of the parent widget (-> "window-less widget") and 
 210    that the two obviously have very different meanings. 
 214 //----------------------------------------------------------------------------- 
 216 //----------------------------------------------------------------------------- 
 218 extern bool       g_blockEventsOnDrag
; 
 219 extern bool       g_blockEventsOnScroll
; 
 220 extern wxCursor   g_globalCursor
; 
 222 static GdkGC 
*g_eraseGC 
= NULL
; 
 224 // mouse capture state: the window which has it and if the mouse is currently 
 226 static wxWindowGTK  
*g_captureWindow 
= (wxWindowGTK
*) NULL
; 
 227 static bool g_captureWindowHasMouse 
= false; 
 229 wxWindowGTK  
*g_focusWindow 
= (wxWindowGTK
*) NULL
; 
 231 // the last window which had the focus - this is normally never NULL (except 
 232 // if we never had focus at all) as even when g_focusWindow is NULL it still 
 233 // keeps its previous value 
 234 wxWindowGTK 
*g_focusWindowLast 
= (wxWindowGTK
*) NULL
; 
 236 // If a window get the focus set but has not been realized 
 237 // yet, defer setting the focus to idle time. 
 238 wxWindowGTK 
*g_delayedFocus 
= (wxWindowGTK
*) NULL
; 
 240 extern bool g_mainThreadLocked
; 
 242 //----------------------------------------------------------------------------- 
 244 //----------------------------------------------------------------------------- 
 249 #   define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance"); 
 251 #   define DEBUG_MAIN_THREAD 
 254 #define DEBUG_MAIN_THREAD 
 257 // the trace mask used for the focus debugging messages 
 258 #define TRACE_FOCUS _T("focus") 
 260 //----------------------------------------------------------------------------- 
 261 // missing gdk functions 
 262 //----------------------------------------------------------------------------- 
 265 gdk_window_warp_pointer (GdkWindow      
*window
, 
 270     window 
= gdk_get_default_root_window(); 
 272   if (!GDK_WINDOW_DESTROYED(window
)) 
 274       XWarpPointer (GDK_WINDOW_XDISPLAY(window
), 
 275                     None
,              /* not source window -> move from anywhere */ 
 276                     GDK_WINDOW_XID(window
),  /* dest window */ 
 277                     0, 0, 0, 0,        /* not source window -> move from anywhere */ 
 282 //----------------------------------------------------------------------------- 
 283 // local code (see below) 
 284 //----------------------------------------------------------------------------- 
 286 // returns the child of win which currently has focus or NULL if not found 
 288 // Note: can't be static, needed by textctrl.cpp. 
 289 wxWindow 
*wxFindFocusedChild(wxWindowGTK 
*win
) 
 291     wxWindow 
*winFocus 
= wxWindowGTK::FindFocus(); 
 293         return (wxWindow 
*)NULL
; 
 295     if ( winFocus 
== win 
) 
 296         return (wxWindow 
*)win
; 
 298     for ( wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
 300           node 
= node
->GetNext() ) 
 302         wxWindow 
*child 
= wxFindFocusedChild(node
->GetData()); 
 307     return (wxWindow 
*)NULL
; 
 310 static void GetScrollbarWidth(GtkWidget
* widget
, int& w
, int& h
) 
 312     GtkScrolledWindow
* scroll_window 
= GTK_SCROLLED_WINDOW(widget
); 
 313     GtkScrolledWindowClass
* scroll_class 
= GTK_SCROLLED_WINDOW_CLASS(GTK_OBJECT_GET_CLASS(scroll_window
)); 
 314     GtkRequisition scroll_req
; 
 317     if (scroll_window
->vscrollbar_visible
) 
 319         scroll_req
.width 
= 2; 
 320         scroll_req
.height 
= 2; 
 321         (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
 322             (scroll_window
->vscrollbar
, &scroll_req 
); 
 323         w 
= scroll_req
.width 
+ 
 324             scroll_class
->scrollbar_spacing
; 
 328     if (scroll_window
->hscrollbar_visible
) 
 330         scroll_req
.width 
= 2; 
 331         scroll_req
.height 
= 2; 
 332         (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
 333             (scroll_window
->hscrollbar
, &scroll_req 
); 
 334         h 
= scroll_req
.height 
+ 
 335             scroll_class
->scrollbar_spacing
; 
 339 static void draw_frame( GtkWidget 
*widget
, wxWindowGTK 
*win 
) 
 341     // wxUniversal widgets draw the borders and scrollbars themselves 
 342 #ifndef __WXUNIVERSAL__ 
 349     if (win
->m_hasScrolling
) 
 351         GetScrollbarWidth(widget
, dw
, dh
); 
 356     if (GTK_WIDGET_NO_WINDOW (widget
)) 
 358         dx 
+= widget
->allocation
.x
; 
 359         dy 
+= widget
->allocation
.y
; 
 362     if (win
->HasFlag(wxRAISED_BORDER
)) 
 364         gtk_paint_shadow (widget
->style
, 
 368                           NULL
, NULL
, NULL
, // FIXME: No clipping? 
 370                           widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh 
); 
 374     if (win
->HasFlag(wxSUNKEN_BORDER
)) 
 376         gtk_paint_shadow (widget
->style
, 
 380                           NULL
, NULL
, NULL
, // FIXME: No clipping? 
 382                           widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh 
); 
 386     if (win
->HasFlag(wxSIMPLE_BORDER
)) 
 389         gc 
= gdk_gc_new( widget
->window 
); 
 390         gdk_gc_set_foreground( gc
, &widget
->style
->black 
); 
 391         gdk_draw_rectangle( widget
->window
, gc
, FALSE
, 
 393                          widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 ); 
 397 #endif // __WXUNIVERSAL__ 
 400 //----------------------------------------------------------------------------- 
 401 // "expose_event" of m_widget 
 402 //----------------------------------------------------------------------------- 
 406 gtk_window_own_expose_callback( GtkWidget 
*widget
, 
 407                                 GdkEventExpose 
*gdk_event
, 
 410     if (gdk_event
->count 
> 0) return FALSE
; 
 412     draw_frame( widget
, win 
); 
 414     (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
); 
 420 //----------------------------------------------------------------------------- 
 421 // "size_request" of m_widget 
 422 //----------------------------------------------------------------------------- 
 424 // make it extern because wxStaticText needs to disconnect this one 
 426 void wxgtk_window_size_request_callback(GtkWidget 
*widget
, 
 427                                         GtkRequisition 
*requisition
, 
 431     win
->GetSize( &w
, &h 
); 
 437     requisition
->height 
= h
; 
 438     requisition
->width 
= w
; 
 444 void wxgtk_combo_size_request_callback(GtkWidget 
*widget
, 
 445                                        GtkRequisition 
*requisition
, 
 448     // This callback is actually hooked into the text entry 
 449     // of the combo box, not the GtkHBox. 
 452     win
->GetSize( &w
, &h 
); 
 458     GtkCombo 
*gcombo 
= GTK_COMBO(win
->m_widget
); 
 460     GtkRequisition entry_req
; 
 462     entry_req
.height 
= 2; 
 463     (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(gcombo
->button
) )->size_request 
) 
 464         (gcombo
->button
, &entry_req 
); 
 466     requisition
->width 
= w 
- entry_req
.width
; 
 467     requisition
->height 
= entry_req
.height
; 
 471 //----------------------------------------------------------------------------- 
 472 // "expose_event" of m_wxwindow 
 473 //----------------------------------------------------------------------------- 
 477 gtk_window_expose_callback( GtkWidget 
*widget
, 
 478                             GdkEventExpose 
*gdk_event
, 
 484         wxapp_install_idle_handler(); 
 486     // This callback gets called in drawing-idle time under 
 487     // GTK 2.0, so we don't need to defer anything to idle 
 490     GtkPizza 
*pizza 
= GTK_PIZZA( widget 
); 
 491     if (gdk_event
->window 
!= pizza
->bin_window
) return FALSE
; 
 496         wxPrintf( wxT("OnExpose from ") ); 
 497         if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName()) 
 498             wxPrintf( win
->GetClassInfo()->GetClassName() ); 
 499         wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event
->area
.x
, 
 500                                          (int)gdk_event
->area
.y
, 
 501                                          (int)gdk_event
->area
.width
, 
 502                                          (int)gdk_event
->area
.height 
); 
 507         win
->m_wxwindow
->style
, 
 511         (GdkRectangle
*) NULL
, 
 513         (char *)"button", // const_cast 
 518     win
->GetUpdateRegion() = wxRegion( gdk_event
->region 
); 
 520     win
->GtkSendPaintEvents(); 
 523     // Let parent window draw window-less widgets 
 524     (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
); 
 530 //----------------------------------------------------------------------------- 
 531 // "key_press_event" from any window 
 532 //----------------------------------------------------------------------------- 
 534 // These are used when transforming Ctrl-alpha to ascii values 1-26 
 535 inline bool wxIsLowerChar(int code
) 
 537     return (code 
>= 'a' && code 
<= 'z' ); 
 540 inline bool wxIsUpperChar(int code
) 
 542     return (code 
>= 'A' && code 
<= 'Z' ); 
 546 // set WXTRACE to this to see the key event codes on the console 
 547 #define TRACE_KEYS  _T("keyevent") 
 549 // translates an X key symbol to WXK_XXX value 
 551 // if isChar is true it means that the value returned will be used for EVT_CHAR 
 552 // event and then we choose the logical WXK_XXX, i.e. '/' for GDK_KP_Divide, 
 553 // for example, while if it is false it means that the value is going to be 
 554 // used for KEY_DOWN/UP events and then we translate GDK_KP_Divide to 
 556 static long wxTranslateKeySymToWXKey(KeySym keysym
, bool isChar
) 
 562         // Shift, Control and Alt don't generate the CHAR events at all 
 565             key_code 
= isChar 
? 0 : WXK_SHIFT
; 
 569             key_code 
= isChar 
? 0 : WXK_CONTROL
; 
 577             key_code 
= isChar 
? 0 : WXK_ALT
; 
 580         // neither do the toggle modifies 
 581         case GDK_Scroll_Lock
: 
 582             key_code 
= isChar 
? 0 : WXK_SCROLL
; 
 586             key_code 
= isChar 
? 0 : WXK_CAPITAL
; 
 590             key_code 
= isChar 
? 0 : WXK_NUMLOCK
; 
 594         // various other special keys 
 607         case GDK_ISO_Left_Tab
: 
 614             key_code 
= WXK_RETURN
; 
 618             key_code 
= WXK_CLEAR
; 
 622             key_code 
= WXK_PAUSE
; 
 626             key_code 
= WXK_SELECT
; 
 630             key_code 
= WXK_PRINT
; 
 634             key_code 
= WXK_EXECUTE
; 
 638             key_code 
= WXK_ESCAPE
; 
 641         // cursor and other extended keyboard keys 
 643             key_code 
= WXK_DELETE
; 
 659             key_code 
= WXK_RIGHT
; 
 666         case GDK_Prior
:     // == GDK_Page_Up 
 667             key_code 
= WXK_PAGEUP
; 
 670         case GDK_Next
:      // == GDK_Page_Down 
 671             key_code 
= WXK_PAGEDOWN
; 
 683             key_code 
= WXK_INSERT
; 
 698             key_code 
= (isChar 
? '0' : WXK_NUMPAD0
) + keysym 
- GDK_KP_0
; 
 702             key_code 
= isChar 
? ' ' : WXK_NUMPAD_SPACE
; 
 706             key_code 
= isChar 
? WXK_TAB 
: WXK_NUMPAD_TAB
; 
 710             key_code 
= isChar 
? WXK_RETURN 
: WXK_NUMPAD_ENTER
; 
 714             key_code 
= isChar 
? WXK_F1 
: WXK_NUMPAD_F1
; 
 718             key_code 
= isChar 
? WXK_F2 
: WXK_NUMPAD_F2
; 
 722             key_code 
= isChar 
? WXK_F3 
: WXK_NUMPAD_F3
; 
 726             key_code 
= isChar 
? WXK_F4 
: WXK_NUMPAD_F4
; 
 730             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_HOME
; 
 734             key_code 
= isChar 
? WXK_LEFT 
: WXK_NUMPAD_LEFT
; 
 738             key_code 
= isChar 
? WXK_UP 
: WXK_NUMPAD_UP
; 
 742             key_code 
= isChar 
? WXK_RIGHT 
: WXK_NUMPAD_RIGHT
; 
 746             key_code 
= isChar 
? WXK_DOWN 
: WXK_NUMPAD_DOWN
; 
 749         case GDK_KP_Prior
: // == GDK_KP_Page_Up 
 750             key_code 
= isChar 
? WXK_PAGEUP 
: WXK_NUMPAD_PAGEUP
; 
 753         case GDK_KP_Next
: // == GDK_KP_Page_Down 
 754             key_code 
= isChar 
? WXK_PAGEDOWN 
: WXK_NUMPAD_PAGEDOWN
; 
 758             key_code 
= isChar 
? WXK_END 
: WXK_NUMPAD_END
; 
 762             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_BEGIN
; 
 766             key_code 
= isChar 
? WXK_INSERT 
: WXK_NUMPAD_INSERT
; 
 770             key_code 
= isChar 
? WXK_DELETE 
: WXK_NUMPAD_DELETE
; 
 774             key_code 
= isChar 
? '=' : WXK_NUMPAD_EQUAL
; 
 777         case GDK_KP_Multiply
: 
 778             key_code 
= isChar 
? '*' : WXK_NUMPAD_MULTIPLY
; 
 782             key_code 
= isChar 
? '+' : WXK_NUMPAD_ADD
; 
 785         case GDK_KP_Separator
: 
 786             // FIXME: what is this? 
 787             key_code 
= isChar 
? '.' : WXK_NUMPAD_SEPARATOR
; 
 790         case GDK_KP_Subtract
: 
 791             key_code 
= isChar 
? '-' : WXK_NUMPAD_SUBTRACT
; 
 795             key_code 
= isChar 
? '.' : WXK_NUMPAD_DECIMAL
; 
 799             key_code 
= isChar 
? '/' : WXK_NUMPAD_DIVIDE
; 
 816             key_code 
= WXK_F1 
+ keysym 
- GDK_F1
; 
 826 static inline bool wxIsAsciiKeysym(KeySym ks
) 
 831 static void wxFillOtherKeyEventFields(wxKeyEvent
& event
, 
 833                                       GdkEventKey 
*gdk_event
) 
 837     GdkModifierType state
; 
 838     if (gdk_event
->window
) 
 839         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
 841     event
.SetTimestamp( gdk_event
->time 
); 
 842     event
.SetId(win
->GetId()); 
 843     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
) != 0; 
 844     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
) != 0; 
 845     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
) != 0; 
 846     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
) != 0; 
 847     event
.m_scanCode 
= gdk_event
->keyval
; 
 848     event
.m_rawCode 
= (wxUint32
) gdk_event
->keyval
; 
 849     event
.m_rawFlags 
= 0; 
 851     event
.m_uniChar 
= gdk_keyval_to_unicode(gdk_event
->keyval
); 
 853     wxGetMousePosition( &x
, &y 
); 
 854     win
->ScreenToClient( &x
, &y 
); 
 857     event
.SetEventObject( win 
); 
 862 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
, 
 864                            GdkEventKey 
*gdk_event
) 
 866     // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string 
 867     //     but only event->keyval which is quite useless to us, so remember 
 868     //     the last character from GDK_KEY_PRESS and reuse it as last resort 
 870     // NB: should be MT-safe as we're always called from the main thread only 
 875     } s_lastKeyPress 
= { 0, 0 }; 
 877     KeySym keysym 
= gdk_event
->keyval
; 
 879     wxLogTrace(TRACE_KEYS
, _T("Key %s event: keysym = %ld"), 
 880                event
.GetEventType() == wxEVT_KEY_UP 
? _T("release") 
 884     long key_code 
= wxTranslateKeySymToWXKey(keysym
, false /* !isChar */); 
 888         // do we have the translation or is it a plain ASCII character? 
 889         if ( (gdk_event
->length 
== 1) || wxIsAsciiKeysym(keysym
) ) 
 891             // we should use keysym if it is ASCII as X does some translations 
 892             // like "I pressed while Control is down" => "Ctrl-I" == "TAB" 
 893             // which we don't want here (but which we do use for OnChar()) 
 894             if ( !wxIsAsciiKeysym(keysym
) ) 
 896                 keysym 
= (KeySym
)gdk_event
->string
[0]; 
 899             // we want to always get the same key code when the same key is 
 900             // pressed regardless of the state of the modifiers, i.e. on a 
 901             // standard US keyboard pressing '5' or '%' ('5' key with 
 902             // Shift) should result in the same key code in OnKeyDown(): 
 903             // '5' (although OnChar() will get either '5' or '%'). 
 905             // to do it we first translate keysym to keycode (== scan code) 
 906             // and then back but always using the lower register 
 907             Display 
*dpy 
= (Display 
*)wxGetDisplay(); 
 908             KeyCode keycode 
= XKeysymToKeycode(dpy
, keysym
); 
 910             wxLogTrace(TRACE_KEYS
, _T("\t-> keycode %d"), keycode
); 
 912             KeySym keysymNormalized 
= XKeycodeToKeysym(dpy
, keycode
, 0); 
 914             // use the normalized, i.e. lower register, keysym if we've 
 916             key_code 
= keysymNormalized 
? keysymNormalized 
: keysym
; 
 918             // as explained above, we want to have lower register key codes 
 919             // normally but for the letter keys we want to have the upper ones 
 921             // NB: don't use XConvertCase() here, we want to do it for letters 
 923             key_code 
= toupper(key_code
); 
 925         else // non ASCII key, what to do? 
 927             // by default, ignore it 
 930             // but if we have cached information from the last KEY_PRESS 
 931             if ( gdk_event
->type 
== GDK_KEY_RELEASE 
) 
 934                 if ( keysym 
== s_lastKeyPress
.keysym 
) 
 936                     key_code 
= s_lastKeyPress
.keycode
; 
 941         if ( gdk_event
->type 
== GDK_KEY_PRESS 
) 
 943             // remember it to be reused for KEY_UP event later 
 944             s_lastKeyPress
.keysym 
= keysym
; 
 945             s_lastKeyPress
.keycode 
= key_code
; 
 949     wxLogTrace(TRACE_KEYS
, _T("\t-> wxKeyCode %ld"), key_code
); 
 951     // sending unknown key events doesn't really make sense 
 955     // now fill all the other fields 
 956     wxFillOtherKeyEventFields(event
, win
, gdk_event
); 
 958     event
.m_keyCode 
= key_code
; 
 960     if ( gdk_event
->type 
== GDK_KEY_PRESS 
||  gdk_event
->type 
== GDK_KEY_RELEASE 
) 
 962         event
.m_uniChar 
= key_code
; 
 972     GtkIMContext 
*context
; 
 973     GdkEventKey  
*lastKeyEvent
; 
 977         context 
= gtk_im_multicontext_new(); 
 982         g_object_unref (context
); 
 988 gtk_window_key_press_callback( GtkWidget 
*widget
, 
 989                                GdkEventKey 
*gdk_event
, 
 995         wxapp_install_idle_handler(); 
 999     if (g_blockEventsOnDrag
) 
1003     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
1005     bool return_after_IM 
= false; 
1007     if( wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1009         // Emit KEY_DOWN event 
1010         ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1014         // Return after IM processing as we cannot do 
1015         // anything with it anyhow. 
1016         return_after_IM 
= true; 
1019     // 2005.01.26 modified by Hong Jen Yee (hzysoft@sina.com.tw): 
1020     // When we get a key_press event here, it could be originate 
1021     // from the current widget or its child widgets.  However, only the widget 
1022     // with the INPUT FOCUS can generate the INITIAL key_press event.  That is, 
1023     // if the CURRENT widget doesn't have the FOCUS at all, this event definitely 
1024     // originated from its child widgets and shouldn't be passed to IM context. 
1025     // In fact, what a GTK+ IM should do is filtering keyEvents and convert them 
1026     // into text input ONLY WHEN THE WIDGET HAS INPUT FOCUS.  Besides, when current 
1027     // widgets has both IM context and input focus, the event should be filtered 
1028     // by gtk_im_context_filter_keypress(). 
1029     // Then, we should, according to GTK+ 2.0 API doc, return whatever it returns. 
1030     if ((!ret
) && (win
->m_imData 
!= NULL
) && ( wxWindow::FindFocus() == win 
)) 
1032         // We should let GTK+ IM filter key event first. According to GTK+ 2.0 API 
1033         // docs, if IM filter returns true, no further processing should be done. 
1034         // we should send the key_down event anyway. 
1035         bool intercepted_by_IM 
= gtk_im_context_filter_keypress(win
->m_imData
->context
, gdk_event
); 
1036         win
->m_imData
->lastKeyEvent 
= NULL
; 
1037         if (intercepted_by_IM
) 
1039             wxLogTrace(TRACE_KEYS
, _T("Key event intercepted by IM")); 
1044     if (return_after_IM
) 
1050         wxWindowGTK 
*ancestor 
= win
; 
1053             int command 
= ancestor
->GetAcceleratorTable()->GetCommand( event 
); 
1056                 wxCommandEvent 
command_event( wxEVT_COMMAND_MENU_SELECTED
, command 
); 
1057                 ret 
= ancestor
->GetEventHandler()->ProcessEvent( command_event 
); 
1060             if (ancestor
->IsTopLevel()) 
1062             ancestor 
= ancestor
->GetParent(); 
1065 #endif // wxUSE_ACCEL 
1067     // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x 
1068     // will only be sent if it is not in an accelerator table. 
1072         KeySym keysym 
= gdk_event
->keyval
; 
1073         // Find key code for EVT_CHAR and EVT_CHAR_HOOK events 
1074         key_code 
= wxTranslateKeySymToWXKey(keysym
, true /* isChar */); 
1077             if ( wxIsAsciiKeysym(keysym
) ) 
1080                 key_code 
= (unsigned char)keysym
; 
1082             // gdk_event->string is actually deprecated 
1083             else if ( gdk_event
->length 
== 1 ) 
1085                 key_code 
= (unsigned char)gdk_event
->string
[0]; 
1091             wxLogTrace(TRACE_KEYS
, _T("Char event: %ld"), key_code
); 
1093             event
.m_keyCode 
= key_code
; 
1095             // To conform to the docs we need to translate Ctrl-alpha 
1096             // characters to values in the range 1-26. 
1097             if ( event
.ControlDown() && 
1098                  ( wxIsLowerChar(key_code
) || wxIsUpperChar(key_code
) )) 
1100                 if ( wxIsLowerChar(key_code
) ) 
1101                     event
.m_keyCode 
= key_code 
- 'a' + 1; 
1102                 if ( wxIsUpperChar(key_code
) ) 
1103                     event
.m_keyCode 
= key_code 
- 'A' + 1; 
1105                 event
.m_uniChar 
= event
.m_keyCode
; 
1109             // Implement OnCharHook by checking ancestor top level windows 
1110             wxWindow 
*parent 
= win
; 
1111             while (parent 
&& !parent
->IsTopLevel()) 
1112                 parent 
= parent
->GetParent(); 
1115                 event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1116                 ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1121                 event
.SetEventType(wxEVT_CHAR
); 
1122                 ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1131     // win is a control: tab can be propagated up 
1133          ((gdk_event
->keyval 
== GDK_Tab
) || (gdk_event
->keyval 
== GDK_ISO_Left_Tab
)) && 
1134 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here - the control may 
1135 //     have this style, yet choose not to process this particular TAB in which 
1136 //     case TAB must still work as a navigational character 
1137 // JS: enabling again to make consistent with other platforms 
1138 //     (with wxTE_PROCESS_TAB you have to call Navigate to get default 
1139 //     navigation behaviour) 
1141          (! (win
->HasFlag(wxTE_PROCESS_TAB
) && win
->IsKindOf(CLASSINFO(wxTextCtrl
)) )) && 
1143          win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) ) 
1145         wxNavigationKeyEvent new_event
; 
1146         new_event
.SetEventObject( win
->GetParent() ); 
1147         // GDK reports GDK_ISO_Left_Tab for SHIFT-TAB 
1148         new_event
.SetDirection( (gdk_event
->keyval 
== GDK_Tab
) ); 
1149         // CTRL-TAB changes the (parent) window, i.e. switch notebook page 
1150         new_event
.SetWindowChange( (gdk_event
->state 
& GDK_CONTROL_MASK
) ); 
1151         new_event
.SetCurrentFocus( win 
); 
1152         ret 
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event 
); 
1155     // generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) 
1157          (gdk_event
->keyval 
== GDK_Escape
) ) 
1159         // however only do it if we have a Cancel button in the dialog, 
1160         // otherwise the user code may get confused by the events from a 
1161         // nonexistent button and, worse, a wxButton might get button event 
1162         // from another button which is not really expected 
1163         wxWindow 
*winForCancel 
= win
, 
1165         while ( winForCancel 
) 
1167             btnCancel 
= winForCancel
->FindWindow(wxID_CANCEL
); 
1170                 // found a cancel button 
1174             if ( winForCancel
->IsTopLevel() ) 
1176                 // no need to look further 
1180             // maybe our parent has a cancel button? 
1181             winForCancel 
= winForCancel
->GetParent(); 
1186             wxCommandEvent 
eventClick(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
); 
1187             eventClick
.SetEventObject(btnCancel
); 
1188             ret 
= btnCancel
->GetEventHandler()->ProcessEvent(eventClick
); 
1194         g_signal_stop_emission_by_name (widget
, "key_press_event"); 
1204 gtk_wxwindow_commit_cb (GtkIMContext 
*context
, 
1208     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
1210     // take modifiers, cursor position, timestamp etc. from the last 
1211     // key_press_event that was fed into Input Method: 
1212     if (window
->m_imData
->lastKeyEvent
) 
1214         wxFillOtherKeyEventFields(event
, 
1215                                   window
, window
->m_imData
->lastKeyEvent
); 
1218     const wxWxCharBuffer 
data(wxGTK_CONV_BACK(str
)); 
1224     // Implement OnCharHook by checking ancestor top level windows 
1225     wxWindow 
*parent 
= window
; 
1226     while (parent 
&& !parent
->IsTopLevel()) 
1227         parent 
= parent
->GetParent(); 
1229     for( const wxChar
* pstr 
= data
; *pstr
; pstr
++ ) 
1232         event
.m_uniChar 
= *pstr
; 
1233         // Backward compatible for ISO-8859-1 
1234         event
.m_keyCode 
= *pstr 
< 256 ? event
.m_uniChar 
: 0; 
1235         wxLogTrace(TRACE_KEYS
, _T("IM sent character '%c'"), event
.m_uniChar
); 
1237         event
.m_keyCode 
= *pstr
; 
1238 #endif  // wxUSE_UNICODE 
1240         // To conform to the docs we need to translate Ctrl-alpha 
1241         // characters to values in the range 1-26. 
1242         if ( event
.ControlDown() && 
1243              ( wxIsLowerChar(*pstr
) || wxIsUpperChar(*pstr
) )) 
1245             if ( wxIsLowerChar(*pstr
) ) 
1246                 event
.m_keyCode 
= *pstr 
- 'a' + 1; 
1247             if ( wxIsUpperChar(*pstr
) ) 
1248                 event
.m_keyCode 
= *pstr 
- 'A' + 1; 
1250             event
.m_keyCode 
= *pstr 
- 'a' + 1; 
1252             event
.m_uniChar 
= event
.m_keyCode
; 
1258             event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1259             ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1264             event
.SetEventType(wxEVT_CHAR
); 
1265             ret 
= window
->GetEventHandler()->ProcessEvent( event 
); 
1272 //----------------------------------------------------------------------------- 
1273 // "key_release_event" from any window 
1274 //----------------------------------------------------------------------------- 
1278 gtk_window_key_release_callback( GtkWidget 
*widget
, 
1279                                  GdkEventKey 
*gdk_event
, 
1285         wxapp_install_idle_handler(); 
1290     if (g_blockEventsOnDrag
) 
1293     wxKeyEvent 
event( wxEVT_KEY_UP 
); 
1294     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1296         // unknown key pressed, ignore (the event would be useless anyhow) 
1300     if ( !win
->GetEventHandler()->ProcessEvent( event 
) ) 
1303     g_signal_stop_emission_by_name (widget
, "key_release_event"); 
1308 // ============================================================================ 
1310 // ============================================================================ 
1312 // ---------------------------------------------------------------------------- 
1313 // mouse event processing helpers 
1314 // ---------------------------------------------------------------------------- 
1316 // init wxMouseEvent with the info from GdkEventXXX struct 
1317 template<typename T
> void InitMouseEvent(wxWindowGTK 
*win
, 
1318                                          wxMouseEvent
& event
, 
1321     event
.SetTimestamp( gdk_event
->time 
); 
1322     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
); 
1323     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
); 
1324     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
); 
1325     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
); 
1326     event
.m_leftDown 
= (gdk_event
->state 
& GDK_BUTTON1_MASK
); 
1327     event
.m_middleDown 
= (gdk_event
->state 
& GDK_BUTTON2_MASK
); 
1328     event
.m_rightDown 
= (gdk_event
->state 
& GDK_BUTTON3_MASK
); 
1329     if (event
.GetEventType() == wxEVT_MOUSEWHEEL
) 
1331        event
.m_linesPerAction 
= 3; 
1332        event
.m_wheelDelta 
= 120; 
1333        if (((GdkEventButton
*)gdk_event
)->button 
== 4) 
1334            event
.m_wheelRotation 
= 120; 
1335        else if (((GdkEventButton
*)gdk_event
)->button 
== 5) 
1336            event
.m_wheelRotation 
= -120; 
1339     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1340     event
.m_x 
= (wxCoord
)gdk_event
->x 
- pt
.x
; 
1341     event
.m_y 
= (wxCoord
)gdk_event
->y 
- pt
.y
; 
1343     event
.SetEventObject( win 
); 
1344     event
.SetId( win
->GetId() ); 
1345     event
.SetTimestamp( gdk_event
->time 
); 
1348 static void AdjustEventButtonState(wxMouseEvent
& event
) 
1350     // GDK reports the old state of the button for a button press event, but 
1351     // for compatibility with MSW and common sense we want m_leftDown be TRUE 
1352     // for a LEFT_DOWN event, not FALSE, so we will invert 
1353     // left/right/middleDown for the corresponding click events 
1355     if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) || 
1356         (event
.GetEventType() == wxEVT_LEFT_DCLICK
) || 
1357         (event
.GetEventType() == wxEVT_LEFT_UP
)) 
1359         event
.m_leftDown 
= !event
.m_leftDown
; 
1363     if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) || 
1364         (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) || 
1365         (event
.GetEventType() == wxEVT_MIDDLE_UP
)) 
1367         event
.m_middleDown 
= !event
.m_middleDown
; 
1371     if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) || 
1372         (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) || 
1373         (event
.GetEventType() == wxEVT_RIGHT_UP
)) 
1375         event
.m_rightDown 
= !event
.m_rightDown
; 
1380 // find the window to send the mouse event too 
1382 wxWindowGTK 
*FindWindowForMouseEvent(wxWindowGTK 
*win
, wxCoord
& x
, wxCoord
& y
) 
1387     if (win
->m_wxwindow
) 
1389         GtkPizza 
*pizza 
= GTK_PIZZA(win
->m_wxwindow
); 
1390         xx 
+= pizza
->xoffset
; 
1391         yy 
+= pizza
->yoffset
; 
1394     wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
1397         wxWindowGTK 
*child 
= node
->GetData(); 
1399         node 
= node
->GetNext(); 
1400         if (!child
->IsShown()) 
1403         if (child
->IsTransparentForMouse()) 
1405             // wxStaticBox is transparent in the box itself 
1406             int xx1 
= child
->m_x
; 
1407             int yy1 
= child
->m_y
; 
1408             int xx2 
= child
->m_x 
+ child
->m_width
; 
1409             int yy2 
= child
->m_y 
+ child
->m_height
; 
1412             if (((xx 
>= xx1
) && (xx 
<= xx1
+10) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1414                 ((xx 
>= xx2
-10) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1416                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy1
+10)) || 
1418                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy2
-1) && (yy 
<= yy2
))) 
1429             if ((child
->m_wxwindow 
== (GtkWidget
*) NULL
) && 
1430                 (child
->m_x 
<= xx
) && 
1431                 (child
->m_y 
<= yy
) && 
1432                 (child
->m_x
+child
->m_width  
>= xx
) && 
1433                 (child
->m_y
+child
->m_height 
>= yy
)) 
1446 //----------------------------------------------------------------------------- 
1447 // "button_press_event" 
1448 //----------------------------------------------------------------------------- 
1452 gtk_window_button_press_callback( GtkWidget 
*widget
, 
1453                                   GdkEventButton 
*gdk_event
, 
1459         wxapp_install_idle_handler(); 
1462     wxPrintf( wxT("1) OnButtonPress from ") ); 
1463     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1464         wxPrintf( win->GetClassInfo()->GetClassName() ); 
1465     wxPrintf( wxT(".\n") ); 
1467     if (!win
->m_hasVMT
) return FALSE
; 
1468     if (g_blockEventsOnDrag
) return TRUE
; 
1469     if (g_blockEventsOnScroll
) return TRUE
; 
1471     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1473     if (win
->m_wxwindow 
&& (g_focusWindow 
!= win
) && win
->AcceptsFocus()) 
1475         gtk_widget_grab_focus( win
->m_wxwindow 
); 
1477         wxPrintf( wxT("GrabFocus from ") ); 
1478         if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1479             wxPrintf( win->GetClassInfo()->GetClassName() ); 
1480         wxPrintf( wxT(".\n") ); 
1484     // GDK sends surplus button down events 
1485     // before a double click event. We 
1486     // need to filter these out. 
1487     if (gdk_event
->type 
== GDK_BUTTON_PRESS
) 
1489         GdkEvent 
*peek_event 
= gdk_event_peek(); 
1492             if ((peek_event
->type 
== GDK_2BUTTON_PRESS
) || 
1493                 (peek_event
->type 
== GDK_3BUTTON_PRESS
)) 
1495                 gdk_event_free( peek_event 
); 
1500                 gdk_event_free( peek_event 
); 
1505     wxEventType event_type 
= wxEVT_NULL
; 
1507     // GdkDisplay is a GTK+ 2.2.0 thing 
1508 #if defined(__WXGTK20__) && GTK_CHECK_VERSION(2, 2, 0) 
1509     if ( gdk_event
->type 
== GDK_2BUTTON_PRESS 
&& 
1510             !gtk_check_version(2,2,0) && 
1511             gdk_event
->button 
>= 1 && gdk_event
->button 
<= 3 ) 
1513         // Reset GDK internal timestamp variables in order to disable GDK 
1514         // triple click events. GDK will then next time believe no button has 
1515         // been clicked just before, and send a normal button click event. 
1516         GdkDisplay
* display 
= gtk_widget_get_display (widget
); 
1517         display
->button_click_time
[1] = 0; 
1518         display
->button_click_time
[0] = 0; 
1522     if (gdk_event
->button 
== 1) 
1524         // note that GDK generates triple click events which are not supported 
1525         // by wxWidgets but still have to be passed to the app as otherwise 
1526         // clicks would simply go missing 
1527         switch (gdk_event
->type
) 
1529             // we shouldn't get triple clicks at all for GTK2 because we 
1530             // suppress them artificially using the code above but we still 
1531             // should map them to something for GTK1 and not just ignore them 
1532             // as this would lose clicks 
1533             case GDK_3BUTTON_PRESS
:     // we could also map this to DCLICK... 
1534             case GDK_BUTTON_PRESS
: 
1535                 event_type 
= wxEVT_LEFT_DOWN
; 
1538             case GDK_2BUTTON_PRESS
: 
1539                 event_type 
= wxEVT_LEFT_DCLICK
; 
1543                 // just to silence gcc warnings 
1547     else if (gdk_event
->button 
== 2) 
1549         switch (gdk_event
->type
) 
1551             case GDK_3BUTTON_PRESS
: 
1552             case GDK_BUTTON_PRESS
: 
1553                 event_type 
= wxEVT_MIDDLE_DOWN
; 
1556             case GDK_2BUTTON_PRESS
: 
1557                 event_type 
= wxEVT_MIDDLE_DCLICK
; 
1564     else if (gdk_event
->button 
== 3) 
1566         switch (gdk_event
->type
) 
1568             case GDK_3BUTTON_PRESS
: 
1569             case GDK_BUTTON_PRESS
: 
1570                 event_type 
= wxEVT_RIGHT_DOWN
; 
1573             case GDK_2BUTTON_PRESS
: 
1574                 event_type 
= wxEVT_RIGHT_DCLICK
; 
1581     else if (gdk_event
->button 
== 4 || gdk_event
->button 
== 5) 
1583         if (gdk_event
->type 
== GDK_BUTTON_PRESS 
) 
1585             event_type 
= wxEVT_MOUSEWHEEL
; 
1589     if ( event_type 
== wxEVT_NULL 
) 
1591         // unknown mouse button or click type 
1595     wxMouseEvent 
event( event_type 
); 
1596     InitMouseEvent( win
, event
, gdk_event 
); 
1598     AdjustEventButtonState(event
); 
1600     // wxListBox actually gets mouse events from the item, so we need to give it 
1601     // a chance to correct this 
1602     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1604     // find the correct window to send the event to: it may be a different one 
1605     // from the one which got it at GTK+ level because some controls don't have 
1606     // their own X window and thus cannot get any events. 
1607     if ( !g_captureWindow 
) 
1608         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1610     // reset the event object and id in case win changed. 
1611     event
.SetEventObject( win 
); 
1612     event
.SetId( win
->GetId() ); 
1614     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1616         g_signal_stop_emission_by_name (widget
, "button_press_event"); 
1620     if (event_type 
== wxEVT_RIGHT_DOWN
) 
1622         // generate a "context menu" event: this is similar to right mouse 
1623         // click under many GUIs except that it is generated differently 
1624         // (right up under MSW, ctrl-click under Mac, right down here) and 
1626         // (a) it's a command event and so is propagated to the parent 
1627         // (b) under some ports it can be generated from kbd too 
1628         // (c) it uses screen coords (because of (a)) 
1629         wxContextMenuEvent 
evtCtx( 
1632             win
->ClientToScreen(event
.GetPosition())); 
1633         evtCtx
.SetEventObject(win
); 
1634         return win
->GetEventHandler()->ProcessEvent(evtCtx
); 
1641 //----------------------------------------------------------------------------- 
1642 // "button_release_event" 
1643 //----------------------------------------------------------------------------- 
1647 gtk_window_button_release_callback( GtkWidget 
*widget
, 
1648                                     GdkEventButton 
*gdk_event
, 
1654         wxapp_install_idle_handler(); 
1656     if (!win
->m_hasVMT
) return FALSE
; 
1657     if (g_blockEventsOnDrag
) return FALSE
; 
1658     if (g_blockEventsOnScroll
) return FALSE
; 
1660     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1662     wxEventType event_type 
= wxEVT_NULL
; 
1664     switch (gdk_event
->button
) 
1667             event_type 
= wxEVT_LEFT_UP
; 
1671             event_type 
= wxEVT_MIDDLE_UP
; 
1675             event_type 
= wxEVT_RIGHT_UP
; 
1679             // unknown button, don't process 
1683     wxMouseEvent 
event( event_type 
); 
1684     InitMouseEvent( win
, event
, gdk_event 
); 
1686     AdjustEventButtonState(event
); 
1688     // same wxListBox hack as above 
1689     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1691     if ( !g_captureWindow 
) 
1692         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1694     // reset the event object and id in case win changed. 
1695     event
.SetEventObject( win 
); 
1696     event
.SetId( win
->GetId() ); 
1698     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1700         g_signal_stop_emission_by_name (widget
, "button_release_event"); 
1708 //----------------------------------------------------------------------------- 
1709 // "motion_notify_event" 
1710 //----------------------------------------------------------------------------- 
1714 gtk_window_motion_notify_callback( GtkWidget 
*widget
, 
1715                                    GdkEventMotion 
*gdk_event
, 
1721         wxapp_install_idle_handler(); 
1723     if (!win
->m_hasVMT
) return FALSE
; 
1724     if (g_blockEventsOnDrag
) return FALSE
; 
1725     if (g_blockEventsOnScroll
) return FALSE
; 
1727     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1729     if (gdk_event
->is_hint
) 
1733         GdkModifierType state
; 
1734         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1740     printf( "OnMotion from " ); 
1741     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1742       printf( win->GetClassInfo()->GetClassName() ); 
1746     wxMouseEvent 
event( wxEVT_MOTION 
); 
1747     InitMouseEvent(win
, event
, gdk_event
); 
1749     if ( g_captureWindow 
) 
1751         // synthesise a mouse enter or leave event if needed 
1752         GdkWindow 
*winUnderMouse 
= gdk_window_at_pointer(NULL
, NULL
); 
1753         // This seems to be necessary and actually been added to 
1754         // GDK itself in version 2.0.X 
1757         bool hasMouse 
= winUnderMouse 
== gdk_event
->window
; 
1758         if ( hasMouse 
!= g_captureWindowHasMouse 
) 
1760             // the mouse changed window 
1761             g_captureWindowHasMouse 
= hasMouse
; 
1763             wxMouseEvent 
eventM(g_captureWindowHasMouse 
? wxEVT_ENTER_WINDOW
 
1764                                                         : wxEVT_LEAVE_WINDOW
); 
1765             InitMouseEvent(win
, eventM
, gdk_event
); 
1766             eventM
.SetEventObject(win
); 
1767             win
->GetEventHandler()->ProcessEvent(eventM
); 
1772         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1774         // reset the event object and id in case win changed. 
1775         event
.SetEventObject( win 
); 
1776         event
.SetId( win
->GetId() ); 
1779     if ( !g_captureWindow 
) 
1781         wxSetCursorEvent 
cevent( event
.m_x
, event
.m_y 
); 
1782         if (win
->GetEventHandler()->ProcessEvent( cevent 
)) 
1784             // Rewrite cursor handling here (away from idle). 
1788     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1790         g_signal_stop_emission_by_name (widget
, "motion_notify_event"); 
1798 //----------------------------------------------------------------------------- 
1799 // "scroll_event", (mouse wheel event) 
1800 //----------------------------------------------------------------------------- 
1804 window_scroll_event(GtkWidget
*, GdkEventScroll
* gdk_event
, wxWindow
* win
) 
1809         wxapp_install_idle_handler(); 
1811     if (gdk_event
->direction 
!= GDK_SCROLL_UP 
&& 
1812         gdk_event
->direction 
!= GDK_SCROLL_DOWN
) 
1817     wxMouseEvent 
event(wxEVT_MOUSEWHEEL
); 
1818     // Can't use InitMouse macro because scroll events don't have button 
1819     event
.SetTimestamp( gdk_event
->time 
); 
1820     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
); 
1821     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
); 
1822     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
); 
1823     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
); 
1824     event
.m_leftDown 
= (gdk_event
->state 
& GDK_BUTTON1_MASK
); 
1825     event
.m_middleDown 
= (gdk_event
->state 
& GDK_BUTTON2_MASK
); 
1826     event
.m_rightDown 
= (gdk_event
->state 
& GDK_BUTTON3_MASK
); 
1827     event
.m_linesPerAction 
= 3; 
1828     event
.m_wheelDelta 
= 120; 
1829     if (gdk_event
->direction 
== GDK_SCROLL_UP
) 
1830         event
.m_wheelRotation 
= 120; 
1832         event
.m_wheelRotation 
= -120; 
1834     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1835     event
.m_x 
= (wxCoord
)gdk_event
->x 
- pt
.x
; 
1836     event
.m_y 
= (wxCoord
)gdk_event
->y 
- pt
.y
; 
1838     event
.SetEventObject( win 
); 
1839     event
.SetId( win
->GetId() ); 
1840     event
.SetTimestamp( gdk_event
->time 
); 
1842     return win
->GetEventHandler()->ProcessEvent(event
); 
1846 //----------------------------------------------------------------------------- 
1848 //----------------------------------------------------------------------------- 
1850 static gboolean 
wxgtk_window_popup_menu_callback(GtkWidget
*, wxWindowGTK
* win
) 
1852     wxContextMenuEvent 
event( 
1856     event
.SetEventObject(win
); 
1857     return win
->GetEventHandler()->ProcessEvent(event
); 
1861 //----------------------------------------------------------------------------- 
1863 //----------------------------------------------------------------------------- 
1865 // send the wxChildFocusEvent and wxFocusEvent, common code of 
1866 // gtk_window_focus_in_callback() and SetFocus() 
1867 static bool DoSendFocusEvents(wxWindow 
*win
) 
1869     // Notify the parent keeping track of focus for the kbd navigation 
1870     // purposes that we got it. 
1871     wxChildFocusEvent 
eventChildFocus(win
); 
1872     (void)win
->GetEventHandler()->ProcessEvent(eventChildFocus
); 
1874     wxFocusEvent 
eventFocus(wxEVT_SET_FOCUS
, win
->GetId()); 
1875     eventFocus
.SetEventObject(win
); 
1877     return win
->GetEventHandler()->ProcessEvent(eventFocus
); 
1882 gtk_window_focus_in_callback( GtkWidget 
*widget
, 
1883                               GdkEventFocus 
*WXUNUSED(event
), 
1889         wxapp_install_idle_handler(); 
1892         gtk_im_context_focus_in(win
->m_imData
->context
); 
1895     g_focusWindow 
= win
; 
1897     wxLogTrace(TRACE_FOCUS
, 
1898                _T("%s: focus in"), win
->GetName().c_str()); 
1902         gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
); 
1906     // caret needs to be informed about focus change 
1907     wxCaret 
*caret 
= win
->GetCaret(); 
1910         caret
->OnSetFocus(); 
1912 #endif // wxUSE_CARET 
1914     gboolean ret 
= FALSE
; 
1916     // does the window itself think that it has the focus? 
1917     if ( !win
->m_hasFocus 
) 
1919         // not yet, notify it 
1920         win
->m_hasFocus 
= true; 
1922         (void)DoSendFocusEvents(win
); 
1927     // Disable default focus handling for custom windows 
1928     // since the default GTK+ handler issues a repaint 
1929     if (win
->m_wxwindow
) 
1936 //----------------------------------------------------------------------------- 
1937 // "focus_out_event" 
1938 //----------------------------------------------------------------------------- 
1942 gtk_window_focus_out_callback( GtkWidget 
*widget
, 
1943                                GdkEventFocus 
*gdk_event
, 
1949         wxapp_install_idle_handler(); 
1952         gtk_im_context_focus_out(win
->m_imData
->context
); 
1954     wxLogTrace( TRACE_FOCUS
, 
1955                 _T("%s: focus out"), win
->GetName().c_str() ); 
1958     wxWindowGTK 
*winFocus 
= wxFindFocusedChild(win
); 
1962     g_focusWindow 
= (wxWindowGTK 
*)NULL
; 
1970     // caret needs to be informed about focus change 
1971     wxCaret 
*caret 
= win
->GetCaret(); 
1974         caret
->OnKillFocus(); 
1976 #endif // wxUSE_CARET 
1978     gboolean ret 
= FALSE
; 
1980     // don't send the window a kill focus event if it thinks that it doesn't 
1981     // have focus already 
1982     if ( win
->m_hasFocus 
) 
1984         win
->m_hasFocus 
= false; 
1986         wxFocusEvent 
event( wxEVT_KILL_FOCUS
, win
->GetId() ); 
1987         event
.SetEventObject( win 
); 
1989         (void)win
->GetEventHandler()->ProcessEvent( event 
); 
1994     // Disable default focus handling for custom windows 
1995     // since the default GTK+ handler issues a repaint 
1996     if (win
->m_wxwindow
) 
2003 //----------------------------------------------------------------------------- 
2004 // "enter_notify_event" 
2005 //----------------------------------------------------------------------------- 
2009 gtk_window_enter_callback( GtkWidget 
*widget
, 
2010                            GdkEventCrossing 
*gdk_event
, 
2016         wxapp_install_idle_handler(); 
2018     if (!win
->m_hasVMT
) return FALSE
; 
2019     if (g_blockEventsOnDrag
) return FALSE
; 
2021     // Event was emitted after a grab 
2022     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
2024     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
2028     GdkModifierType state 
= (GdkModifierType
)0; 
2030     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
2032     wxMouseEvent 
event( wxEVT_ENTER_WINDOW 
); 
2033     InitMouseEvent(win
, event
, gdk_event
); 
2034     wxPoint pt 
= win
->GetClientAreaOrigin(); 
2035     event
.m_x 
= x 
+ pt
.x
; 
2036     event
.m_y 
= y 
+ pt
.y
; 
2038     if ( !g_captureWindow 
) 
2040         wxSetCursorEvent 
cevent( event
.m_x
, event
.m_y 
); 
2041         if (win
->GetEventHandler()->ProcessEvent( cevent 
)) 
2043             // Rewrite cursor handling here (away from idle). 
2047     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
2049        g_signal_stop_emission_by_name (widget
, "enter_notify_event"); 
2057 //----------------------------------------------------------------------------- 
2058 // "leave_notify_event" 
2059 //----------------------------------------------------------------------------- 
2063 gtk_window_leave_callback( GtkWidget 
*widget
, 
2064                            GdkEventCrossing 
*gdk_event
, 
2070         wxapp_install_idle_handler(); 
2072     if (!win
->m_hasVMT
) return FALSE
; 
2073     if (g_blockEventsOnDrag
) return FALSE
; 
2075     // Event was emitted after an ungrab 
2076     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
2078     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
2080     wxMouseEvent 
event( wxEVT_LEAVE_WINDOW 
); 
2081     event
.SetTimestamp( gdk_event
->time 
); 
2082     event
.SetEventObject( win 
); 
2086     GdkModifierType state 
= (GdkModifierType
)0; 
2088     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
2090     event
.m_shiftDown 
= (state 
& GDK_SHIFT_MASK
) != 0; 
2091     event
.m_controlDown 
= (state 
& GDK_CONTROL_MASK
) != 0; 
2092     event
.m_altDown 
= (state 
& GDK_MOD1_MASK
) != 0; 
2093     event
.m_metaDown 
= (state 
& GDK_MOD2_MASK
) != 0; 
2094     event
.m_leftDown 
= (state 
& GDK_BUTTON1_MASK
) != 0; 
2095     event
.m_middleDown 
= (state 
& GDK_BUTTON2_MASK
) != 0; 
2096     event
.m_rightDown 
= (state 
& GDK_BUTTON3_MASK
) != 0; 
2098     wxPoint pt 
= win
->GetClientAreaOrigin(); 
2099     event
.m_x 
= x 
+ pt
.x
; 
2100     event
.m_y 
= y 
+ pt
.y
; 
2102     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
2104         g_signal_stop_emission_by_name (widget
, "leave_notify_event"); 
2112 //----------------------------------------------------------------------------- 
2113 // "value_changed" from scrollbar 
2114 //----------------------------------------------------------------------------- 
2118 gtk_scrollbar_value_changed(GtkRange
* range
, wxWindow
* win
) 
2120     wxEventType eventType 
= win
->GetScrollEventType(range
); 
2121     if (eventType 
!= wxEVT_NULL
) 
2123         // Convert scroll event type to scrollwin event type 
2124         eventType 
+= wxEVT_SCROLLWIN_TOP 
- wxEVT_SCROLL_TOP
; 
2125         const int orient 
= range 
== win
->m_scrollBar
[0] ? wxHORIZONTAL 
: wxVERTICAL
; 
2126         const int i 
= orient 
== wxVERTICAL
; 
2127         wxScrollWinEvent 
event(eventType
, win
->GetScrollPos(orient
), orient
); 
2128         event
.SetEventObject(win
); 
2129         win
->m_blockValueChanged
[i
] = true; 
2130         win
->GetEventHandler()->ProcessEvent(event
); 
2131         win
->m_blockValueChanged
[i
] = false; 
2136 //----------------------------------------------------------------------------- 
2137 // "button_press_event" from scrollbar 
2138 //----------------------------------------------------------------------------- 
2142 gtk_scrollbar_button_press_event(GtkRange
*, GdkEventButton
*, wxWindow
* win
) 
2147         wxapp_install_idle_handler(); 
2149     g_blockEventsOnScroll 
= true; 
2150     win
->m_mouseButtonDown 
= true; 
2156 //----------------------------------------------------------------------------- 
2157 // "event_after" from scrollbar 
2158 //----------------------------------------------------------------------------- 
2162 gtk_scrollbar_event_after(GtkRange
* range
, GdkEvent
* event
, wxWindow
* win
) 
2164     if (event
->type 
== GDK_BUTTON_RELEASE
) 
2166         g_signal_handlers_block_by_func(range
, (void*)gtk_scrollbar_event_after
, win
); 
2168         const int orient 
= range 
== win
->m_scrollBar
[0] ? wxHORIZONTAL 
: wxVERTICAL
; 
2169         wxScrollWinEvent 
event(wxEVT_SCROLLWIN_THUMBRELEASE
, win
->GetScrollPos(orient
), orient
); 
2170         event
.SetEventObject(win
); 
2171         win
->GetEventHandler()->ProcessEvent(event
); 
2176 //----------------------------------------------------------------------------- 
2177 // "button_release_event" from scrollbar 
2178 //----------------------------------------------------------------------------- 
2182 gtk_scrollbar_button_release_event(GtkRange
* range
, GdkEventButton
*, wxWindow
* win
) 
2186     g_blockEventsOnScroll 
= false; 
2187     win
->m_mouseButtonDown 
= false; 
2188     // If thumb tracking 
2189     if (win
->m_isScrolling
) 
2191         win
->m_isScrolling 
= false; 
2192         // Hook up handler to send thumb release event after this emission is finished. 
2193         // To allow setting scroll position from event handler, sending event must 
2194         // be deferred until after the GtkRange handler for this signal has run 
2195         g_signal_handlers_unblock_by_func(range
, (void*)gtk_scrollbar_event_after
, win
); 
2202 // ---------------------------------------------------------------------------- 
2203 // this wxWindowBase function is implemented here (in platform-specific file) 
2204 // because it is static and so couldn't be made virtual 
2205 // ---------------------------------------------------------------------------- 
2207 wxWindow 
*wxWindowBase::DoFindFocus() 
2209     // the cast is necessary when we compile in wxUniversal mode 
2210     return (wxWindow 
*)g_focusWindow
; 
2213 //----------------------------------------------------------------------------- 
2214 // "realize" from m_widget 
2215 //----------------------------------------------------------------------------- 
2217 /* We cannot set colours and fonts before the widget has 
2218    been realized, so we do this directly after realization. */ 
2222 gtk_window_realized_callback( GtkWidget 
*m_widget
, wxWindow 
*win 
) 
2227         wxapp_install_idle_handler(); 
2231         GtkPizza 
*pizza 
= GTK_PIZZA( m_widget 
); 
2232         gtk_im_context_set_client_window( win
->m_imData
->context
, 
2233                                           pizza
->bin_window 
); 
2236     wxWindowCreateEvent 
event( win 
); 
2237     event
.SetEventObject( win 
); 
2238     win
->GetEventHandler()->ProcessEvent( event 
); 
2242 //----------------------------------------------------------------------------- 
2244 //----------------------------------------------------------------------------- 
2248 void gtk_window_size_callback( GtkWidget 
*WXUNUSED(widget
), 
2249                                GtkAllocation 
*WXUNUSED(alloc
), 
2253         wxapp_install_idle_handler(); 
2255     int client_width 
= 0; 
2256     int client_height 
= 0; 
2257     win
->GetClientSize( &client_width
, &client_height 
); 
2258     if ((client_width 
== win
->m_oldClientWidth
) && (client_height 
== win
->m_oldClientHeight
)) 
2261     win
->m_oldClientWidth 
= client_width
; 
2262     win
->m_oldClientHeight 
= client_height
; 
2264     if (!win
->m_nativeSizeEvent
) 
2266         wxSizeEvent 
event( win
->GetSize(), win
->GetId() ); 
2267         event
.SetEventObject( win 
); 
2268         win
->GetEventHandler()->ProcessEvent( event 
); 
2275     #define WXUNUSED_UNLESS_XIM(param)  param 
2277     #define WXUNUSED_UNLESS_XIM(param)  WXUNUSED(param) 
2280 /* Resize XIM window */ 
2284 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
), 
2285                                  GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
), 
2286                                  wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) ) 
2289         wxapp_install_idle_handler(); 
2295     if  (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
) 
2299         gdk_drawable_get_size (widget
->window
, &width
, &height
); 
2300         win
->m_icattr
->preedit_area
.width 
= width
; 
2301         win
->m_icattr
->preedit_area
.height 
= height
; 
2302         gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
); 
2308 //----------------------------------------------------------------------------- 
2309 // "realize" from m_wxwindow 
2310 //----------------------------------------------------------------------------- 
2312 /* Initialize XIM support */ 
2316 gtk_wxwindow_realized_callback( GtkWidget 
* WXUNUSED_UNLESS_XIM(widget
), 
2317                                 wxWindowGTK 
* WXUNUSED_UNLESS_XIM(win
) ) 
2320         wxapp_install_idle_handler(); 
2323     if (win
->m_ic
) return; 
2324     if (!widget
) return; 
2325     if (!gdk_im_ready()) return; 
2327     win
->m_icattr 
= gdk_ic_attr_new(); 
2328     if (!win
->m_icattr
) return; 
2332     GdkColormap 
*colormap
; 
2333     GdkICAttr 
*attr 
= win
->m_icattr
; 
2334     unsigned attrmask 
= GDK_IC_ALL_REQ
; 
2336     GdkIMStyle supported_style 
= (GdkIMStyle
) 
2337                                   (GDK_IM_PREEDIT_NONE 
| 
2338                                    GDK_IM_PREEDIT_NOTHING 
| 
2339                                    GDK_IM_PREEDIT_POSITION 
| 
2340                                    GDK_IM_STATUS_NONE 
| 
2341                                    GDK_IM_STATUS_NOTHING
); 
2343     if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2344         supported_style 
= (GdkIMStyle
)(supported_style 
& ~GDK_IM_PREEDIT_POSITION
); 
2346     attr
->style 
= style 
= gdk_im_decide_style (supported_style
); 
2347     attr
->client_window 
= widget
->window
; 
2349     if ((colormap 
= gtk_widget_get_colormap (widget
)) != 
2350             gtk_widget_get_default_colormap ()) 
2352         attrmask 
|= GDK_IC_PREEDIT_COLORMAP
; 
2353         attr
->preedit_colormap 
= colormap
; 
2356     attrmask 
|= GDK_IC_PREEDIT_FOREGROUND
; 
2357     attrmask 
|= GDK_IC_PREEDIT_BACKGROUND
; 
2358     attr
->preedit_foreground 
= widget
->style
->fg
[GTK_STATE_NORMAL
]; 
2359     attr
->preedit_background 
= widget
->style
->base
[GTK_STATE_NORMAL
]; 
2361     switch (style 
& GDK_IM_PREEDIT_MASK
) 
2363         case GDK_IM_PREEDIT_POSITION
: 
2364             if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2366                 g_warning ("over-the-spot style requires fontset"); 
2370             gdk_drawable_get_size (widget
->window
, &width
, &height
); 
2372             attrmask 
|= GDK_IC_PREEDIT_POSITION_REQ
; 
2373             attr
->spot_location
.x 
= 0; 
2374             attr
->spot_location
.y 
= height
; 
2375             attr
->preedit_area
.x 
= 0; 
2376             attr
->preedit_area
.y 
= 0; 
2377             attr
->preedit_area
.width 
= width
; 
2378             attr
->preedit_area
.height 
= height
; 
2379             attr
->preedit_fontset 
= widget
->style
->font
; 
2384       win
->m_ic 
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
); 
2386       if (win
->m_ic 
== NULL
) 
2387           g_warning ("Can't create input context."); 
2390           mask 
= gdk_window_get_events (widget
->window
); 
2391           mask 
= (GdkEventMask
)(mask 
| gdk_ic_get_events (win
->m_ic
)); 
2392           gdk_window_set_events (widget
->window
, mask
); 
2394           if (GTK_WIDGET_HAS_FOCUS(widget
)) 
2395               gdk_im_begin (win
->m_ic
, widget
->window
); 
2401 //----------------------------------------------------------------------------- 
2402 // InsertChild for wxWindowGTK. 
2403 //----------------------------------------------------------------------------- 
2405 /* Callback for wxWindowGTK. This very strange beast has to be used because 
2406  * C++ has no virtual methods in a constructor. We have to emulate a 
2407  * virtual function here as wxNotebook requires a different way to insert 
2408  * a child in it. I had opted for creating a wxNotebookPage window class 
2409  * which would have made this superfluous (such in the MDI window system), 
2410  * but no-one was listening to me... */ 
2412 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child 
) 
2414     /* the window might have been scrolled already, do we 
2415        have to adapt the position */ 
2416     GtkPizza 
*pizza 
= GTK_PIZZA(parent
->m_wxwindow
); 
2417     child
->m_x 
+= pizza
->xoffset
; 
2418     child
->m_y 
+= pizza
->yoffset
; 
2420     gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
), 
2421                      GTK_WIDGET(child
->m_widget
), 
2428 //----------------------------------------------------------------------------- 
2430 //----------------------------------------------------------------------------- 
2432 wxWindow 
*wxGetActiveWindow() 
2434     return wxWindow::FindFocus(); 
2438 wxMouseState 
wxGetMouseState() 
2444     GdkModifierType mask
; 
2446     gdk_window_get_pointer(NULL
, &x
, &y
, &mask
); 
2450     ms
.SetLeftDown(mask 
& GDK_BUTTON1_MASK
); 
2451     ms
.SetMiddleDown(mask 
& GDK_BUTTON2_MASK
); 
2452     ms
.SetRightDown(mask 
& GDK_BUTTON3_MASK
); 
2454     ms
.SetControlDown(mask 
& GDK_CONTROL_MASK
); 
2455     ms
.SetShiftDown(mask 
& GDK_SHIFT_MASK
); 
2456     ms
.SetAltDown(mask 
& GDK_MOD1_MASK
); 
2457     ms
.SetMetaDown(mask 
& GDK_MOD2_MASK
); 
2462 //----------------------------------------------------------------------------- 
2464 //----------------------------------------------------------------------------- 
2466 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
2468 #ifdef __WXUNIVERSAL__ 
2469     IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
) 
2471     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
2472 #endif // __WXUNIVERSAL__/__WXGTK__ 
2474 void wxWindowGTK::Init() 
2477     m_widget 
= (GtkWidget 
*) NULL
; 
2478     m_wxwindow 
= (GtkWidget 
*) NULL
; 
2479     m_focusWidget 
= (GtkWidget 
*) NULL
; 
2489     m_needParent 
= true; 
2490     m_isBeingDeleted 
= false; 
2493     m_nativeSizeEvent 
= false; 
2495     m_hasScrolling 
= false; 
2496     m_isScrolling 
= false; 
2497     m_mouseButtonDown 
= false; 
2498     m_blockScrollEvent 
= false; 
2501     m_scrollBar
[1] = NULL
; 
2504     m_blockValueChanged
[0] = 
2505     m_blockValueChanged
[1] = false; 
2508     m_oldClientHeight 
= 0; 
2512     m_insertCallback 
= (wxInsertChildFunction
) NULL
; 
2514     m_acceptsFocus 
= false; 
2517     m_clipPaintRegion 
= false; 
2519     m_needsStyleChange 
= false; 
2521     m_cursor 
= *wxSTANDARD_CURSOR
; 
2524     m_dirtyTabOrder 
= false; 
2527 wxWindowGTK::wxWindowGTK() 
2532 wxWindowGTK::wxWindowGTK( wxWindow 
*parent
, 
2537                           const wxString 
&name  
) 
2541     Create( parent
, id
, pos
, size
, style
, name 
); 
2544 bool wxWindowGTK::Create( wxWindow 
*parent
, 
2549                           const wxString 
&name  
) 
2551     if (!PreCreation( parent
, pos
, size 
) || 
2552         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
2554         wxFAIL_MSG( wxT("wxWindowGTK creation failed") ); 
2558     m_insertCallback 
= wxInsertChildInWindow
; 
2560     m_widget 
= gtk_scrolled_window_new( (GtkAdjustment 
*) NULL
, (GtkAdjustment 
*) NULL 
); 
2561     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
2563     GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
2565     GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2566     scroll_class
->scrollbar_spacing 
= 0; 
2568     gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
2570     m_scrollBar
[0] = GTK_RANGE(scrolledWindow
->hscrollbar
); 
2571     m_scrollBar
[1] = GTK_RANGE(scrolledWindow
->vscrollbar
); 
2573     m_wxwindow 
= gtk_pizza_new(); 
2575 #ifndef __WXUNIVERSAL__ 
2576     GtkPizza 
*pizza 
= GTK_PIZZA(m_wxwindow
); 
2578     if (HasFlag(wxRAISED_BORDER
)) 
2580         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT 
); 
2582     else if (HasFlag(wxSUNKEN_BORDER
)) 
2584         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN 
); 
2586     else if (HasFlag(wxSIMPLE_BORDER
)) 
2588         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN 
); 
2592         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE 
); 
2594 #endif // __WXUNIVERSAL__ 
2596     gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
2598     GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
2599     m_acceptsFocus 
= true; 
2601     // these handlers block mouse events to any window during scrolling such as 
2602     // motion events and prevent GTK and wxWidgets from fighting over where the 
2604     g_signal_connect(m_scrollBar
[0], "button_press_event", 
2605                      G_CALLBACK(gtk_scrollbar_button_press_event
), this); 
2606     g_signal_connect(m_scrollBar
[1], "button_press_event", 
2607                      G_CALLBACK(gtk_scrollbar_button_press_event
), this); 
2608     g_signal_connect(m_scrollBar
[0], "button_release_event", 
2609                      G_CALLBACK(gtk_scrollbar_button_release_event
), this); 
2610     g_signal_connect(m_scrollBar
[1], "button_release_event", 
2611                      G_CALLBACK(gtk_scrollbar_button_release_event
), this); 
2613     handler_id 
= g_signal_connect( 
2614         m_scrollBar
[0], "event_after", G_CALLBACK(gtk_scrollbar_event_after
), this); 
2615     g_signal_handler_block(m_scrollBar
[0], handler_id
); 
2616     handler_id 
= g_signal_connect( 
2617         m_scrollBar
[1], "event_after", G_CALLBACK(gtk_scrollbar_event_after
), this); 
2618     g_signal_handler_block(m_scrollBar
[1], handler_id
); 
2620     // these handlers get notified when scrollbar slider moves 
2622     g_signal_connect(m_scrollBar
[0], "value_changed", 
2623                      G_CALLBACK(gtk_scrollbar_value_changed
), this); 
2624     g_signal_connect(m_scrollBar
[1], "value_changed", 
2625                      G_CALLBACK(gtk_scrollbar_value_changed
), this); 
2627     gtk_widget_show( m_wxwindow 
); 
2630         m_parent
->DoAddChild( this ); 
2632     m_focusWidget 
= m_wxwindow
; 
2639 wxWindowGTK::~wxWindowGTK() 
2643     if (g_focusWindow 
== this) 
2644         g_focusWindow 
= NULL
; 
2646     if ( g_delayedFocus 
== this ) 
2647         g_delayedFocus 
= NULL
; 
2649     m_isBeingDeleted 
= true; 
2652     // destroy children before destroying this window itself 
2655     // unhook focus handlers to prevent stray events being 
2656     // propagated to this (soon to be) dead object 
2657     if (m_focusWidget 
!= NULL
) 
2659         g_signal_handlers_disconnect_by_func (m_focusWidget
, 
2660                                               (gpointer
) gtk_window_focus_in_callback
, 
2662         g_signal_handlers_disconnect_by_func (m_focusWidget
, 
2663                                               (gpointer
) gtk_window_focus_out_callback
, 
2672         gdk_ic_destroy (m_ic
); 
2674         gdk_ic_attr_destroy (m_icattr
); 
2677     // delete before the widgets to avoid a crash on solaris 
2682         gtk_widget_destroy( m_wxwindow 
); 
2683         m_wxwindow 
= (GtkWidget
*) NULL
; 
2688         gtk_widget_destroy( m_widget 
); 
2689         m_widget 
= (GtkWidget
*) NULL
; 
2693 bool wxWindowGTK::PreCreation( wxWindowGTK 
*parent
, const wxPoint 
&pos
,  const wxSize 
&size 
) 
2695     wxCHECK_MSG( !m_needParent 
|| parent
, false, wxT("Need complete parent.") ); 
2697     // Use either the given size, or the default if -1 is given. 
2698     // See wxWindowBase for these functions. 
2699     m_width 
= WidthDefault(size
.x
) ; 
2700     m_height 
= HeightDefault(size
.y
); 
2708 void wxWindowGTK::PostCreation() 
2710     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2716             // these get reported to wxWidgets -> wxPaintEvent 
2718             gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE 
); 
2720             g_signal_connect (m_wxwindow
, "expose_event", 
2721                               G_CALLBACK (gtk_window_expose_callback
), this); 
2723             gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow
), HasFlag( wxFULL_REPAINT_ON_RESIZE 
) ); 
2726         // Create input method handler 
2727         m_imData 
= new wxGtkIMData
; 
2729         // Cannot handle drawing preedited text yet 
2730         gtk_im_context_set_use_preedit( m_imData
->context
, FALSE 
); 
2732         g_signal_connect (m_imData
->context
, "commit", 
2733                           G_CALLBACK (gtk_wxwindow_commit_cb
), this); 
2735         // these are called when the "sunken" or "raised" borders are drawn 
2736         g_signal_connect (m_widget
, "expose_event", 
2737                           G_CALLBACK (gtk_window_own_expose_callback
), this); 
2742     if (!GTK_IS_WINDOW(m_widget
)) 
2744         if (m_focusWidget 
== NULL
) 
2745             m_focusWidget 
= m_widget
; 
2749             g_signal_connect (m_focusWidget
, "focus_in_event", 
2750                           G_CALLBACK (gtk_window_focus_in_callback
), this); 
2751             g_signal_connect (m_focusWidget
, "focus_out_event", 
2752                                 G_CALLBACK (gtk_window_focus_out_callback
), this); 
2756             g_signal_connect_after (m_focusWidget
, "focus_in_event", 
2757                           G_CALLBACK (gtk_window_focus_in_callback
), this); 
2758             g_signal_connect_after (m_focusWidget
, "focus_out_event", 
2759                                 G_CALLBACK (gtk_window_focus_out_callback
), this); 
2763     // connect to the various key and mouse handlers 
2765     GtkWidget 
*connect_widget 
= GetConnectWidget(); 
2767     ConnectWidget( connect_widget 
); 
2769     /* We cannot set colours, fonts and cursors before the widget has 
2770        been realized, so we do this directly after realization */ 
2771     g_signal_connect (connect_widget
, "realize", 
2772                       G_CALLBACK (gtk_window_realized_callback
), this); 
2776         // Catch native resize events 
2777         g_signal_connect (m_wxwindow
, "size_allocate", 
2778                           G_CALLBACK (gtk_window_size_callback
), this); 
2780         // Initialize XIM support 
2781         g_signal_connect (m_wxwindow
, "realize", 
2782                           G_CALLBACK (gtk_wxwindow_realized_callback
), this); 
2784         // And resize XIM window 
2785         g_signal_connect (m_wxwindow
, "size_allocate", 
2786                           G_CALLBACK (gtk_wxwindow_size_callback
), this); 
2789     if (GTK_IS_COMBO(m_widget
)) 
2791         GtkCombo 
*gcombo 
= GTK_COMBO(m_widget
); 
2793         g_signal_connect (gcombo
->entry
, "size_request", 
2794                           G_CALLBACK (wxgtk_combo_size_request_callback
), 
2797 #ifdef GTK_IS_FILE_CHOOSER_BUTTON 
2798     else if (GTK_IS_FILE_CHOOSER_BUTTON(m_widget
)) 
2800         // If we connect to the "size_request" signal of a GtkFileChooserButton 
2801         // then that control won't be sized properly when placed inside sizers 
2802         // (this can be tested removing this elseif and running XRC or WIDGETS samples) 
2803         // FIXME: what should be done here ? 
2808         // This is needed if we want to add our windows into native 
2809         // GTK controls, such as the toolbar. With this callback, the 
2810         // toolbar gets to know the correct size (the one set by the 
2811         // programmer). Sadly, it misbehaves for wxComboBox. 
2812         g_signal_connect (m_widget
, "size_request", 
2813                           G_CALLBACK (wxgtk_window_size_request_callback
), 
2817     InheritAttributes(); 
2821     // unless the window was created initially hidden (i.e. Hide() had been 
2822     // called before Create()), we should show it at GTK+ level as well 
2824         gtk_widget_show( m_widget 
); 
2827 void wxWindowGTK::ConnectWidget( GtkWidget 
*widget 
) 
2829     g_signal_connect (widget
, "key_press_event", 
2830                       G_CALLBACK (gtk_window_key_press_callback
), this); 
2831     g_signal_connect (widget
, "key_release_event", 
2832                       G_CALLBACK (gtk_window_key_release_callback
), this); 
2833     g_signal_connect (widget
, "button_press_event", 
2834                       G_CALLBACK (gtk_window_button_press_callback
), this); 
2835     g_signal_connect (widget
, "button_release_event", 
2836                       G_CALLBACK (gtk_window_button_release_callback
), this); 
2837     g_signal_connect (widget
, "motion_notify_event", 
2838                       G_CALLBACK (gtk_window_motion_notify_callback
), this); 
2839     g_signal_connect (widget
, "scroll_event", 
2840                       G_CALLBACK (window_scroll_event
), this); 
2841     g_signal_connect (widget
, "popup_menu", 
2842                      G_CALLBACK (wxgtk_window_popup_menu_callback
), this); 
2843     g_signal_connect (widget
, "enter_notify_event", 
2844                       G_CALLBACK (gtk_window_enter_callback
), this); 
2845     g_signal_connect (widget
, "leave_notify_event", 
2846                       G_CALLBACK (gtk_window_leave_callback
), this); 
2849 bool wxWindowGTK::Destroy() 
2851     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2855     return wxWindowBase::Destroy(); 
2858 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
) 
2860     gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height 
); 
2863 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
2865     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2866     wxASSERT_MSG( (m_parent 
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") ); 
2869     printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height ); 
2872     if (m_resizing
) return; /* I don't like recursions */ 
2875     int currentX
, currentY
; 
2876     GetPosition(¤tX
, ¤tY
); 
2877     if (x 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
2879     if (y 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
2881     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
2883     // calculate the best size if we should auto size the window 
2884     if ( ((sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1) || 
2885          ((sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1) ) 
2887         const wxSize sizeBest 
= GetBestSize(); 
2888         if ( (sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1 ) 
2890         if ( (sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1 ) 
2891             height 
= sizeBest
.y
; 
2899     int minWidth  
= GetMinWidth(), 
2900         minHeight 
= GetMinHeight(), 
2901         maxWidth  
= GetMaxWidth(), 
2902         maxHeight 
= GetMaxHeight(); 
2904     if ((minWidth  
!= -1) && (m_width  
< minWidth 
)) m_width  
= minWidth
; 
2905     if ((minHeight 
!= -1) && (m_height 
< minHeight
)) m_height 
= minHeight
; 
2906     if ((maxWidth  
!= -1) && (m_width  
> maxWidth 
)) m_width  
= maxWidth
; 
2907     if ((maxHeight 
!= -1) && (m_height 
> maxHeight
)) m_height 
= maxHeight
; 
2909 #if wxUSE_TOOLBAR_NATIVE 
2910     if (wxDynamicCast(GetParent(), wxToolBar
)) 
2912        // don't take the x,y values, they're wrong because toolbar sets them 
2913        GtkWidget  
*widget 
= GTK_WIDGET(m_widget
); 
2914        gtk_widget_set_size_request (widget
, m_width
, m_height
); 
2915        if (GTK_WIDGET_VISIBLE (widget
)) 
2916             gtk_widget_queue_resize (widget
); 
2920     if (m_parent
->m_wxwindow 
== NULL
) // i.e. wxNotebook 
2922         // don't set the size for children of wxNotebook, just take the values. 
2930         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
2931         if ((sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) == 0) 
2933             if (x 
!= -1) m_x 
= x 
+ pizza
->xoffset
; 
2934             if (y 
!= -1) m_y 
= y 
+ pizza
->yoffset
; 
2938             m_x 
= x 
+ pizza
->xoffset
; 
2939             m_y 
= y 
+ pizza
->yoffset
; 
2942         int left_border 
= 0; 
2943         int right_border 
= 0; 
2945         int bottom_border 
= 0; 
2947         /* the default button has a border around it */ 
2948         if (GTK_WIDGET_CAN_DEFAULT(m_widget
)) 
2950             GtkBorder 
*default_border 
= NULL
; 
2951             gtk_widget_style_get( m_widget
, "default_border", &default_border
, NULL 
); 
2954                 left_border 
+= default_border
->left
; 
2955                 right_border 
+= default_border
->right
; 
2956                 top_border 
+= default_border
->top
; 
2957                 bottom_border 
+= default_border
->bottom
; 
2958                 g_free( default_border 
); 
2962         DoMoveWindow( m_x
-top_border
, 
2964                       m_width
+left_border
+right_border
, 
2965                       m_height
+top_border
+bottom_border 
); 
2970         /* Sometimes the client area changes size without the 
2971            whole windows's size changing, but if the whole 
2972            windows's size doesn't change, no wxSizeEvent will 
2973            normally be sent. Here we add an extra test if 
2974            the client test has been changed and this will 
2976         GetClientSize( &m_oldClientWidth
, &m_oldClientHeight 
); 
2980     wxPrintf( "OnSize sent from " ); 
2981     if (GetClassInfo() && GetClassInfo()->GetClassName()) 
2982         wxPrintf( GetClassInfo()->GetClassName() ); 
2983     wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height ); 
2986     if (!m_nativeSizeEvent
) 
2988         wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
2989         event
.SetEventObject( this ); 
2990         GetEventHandler()->ProcessEvent( event 
); 
2996 void wxWindowGTK::OnInternalIdle() 
2998     if ( m_dirtyTabOrder 
) 
3000         m_dirtyTabOrder 
= false; 
3004     // Update style if the window was not yet realized 
3005     // and SetBackgroundStyle(wxBG_STYLE_CUSTOM) was called 
3006     if (m_needsStyleChange
) 
3008         SetBackgroundStyle(GetBackgroundStyle()); 
3009         m_needsStyleChange 
= false; 
3012     // Update invalidated regions. 
3015     wxCursor cursor 
= m_cursor
; 
3016     if (g_globalCursor
.Ok()) cursor 
= g_globalCursor
; 
3020         /* I now set the cursor anew in every OnInternalIdle call 
3021            as setting the cursor in a parent window also effects the 
3022            windows above so that checking for the current cursor is 
3027             GdkWindow 
*window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3029                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3031             if (!g_globalCursor
.Ok()) 
3032                 cursor 
= *wxSTANDARD_CURSOR
; 
3034             window 
= m_widget
->window
; 
3035             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
3036                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3039         else if ( m_widget 
) 
3041             GdkWindow 
*window 
= m_widget
->window
; 
3042             if ( window 
&& !GTK_WIDGET_NO_WINDOW(m_widget
) ) 
3043                gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3047     if (wxUpdateUIEvent::CanUpdate(this)) 
3048         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
3051 void wxWindowGTK::DoGetSize( int *width
, int *height 
) const 
3053     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3055     if (width
) (*width
) = m_width
; 
3056     if (height
) (*height
) = m_height
; 
3059 void wxWindowGTK::DoSetClientSize( int width
, int height 
) 
3061     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3070             GetScrollbarWidth(m_widget
, dw
, dh
); 
3073 #ifndef __WXUNIVERSAL__ 
3074         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
3076             // shadow border size is 2 
3080         if (HasFlag(wxSIMPLE_BORDER
)) 
3082             // simple border size is 1 
3086 #endif // __WXUNIVERSAL__ 
3092     SetSize(width
, height
); 
3095 void wxWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
3097     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3109             GetScrollbarWidth(m_widget
, dw
, dh
); 
3112 #ifndef __WXUNIVERSAL__ 
3113         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
3115             // shadow border size is 2 
3119         if (HasFlag(wxSIMPLE_BORDER
)) 
3121             // simple border size is 1 
3125 #endif // __WXUNIVERSAL__ 
3131     if (width
) *width 
= w
; 
3132     if (height
) *height 
= h
; 
3135 void wxWindowGTK::DoGetPosition( int *x
, int *y 
) const 
3137     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3141     if (m_parent 
&& m_parent
->m_wxwindow
) 
3143         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
3144         dx 
= pizza
->xoffset
; 
3145         dy 
= pizza
->yoffset
; 
3148     if (x
) (*x
) = m_x 
- dx
; 
3149     if (y
) (*y
) = m_y 
- dy
; 
3152 void wxWindowGTK::DoClientToScreen( int *x
, int *y 
) const 
3154     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3156     if (!m_widget
->window
) return; 
3158     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3160         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3162         source 
= m_widget
->window
; 
3166     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3170         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3172             org_x 
+= m_widget
->allocation
.x
; 
3173             org_y 
+= m_widget
->allocation
.y
; 
3181 void wxWindowGTK::DoScreenToClient( int *x
, int *y 
) const 
3183     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3185     if (!m_widget
->window
) return; 
3187     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3189         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3191         source 
= m_widget
->window
; 
3195     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3199         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3201             org_x 
+= m_widget
->allocation
.x
; 
3202             org_y 
+= m_widget
->allocation
.y
; 
3210 bool wxWindowGTK::Show( bool show 
) 
3212     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3214     if (!wxWindowBase::Show(show
)) 
3221         gtk_widget_show( m_widget 
); 
3223         gtk_widget_hide( m_widget 
); 
3225     wxShowEvent 
eventShow(GetId(), show
); 
3226     eventShow
.SetEventObject(this); 
3228     GetEventHandler()->ProcessEvent(eventShow
); 
3233 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
) 
3235     win
->OnParentEnable(enable
); 
3237     // Recurse, so that children have the opportunity to Do The Right Thing 
3238     // and reset colours that have been messed up by a parent's (really ancestor's) 
3240     for ( wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
3242           node 
= node
->GetNext() ) 
3244         wxWindow 
*child 
= node
->GetData(); 
3245         if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
))) 
3246             wxWindowNotifyEnable(child
, enable
); 
3250 bool wxWindowGTK::Enable( bool enable 
) 
3252     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3254     if (!wxWindowBase::Enable(enable
)) 
3260     gtk_widget_set_sensitive( m_widget
, enable 
); 
3262         gtk_widget_set_sensitive( m_wxwindow
, enable 
); 
3264     wxWindowNotifyEnable(this, enable
); 
3269 int wxWindowGTK::GetCharHeight() const 
3271     wxCHECK_MSG( (m_widget 
!= NULL
), 12, wxT("invalid window") ); 
3273     wxFont font 
= GetFont(); 
3274     wxCHECK_MSG( font
.Ok(), 12, wxT("invalid font") ); 
3276     PangoContext 
*context 
= NULL
; 
3278         context 
= gtk_widget_get_pango_context( m_widget 
); 
3283     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
3284     PangoLayout 
*layout 
= pango_layout_new(context
); 
3285     pango_layout_set_font_description(layout
, desc
); 
3286     pango_layout_set_text(layout
, "H", 1); 
3287     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
3289     PangoRectangle rect
; 
3290     pango_layout_line_get_extents(line
, NULL
, &rect
); 
3292     g_object_unref (layout
); 
3294     return (int) PANGO_PIXELS(rect
.height
); 
3297 int wxWindowGTK::GetCharWidth() const 
3299     wxCHECK_MSG( (m_widget 
!= NULL
), 8, wxT("invalid window") ); 
3301     wxFont font 
= GetFont(); 
3302     wxCHECK_MSG( font
.Ok(), 8, wxT("invalid font") ); 
3304     PangoContext 
*context 
= NULL
; 
3306         context 
= gtk_widget_get_pango_context( m_widget 
); 
3311     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
3312     PangoLayout 
*layout 
= pango_layout_new(context
); 
3313     pango_layout_set_font_description(layout
, desc
); 
3314     pango_layout_set_text(layout
, "g", 1); 
3315     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
3317     PangoRectangle rect
; 
3318     pango_layout_line_get_extents(line
, NULL
, &rect
); 
3320     g_object_unref (layout
); 
3322     return (int) PANGO_PIXELS(rect
.width
); 
3325 void wxWindowGTK::GetTextExtent( const wxString
& string
, 
3329                                  int *externalLeading
, 
3330                                  const wxFont 
*theFont 
) const 
3332     wxFont fontToUse 
= theFont 
? *theFont 
: GetFont(); 
3334     wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") ); 
3343     PangoContext 
*context 
= NULL
; 
3345         context 
= gtk_widget_get_pango_context( m_widget 
); 
3354     PangoFontDescription 
*desc 
= fontToUse
.GetNativeFontInfo()->description
; 
3355     PangoLayout 
*layout 
= pango_layout_new(context
); 
3356     pango_layout_set_font_description(layout
, desc
); 
3358         const wxCharBuffer data 
= wxGTK_CONV( string 
); 
3360             pango_layout_set_text(layout
, data
, strlen(data
)); 
3363     PangoRectangle rect
; 
3364     pango_layout_get_extents(layout
, NULL
, &rect
); 
3366     if (x
) (*x
) = (wxCoord
) PANGO_PIXELS(rect
.width
); 
3367     if (y
) (*y
) = (wxCoord
) PANGO_PIXELS(rect
.height
); 
3370         PangoLayoutIter 
*iter 
= pango_layout_get_iter(layout
); 
3371         int baseline 
= pango_layout_iter_get_baseline(iter
); 
3372         pango_layout_iter_free(iter
); 
3373         *descent 
= *y 
- PANGO_PIXELS(baseline
); 
3375     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3377     g_object_unref (layout
); 
3380 void wxWindowGTK::SetFocus() 
3382     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3385         // don't do anything if we already have focus 
3391         if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
)) 
3393             gtk_widget_grab_focus (m_wxwindow
); 
3398         if (GTK_IS_CONTAINER(m_widget
)) 
3400             gtk_widget_child_focus( m_widget
, GTK_DIR_TAB_FORWARD 
); 
3403         if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) ) 
3406             if (!GTK_WIDGET_REALIZED(m_widget
)) 
3408                 // we can't set the focus to the widget now so we remember that 
3409                 // it should be focused and will do it later, during the idle 
3410                 // time, as soon as we can 
3411                 wxLogTrace(TRACE_FOCUS
, 
3412                            _T("Delaying setting focus to %s(%s)"), 
3413                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3415                 g_delayedFocus 
= this; 
3419                 wxLogTrace(TRACE_FOCUS
, 
3420                            _T("Setting focus to %s(%s)"), 
3421                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3423                 gtk_widget_grab_focus (m_widget
); 
3428            wxLogTrace(TRACE_FOCUS
, 
3429                       _T("Can't set focus to %s(%s)"), 
3430                       GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3435 bool wxWindowGTK::AcceptsFocus() const 
3437     return m_acceptsFocus 
&& wxWindowBase::AcceptsFocus(); 
3440 bool wxWindowGTK::Reparent( wxWindowBase 
*newParentBase 
) 
3442     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3444     wxWindowGTK 
*oldParent 
= m_parent
, 
3445              *newParent 
= (wxWindowGTK 
*)newParentBase
; 
3447     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3449     if ( !wxWindowBase::Reparent(newParent
) ) 
3452     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3454     /* prevent GTK from deleting the widget arbitrarily */ 
3455     gtk_widget_ref( m_widget 
); 
3459         gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget 
); 
3462     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3466         /* insert GTK representation */ 
3467         (*(newParent
->m_insertCallback
))(newParent
, this); 
3470     /* reverse: prevent GTK from deleting the widget arbitrarily */ 
3471     gtk_widget_unref( m_widget 
); 
3476 void wxWindowGTK::DoAddChild(wxWindowGTK 
*child
) 
3478     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3480     wxASSERT_MSG( (child 
!= NULL
), wxT("invalid child window") ); 
3482     wxASSERT_MSG( (m_insertCallback 
!= NULL
), wxT("invalid child insertion function") ); 
3487     /* insert GTK representation */ 
3488     (*m_insertCallback
)(this, child
); 
3491 void wxWindowGTK::AddChild(wxWindowBase 
*child
) 
3493     wxWindowBase::AddChild(child
); 
3494     m_dirtyTabOrder 
= true; 
3496         wxapp_install_idle_handler(); 
3499 void wxWindowGTK::RemoveChild(wxWindowBase 
*child
) 
3501     wxWindowBase::RemoveChild(child
); 
3502     m_dirtyTabOrder 
= true; 
3504         wxapp_install_idle_handler(); 
3507 void wxWindowGTK::DoMoveInTabOrder(wxWindow 
*win
, MoveKind move
) 
3509     wxWindowBase::DoMoveInTabOrder(win
, move
); 
3510     m_dirtyTabOrder 
= true; 
3512         wxapp_install_idle_handler(); 
3515 bool wxWindowGTK::GTKWidgetNeedsMnemonic() const 
3517     // none needed by default 
3521 void wxWindowGTK::GTKWidgetDoSetMnemonic(GtkWidget
* WXUNUSED(w
)) 
3523     // nothing to do by default since none is needed 
3526 void wxWindowGTK::RealizeTabOrder() 
3530         if ( !m_children
.empty() ) 
3532             // we don't only construct the correct focus chain but also use 
3533             // this opportunity to update the mnemonic widgets for the widgets 
3536             GList 
*chain 
= NULL
; 
3537             wxWindowGTK
* mnemonicWindow 
= NULL
; 
3539             for ( wxWindowList::const_iterator i 
= m_children
.begin(); 
3540                   i 
!= m_children
.end(); 
3543                 wxWindowGTK 
*win 
= *i
; 
3545                 if ( mnemonicWindow 
) 
3547                     if ( win
->AcceptsFocusFromKeyboard() ) 
3549                         // wxComboBox et al. needs to focus on on a different 
3550                         // widget than m_widget, so if the main widget isn't 
3551                         // focusable try the connect widget 
3552                         GtkWidget
* w 
= win
->m_widget
; 
3553                         if ( !GTK_WIDGET_CAN_FOCUS(w
) ) 
3555                             w 
= win
->GetConnectWidget(); 
3556                             if ( !GTK_WIDGET_CAN_FOCUS(w
) ) 
3562                             mnemonicWindow
->GTKWidgetDoSetMnemonic(w
); 
3563                             mnemonicWindow 
= NULL
; 
3567                 else if ( win
->GTKWidgetNeedsMnemonic() ) 
3569                     mnemonicWindow 
= win
; 
3572                 chain 
= g_list_prepend(chain
, win
->m_widget
); 
3575             chain 
= g_list_reverse(chain
); 
3577             gtk_container_set_focus_chain(GTK_CONTAINER(m_wxwindow
), chain
); 
3582             gtk_container_unset_focus_chain(GTK_CONTAINER(m_wxwindow
)); 
3587 void wxWindowGTK::Raise() 
3589     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3591     if (m_wxwindow 
&& m_wxwindow
->window
) 
3593         gdk_window_raise( m_wxwindow
->window 
); 
3595     else if (m_widget
->window
) 
3597         gdk_window_raise( m_widget
->window 
); 
3601 void wxWindowGTK::Lower() 
3603     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3605     if (m_wxwindow 
&& m_wxwindow
->window
) 
3607         gdk_window_lower( m_wxwindow
->window 
); 
3609     else if (m_widget
->window
) 
3611         gdk_window_lower( m_widget
->window 
); 
3615 bool wxWindowGTK::SetCursor( const wxCursor 
&cursor 
) 
3617     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3619     if (cursor 
== m_cursor
) 
3623         wxapp_install_idle_handler(); 
3625     if (cursor 
== wxNullCursor
) 
3626        return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR 
); 
3628        return wxWindowBase::SetCursor( cursor 
); 
3631 void wxWindowGTK::WarpPointer( int x
, int y 
) 
3633     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3635     // We provide this function ourselves as it is 
3636     // missing in GDK (top of this file). 
3638     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3640         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3642         window 
= GetConnectWidget()->window
; 
3645         gdk_window_warp_pointer( window
, x
, y 
); 
3648 bool wxWindowGTK::ScrollLines(int lines
) 
3650     bool changed 
= false; 
3651     GtkRange
* range 
= m_scrollBar
[1]; 
3654         GtkAdjustment
* adj 
= range
->adjustment
; 
3655         const int pos 
= int(adj
->value 
+ 0.5); 
3656         gtk_range_set_value(range
, pos 
+ lines
); 
3657         changed 
= pos 
!= int(adj
->value 
+ 0.5); 
3662 bool wxWindowGTK::ScrollPages(int pages
) 
3664     bool changed 
= false; 
3665     GtkRange
* range 
= m_scrollBar
[1]; 
3668         GtkAdjustment
* adj 
= range
->adjustment
; 
3669         const int pos 
= int(adj
->value 
+ 0.5); 
3670         gtk_range_set_value(range
, pos 
+ pages 
* adj
->page_size
); 
3671         changed 
= pos 
!= int(adj
->value 
+ 0.5); 
3676 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect 
*rect 
) 
3680     if (!m_widget
->window
) 
3685         GdkRectangle gdk_rect
, 
3689             gdk_rect
.x 
= rect
->x
; 
3690             gdk_rect
.y 
= rect
->y
; 
3691             gdk_rect
.width 
= rect
->width
; 
3692             gdk_rect
.height 
= rect
->height
; 
3695         else // invalidate everything 
3700         gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, p
, TRUE 
); 
3704 void wxWindowGTK::Update() 
3708     // when we call Update() we really want to update the window immediately on 
3709     // screen, even if it means flushing the entire queue and hence slowing down 
3710     // everything -- but it should still be done, it's just that Update() should 
3711     // be called very rarely 
3715 void wxWindowGTK::GtkUpdate() 
3717     if (m_wxwindow 
&& GTK_PIZZA(m_wxwindow
)->bin_window
) 
3718         gdk_window_process_updates( GTK_PIZZA(m_wxwindow
)->bin_window
, FALSE 
); 
3719     if (m_widget 
&& m_widget
->window
) 
3720         gdk_window_process_updates( m_widget
->window
, FALSE 
); 
3722     // for consistency with other platforms (and also because it's convenient 
3723     // to be able to update an entire TLW by calling Update() only once), we 
3724     // should also update all our children here 
3725     for ( wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
3727           node 
= node
->GetNext() ) 
3729         node
->GetData()->GtkUpdate(); 
3733 void wxWindowGTK::GtkSendPaintEvents() 
3737         m_updateRegion
.Clear(); 
3741     // Clip to paint region in wxClientDC 
3742     m_clipPaintRegion 
= true; 
3744     // widget to draw on 
3745     GtkPizza 
*pizza 
= GTK_PIZZA (m_wxwindow
); 
3747     if (GetThemeEnabled() && (GetBackgroundStyle() == wxBG_STYLE_SYSTEM
)) 
3749         // find ancestor from which to steal background 
3750         wxWindow 
*parent 
= wxGetTopLevelParent((wxWindow 
*)this); 
3752             parent 
= (wxWindow
*)this; 
3754         if (GTK_WIDGET_MAPPED(parent
->m_widget
)) 
3756             wxRegionIterator 
upd( m_updateRegion 
); 
3760                 rect
.x 
= upd
.GetX(); 
3761                 rect
.y 
= upd
.GetY(); 
3762                 rect
.width 
= upd
.GetWidth(); 
3763                 rect
.height 
= upd
.GetHeight(); 
3765                 gtk_paint_flat_box( parent
->m_widget
->style
, 
3767                             (GtkStateType
)GTK_WIDGET_STATE(m_wxwindow
), 
3781         wxWindowDC 
dc( (wxWindow
*)this ); 
3782         dc
.SetClippingRegion( m_updateRegion 
); 
3784         wxEraseEvent 
erase_event( GetId(), &dc 
); 
3785         erase_event
.SetEventObject( this ); 
3787         GetEventHandler()->ProcessEvent(erase_event
); 
3790     wxNcPaintEvent 
nc_paint_event( GetId() ); 
3791     nc_paint_event
.SetEventObject( this ); 
3792     GetEventHandler()->ProcessEvent( nc_paint_event 
); 
3794     wxPaintEvent 
paint_event( GetId() ); 
3795     paint_event
.SetEventObject( this ); 
3796     GetEventHandler()->ProcessEvent( paint_event 
); 
3798     m_clipPaintRegion 
= false; 
3800     m_updateRegion
.Clear(); 
3803 void wxWindowGTK::SetDoubleBuffered( bool on 
) 
3805     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3808         gtk_widget_set_double_buffered( m_wxwindow
, on 
); 
3811 void wxWindowGTK::ClearBackground() 
3813     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3817 void wxWindowGTK::DoSetToolTip( wxToolTip 
*tip 
) 
3819     wxWindowBase::DoSetToolTip(tip
); 
3822         m_tooltip
->Apply( (wxWindow 
*)this ); 
3825 void wxWindowGTK::ApplyToolTip( GtkTooltips 
*tips
, const wxChar 
*tip 
) 
3827     wxString 
tmp( tip 
); 
3828     gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxGTK_CONV(tmp
), (gchar
*) NULL 
); 
3830 #endif // wxUSE_TOOLTIPS 
3832 bool wxWindowGTK::SetBackgroundColour( const wxColour 
&colour 
) 
3834     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3836     if (!wxWindowBase::SetBackgroundColour(colour
)) 
3841         // We need the pixel value e.g. for background clearing. 
3842         m_backgroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
3845     // apply style change (forceStyle=true so that new style is applied 
3846     // even if the bg colour changed from valid to wxNullColour) 
3847     if (GetBackgroundStyle() != wxBG_STYLE_CUSTOM
) 
3848         ApplyWidgetStyle(true); 
3853 bool wxWindowGTK::SetForegroundColour( const wxColour 
&colour 
) 
3855     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3857     if (!wxWindowBase::SetForegroundColour(colour
)) 
3864         // We need the pixel value e.g. for background clearing. 
3865         m_foregroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
3868     // apply style change (forceStyle=true so that new style is applied 
3869     // even if the bg colour changed from valid to wxNullColour): 
3870     ApplyWidgetStyle(true); 
3875 PangoContext 
*wxWindowGTK::GtkGetPangoDefaultContext() 
3877     return gtk_widget_get_pango_context( m_widget 
); 
3880 GtkRcStyle 
*wxWindowGTK::CreateWidgetStyle(bool forceStyle
) 
3882     // do we need to apply any changes at all? 
3885          !m_foregroundColour
.Ok() && !m_backgroundColour
.Ok() ) 
3890     GtkRcStyle 
*style 
= gtk_rc_style_new(); 
3895             pango_font_description_copy( m_font
.GetNativeFontInfo()->description 
); 
3898     if ( m_foregroundColour
.Ok() ) 
3900         const GdkColor 
*fg 
= m_foregroundColour
.GetColor(); 
3902         style
->fg
[GTK_STATE_NORMAL
] = *fg
; 
3903         style
->color_flags
[GTK_STATE_NORMAL
] = GTK_RC_FG
; 
3905         style
->fg
[GTK_STATE_PRELIGHT
] = *fg
; 
3906         style
->color_flags
[GTK_STATE_PRELIGHT
] = GTK_RC_FG
; 
3908         style
->fg
[GTK_STATE_ACTIVE
] = *fg
; 
3909         style
->color_flags
[GTK_STATE_ACTIVE
] = GTK_RC_FG
; 
3912     if ( m_backgroundColour
.Ok() ) 
3914         const GdkColor 
*bg 
= m_backgroundColour
.GetColor(); 
3916         style
->bg
[GTK_STATE_NORMAL
] = *bg
; 
3917         style
->base
[GTK_STATE_NORMAL
] = *bg
; 
3918         style
->color_flags
[GTK_STATE_NORMAL
] = (GtkRcFlags
) 
3919             (style
->color_flags
[GTK_STATE_NORMAL
] | GTK_RC_BG 
| GTK_RC_BASE
); 
3921         style
->bg
[GTK_STATE_PRELIGHT
] = *bg
; 
3922         style
->base
[GTK_STATE_PRELIGHT
] = *bg
; 
3923         style
->color_flags
[GTK_STATE_PRELIGHT
] = (GtkRcFlags
) 
3924             (style
->color_flags
[GTK_STATE_PRELIGHT
] | GTK_RC_BG 
| GTK_RC_BASE
); 
3926         style
->bg
[GTK_STATE_ACTIVE
] = *bg
; 
3927         style
->base
[GTK_STATE_ACTIVE
] = *bg
; 
3928         style
->color_flags
[GTK_STATE_ACTIVE
] = (GtkRcFlags
) 
3929             (style
->color_flags
[GTK_STATE_ACTIVE
] | GTK_RC_BG 
| GTK_RC_BASE
); 
3931         style
->bg
[GTK_STATE_INSENSITIVE
] = *bg
; 
3932         style
->base
[GTK_STATE_INSENSITIVE
] = *bg
; 
3933         style
->color_flags
[GTK_STATE_INSENSITIVE
] = (GtkRcFlags
) 
3934             (style
->color_flags
[GTK_STATE_INSENSITIVE
] | GTK_RC_BG 
| GTK_RC_BASE
); 
3940 void wxWindowGTK::ApplyWidgetStyle(bool forceStyle
) 
3942     GtkRcStyle 
*style 
= CreateWidgetStyle(forceStyle
); 
3945         DoApplyWidgetStyle(style
); 
3946         gtk_rc_style_unref(style
); 
3949     // Style change may affect GTK+'s size calculation: 
3950     InvalidateBestSize(); 
3953 void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
3956         gtk_widget_modify_style(m_wxwindow
, style
); 
3958         gtk_widget_modify_style(m_widget
, style
); 
3961 bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style
) 
3963     wxWindowBase::SetBackgroundStyle(style
); 
3965     if (style 
== wxBG_STYLE_CUSTOM
) 
3967         GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3969             window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3971             window 
= GetConnectWidget()->window
; 
3975             // Make sure GDK/X11 doesn't refresh the window 
3977             gdk_window_set_back_pixmap( window
, None
, False 
); 
3979             Display
* display 
= GDK_WINDOW_DISPLAY(window
); 
3982             m_needsStyleChange 
= false; 
3985             // Do in OnIdle, because the window is not yet available 
3986             m_needsStyleChange 
= true; 
3988         // Don't apply widget style, or we get a grey background 
3992         // apply style change (forceStyle=true so that new style is applied 
3993         // even if the bg colour changed from valid to wxNullColour): 
3994         ApplyWidgetStyle(true); 
3999 #if wxUSE_DRAG_AND_DROP 
4001 void wxWindowGTK::SetDropTarget( wxDropTarget 
*dropTarget 
) 
4003     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4005     GtkWidget 
*dnd_widget 
= GetConnectWidget(); 
4007     if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget 
); 
4009     if (m_dropTarget
) delete m_dropTarget
; 
4010     m_dropTarget 
= dropTarget
; 
4012     if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget 
); 
4015 #endif // wxUSE_DRAG_AND_DROP 
4017 GtkWidget
* wxWindowGTK::GetConnectWidget() 
4019     GtkWidget 
*connect_widget 
= m_widget
; 
4020     if (m_wxwindow
) connect_widget 
= m_wxwindow
; 
4022     return connect_widget
; 
4025 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow 
*window 
) 
4028         return (window 
== GTK_PIZZA(m_wxwindow
)->bin_window
); 
4030     return (window 
== m_widget
->window
); 
4033 bool wxWindowGTK::SetFont( const wxFont 
&font 
) 
4035     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
4037     if (!wxWindowBase::SetFont(font
)) 
4040     // apply style change (forceStyle=true so that new style is applied 
4041     // even if the font changed from valid to wxNullFont): 
4042     ApplyWidgetStyle(true); 
4047 void wxWindowGTK::DoCaptureMouse() 
4049     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4051     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4053         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4055         window 
= GetConnectWidget()->window
; 
4057     wxCHECK_RET( window
, _T("CaptureMouse() failed") ); 
4059     const wxCursor
* cursor 
= &m_cursor
; 
4061         cursor 
= wxSTANDARD_CURSOR
; 
4063     gdk_pointer_grab( window
, FALSE
, 
4065                          (GDK_BUTTON_PRESS_MASK 
| 
4066                           GDK_BUTTON_RELEASE_MASK 
| 
4067                           GDK_POINTER_MOTION_HINT_MASK 
| 
4068                           GDK_POINTER_MOTION_MASK
), 
4070                       cursor
->GetCursor(), 
4071                       (guint32
)GDK_CURRENT_TIME 
); 
4072     g_captureWindow 
= this; 
4073     g_captureWindowHasMouse 
= true; 
4076 void wxWindowGTK::DoReleaseMouse() 
4078     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4080     wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") ); 
4082     g_captureWindow 
= (wxWindowGTK
*) NULL
; 
4084     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4086         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4088         window 
= GetConnectWidget()->window
; 
4093     gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME 
); 
4097 wxWindow 
*wxWindowBase::GetCapture() 
4099     return (wxWindow 
*)g_captureWindow
; 
4102 bool wxWindowGTK::IsRetained() const 
4107 void wxWindowGTK::BlockScrollEvent() 
4109     wxASSERT(!m_blockScrollEvent
); 
4110     m_blockScrollEvent 
= true; 
4113 void wxWindowGTK::UnblockScrollEvent() 
4115     wxASSERT(m_blockScrollEvent
); 
4116     m_blockScrollEvent 
= false; 
4119 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
, 
4122     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4123     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4127         m_hasScrolling 
= true; 
4131         // GtkRange requires upper > lower 
4136     if (pos 
> range 
- thumbVisible
) 
4137         pos 
= range 
- thumbVisible
; 
4140     const int i 
= orient 
== wxVERTICAL
; 
4141     GtkAdjustment
* adj 
= m_scrollBar
[i
]->adjustment
; 
4142     adj
->step_increment 
= 1; 
4143     adj
->page_increment 
= 
4144     adj
->page_size 
= thumbVisible
; 
4146     SetScrollPos(orient
, pos
); 
4147     gtk_adjustment_changed(adj
); 
4150 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) ) 
4152     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4153     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4155     // This check is more than an optimization. Without it, the slider 
4156     //   will not move smoothly while tracking when using wxScrollHelper. 
4157     if (GetScrollPos(orient
) != pos
) 
4159         const int i 
= orient 
== wxVERTICAL
; 
4160         GtkAdjustment
* adj 
= m_scrollBar
[i
]->adjustment
; 
4161         const int max 
= int(adj
->upper 
- adj
->page_size
); 
4168         // If a "value_changed" signal emission is not already in progress 
4169         if (!m_blockValueChanged
[i
]) 
4171             gtk_adjustment_value_changed(adj
); 
4176 int wxWindowGTK::GetScrollThumb( int orient 
) const 
4178     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4179     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4181     const int i 
= orient 
== wxVERTICAL
; 
4182     return int(m_scrollBar
[i
]->adjustment
->page_size
); 
4185 int wxWindowGTK::GetScrollPos( int orient 
) const 
4187     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4188     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4190     const int i 
= orient 
== wxVERTICAL
; 
4191     return int(m_scrollBar
[i
]->adjustment
->value 
+ 0.5); 
4194 int wxWindowGTK::GetScrollRange( int orient 
) const 
4196     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4197     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4199     const int i 
= orient 
== wxVERTICAL
; 
4200     return int(m_scrollBar
[i
]->adjustment
->upper
); 
4203 // Determine if increment is the same as +/-x, allowing for some small 
4204 //   difference due to possible inexactness in floating point arithmetic 
4205 static inline bool IsScrollIncrement(double increment
, double x
) 
4207     wxASSERT(increment 
> 0); 
4208     const double tolerance 
= 1.0 / 1024; 
4209     return fabs(increment 
- fabs(x
)) < tolerance
; 
4212 wxEventType 
wxWindowGTK::GetScrollEventType(GtkRange
* range
) 
4217         wxapp_install_idle_handler(); 
4219     wxASSERT(range 
== m_scrollBar
[0] || range 
== m_scrollBar
[1]); 
4221     const int barIndex 
= range 
== m_scrollBar
[1]; 
4222     GtkAdjustment
* adj 
= range
->adjustment
; 
4223     const int value 
= int(adj
->value 
+ 0.5); 
4224     // save previous position 
4225     const double oldPos 
= m_scrollPos
[barIndex
]; 
4226     // update current position 
4227     m_scrollPos
[barIndex
] = adj
->value
; 
4228     // If event should be ignored, or integral position has not changed 
4229     if (!m_hasVMT 
|| g_blockEventsOnDrag 
|| value 
== int(oldPos 
+ 0.5)) 
4234     wxEventType eventType 
= wxEVT_SCROLL_THUMBTRACK
; 
4237         // Difference from last change event 
4238         const double diff 
= adj
->value 
- oldPos
; 
4239         const bool isDown 
= diff 
> 0; 
4241         if (IsScrollIncrement(adj
->step_increment
, diff
)) 
4243             eventType 
= isDown 
? wxEVT_SCROLL_LINEDOWN 
: wxEVT_SCROLL_LINEUP
; 
4245         else if (IsScrollIncrement(adj
->page_increment
, diff
)) 
4247             eventType 
= isDown 
? wxEVT_SCROLL_PAGEDOWN 
: wxEVT_SCROLL_PAGEUP
; 
4249         else if (m_mouseButtonDown
) 
4251             // Assume track event 
4252             m_isScrolling 
= true; 
4258 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) ) 
4260     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4262     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4264     // No scrolling requested. 
4265     if ((dx 
== 0) && (dy 
== 0)) return; 
4267     m_clipPaintRegion 
= true; 
4269     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy 
); 
4271     m_clipPaintRegion 
= false; 
4274 void wxWindowGTK::GtkScrolledWindowSetBorder(GtkWidget
* w
, int wxstyle
) 
4276     //RN: Note that static controls usually have no border on gtk, so maybe 
4277     //it makes sense to treat that as simply no border at the wx level 
4279     if (!(wxstyle 
& wxNO_BORDER
) && !(wxstyle 
& wxBORDER_STATIC
)) 
4281         GtkShadowType gtkstyle
; 
4283         if(wxstyle 
& wxBORDER_RAISED
) 
4284             gtkstyle 
= GTK_SHADOW_OUT
; 
4285         else if (wxstyle 
& wxBORDER_SUNKEN
) 
4286             gtkstyle 
= GTK_SHADOW_IN
; 
4287         else if (wxstyle 
& wxBORDER_DOUBLE
) 
4288             gtkstyle 
= GTK_SHADOW_ETCHED_IN
; 
4290             gtkstyle 
= GTK_SHADOW_IN
; 
4292         gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(w
), 
4297 void wxWindowGTK::SetWindowStyleFlag( long style 
) 
4299     // Updates the internal variable. NB: Now m_windowStyle bits carry the _new_ style values already 
4300     wxWindowBase::SetWindowStyleFlag(style
); 
4303 // Find the wxWindow at the current mouse position, also returning the mouse 
4305 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
4307     pt 
= wxGetMousePosition(); 
4308     wxWindow
* found 
= wxFindWindowAtPoint(pt
); 
4312 // Get the current mouse position. 
4313 wxPoint 
wxGetMousePosition() 
4315   /* This crashes when used within wxHelpContext, 
4316      so we have to use the X-specific implementation below. 
4318     GdkModifierType *mask; 
4319     (void) gdk_window_get_pointer(NULL, &x, &y, mask); 
4321     return wxPoint(x, y); 
4325     GdkWindow
* windowAtPtr 
= gdk_window_at_pointer(& x
, & y
); 
4327     Display 
*display 
= windowAtPtr 
? GDK_WINDOW_XDISPLAY(windowAtPtr
) : GDK_DISPLAY(); 
4328     Window rootWindow 
= RootWindowOfScreen (DefaultScreenOfDisplay(display
)); 
4329     Window rootReturn
, childReturn
; 
4330     int rootX
, rootY
, winX
, winY
; 
4331     unsigned int maskReturn
; 
4333     XQueryPointer (display
, 
4337                    &rootX
, &rootY
, &winX
, &winY
, &maskReturn
); 
4338     return wxPoint(rootX
, rootY
); 
4342 // Needed for implementing e.g. combobox on wxGTK within a modal dialog. 
4343 void wxAddGrab(wxWindow
* window
) 
4345     gtk_grab_add( (GtkWidget
*) window
->GetHandle() ); 
4348 void wxRemoveGrab(wxWindow
* window
) 
4350     gtk_grab_remove( (GtkWidget
*) window
->GetHandle() ); 
4353 // ---------------------------------------------------------------------------- 
4355 // ---------------------------------------------------------------------------- 
4357 class wxWinModule 
: public wxModule
 
4364     DECLARE_DYNAMIC_CLASS(wxWinModule
) 
4367 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
) 
4369 bool wxWinModule::OnInit() 
4371     // g_eraseGC = gdk_gc_new( gdk_get_default_root_window() ); 
4372     // gdk_gc_set_fill( g_eraseGC, GDK_SOLID ); 
4377 void wxWinModule::OnExit() 
4380         g_object_unref (g_eraseGC
);