1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk1/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/combobox.h" 
  32     #include "wx/layout.h" 
  33     #include "wx/statusbr.h" 
  35     #include "wx/module.h" 
  38 #if wxUSE_DRAG_AND_DROP 
  43     #include "wx/tooltip.h" 
  50 #include "wx/fontutil.h" 
  53     #include "wx/thread.h" 
  58 #include "wx/gtk1/private.h" 
  59 #include <gdk/gdkprivate.h> 
  60 #include <gdk/gdkkeysyms.h> 
  64 #include <gtk/gtkprivate.h> 
  66 #include "wx/gtk1/win_gtk.h" 
  68 //----------------------------------------------------------------------------- 
  69 // documentation on internals 
  70 //----------------------------------------------------------------------------- 
  73    I have been asked several times about writing some documentation about 
  74    the GTK port of wxWidgets, especially its internal structures. Obviously, 
  75    you cannot understand wxGTK without knowing a little about the GTK, but 
  76    some more information about what the wxWindow, which is the base class 
  77    for all other window classes, does seems required as well. 
  81    What does wxWindow do? It contains the common interface for the following 
  82    jobs of its descendants: 
  84    1) Define the rudimentary behaviour common to all window classes, such as 
  85    resizing, intercepting user input (so as to make it possible to use these 
  86    events for special purposes in a derived class), window names etc. 
  88    2) Provide the possibility to contain and manage children, if the derived 
  89    class is allowed to contain children, which holds true for those window 
  90    classes which do not display a native GTK widget. To name them, these 
  91    classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame- 
  92    work classes are a special case and are handled a bit differently from 
  93    the rest. The same holds true for the wxNotebook class. 
  95    3) Provide the possibility to draw into a client area of a window. This, 
  96    too, only holds true for classes that do not display a native GTK widget 
  99    4) Provide the entire mechanism for scrolling widgets. This actual inter- 
 100    face for this is usually in wxScrolledWindow, but the GTK implementation 
 103    5) A multitude of helper or extra methods for special purposes, such as 
 104    Drag'n'Drop, managing validators etc. 
 106    6) Display a border (sunken, raised, simple or none). 
 108    Normally one might expect, that one wxWidgets window would always correspond 
 109    to one GTK widget. Under GTK, there is no such allround widget that has all 
 110    the functionality. Moreover, the GTK defines a client area as a different 
 111    widget from the actual widget you are handling. Last but not least some 
 112    special classes (e.g. wxFrame) handle different categories of widgets and 
 113    still have the possibility to draw something in the client area. 
 114    It was therefore required to write a special purpose GTK widget, that would 
 115    represent a client area in the sense of wxWidgets capable to do the jobs 
 116    2), 3) and 4). I have written this class and it resides in win_gtk.c of 
 119    All windows must have a widget, with which they interact with other under- 
 120    lying GTK widgets. It is this widget, e.g. that has to be resized etc and 
 121    the wxWindow class has a member variable called m_widget which holds a 
 122    pointer to this widget. When the window class represents a GTK native widget, 
 123    this is (in most cases) the only GTK widget the class manages. E.g. the 
 124    wxStaticText class handles only a GtkLabel widget a pointer to which you 
 125    can find in m_widget (defined in wxWindow) 
 127    When the class has a client area for drawing into and for containing children 
 128    it has to handle the client area widget (of the type GtkPizza, defined in 
 129    win_gtk.c), but there could be any number of widgets, handled by a class 
 130    The common rule for all windows is only, that the widget that interacts with 
 131    the rest of GTK must be referenced in m_widget and all other widgets must be 
 132    children of this widget on the GTK level. The top-most widget, which also 
 133    represents the client area, must be in the m_wxwindow field and must be of 
 136    As I said, the window classes that display a GTK native widget only have 
 137    one widget, so in the case of e.g. the wxButton class m_widget holds a 
 138    pointer to a GtkButton widget. But windows with client areas (for drawing 
 139    and children) have a m_widget field that is a pointer to a GtkScrolled- 
 140    Window and a m_wxwindow field that is pointer to a GtkPizza and this 
 141    one is (in the GTK sense) a child of the GtkScrolledWindow. 
 143    If the m_wxwindow field is set, then all input to this widget is inter- 
 144    cepted and sent to the wxWidgets class. If not, all input to the widget 
 145    that gets pointed to by m_widget gets intercepted and sent to the class. 
 149    The design of scrolling in wxWidgets is markedly different from that offered 
 150    by the GTK itself and therefore we cannot simply take it as it is. In GTK, 
 151    clicking on a scrollbar belonging to scrolled window will inevitably move 
 152    the window. In wxWidgets, the scrollbar will only emit an event, send this 
 153    to (normally) a wxScrolledWindow and that class will call ScrollWindow() 
 154    which actually moves the window and its subchildren. Note that GtkPizza 
 155    memorizes how much it has been scrolled but that wxWidgets forgets this 
 156    so that the two coordinates systems have to be kept in synch. This is done 
 157    in various places using the pizza->xoffset and pizza->yoffset values. 
 161    Singularily the most broken code in GTK is the code that is supposed to 
 162    inform subwindows (child windows) about new positions. Very often, duplicate 
 163    events are sent without changes in size or position, equally often no 
 164    events are sent at all (All this is due to a bug in the GtkContainer code 
 165    which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores 
 166    GTK's own system and it simply waits for size events for toplevel windows 
 167    and then iterates down the respective size events to all window. This has 
 168    the disadvantage that windows might get size events before the GTK widget 
 169    actually has the reported size. This doesn't normally pose any problem, but 
 170    the OpenGL drawing routines rely on correct behaviour. Therefore, I have 
 171    added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas, 
 172    i.e. the wxGLCanvas will emit a size event, when (and not before) the X11 
 173    window that is used for OpenGL output really has that size (as reported by 
 178    If someone at some point of time feels the immense desire to have a look at, 
 179    change or attempt to optimise the Refresh() logic, this person will need an 
 180    intimate understanding of what "draw" and "expose" events are and what 
 181    they are used for, in particular when used in connection with GTK's 
 182    own windowless widgets. Beware. 
 186    Cursors, too, have been a constant source of pleasure. The main difficulty 
 187    is that a GdkWindow inherits a cursor if the programmer sets a new cursor 
 188    for the parent. To prevent this from doing too much harm, I use idle time 
 189    to set the cursor over and over again, starting from the toplevel windows 
 190    and ending with the youngest generation (speaking of parent and child windows). 
 191    Also don't forget that cursors (like much else) are connected to GdkWindows, 
 192    not GtkWidgets and that the "window" field of a GtkWidget might very well 
 193    point to the GdkWindow of the parent widget (-> "window-less widget") and 
 194    that the two obviously have very different meanings. 
 198 //----------------------------------------------------------------------------- 
 200 //----------------------------------------------------------------------------- 
 202 extern bool       g_blockEventsOnDrag
; 
 203 extern bool       g_blockEventsOnScroll
; 
 204 extern wxCursor   g_globalCursor
; 
 206 static GdkGC 
*g_eraseGC 
= NULL
; 
 208 // mouse capture state: the window which has it and if the mouse is currently 
 210 static wxWindowGTK  
*g_captureWindow 
= (wxWindowGTK
*) NULL
; 
 211 static bool g_captureWindowHasMouse 
= false; 
 213 wxWindowGTK  
*g_focusWindow 
= (wxWindowGTK
*) NULL
; 
 215 // the last window which had the focus - this is normally never NULL (except 
 216 // if we never had focus at all) as even when g_focusWindow is NULL it still 
 217 // keeps its previous value 
 218 wxWindowGTK 
*g_focusWindowLast 
= (wxWindowGTK
*) NULL
; 
 220 // If a window get the focus set but has not been realized 
 221 // yet, defer setting the focus to idle time. 
 222 wxWindowGTK 
*g_delayedFocus 
= (wxWindowGTK
*) NULL
; 
 224 // hack: we need something to pass to gtk_menu_popup, so we store the time of 
 225 // the last click here (extern: used from gtk/menu.cpp) 
 226 guint32 wxGtkTimeLastClick 
= 0; 
 228 // global variables because GTK+ DnD want to have the 
 229 // mouse event that caused it 
 230 GdkEvent 
*g_lastMouseEvent 
= (GdkEvent
*) NULL
; 
 231 int g_lastButtonNumber 
= 0; 
 233 extern bool g_mainThreadLocked
; 
 235 //----------------------------------------------------------------------------- 
 237 //----------------------------------------------------------------------------- 
 242 #   define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance"); 
 244 #   define DEBUG_MAIN_THREAD 
 247 #define DEBUG_MAIN_THREAD 
 250 // the trace mask used for the focus debugging messages 
 251 #define TRACE_FOCUS _T("focus") 
 253 //----------------------------------------------------------------------------- 
 254 // missing gdk functions 
 255 //----------------------------------------------------------------------------- 
 258 gdk_window_warp_pointer (GdkWindow      
*window
, 
 262   GdkWindowPrivate 
*priv
; 
 265     window 
= GDK_ROOT_PARENT(); 
 267   priv 
= (GdkWindowPrivate
*) window
; 
 269   if (!priv
->destroyed
) 
 271       XWarpPointer (priv
->xdisplay
, 
 272                     None
,              /* not source window -> move from anywhere */ 
 273                     priv
->xwindow
,  /* dest window */ 
 274                     0, 0, 0, 0,        /* not source window -> move from anywhere */ 
 279 //----------------------------------------------------------------------------- 
 281 //----------------------------------------------------------------------------- 
 283 extern void wxapp_install_idle_handler(); 
 284 extern bool g_isIdle
; 
 286 //----------------------------------------------------------------------------- 
 287 // local code (see below) 
 288 //----------------------------------------------------------------------------- 
 290 // returns the child of win which currently has focus or NULL if not found 
 292 // Note: can't be static, needed by textctrl.cpp. 
 293 wxWindow 
*wxFindFocusedChild(wxWindowGTK 
*win
) 
 295     wxWindow 
*winFocus 
= wxWindowGTK::FindFocus(); 
 297         return (wxWindow 
*)NULL
; 
 299     if ( winFocus 
== win 
) 
 300         return (wxWindow 
*)win
; 
 302     for ( wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
 304           node 
= node
->GetNext() ) 
 306         wxWindow 
*child 
= wxFindFocusedChild(node
->GetData()); 
 311     return (wxWindow 
*)NULL
; 
 314 static void draw_frame( GtkWidget 
*widget
, wxWindowGTK 
*win 
) 
 316     // wxUniversal widgets draw the borders and scrollbars themselves 
 317 #ifndef __WXUNIVERSAL__ 
 324     if (win
->m_hasScrolling
) 
 326         GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(widget
); 
 328         GtkRequisition vscroll_req
; 
 329         vscroll_req
.width 
= 2; 
 330         vscroll_req
.height 
= 2; 
 331         (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
 332             (scroll_window
->vscrollbar
, &vscroll_req 
); 
 334         GtkRequisition hscroll_req
; 
 335         hscroll_req
.width 
= 2; 
 336         hscroll_req
.height 
= 2; 
 337         (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
 338             (scroll_window
->hscrollbar
, &hscroll_req 
); 
 340         GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) ); 
 342         if (scroll_window
->vscrollbar_visible
) 
 344             dw 
+= vscroll_req
.width
; 
 345             dw 
+= scroll_class
->scrollbar_spacing
; 
 348         if (scroll_window
->hscrollbar_visible
) 
 350             dh 
+= hscroll_req
.height
; 
 351             dh 
+= scroll_class
->scrollbar_spacing
; 
 357     if (GTK_WIDGET_NO_WINDOW (widget
)) 
 359         dx 
+= widget
->allocation
.x
; 
 360         dy 
+= widget
->allocation
.y
; 
 363     if (win
->HasFlag(wxRAISED_BORDER
)) 
 365         gtk_draw_shadow( widget
->style
, 
 370                          widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh 
); 
 374     if (win
->HasFlag(wxSUNKEN_BORDER
)) 
 376         gtk_draw_shadow( widget
->style
, 
 381                          widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh 
); 
 385     if (win
->HasFlag(wxSIMPLE_BORDER
)) 
 388         gc 
= gdk_gc_new( widget
->window 
); 
 389         gdk_gc_set_foreground( gc
, &widget
->style
->black 
); 
 390         gdk_draw_rectangle( widget
->window
, gc
, FALSE
, 
 392                          widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 ); 
 396 #endif // __WXUNIVERSAL__ 
 399 //----------------------------------------------------------------------------- 
 400 // "expose_event" of m_widget 
 401 //----------------------------------------------------------------------------- 
 404 static gint 
gtk_window_own_expose_callback( GtkWidget 
*widget
, GdkEventExpose 
*gdk_event
, wxWindowGTK 
*win 
) 
 406     if (gdk_event
->count 
> 0) return FALSE
; 
 408     draw_frame( widget
, win 
); 
 414 //----------------------------------------------------------------------------- 
 415 // "draw" of m_widget 
 416 //----------------------------------------------------------------------------- 
 419 static void gtk_window_own_draw_callback( GtkWidget 
*widget
, GdkRectangle 
*WXUNUSED(rect
), wxWindowGTK 
*win 
) 
 421     draw_frame( widget
, win 
); 
 425 //----------------------------------------------------------------------------- 
 426 // "size_request" of m_widget 
 427 //----------------------------------------------------------------------------- 
 429 // make it extern because wxStaticText needs to disconnect this one 
 431 void wxgtk_window_size_request_callback(GtkWidget 
*widget
, 
 432                                         GtkRequisition 
*requisition
, 
 436     win
->GetSize( &w
, &h 
); 
 442     requisition
->height 
= h
; 
 443     requisition
->width 
= w
; 
 449 void wxgtk_combo_size_request_callback(GtkWidget 
*widget
, 
 450                                        GtkRequisition 
*requisition
, 
 453     // This callback is actually hooked into the text entry 
 454     // of the combo box, not the GtkHBox. 
 457     win
->GetSize( &w
, &h 
); 
 463     GtkCombo 
*gcombo 
= GTK_COMBO(win
->m_widget
); 
 465     GtkRequisition entry_req
; 
 467     entry_req
.height 
= 2; 
 468     (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(gcombo
->button
) )->size_request 
) 
 469         (gcombo
->button
, &entry_req 
); 
 471     requisition
->width 
= w 
- entry_req
.width
; 
 472     requisition
->height 
= entry_req
.height
; 
 476 //----------------------------------------------------------------------------- 
 477 // "expose_event" of m_wxwindow 
 478 //----------------------------------------------------------------------------- 
 481 static int gtk_window_expose_callback( GtkWidget 
*widget
, 
 482                                        GdkEventExpose 
*gdk_event
, 
 488         wxapp_install_idle_handler(); 
 490     // This gets called immediately after an expose event 
 491     // under GTK 1.2 so we collect the calls and wait for 
 492     // the idle handler to pick things up. 
 494     win
->GetUpdateRegion().Union( gdk_event
->area
.x
, 
 496                                   gdk_event
->area
.width
, 
 497                                   gdk_event
->area
.height 
); 
 498     win
->m_clearRegion
.Union( gdk_event
->area
.x
, 
 500                                   gdk_event
->area
.width
, 
 501                                   gdk_event
->area
.height 
); 
 503     // Actual redrawing takes place in idle time. 
 510 //----------------------------------------------------------------------------- 
 511 // "event" of m_wxwindow 
 512 //----------------------------------------------------------------------------- 
 514 // GTK thinks it is clever and filters out a certain amount of "unneeded" 
 515 // expose events. We need them, of course, so we override the main event 
 516 // procedure in GtkWidget by giving our own handler for all system events. 
 517 // There, we look for expose events ourselves whereas all other events are 
 522 gint 
gtk_window_event_event_callback( GtkWidget 
*widget
, 
 523                                       GdkEventExpose 
*event
, 
 526     if (event
->type 
== GDK_EXPOSE
) 
 528         gint ret 
= gtk_window_expose_callback( widget
, event
, win 
); 
 536 //----------------------------------------------------------------------------- 
 537 // "draw" of m_wxwindow 
 538 //----------------------------------------------------------------------------- 
 540 // This callback is a complete replacement of the gtk_pizza_draw() function, 
 541 // which is disabled. 
 544 static void gtk_window_draw_callback( GtkWidget 
*widget
, 
 551         wxapp_install_idle_handler(); 
 553     // if there are any children we must refresh everything 
 556     if ( !win
->HasFlag(wxFULL_REPAINT_ON_RESIZE
) && 
 557             win
->GetChildren().IsEmpty() ) 
 565         wxPrintf( wxT("OnDraw from ") ); 
 566         if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName()) 
 567             wxPrintf( win
->GetClassInfo()->GetClassName() ); 
 568         wxPrintf( wxT(" %d %d %d %d\n"), (int)rect
->x
, 
 575 #ifndef __WXUNIVERSAL__ 
 576     GtkPizza 
*pizza 
= GTK_PIZZA (widget
); 
 578     if (win
->GetThemeEnabled() && win
->GetBackgroundStyle() == wxBG_STYLE_SYSTEM
) 
 580         wxWindow 
*parent 
= win
->GetParent(); 
 581         while (parent 
&& !parent
->IsTopLevel()) 
 582             parent 
= parent
->GetParent(); 
 586         gtk_paint_flat_box (parent
->m_widget
->style
, 
 597     win
->m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
 598     win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
 600     // Update immediately, not in idle time. 
 603 #ifndef __WXUNIVERSAL__ 
 604     // Redraw child widgets 
 605     GList 
*children 
= pizza
->children
; 
 608         GtkPizzaChild 
*child 
= (GtkPizzaChild
*) children
->data
; 
 609         children 
= children
->next
; 
 611         GdkRectangle child_area
; 
 612         if (gtk_widget_intersect (child
->widget
, rect
, &child_area
)) 
 614             gtk_widget_draw (child
->widget
, &child_area 
/* (GdkRectangle*) NULL*/ ); 
 621 //----------------------------------------------------------------------------- 
 622 // "key_press_event" from any window 
 623 //----------------------------------------------------------------------------- 
 625 // set WXTRACE to this to see the key event codes on the console 
 626 #define TRACE_KEYS  _T("keyevent") 
 628 // translates an X key symbol to WXK_XXX value 
 630 // if isChar is true it means that the value returned will be used for EVT_CHAR 
 631 // event and then we choose the logical WXK_XXX, i.e. '/' for GDK_KP_Divide, 
 632 // for example, while if it is false it means that the value is going to be 
 633 // used for KEY_DOWN/UP events and then we translate GDK_KP_Divide to 
 635 static long wxTranslateKeySymToWXKey(KeySym keysym
, bool isChar
) 
 641         // Shift, Control and Alt don't generate the CHAR events at all 
 644             key_code 
= isChar 
? 0 : WXK_SHIFT
; 
 648             key_code 
= isChar 
? 0 : WXK_CONTROL
; 
 656             key_code 
= isChar 
? 0 : WXK_ALT
; 
 659         // neither do the toggle modifies 
 660         case GDK_Scroll_Lock
: 
 661             key_code 
= isChar 
? 0 : WXK_SCROLL
; 
 665             key_code 
= isChar 
? 0 : WXK_CAPITAL
; 
 669             key_code 
= isChar 
? 0 : WXK_NUMLOCK
; 
 673         // various other special keys 
 686         case GDK_ISO_Left_Tab
: 
 693             key_code 
= WXK_RETURN
; 
 697             key_code 
= WXK_CLEAR
; 
 701             key_code 
= WXK_PAUSE
; 
 705             key_code 
= WXK_SELECT
; 
 709             key_code 
= WXK_PRINT
; 
 713             key_code 
= WXK_EXECUTE
; 
 717             key_code 
= WXK_ESCAPE
; 
 720         // cursor and other extended keyboard keys 
 722             key_code 
= WXK_DELETE
; 
 738             key_code 
= WXK_RIGHT
; 
 745         case GDK_Prior
:     // == GDK_Page_Up 
 746             key_code 
= WXK_PAGEUP
; 
 749         case GDK_Next
:      // == GDK_Page_Down 
 750             key_code 
= WXK_PAGEDOWN
; 
 762             key_code 
= WXK_INSERT
; 
 777             key_code 
= (isChar 
? '0' : WXK_NUMPAD0
) + keysym 
- GDK_KP_0
; 
 781             key_code 
= isChar 
? ' ' : WXK_NUMPAD_SPACE
; 
 785             key_code 
= isChar 
? WXK_TAB 
: WXK_NUMPAD_TAB
; 
 789             key_code 
= isChar 
? WXK_RETURN 
: WXK_NUMPAD_ENTER
; 
 793             key_code 
= isChar 
? WXK_F1 
: WXK_NUMPAD_F1
; 
 797             key_code 
= isChar 
? WXK_F2 
: WXK_NUMPAD_F2
; 
 801             key_code 
= isChar 
? WXK_F3 
: WXK_NUMPAD_F3
; 
 805             key_code 
= isChar 
? WXK_F4 
: WXK_NUMPAD_F4
; 
 809             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_HOME
; 
 813             key_code 
= isChar 
? WXK_LEFT 
: WXK_NUMPAD_LEFT
; 
 817             key_code 
= isChar 
? WXK_UP 
: WXK_NUMPAD_UP
; 
 821             key_code 
= isChar 
? WXK_RIGHT 
: WXK_NUMPAD_RIGHT
; 
 825             key_code 
= isChar 
? WXK_DOWN 
: WXK_NUMPAD_DOWN
; 
 828         case GDK_KP_Prior
: // == GDK_KP_Page_Up 
 829             key_code 
= isChar 
? WXK_PAGEUP 
: WXK_NUMPAD_PAGEUP
; 
 832         case GDK_KP_Next
: // == GDK_KP_Page_Down 
 833             key_code 
= isChar 
? WXK_PAGEDOWN 
: WXK_NUMPAD_PAGEDOWN
; 
 837             key_code 
= isChar 
? WXK_END 
: WXK_NUMPAD_END
; 
 841             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_BEGIN
; 
 845             key_code 
= isChar 
? WXK_INSERT 
: WXK_NUMPAD_INSERT
; 
 849             key_code 
= isChar 
? WXK_DELETE 
: WXK_NUMPAD_DELETE
; 
 853             key_code 
= isChar 
? '=' : WXK_NUMPAD_EQUAL
; 
 856         case GDK_KP_Multiply
: 
 857             key_code 
= isChar 
? '*' : WXK_NUMPAD_MULTIPLY
; 
 861             key_code 
= isChar 
? '+' : WXK_NUMPAD_ADD
; 
 864         case GDK_KP_Separator
: 
 865             // FIXME: what is this? 
 866             key_code 
= isChar 
? '.' : WXK_NUMPAD_SEPARATOR
; 
 869         case GDK_KP_Subtract
: 
 870             key_code 
= isChar 
? '-' : WXK_NUMPAD_SUBTRACT
; 
 874             key_code 
= isChar 
? '.' : WXK_NUMPAD_DECIMAL
; 
 878             key_code 
= isChar 
? '/' : WXK_NUMPAD_DIVIDE
; 
 895             key_code 
= WXK_F1 
+ keysym 
- GDK_F1
; 
 905 static inline bool wxIsAsciiKeysym(KeySym ks
) 
 910 static void wxFillOtherKeyEventFields(wxKeyEvent
& event
, 
 912                                       GdkEventKey 
*gdk_event
) 
 916     GdkModifierType state
; 
 917     if (gdk_event
->window
) 
 918         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
 920     event
.SetTimestamp( gdk_event
->time 
); 
 921     event
.SetId(win
->GetId()); 
 922     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
) != 0; 
 923     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
) != 0; 
 924     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
) != 0; 
 925     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
) != 0; 
 926     event
.m_scanCode 
= gdk_event
->keyval
; 
 927     event
.m_rawCode 
= (wxUint32
) gdk_event
->keyval
; 
 928     event
.m_rawFlags 
= 0; 
 930     event
.m_uniChar 
= gdk_keyval_to_unicode(gdk_event
->keyval
); 
 932     wxGetMousePosition( &x
, &y 
); 
 933     win
->ScreenToClient( &x
, &y 
); 
 936     event
.SetEventObject( win 
); 
 941 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
, 
 943                            GdkEventKey 
*gdk_event
) 
 945     // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string 
 946     //     but only event->keyval which is quite useless to us, so remember 
 947     //     the last character from GDK_KEY_PRESS and reuse it as last resort 
 949     // NB: should be MT-safe as we're always called from the main thread only 
 954     } s_lastKeyPress 
= { 0, 0 }; 
 956     KeySym keysym 
= gdk_event
->keyval
; 
 958     wxLogTrace(TRACE_KEYS
, _T("Key %s event: keysym = %ld"), 
 959                event
.GetEventType() == wxEVT_KEY_UP 
? _T("release") 
 963     long key_code 
= wxTranslateKeySymToWXKey(keysym
, false /* !isChar */); 
 967         // do we have the translation or is it a plain ASCII character? 
 968         if ( (gdk_event
->length 
== 1) || wxIsAsciiKeysym(keysym
) ) 
 970             // we should use keysym if it is ASCII as X does some translations 
 971             // like "I pressed while Control is down" => "Ctrl-I" == "TAB" 
 972             // which we don't want here (but which we do use for OnChar()) 
 973             if ( !wxIsAsciiKeysym(keysym
) ) 
 975                 keysym 
= (KeySym
)gdk_event
->string
[0]; 
 978             // we want to always get the same key code when the same key is 
 979             // pressed regardless of the state of the modifiers, i.e. on a 
 980             // standard US keyboard pressing '5' or '%' ('5' key with 
 981             // Shift) should result in the same key code in OnKeyDown(): 
 982             // '5' (although OnChar() will get either '5' or '%'). 
 984             // to do it we first translate keysym to keycode (== scan code) 
 985             // and then back but always using the lower register 
 986             Display 
*dpy 
= (Display 
*)wxGetDisplay(); 
 987             KeyCode keycode 
= XKeysymToKeycode(dpy
, keysym
); 
 989             wxLogTrace(TRACE_KEYS
, _T("\t-> keycode %d"), keycode
); 
 991             KeySym keysymNormalized 
= XKeycodeToKeysym(dpy
, keycode
, 0); 
 993             // use the normalized, i.e. lower register, keysym if we've 
 995             key_code 
= keysymNormalized 
? keysymNormalized 
: keysym
; 
 997             // as explained above, we want to have lower register key codes 
 998             // normally but for the letter keys we want to have the upper ones 
1000             // NB: don't use XConvertCase() here, we want to do it for letters 
1002             key_code 
= toupper(key_code
); 
1004         else // non ASCII key, what to do? 
1006             // by default, ignore it 
1009             // but if we have cached information from the last KEY_PRESS 
1010             if ( gdk_event
->type 
== GDK_KEY_RELEASE 
) 
1013                 if ( keysym 
== s_lastKeyPress
.keysym 
) 
1015                     key_code 
= s_lastKeyPress
.keycode
; 
1020         if ( gdk_event
->type 
== GDK_KEY_PRESS 
) 
1022             // remember it to be reused for KEY_UP event later 
1023             s_lastKeyPress
.keysym 
= keysym
; 
1024             s_lastKeyPress
.keycode 
= key_code
; 
1028     wxLogTrace(TRACE_KEYS
, _T("\t-> wxKeyCode %ld"), key_code
); 
1030     // sending unknown key events doesn't really make sense 
1034     // now fill all the other fields 
1035     wxFillOtherKeyEventFields(event
, win
, gdk_event
); 
1037     event
.m_keyCode 
= key_code
; 
1044 static gint 
gtk_window_key_press_callback( GtkWidget 
*widget
, 
1045                                            GdkEventKey 
*gdk_event
, 
1051         wxapp_install_idle_handler(); 
1055     if (g_blockEventsOnDrag
) 
1059     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
1061     bool return_after_IM 
= false; 
1063     if( wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) == false ) 
1065         // Emit KEY_DOWN event 
1066         ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1070         // Return after IM processing as we cannot do 
1071         // anything with it anyhow. 
1072         return_after_IM 
= true; 
1075     // This is for GTK+ 1.2 only. The char event generatation for GTK+ 2.0 is done 
1076     // in the "commit" handler. 
1078     // 2005.02.02 modified by Hong Jen Yee (hzysoft@sina.com.tw). 
1079     // In GTK+ 1.2, strings sent by IMs are also regarded as key_press events whose 
1080     // keyCodes cannot be recognized by wxWidgets. These MBCS strings, however, are 
1081     // composed of more than one character, which means gdk_event->length will always 
1082     // greater than one. When gtk_event->length == 1, this may be an ASCII character 
1083     // and can be translated by wx.  However, when MBCS characters are sent by IM, 
1084     // gdk_event->length will >= 2. So neither should we pass it to accelerator table, 
1085     // nor should we pass it to controls. The following explanation was excerpted 
1086     // from GDK documentation. 
1087     // gint length : the length of string. 
1088     // gchar *string : a null-terminated multi-byte string containing the composed 
1089     // characters resulting from the key press. When text is being input, in a GtkEntry 
1090     // for example, it is these characters which should be added to the input buffer. 
1091     // When using Input Methods to support internationalized text input, the composed 
1092     // characters appear here after the pre-editing has been completed. 
1094     if ( (!ret
) && (gdk_event
->length 
> 1) ) // If this event contains a pre-edited string from IM. 
1096         // We should translate this key event into wxEVT_CHAR not wxEVT_KEY_DOWN. 
1097         #if wxUSE_UNICODE   // GTK+ 1.2 is not UTF-8 based. 
1098             const wxWCharBuffer string 
= wxConvLocal
.cMB2WC( gdk_event
->string 
); 
1102             const char* string 
= gdk_event
->string
; 
1105         // Implement OnCharHook by checking ancestor top level windows 
1106         wxWindow 
*parent 
= win
; 
1107         while (parent 
&& !parent
->IsTopLevel()) 
1108             parent 
= parent
->GetParent(); 
1110         for( const wxChar
* pstr 
= string
; *pstr
; pstr
++ ) 
1113             event
.m_uniChar 
= *pstr
; 
1114             // Backward compatible for ISO-8859-1 
1115             event
.m_keyCode 
= *pstr 
< 256 ? event
.m_uniChar 
: 0; 
1117             event
.m_keyCode 
= *pstr
; 
1121                 event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1122                 ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1126                 event
.SetEventType(wxEVT_CHAR
); 
1127                 win
->GetEventHandler()->ProcessEvent( event 
); 
1133     if (return_after_IM
) 
1139         wxWindowGTK 
*ancestor 
= win
; 
1142             int command 
= ancestor
->GetAcceleratorTable()->GetCommand( event 
); 
1145                 wxCommandEvent 
command_event( wxEVT_COMMAND_MENU_SELECTED
, command 
); 
1146                 ret 
= ancestor
->GetEventHandler()->ProcessEvent( command_event 
); 
1149             if (ancestor
->IsTopLevel()) 
1151             ancestor 
= ancestor
->GetParent(); 
1154 #endif // wxUSE_ACCEL 
1156     // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x 
1157     // will only be sent if it is not in an accelerator table. 
1161         KeySym keysym 
= gdk_event
->keyval
; 
1162         // Find key code for EVT_CHAR and EVT_CHAR_HOOK events 
1163         key_code 
= wxTranslateKeySymToWXKey(keysym
, true /* isChar */); 
1166             if ( wxIsAsciiKeysym(keysym
) ) 
1169                 key_code 
= (unsigned char)keysym
; 
1171             // gdk_event->string is actually deprecated 
1172             else if ( gdk_event
->length 
== 1 ) 
1174                 key_code 
= (unsigned char)gdk_event
->string
[0]; 
1180             wxLogTrace(TRACE_KEYS
, _T("Char event: %ld"), key_code
); 
1182             event
.m_keyCode 
= key_code
; 
1184             // Implement OnCharHook by checking ancestor top level windows 
1185             wxWindow 
*parent 
= win
; 
1186             while (parent 
&& !parent
->IsTopLevel()) 
1187                 parent 
= parent
->GetParent(); 
1190                 event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1191                 ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1196                 event
.SetEventType(wxEVT_CHAR
); 
1197                 ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1206     // win is a control: tab can be propagated up 
1208          ((gdk_event
->keyval 
== GDK_Tab
) || (gdk_event
->keyval 
== GDK_ISO_Left_Tab
)) && 
1209 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here - the control may 
1210 //     have this style, yet choose not to process this particular TAB in which 
1211 //     case TAB must still work as a navigational character 
1212 // JS: enabling again to make consistent with other platforms 
1213 //     (with wxTE_PROCESS_TAB you have to call Navigate to get default 
1214 //     navigation behaviour) 
1216          (! (win
->HasFlag(wxTE_PROCESS_TAB
) && win
->IsKindOf(CLASSINFO(wxTextCtrl
)) )) && 
1218          win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) ) 
1220         wxNavigationKeyEvent new_event
; 
1221         new_event
.SetEventObject( win
->GetParent() ); 
1222         // GDK reports GDK_ISO_Left_Tab for SHIFT-TAB 
1223         new_event
.SetDirection( (gdk_event
->keyval 
== GDK_Tab
) ); 
1224         // CTRL-TAB changes the (parent) window, i.e. switch notebook page 
1225         new_event
.SetWindowChange( (gdk_event
->state 
& GDK_CONTROL_MASK
) ); 
1226         new_event
.SetCurrentFocus( win 
); 
1227         ret 
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event 
); 
1230     // generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) 
1232          (gdk_event
->keyval 
== GDK_Escape
) ) 
1234         // however only do it if we have a Cancel button in the dialog, 
1235         // otherwise the user code may get confused by the events from a 
1236         // non-existing button and, worse, a wxButton might get button event 
1237         // from another button which is not really expected 
1238         wxWindow 
*winForCancel 
= win
, 
1240         while ( winForCancel 
) 
1242             btnCancel 
= winForCancel
->FindWindow(wxID_CANCEL
); 
1245                 // found a cancel button 
1249             if ( winForCancel
->IsTopLevel() ) 
1251                 // no need to look further 
1255             // maybe our parent has a cancel button? 
1256             winForCancel 
= winForCancel
->GetParent(); 
1261             wxCommandEvent 
eventClick(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
); 
1262             eventClick
.SetEventObject(btnCancel
); 
1263             ret 
= btnCancel
->GetEventHandler()->ProcessEvent(eventClick
); 
1269         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" ); 
1277 //----------------------------------------------------------------------------- 
1278 // "key_release_event" from any window 
1279 //----------------------------------------------------------------------------- 
1282 static gint 
gtk_window_key_release_callback( GtkWidget 
*widget
, 
1283                                              GdkEventKey 
*gdk_event
, 
1289         wxapp_install_idle_handler(); 
1294     if (g_blockEventsOnDrag
) 
1297     wxKeyEvent 
event( wxEVT_KEY_UP 
); 
1298     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1300         // unknown key pressed, ignore (the event would be useless anyhow) 
1304     if ( !win
->GetEventHandler()->ProcessEvent( event 
) ) 
1307     gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" ); 
1312 // ============================================================================ 
1314 // ============================================================================ 
1316 // ---------------------------------------------------------------------------- 
1317 // mouse event processing helpers 
1318 // ---------------------------------------------------------------------------- 
1320 // init wxMouseEvent with the info from GdkEventXXX struct 
1321 template<typename T
> void InitMouseEvent(wxWindowGTK 
*win
, 
1322                                          wxMouseEvent
& event
, 
1325     event
.SetTimestamp( gdk_event
->time 
); 
1326     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
); 
1327     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
); 
1328     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
); 
1329     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
); 
1330     event
.m_leftDown 
= (gdk_event
->state 
& GDK_BUTTON1_MASK
); 
1331     event
.m_middleDown 
= (gdk_event
->state 
& GDK_BUTTON2_MASK
); 
1332     event
.m_rightDown 
= (gdk_event
->state 
& GDK_BUTTON3_MASK
); 
1333     if (event
.GetEventType() == wxEVT_MOUSEWHEEL
) 
1335        event
.m_linesPerAction 
= 3; 
1336        event
.m_wheelDelta 
= 120; 
1337        if (((GdkEventButton
*)gdk_event
)->button 
== 4) 
1338            event
.m_wheelRotation 
= 120; 
1339        else if (((GdkEventButton
*)gdk_event
)->button 
== 5) 
1340            event
.m_wheelRotation 
= -120; 
1343     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1344     event
.m_x 
= (wxCoord
)gdk_event
->x 
- pt
.x
; 
1345     event
.m_y 
= (wxCoord
)gdk_event
->y 
- pt
.y
; 
1347     event
.SetEventObject( win 
); 
1348     event
.SetId( win
->GetId() ); 
1349     event
.SetTimestamp( gdk_event
->time 
); 
1352 static void AdjustEventButtonState(wxMouseEvent
& event
) 
1354     // GDK reports the old state of the button for a button press event, but 
1355     // for compatibility with MSW and common sense we want m_leftDown be true 
1356     // for a LEFT_DOWN event, not FALSE, so we will invert 
1357     // left/right/middleDown for the corresponding click events 
1359     if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) || 
1360         (event
.GetEventType() == wxEVT_LEFT_DCLICK
) || 
1361         (event
.GetEventType() == wxEVT_LEFT_UP
)) 
1363         event
.m_leftDown 
= !event
.m_leftDown
; 
1367     if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) || 
1368         (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) || 
1369         (event
.GetEventType() == wxEVT_MIDDLE_UP
)) 
1371         event
.m_middleDown 
= !event
.m_middleDown
; 
1375     if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) || 
1376         (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) || 
1377         (event
.GetEventType() == wxEVT_RIGHT_UP
)) 
1379         event
.m_rightDown 
= !event
.m_rightDown
; 
1384 // find the window to send the mouse event too 
1386 wxWindowGTK 
*FindWindowForMouseEvent(wxWindowGTK 
*win
, wxCoord
& x
, wxCoord
& y
) 
1391     if (win
->m_wxwindow
) 
1393         GtkPizza 
*pizza 
= GTK_PIZZA(win
->m_wxwindow
); 
1394         xx 
+= pizza
->xoffset
; 
1395         yy 
+= pizza
->yoffset
; 
1398     wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
1401         wxWindowGTK 
*child 
= node
->GetData(); 
1403         node 
= node
->GetNext(); 
1404         if (!child
->IsShown()) 
1407         if (child
->IsTransparentForMouse()) 
1409             // wxStaticBox is transparent in the box itself 
1410             int xx1 
= child
->m_x
; 
1411             int yy1 
= child
->m_y
; 
1412             int xx2 
= child
->m_x 
+ child
->m_width
; 
1413             int yy2 
= child
->m_y 
+ child
->m_height
; 
1416             if (((xx 
>= xx1
) && (xx 
<= xx1
+10) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1418                 ((xx 
>= xx2
-10) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1420                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy1
+10)) || 
1422                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy2
-1) && (yy 
<= yy2
))) 
1433             if ((child
->m_wxwindow 
== (GtkWidget
*) NULL
) && 
1434                 (child
->m_x 
<= xx
) && 
1435                 (child
->m_y 
<= yy
) && 
1436                 (child
->m_x
+child
->m_width  
>= xx
) && 
1437                 (child
->m_y
+child
->m_height 
>= yy
)) 
1450 //----------------------------------------------------------------------------- 
1451 // "button_press_event" 
1452 //----------------------------------------------------------------------------- 
1455 static gint 
gtk_window_button_press_callback( GtkWidget 
*widget
, 
1456                                               GdkEventButton 
*gdk_event
, 
1462         wxapp_install_idle_handler(); 
1465     wxPrintf( wxT("1) OnButtonPress from ") ); 
1466     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1467         wxPrintf( win->GetClassInfo()->GetClassName() ); 
1468     wxPrintf( wxT(".\n") ); 
1470     if (!win
->m_hasVMT
) return FALSE
; 
1471     if (g_blockEventsOnDrag
) return TRUE
; 
1472     if (g_blockEventsOnScroll
) return TRUE
; 
1474     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1476     g_lastButtonNumber 
= gdk_event
->button
; 
1478     if (win
->m_wxwindow 
&& (g_focusWindow 
!= win
) && win
->AcceptsFocus()) 
1480         gtk_widget_grab_focus( win
->m_wxwindow 
); 
1482         wxPrintf( wxT("GrabFocus from ") ); 
1483         if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1484             wxPrintf( win->GetClassInfo()->GetClassName() ); 
1485         wxPrintf( wxT(".\n") ); 
1489     // GDK sends surplus button down events 
1490     // before a double click event. We 
1491     // need to filter these out. 
1492     if (gdk_event
->type 
== GDK_BUTTON_PRESS
) 
1494         GdkEvent 
*peek_event 
= gdk_event_peek(); 
1497             if ((peek_event
->type 
== GDK_2BUTTON_PRESS
) || 
1498                 (peek_event
->type 
== GDK_3BUTTON_PRESS
)) 
1500                 gdk_event_free( peek_event 
); 
1505                 gdk_event_free( peek_event 
); 
1510     wxEventType event_type 
= wxEVT_NULL
; 
1512     if (gdk_event
->button 
== 1) 
1514         // note that GDK generates triple click events which are not supported 
1515         // by wxWidgets but still have to be passed to the app as otherwise 
1516         // clicks would simply go missing 
1517         switch (gdk_event
->type
) 
1519             // we shouldn't get triple clicks at all for GTK2 because we 
1520             // suppress them artificially using the code above but we still 
1521             // should map them to something for GTK1 and not just ignore them 
1522             // as this would lose clicks 
1523             case GDK_3BUTTON_PRESS
:     // we could also map this to DCLICK... 
1524             case GDK_BUTTON_PRESS
: 
1525                 event_type 
= wxEVT_LEFT_DOWN
; 
1528             case GDK_2BUTTON_PRESS
: 
1529                 event_type 
= wxEVT_LEFT_DCLICK
; 
1533                 // just to silence gcc warnings 
1537     else if (gdk_event
->button 
== 2) 
1539         switch (gdk_event
->type
) 
1541             case GDK_3BUTTON_PRESS
: 
1542             case GDK_BUTTON_PRESS
: 
1543                 event_type 
= wxEVT_MIDDLE_DOWN
; 
1546             case GDK_2BUTTON_PRESS
: 
1547                 event_type 
= wxEVT_MIDDLE_DCLICK
; 
1554     else if (gdk_event
->button 
== 3) 
1556         switch (gdk_event
->type
) 
1558             case GDK_3BUTTON_PRESS
: 
1559             case GDK_BUTTON_PRESS
: 
1560                 event_type 
= wxEVT_RIGHT_DOWN
; 
1563             case GDK_2BUTTON_PRESS
: 
1564                 event_type 
= wxEVT_RIGHT_DCLICK
; 
1571     else if (gdk_event
->button 
== 4 || gdk_event
->button 
== 5) 
1573         if (gdk_event
->type 
== GDK_BUTTON_PRESS 
) 
1575             event_type 
= wxEVT_MOUSEWHEEL
; 
1579     if ( event_type 
== wxEVT_NULL 
) 
1581         // unknown mouse button or click type 
1585     g_lastMouseEvent 
= (GdkEvent
*) gdk_event
; 
1587     wxMouseEvent 
event( event_type 
); 
1588     InitMouseEvent( win
, event
, gdk_event 
); 
1590     AdjustEventButtonState(event
); 
1592     // wxListBox actually gets mouse events from the item, so we need to give it 
1593     // a chance to correct this 
1594     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1596     // find the correct window to send the event to: it may be a different one 
1597     // from the one which got it at GTK+ level because some controls don't have 
1598     // their own X window and thus cannot get any events. 
1599     if ( !g_captureWindow 
) 
1600         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1602     wxGtkTimeLastClick 
= gdk_event
->time
; 
1604     if (event_type 
== wxEVT_LEFT_DCLICK
) 
1606         // GTK 1.2 crashes when intercepting double 
1607         // click events from both wxSpinButton and 
1609         if (GTK_IS_SPIN_BUTTON(win
->m_widget
)) 
1611             // Just disable this event for now. 
1616     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1618         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" ); 
1619         g_lastMouseEvent 
= NULL
; 
1622     g_lastMouseEvent 
= NULL
; 
1624     if (event_type 
== wxEVT_RIGHT_DOWN
) 
1626         // generate a "context menu" event: this is similar to right mouse 
1627         // click under many GUIs except that it is generated differently 
1628         // (right up under MSW, ctrl-click under Mac, right down here) and 
1630         // (a) it's a command event and so is propagated to the parent 
1631         // (b) under some ports it can be generated from kbd too 
1632         // (c) it uses screen coords (because of (a)) 
1633         wxContextMenuEvent 
evtCtx( 
1636             win
->ClientToScreen(event
.GetPosition())); 
1637         evtCtx
.SetEventObject(win
); 
1638         return win
->GetEventHandler()->ProcessEvent(evtCtx
); 
1645 //----------------------------------------------------------------------------- 
1646 // "button_release_event" 
1647 //----------------------------------------------------------------------------- 
1650 static gint 
gtk_window_button_release_callback( GtkWidget 
*widget
, 
1651                                                 GdkEventButton 
*gdk_event
, 
1657         wxapp_install_idle_handler(); 
1659     if (!win
->m_hasVMT
) return FALSE
; 
1660     if (g_blockEventsOnDrag
) return FALSE
; 
1661     if (g_blockEventsOnScroll
) return FALSE
; 
1663     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1665     g_lastButtonNumber 
= 0; 
1667     wxEventType event_type 
= wxEVT_NULL
; 
1669     switch (gdk_event
->button
) 
1672             event_type 
= wxEVT_LEFT_UP
; 
1676             event_type 
= wxEVT_MIDDLE_UP
; 
1680             event_type 
= wxEVT_RIGHT_UP
; 
1684             // unknwon button, don't process 
1688     g_lastMouseEvent 
= (GdkEvent
*) gdk_event
; 
1690     wxMouseEvent 
event( event_type 
); 
1691     InitMouseEvent( win
, event
, gdk_event 
); 
1693     AdjustEventButtonState(event
); 
1695     // same wxListBox hack as above 
1696     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1698     if ( !g_captureWindow 
) 
1699         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1701     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1703         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" ); 
1711 //----------------------------------------------------------------------------- 
1712 // "motion_notify_event" 
1713 //----------------------------------------------------------------------------- 
1716 static gint 
gtk_window_motion_notify_callback( GtkWidget 
*widget
, 
1717                                                GdkEventMotion 
*gdk_event
, 
1723         wxapp_install_idle_handler(); 
1725     if (!win
->m_hasVMT
) return FALSE
; 
1726     if (g_blockEventsOnDrag
) return FALSE
; 
1727     if (g_blockEventsOnScroll
) return FALSE
; 
1729     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1731     if (gdk_event
->is_hint
) 
1735         GdkModifierType state
; 
1736         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1741     g_lastMouseEvent 
= (GdkEvent
*) gdk_event
; 
1744     printf( "OnMotion from " ); 
1745     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1746       printf( win->GetClassInfo()->GetClassName() ); 
1750     wxMouseEvent 
event( wxEVT_MOTION 
); 
1751     InitMouseEvent(win
, event
, gdk_event
); 
1753     if ( g_captureWindow 
) 
1755         // synthetize a mouse enter or leave event if needed 
1756         GdkWindow 
*winUnderMouse 
= gdk_window_at_pointer(NULL
, NULL
); 
1757         // This seems to be necessary and actually been added to 
1758         // GDK itself in version 2.0.X 
1761         bool hasMouse 
= winUnderMouse 
== gdk_event
->window
; 
1762         if ( hasMouse 
!= g_captureWindowHasMouse 
) 
1764             // the mouse changed window 
1765             g_captureWindowHasMouse 
= hasMouse
; 
1767             wxMouseEvent 
eventM(g_captureWindowHasMouse 
? wxEVT_ENTER_WINDOW
 
1768                                                         : wxEVT_LEAVE_WINDOW
); 
1769             InitMouseEvent(win
, eventM
, gdk_event
); 
1770             eventM
.SetEventObject(win
); 
1771             win
->GetEventHandler()->ProcessEvent(eventM
); 
1776         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1779     bool ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1780     g_lastMouseEvent 
= NULL
; 
1784         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" ); 
1787     return ret 
? TRUE 
: FALSE
; 
1791 //----------------------------------------------------------------------------- 
1793 //----------------------------------------------------------------------------- 
1795 // send the wxChildFocusEvent and wxFocusEvent, common code of 
1796 // gtk_window_focus_in_callback() and SetFocus() 
1797 static bool DoSendFocusEvents(wxWindow 
*win
) 
1799     // Notify the parent keeping track of focus for the kbd navigation 
1800     // purposes that we got it. 
1801     wxChildFocusEvent 
eventChildFocus(win
); 
1802     (void)win
->GetEventHandler()->ProcessEvent(eventChildFocus
); 
1804     wxFocusEvent 
eventFocus(wxEVT_SET_FOCUS
, win
->GetId()); 
1805     eventFocus
.SetEventObject(win
); 
1807     return win
->GetEventHandler()->ProcessEvent(eventFocus
); 
1811 static gint 
gtk_window_focus_in_callback( GtkWidget 
*widget
, 
1812                                           GdkEvent 
*WXUNUSED(event
), 
1818         wxapp_install_idle_handler(); 
1821     g_focusWindow 
= win
; 
1823     wxLogTrace(TRACE_FOCUS
, 
1824                _T("%s: focus in"), win
->GetName().c_str()); 
1828         gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
); 
1832     // caret needs to be informed about focus change 
1833     wxCaret 
*caret 
= win
->GetCaret(); 
1836         caret
->OnSetFocus(); 
1838 #endif // wxUSE_CARET 
1840     // does the window itself think that it has the focus? 
1841     if ( !win
->m_hasFocus 
) 
1843         // not yet, notify it 
1844         win
->m_hasFocus 
= true; 
1846         if ( DoSendFocusEvents(win
) ) 
1848            gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" ); 
1857 //----------------------------------------------------------------------------- 
1858 // "focus_out_event" 
1859 //----------------------------------------------------------------------------- 
1862 static gint 
gtk_window_focus_out_callback( GtkWidget 
*widget
, GdkEventFocus 
*gdk_event
, wxWindowGTK 
*win 
) 
1867         wxapp_install_idle_handler(); 
1869     wxLogTrace( TRACE_FOCUS
, 
1870                 _T("%s: focus out"), win
->GetName().c_str() ); 
1873     wxWindowGTK 
*winFocus 
= wxFindFocusedChild(win
); 
1877     g_focusWindow 
= (wxWindowGTK 
*)NULL
; 
1885     // caret needs to be informed about focus change 
1886     wxCaret 
*caret 
= win
->GetCaret(); 
1889         caret
->OnKillFocus(); 
1891 #endif // wxUSE_CARET 
1893     // don't send the window a kill focus event if it thinks that it doesn't 
1894     // have focus already 
1895     if ( win
->m_hasFocus 
) 
1897         win
->m_hasFocus 
= false; 
1899         wxFocusEvent 
event( wxEVT_KILL_FOCUS
, win
->GetId() ); 
1900         event
.SetEventObject( win 
); 
1902         // even if we did process the event in wx code, still let GTK itself 
1903         // process it too as otherwise bad things happen, especially in GTK2 
1904         // where the text control simply aborts the program if it doesn't get 
1905         // the matching focus out event 
1906         (void)win
->GetEventHandler()->ProcessEvent( event 
); 
1913 //----------------------------------------------------------------------------- 
1914 // "enter_notify_event" 
1915 //----------------------------------------------------------------------------- 
1919 gint 
gtk_window_enter_callback( GtkWidget 
*widget
, 
1920                                 GdkEventCrossing 
*gdk_event
, 
1926         wxapp_install_idle_handler(); 
1928     if (!win
->m_hasVMT
) return FALSE
; 
1929     if (g_blockEventsOnDrag
) return FALSE
; 
1931     // Event was emitted after a grab 
1932     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
1934     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1938     GdkModifierType state 
= (GdkModifierType
)0; 
1940     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
1942     wxMouseEvent 
event( wxEVT_ENTER_WINDOW 
); 
1943     InitMouseEvent(win
, event
, gdk_event
); 
1944     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1945     event
.m_x 
= x 
+ pt
.x
; 
1946     event
.m_y 
= y 
+ pt
.y
; 
1948     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1950        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" ); 
1958 //----------------------------------------------------------------------------- 
1959 // "leave_notify_event" 
1960 //----------------------------------------------------------------------------- 
1963 static gint 
gtk_window_leave_callback( GtkWidget 
*widget
, GdkEventCrossing 
*gdk_event
, wxWindowGTK 
*win 
) 
1968         wxapp_install_idle_handler(); 
1970     if (!win
->m_hasVMT
) return FALSE
; 
1971     if (g_blockEventsOnDrag
) return FALSE
; 
1973     // Event was emitted after an ungrab 
1974     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
1976     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1978     wxMouseEvent 
event( wxEVT_LEAVE_WINDOW 
); 
1979     event
.SetTimestamp( gdk_event
->time 
); 
1980     event
.SetEventObject( win 
); 
1984     GdkModifierType state 
= (GdkModifierType
)0; 
1986     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
1988     event
.m_shiftDown 
= (state 
& GDK_SHIFT_MASK
) != 0; 
1989     event
.m_controlDown 
= (state 
& GDK_CONTROL_MASK
) != 0; 
1990     event
.m_altDown 
= (state 
& GDK_MOD1_MASK
) != 0; 
1991     event
.m_metaDown 
= (state 
& GDK_MOD2_MASK
) != 0; 
1992     event
.m_leftDown 
= (state 
& GDK_BUTTON1_MASK
) != 0; 
1993     event
.m_middleDown 
= (state 
& GDK_BUTTON2_MASK
) != 0; 
1994     event
.m_rightDown 
= (state 
& GDK_BUTTON3_MASK
) != 0; 
1996     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1997     event
.m_x 
= x 
+ pt
.x
; 
1998     event
.m_y 
= y 
+ pt
.y
; 
2000     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
2002         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" ); 
2010 //----------------------------------------------------------------------------- 
2011 // "value_changed" from m_vAdjust 
2012 //----------------------------------------------------------------------------- 
2015 static void gtk_window_vscroll_callback( GtkAdjustment 
*adjust
, 
2022         wxapp_install_idle_handler(); 
2024     if (g_blockEventsOnDrag
) return; 
2026     if (!win
->m_hasVMT
) return; 
2028     float diff 
= adjust
->value 
- win
->m_oldVerticalPos
; 
2029     if (fabs(diff
) < 0.2) return; 
2031     win
->m_oldVerticalPos 
= adjust
->value
; 
2033     GtkScrolledWindow   
*sw 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
2034     wxEventType         command 
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->vscrollbar
)); 
2036     int value 
= (int)(adjust
->value
+0.5); 
2038     wxScrollWinEvent 
event( command
, value
, wxVERTICAL 
); 
2039     event
.SetEventObject( win 
); 
2040     win
->GetEventHandler()->ProcessEvent( event 
); 
2044 //----------------------------------------------------------------------------- 
2045 // "value_changed" from m_hAdjust 
2046 //----------------------------------------------------------------------------- 
2049 static void gtk_window_hscroll_callback( GtkAdjustment 
*adjust
, 
2056         wxapp_install_idle_handler(); 
2058     if (g_blockEventsOnDrag
) return; 
2059     if (!win
->m_hasVMT
) return; 
2061     float diff 
= adjust
->value 
- win
->m_oldHorizontalPos
; 
2062     if (fabs(diff
) < 0.2) return; 
2064     GtkScrolledWindow   
*sw 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
2065     wxEventType         command 
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->hscrollbar
)); 
2067     win
->m_oldHorizontalPos 
= adjust
->value
; 
2069     int value 
= (int)(adjust
->value
+0.5); 
2071     wxScrollWinEvent 
event( command
, value
, wxHORIZONTAL 
); 
2072     event
.SetEventObject( win 
); 
2073     win
->GetEventHandler()->ProcessEvent( event 
); 
2077 //----------------------------------------------------------------------------- 
2078 // "button_press_event" from scrollbar 
2079 //----------------------------------------------------------------------------- 
2082 static gint 
gtk_scrollbar_button_press_callback( GtkRange 
*widget
, 
2083                                                  GdkEventButton 
*gdk_event
, 
2089         wxapp_install_idle_handler(); 
2092     g_blockEventsOnScroll 
= true; 
2094     // FIXME: there is no 'slider' field in GTK+ 2.0 any more 
2095     win
->m_isScrolling 
= (gdk_event
->window 
== widget
->slider
); 
2101 //----------------------------------------------------------------------------- 
2102 // "button_release_event" from scrollbar 
2103 //----------------------------------------------------------------------------- 
2106 static gint 
gtk_scrollbar_button_release_callback( GtkRange 
*widget
, 
2107                                                    GdkEventButton 
*WXUNUSED(gdk_event
), 
2112 //  don't test here as we can release the mouse while being over 
2113 //  a different window than the slider 
2115 //    if (gdk_event->window != widget->slider) return FALSE; 
2117     g_blockEventsOnScroll 
= false; 
2119     if (win
->m_isScrolling
) 
2121         wxEventType command 
= wxEVT_SCROLLWIN_THUMBRELEASE
; 
2125         GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
2126         if (widget 
== GTK_RANGE(scrolledWindow
->hscrollbar
)) 
2128             value 
= (int)(win
->m_hAdjust
->value
+0.5); 
2131         if (widget 
== GTK_RANGE(scrolledWindow
->vscrollbar
)) 
2133             value 
= (int)(win
->m_vAdjust
->value
+0.5); 
2137         wxScrollWinEvent 
event( command
, value
, dir 
); 
2138         event
.SetEventObject( win 
); 
2139         win
->GetEventHandler()->ProcessEvent( event 
); 
2142     win
->m_isScrolling 
= false; 
2148 // ---------------------------------------------------------------------------- 
2149 // this wxWindowBase function is implemented here (in platform-specific file) 
2150 // because it is static and so couldn't be made virtual 
2151 // ---------------------------------------------------------------------------- 
2153 wxWindow 
*wxWindowBase::DoFindFocus() 
2155     // the cast is necessary when we compile in wxUniversal mode 
2156     return (wxWindow 
*)g_focusWindow
; 
2159 //----------------------------------------------------------------------------- 
2160 // "realize" from m_widget 
2161 //----------------------------------------------------------------------------- 
2163 /* We cannot set colours and fonts before the widget has 
2164    been realized, so we do this directly after realization. */ 
2168 gtk_window_realized_callback( GtkWidget 
*m_widget
, wxWindow 
*win 
) 
2173         wxapp_install_idle_handler(); 
2175     wxWindowCreateEvent 
event( win 
); 
2176     event
.SetEventObject( win 
); 
2177     win
->GetEventHandler()->ProcessEvent( event 
); 
2183 //----------------------------------------------------------------------------- 
2185 //----------------------------------------------------------------------------- 
2189 void gtk_window_size_callback( GtkWidget 
*WXUNUSED(widget
), 
2190                                GtkAllocation 
*WXUNUSED(alloc
), 
2194         wxapp_install_idle_handler(); 
2196     if (!win
->m_hasScrolling
) return; 
2198     int client_width 
= 0; 
2199     int client_height 
= 0; 
2200     win
->GetClientSize( &client_width
, &client_height 
); 
2201     if ((client_width 
== win
->m_oldClientWidth
) && (client_height 
== win
->m_oldClientHeight
)) 
2204     win
->m_oldClientWidth 
= client_width
; 
2205     win
->m_oldClientHeight 
= client_height
; 
2207     if (!win
->m_nativeSizeEvent
) 
2209         wxSizeEvent 
event( win
->GetSize(), win
->GetId() ); 
2210         event
.SetEventObject( win 
); 
2211         win
->GetEventHandler()->ProcessEvent( event 
); 
2218     #define WXUNUSED_UNLESS_XIM(param)  param 
2220     #define WXUNUSED_UNLESS_XIM(param)  WXUNUSED(param) 
2223 /* Resize XIM window */ 
2227 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
), 
2228                                  GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
), 
2229                                  wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) ) 
2232         wxapp_install_idle_handler(); 
2238     if  (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
) 
2242         gdk_window_get_size (widget
->window
, &width
, &height
); 
2243         win
->m_icattr
->preedit_area
.width 
= width
; 
2244         win
->m_icattr
->preedit_area
.height 
= height
; 
2245         gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
); 
2251 //----------------------------------------------------------------------------- 
2252 // "realize" from m_wxwindow 
2253 //----------------------------------------------------------------------------- 
2255 /* Initialize XIM support */ 
2259 gtk_wxwindow_realized_callback( GtkWidget 
* WXUNUSED_UNLESS_XIM(widget
), 
2260                                 wxWindowGTK 
* WXUNUSED_UNLESS_XIM(win
) ) 
2263         wxapp_install_idle_handler(); 
2266     if (win
->m_ic
) return FALSE
; 
2267     if (!widget
) return FALSE
; 
2268     if (!gdk_im_ready()) return FALSE
; 
2270     win
->m_icattr 
= gdk_ic_attr_new(); 
2271     if (!win
->m_icattr
) return FALSE
; 
2275     GdkColormap 
*colormap
; 
2276     GdkICAttr 
*attr 
= win
->m_icattr
; 
2277     unsigned attrmask 
= GDK_IC_ALL_REQ
; 
2279     GdkIMStyle supported_style 
= (GdkIMStyle
) 
2280                                   (GDK_IM_PREEDIT_NONE 
| 
2281                                    GDK_IM_PREEDIT_NOTHING 
| 
2282                                    GDK_IM_PREEDIT_POSITION 
| 
2283                                    GDK_IM_STATUS_NONE 
| 
2284                                    GDK_IM_STATUS_NOTHING
); 
2286     if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2287         supported_style 
= (GdkIMStyle
)(supported_style 
& ~GDK_IM_PREEDIT_POSITION
); 
2289     attr
->style 
= style 
= gdk_im_decide_style (supported_style
); 
2290     attr
->client_window 
= widget
->window
; 
2292     if ((colormap 
= gtk_widget_get_colormap (widget
)) != 
2293             gtk_widget_get_default_colormap ()) 
2295         attrmask 
|= GDK_IC_PREEDIT_COLORMAP
; 
2296         attr
->preedit_colormap 
= colormap
; 
2299     attrmask 
|= GDK_IC_PREEDIT_FOREGROUND
; 
2300     attrmask 
|= GDK_IC_PREEDIT_BACKGROUND
; 
2301     attr
->preedit_foreground 
= widget
->style
->fg
[GTK_STATE_NORMAL
]; 
2302     attr
->preedit_background 
= widget
->style
->base
[GTK_STATE_NORMAL
]; 
2304     switch (style 
& GDK_IM_PREEDIT_MASK
) 
2306         case GDK_IM_PREEDIT_POSITION
: 
2307             if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2309                 g_warning ("over-the-spot style requires fontset"); 
2313             gdk_window_get_size (widget
->window
, &width
, &height
); 
2315             attrmask 
|= GDK_IC_PREEDIT_POSITION_REQ
; 
2316             attr
->spot_location
.x 
= 0; 
2317             attr
->spot_location
.y 
= height
; 
2318             attr
->preedit_area
.x 
= 0; 
2319             attr
->preedit_area
.y 
= 0; 
2320             attr
->preedit_area
.width 
= width
; 
2321             attr
->preedit_area
.height 
= height
; 
2322             attr
->preedit_fontset 
= widget
->style
->font
; 
2327       win
->m_ic 
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
); 
2329       if (win
->m_ic 
== NULL
) 
2330           g_warning ("Can't create input context."); 
2333           mask 
= gdk_window_get_events (widget
->window
); 
2334           mask 
= (GdkEventMask
)(mask 
| gdk_ic_get_events (win
->m_ic
)); 
2335           gdk_window_set_events (widget
->window
, mask
); 
2337           if (GTK_WIDGET_HAS_FOCUS(widget
)) 
2338               gdk_im_begin (win
->m_ic
, widget
->window
); 
2346 //----------------------------------------------------------------------------- 
2347 // InsertChild for wxWindowGTK. 
2348 //----------------------------------------------------------------------------- 
2350 /* Callback for wxWindowGTK. This very strange beast has to be used because 
2351  * C++ has no virtual methods in a constructor. We have to emulate a 
2352  * virtual function here as wxNotebook requires a different way to insert 
2353  * a child in it. I had opted for creating a wxNotebookPage window class 
2354  * which would have made this superfluous (such in the MDI window system), 
2355  * but no-one was listening to me... */ 
2357 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child 
) 
2359     /* the window might have been scrolled already, do we 
2360        have to adapt the position */ 
2361     GtkPizza 
*pizza 
= GTK_PIZZA(parent
->m_wxwindow
); 
2362     child
->m_x 
+= pizza
->xoffset
; 
2363     child
->m_y 
+= pizza
->yoffset
; 
2365     gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
), 
2366                      GTK_WIDGET(child
->m_widget
), 
2373 //----------------------------------------------------------------------------- 
2375 //----------------------------------------------------------------------------- 
2377 wxWindow 
*wxGetActiveWindow() 
2379     return wxWindow::FindFocus(); 
2383 wxMouseState 
wxGetMouseState() 
2389     GdkModifierType mask
; 
2391     gdk_window_get_pointer(NULL
, &x
, &y
, &mask
); 
2395     ms
.SetLeftDown(mask 
& GDK_BUTTON1_MASK
); 
2396     ms
.SetMiddleDown(mask 
& GDK_BUTTON2_MASK
); 
2397     ms
.SetRightDown(mask 
& GDK_BUTTON3_MASK
); 
2399     ms
.SetControlDown(mask 
& GDK_CONTROL_MASK
); 
2400     ms
.SetShiftDown(mask 
& GDK_SHIFT_MASK
); 
2401     ms
.SetAltDown(mask 
& GDK_MOD1_MASK
); 
2402     ms
.SetMetaDown(mask 
& GDK_MOD2_MASK
); 
2407 //----------------------------------------------------------------------------- 
2409 //----------------------------------------------------------------------------- 
2411 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
2413 #ifdef __WXUNIVERSAL__ 
2414     IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
) 
2416     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
2417 #endif // __WXUNIVERSAL__/__WXGTK__ 
2419 void wxWindowGTK::Init() 
2422     m_widget 
= (GtkWidget 
*) NULL
; 
2423     m_wxwindow 
= (GtkWidget 
*) NULL
; 
2424     m_focusWidget 
= (GtkWidget 
*) NULL
; 
2434     m_needParent 
= true; 
2435     m_isBeingDeleted 
= false; 
2438     m_nativeSizeEvent 
= false; 
2440     m_hasScrolling 
= false; 
2441     m_isScrolling 
= false; 
2443     m_hAdjust 
= (GtkAdjustment
*) NULL
; 
2444     m_vAdjust 
= (GtkAdjustment
*) NULL
; 
2445     m_oldHorizontalPos 
= 
2446     m_oldVerticalPos 
= 0.0; 
2448     m_oldClientHeight 
= 0; 
2452     m_insertCallback 
= (wxInsertChildFunction
) NULL
; 
2454     m_acceptsFocus 
= false; 
2457     m_clipPaintRegion 
= false; 
2459     m_needsStyleChange 
= false; 
2461     m_cursor 
= *wxSTANDARD_CURSOR
; 
2464     m_ic 
= (GdkIC
*) NULL
; 
2465     m_icattr 
= (GdkICAttr
*) NULL
; 
2469 wxWindowGTK::wxWindowGTK() 
2474 wxWindowGTK::wxWindowGTK( wxWindow 
*parent
, 
2479                           const wxString 
&name  
) 
2483     Create( parent
, id
, pos
, size
, style
, name 
); 
2486 bool wxWindowGTK::Create( wxWindow 
*parent
, 
2491                           const wxString 
&name  
) 
2493     if (!PreCreation( parent
, pos
, size 
) || 
2494         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
2496         wxFAIL_MSG( wxT("wxWindowGTK creation failed") ); 
2500     m_insertCallback 
= wxInsertChildInWindow
; 
2502     m_widget 
= gtk_scrolled_window_new( (GtkAdjustment 
*) NULL
, (GtkAdjustment 
*) NULL 
); 
2503     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
2505     GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
2507     GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2508     scroll_class
->scrollbar_spacing 
= 0; 
2510     gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
2512     m_hAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) ); 
2513     m_vAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) ); 
2515     m_wxwindow 
= gtk_pizza_new(); 
2517 #ifndef __WXUNIVERSAL__ 
2518     GtkPizza 
*pizza 
= GTK_PIZZA(m_wxwindow
); 
2520     if (HasFlag(wxRAISED_BORDER
)) 
2522         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT 
); 
2524     else if (HasFlag(wxSUNKEN_BORDER
)) 
2526         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN 
); 
2528     else if (HasFlag(wxSIMPLE_BORDER
)) 
2530         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN 
); 
2534         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE 
); 
2536 #endif // __WXUNIVERSAL__ 
2538     gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
2540     GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
2541     m_acceptsFocus 
= true; 
2543     // I _really_ don't want scrollbars in the beginning 
2544     m_vAdjust
->lower 
= 0.0; 
2545     m_vAdjust
->upper 
= 1.0; 
2546     m_vAdjust
->value 
= 0.0; 
2547     m_vAdjust
->step_increment 
= 1.0; 
2548     m_vAdjust
->page_increment 
= 1.0; 
2549     m_vAdjust
->page_size 
= 5.0; 
2550     gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
2551     m_hAdjust
->lower 
= 0.0; 
2552     m_hAdjust
->upper 
= 1.0; 
2553     m_hAdjust
->value 
= 0.0; 
2554     m_hAdjust
->step_increment 
= 1.0; 
2555     m_hAdjust
->page_increment 
= 1.0; 
2556     m_hAdjust
->page_size 
= 5.0; 
2557     gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
2559     // these handlers block mouse events to any window during scrolling such as 
2560     // motion events and prevent GTK and wxWidgets from fighting over where the 
2563     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event", 
2564           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
2566     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event", 
2567           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
2569     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event", 
2570           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
2572     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event", 
2573           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
2575     // these handlers get notified when screen updates are required either when 
2576     // scrolling or when the window size (and therefore scrollbar configuration) 
2579     gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
2580           (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
2581     gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
2582           (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
2584     gtk_widget_show( m_wxwindow 
); 
2587         m_parent
->DoAddChild( this ); 
2589     m_focusWidget 
= m_wxwindow
; 
2596 wxWindowGTK::~wxWindowGTK() 
2600     if (g_focusWindow 
== this) 
2601         g_focusWindow 
= NULL
; 
2603     if ( g_delayedFocus 
== this ) 
2604         g_delayedFocus 
= NULL
; 
2606     m_isBeingDeleted 
= true; 
2609     // destroy children before destroying this window itself 
2612     // unhook focus handlers to prevent stray events being 
2613     // propagated to this (soon to be) dead object 
2614     if (m_focusWidget 
!= NULL
) 
2616         gtk_signal_disconnect_by_func( GTK_OBJECT(m_focusWidget
), 
2617             (GtkSignalFunc
) gtk_window_focus_in_callback
, (gpointer
) this ); 
2618         gtk_signal_disconnect_by_func( GTK_OBJECT(m_focusWidget
), 
2619             (GtkSignalFunc
) gtk_window_focus_out_callback
, (gpointer
) this ); 
2627         gdk_ic_destroy (m_ic
); 
2629         gdk_ic_attr_destroy (m_icattr
); 
2634         gtk_widget_destroy( m_wxwindow 
); 
2635         m_wxwindow 
= (GtkWidget
*) NULL
; 
2640         gtk_widget_destroy( m_widget 
); 
2641         m_widget 
= (GtkWidget
*) NULL
; 
2645 bool wxWindowGTK::PreCreation( wxWindowGTK 
*parent
, const wxPoint 
&pos
,  const wxSize 
&size 
) 
2647     wxCHECK_MSG( !m_needParent 
|| parent
, false, wxT("Need complete parent.") ); 
2649     // Use either the given size, or the default if -1 is given. 
2650     // See wxWindowBase for these functions. 
2651     m_width 
= WidthDefault(size
.x
) ; 
2652     m_height 
= HeightDefault(size
.y
); 
2660 void wxWindowGTK::PostCreation() 
2662     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2668             // these get reported to wxWidgets -> wxPaintEvent 
2670             gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE 
); 
2672             gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event", 
2673                 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this ); 
2675             gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw", 
2676                 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this ); 
2678             if (!HasFlag(wxFULL_REPAINT_ON_RESIZE
)) 
2680                 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event", 
2681                     GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this ); 
2685         // these are called when the "sunken" or "raised" borders are drawn 
2686         gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event", 
2687           GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this ); 
2689         gtk_signal_connect( GTK_OBJECT(m_widget
), "draw", 
2690           GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this ); 
2695     if (!GTK_IS_WINDOW(m_widget
)) 
2697         if (m_focusWidget 
== NULL
) 
2698             m_focusWidget 
= m_widget
; 
2700         gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event", 
2701             GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this ); 
2703         gtk_signal_connect_after( GTK_OBJECT(m_focusWidget
), "focus_out_event", 
2704             GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this ); 
2707     // connect to the various key and mouse handlers 
2709     GtkWidget 
*connect_widget 
= GetConnectWidget(); 
2711     ConnectWidget( connect_widget 
); 
2713     /* We cannot set colours, fonts and cursors before the widget has 
2714        been realized, so we do this directly after realization */ 
2715     gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize", 
2716                             GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this ); 
2720         // Catch native resize events 
2721         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate", 
2722                             GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this ); 
2724         // Initialize XIM support 
2725         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize", 
2726                             GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this ); 
2728         // And resize XIM window 
2729         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate", 
2730                             GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this ); 
2733     if (GTK_IS_COMBO(m_widget
)) 
2735         GtkCombo 
*gcombo 
= GTK_COMBO(m_widget
); 
2737         gtk_signal_connect( GTK_OBJECT(gcombo
->entry
), "size_request", 
2738                             GTK_SIGNAL_FUNC(wxgtk_combo_size_request_callback
), 
2743         // This is needed if we want to add our windows into native 
2744         // GTK controls, such as the toolbar. With this callback, the 
2745         // toolbar gets to know the correct size (the one set by the 
2746         // programmer). Sadly, it misbehaves for wxComboBox. 
2747         gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request", 
2748                             GTK_SIGNAL_FUNC(wxgtk_window_size_request_callback
), 
2752     InheritAttributes(); 
2756     // unless the window was created initially hidden (i.e. Hide() had been 
2757     // called before Create()), we should show it at GTK+ level as well 
2759         gtk_widget_show( m_widget 
); 
2762 void wxWindowGTK::ConnectWidget( GtkWidget 
*widget 
) 
2764     gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event", 
2765       GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this ); 
2767     gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event", 
2768       GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this ); 
2770     gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event", 
2771       GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this ); 
2773     gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event", 
2774       GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this ); 
2776     gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event", 
2777       GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this ); 
2779     gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event", 
2780       GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this ); 
2782     gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event", 
2783       GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this ); 
2786 bool wxWindowGTK::Destroy() 
2788     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2792     return wxWindowBase::Destroy(); 
2795 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
) 
2797     gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height 
); 
2800 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
2802     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2803     wxASSERT_MSG( (m_parent 
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") ); 
2806     printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height ); 
2809     if (m_resizing
) return; /* I don't like recursions */ 
2812     int currentX
, currentY
; 
2813     GetPosition(¤tX
, ¤tY
); 
2814     if (x 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
2816     if (y 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
2818     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
2820     if (m_parent
->m_wxwindow 
== NULL
) /* i.e. wxNotebook */ 
2822         /* don't set the size for children of wxNotebook, just take the values. */ 
2830         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
2831         if ((sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) == 0) 
2833             if (x 
!= -1) m_x 
= x 
+ pizza
->xoffset
; 
2834             if (y 
!= -1) m_y 
= y 
+ pizza
->yoffset
; 
2838             m_x 
= x 
+ pizza
->xoffset
; 
2839             m_y 
= y 
+ pizza
->yoffset
; 
2842         // calculate the best size if we should auto size the window 
2843         if ( ((sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1) || 
2844                 ((sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1) ) 
2846             const wxSize sizeBest 
= GetBestSize(); 
2847             if ( (sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1 ) 
2849             if ( (sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1 ) 
2850                 height 
= sizeBest
.y
; 
2858         int minWidth 
= GetMinWidth(), 
2859             minHeight 
= GetMinHeight(), 
2860             maxWidth 
= GetMaxWidth(), 
2861             maxHeight 
= GetMaxHeight(); 
2863         if ((minWidth 
!= -1) && (m_width 
< minWidth
)) m_width 
= minWidth
; 
2864         if ((minHeight 
!= -1) && (m_height 
< minHeight
)) m_height 
= minHeight
; 
2865         if ((maxWidth 
!= -1) && (m_width 
> maxWidth
)) m_width 
= maxWidth
; 
2866         if ((maxHeight 
!= -1) && (m_height 
> maxHeight
)) m_height 
= maxHeight
; 
2868         int left_border 
= 0; 
2869         int right_border 
= 0; 
2871         int bottom_border 
= 0; 
2873         /* the default button has a border around it */ 
2874         if (GTK_WIDGET_CAN_DEFAULT(m_widget
)) 
2882         DoMoveWindow( m_x
-top_border
, 
2884                       m_width
+left_border
+right_border
, 
2885                       m_height
+top_border
+bottom_border 
); 
2890         /* Sometimes the client area changes size without the 
2891            whole windows's size changing, but if the whole 
2892            windows's size doesn't change, no wxSizeEvent will 
2893            normally be sent. Here we add an extra test if 
2894            the client test has been changed and this will 
2896         GetClientSize( &m_oldClientWidth
, &m_oldClientHeight 
); 
2900     wxPrintf( "OnSize sent from " ); 
2901     if (GetClassInfo() && GetClassInfo()->GetClassName()) 
2902         wxPrintf( GetClassInfo()->GetClassName() ); 
2903     wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height ); 
2906     if (!m_nativeSizeEvent
) 
2908         wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
2909         event
.SetEventObject( this ); 
2910         GetEventHandler()->ProcessEvent( event 
); 
2916 void wxWindowGTK::OnInternalIdle() 
2918     // Update style if the window was not yet realized 
2919     // and SetBackgroundStyle(wxBG_STYLE_CUSTOM) was called 
2920     if (m_needsStyleChange
) 
2922         SetBackgroundStyle(GetBackgroundStyle()); 
2923         m_needsStyleChange 
= false; 
2926     // Update invalidated regions. 
2929     wxCursor cursor 
= m_cursor
; 
2930     if (g_globalCursor
.Ok()) cursor 
= g_globalCursor
; 
2934         /* I now set the cursor anew in every OnInternalIdle call 
2935            as setting the cursor in a parent window also effects the 
2936            windows above so that checking for the current cursor is 
2941             GdkWindow 
*window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
2943                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2945             if (!g_globalCursor
.Ok()) 
2946                 cursor 
= *wxSTANDARD_CURSOR
; 
2948             window 
= m_widget
->window
; 
2949             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
2950                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2953         else if ( m_widget 
) 
2955             GdkWindow 
*window 
= m_widget
->window
; 
2956             if ( window 
&& !GTK_WIDGET_NO_WINDOW(m_widget
) ) 
2957                gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2961     if (wxUpdateUIEvent::CanUpdate(this)) 
2962         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
2965 void wxWindowGTK::DoGetSize( int *width
, int *height 
) const 
2967     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2969     if (width
) (*width
) = m_width
; 
2970     if (height
) (*height
) = m_height
; 
2973 void wxWindowGTK::DoSetClientSize( int width
, int height 
) 
2975     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2979         SetSize( width
, height 
); 
2986 #ifndef __WXUNIVERSAL__ 
2987         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
2989             /* when using GTK 1.2 we set the shadow border size to 2 */ 
2993         if (HasFlag(wxSIMPLE_BORDER
)) 
2995             /* when using GTK 1.2 we set the simple border size to 1 */ 
2999 #endif // __WXUNIVERSAL__ 
3003             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
3005             GtkRequisition vscroll_req
; 
3006             vscroll_req
.width 
= 2; 
3007             vscroll_req
.height 
= 2; 
3008             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
3009                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
3011             GtkRequisition hscroll_req
; 
3012             hscroll_req
.width 
= 2; 
3013             hscroll_req
.height 
= 2; 
3014             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
3015                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
3017             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
3019             if (scroll_window
->vscrollbar_visible
) 
3021                 dw 
+= vscroll_req
.width
; 
3022                 dw 
+= scroll_class
->scrollbar_spacing
; 
3025             if (scroll_window
->hscrollbar_visible
) 
3027                 dh 
+= hscroll_req
.height
; 
3028                 dh 
+= scroll_class
->scrollbar_spacing
; 
3032        SetSize( width
+dw
, height
+dh 
); 
3036 void wxWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
3038     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3042         if (width
) (*width
) = m_width
; 
3043         if (height
) (*height
) = m_height
; 
3050 #ifndef __WXUNIVERSAL__ 
3051         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
3053             /* when using GTK 1.2 we set the shadow border size to 2 */ 
3057         if (HasFlag(wxSIMPLE_BORDER
)) 
3059             /* when using GTK 1.2 we set the simple border size to 1 */ 
3063 #endif // __WXUNIVERSAL__ 
3067             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
3069             GtkRequisition vscroll_req
; 
3070             vscroll_req
.width 
= 2; 
3071             vscroll_req
.height 
= 2; 
3072             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
3073                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
3075             GtkRequisition hscroll_req
; 
3076             hscroll_req
.width 
= 2; 
3077             hscroll_req
.height 
= 2; 
3078             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
3079                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
3081             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
3083             if (scroll_window
->vscrollbar_visible
) 
3085                 dw 
+= vscroll_req
.width
; 
3086                 dw 
+= scroll_class
->scrollbar_spacing
; 
3089             if (scroll_window
->hscrollbar_visible
) 
3091                 dh 
+= hscroll_req
.height
; 
3092                 dh 
+= scroll_class
->scrollbar_spacing
; 
3096         if (width
) (*width
) = m_width 
- dw
; 
3097         if (height
) (*height
) = m_height 
- dh
; 
3101     printf( "GetClientSize, name %s ", GetName().c_str() ); 
3102     if (width) printf( " width = %d", (*width) ); 
3103     if (height) printf( " height = %d", (*height) ); 
3108 void wxWindowGTK::DoGetPosition( int *x
, int *y 
) const 
3110     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3114     if (m_parent 
&& m_parent
->m_wxwindow
) 
3116         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
3117         dx 
= pizza
->xoffset
; 
3118         dy 
= pizza
->yoffset
; 
3121     if (x
) (*x
) = m_x 
- dx
; 
3122     if (y
) (*y
) = m_y 
- dy
; 
3125 void wxWindowGTK::DoClientToScreen( int *x
, int *y 
) const 
3127     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3129     if (!m_widget
->window
) return; 
3131     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3133         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3135         source 
= m_widget
->window
; 
3139     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3143         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3145             org_x 
+= m_widget
->allocation
.x
; 
3146             org_y 
+= m_widget
->allocation
.y
; 
3154 void wxWindowGTK::DoScreenToClient( int *x
, int *y 
) const 
3156     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3158     if (!m_widget
->window
) return; 
3160     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3162         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3164         source 
= m_widget
->window
; 
3168     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3172         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3174             org_x 
+= m_widget
->allocation
.x
; 
3175             org_y 
+= m_widget
->allocation
.y
; 
3183 bool wxWindowGTK::Show( bool show 
) 
3185     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3187     if (!wxWindowBase::Show(show
)) 
3194         gtk_widget_show( m_widget 
); 
3196         gtk_widget_hide( m_widget 
); 
3198     wxShowEvent 
eventShow(GetId(), show
); 
3199     eventShow
.SetEventObject(this); 
3201     GetEventHandler()->ProcessEvent(eventShow
); 
3206 void wxWindowGTK::DoEnable( bool enable 
) 
3208     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3210     gtk_widget_set_sensitive( m_widget
, enable 
); 
3212         gtk_widget_set_sensitive( m_wxwindow
, enable 
); 
3215 int wxWindowGTK::GetCharHeight() const 
3217     wxCHECK_MSG( (m_widget 
!= NULL
), 12, wxT("invalid window") ); 
3219     wxFont font 
= GetFont(); 
3220     wxCHECK_MSG( font
.Ok(), 12, wxT("invalid font") ); 
3222     GdkFont 
*gfont 
= font
.GetInternalFont( 1.0 ); 
3224     return gfont
->ascent 
+ gfont
->descent
; 
3227 int wxWindowGTK::GetCharWidth() const 
3229     wxCHECK_MSG( (m_widget 
!= NULL
), 8, wxT("invalid window") ); 
3231     wxFont font 
= GetFont(); 
3232     wxCHECK_MSG( font
.Ok(), 8, wxT("invalid font") ); 
3234     GdkFont 
*gfont 
= font
.GetInternalFont( 1.0 ); 
3236     return gdk_string_width( gfont
, "g" ); 
3239 void wxWindowGTK::GetTextExtent( const wxString
& string
, 
3243                                  int *externalLeading
, 
3244                                  const wxFont 
*theFont 
) const 
3246     wxFont fontToUse 
= theFont 
? *theFont 
: GetFont(); 
3248     wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") ); 
3257     GdkFont 
*font 
= fontToUse
.GetInternalFont( 1.0 ); 
3258     if (x
) (*x
) = gdk_string_width( font
, wxGTK_CONV( string 
) ); 
3259     if (y
) (*y
) = font
->ascent 
+ font
->descent
; 
3260     if (descent
) (*descent
) = font
->descent
; 
3261     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3264 void wxWindowGTK::SetFocus() 
3266     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3269         // don't do anything if we already have focus 
3275         if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
)) 
3277             gtk_widget_grab_focus (m_wxwindow
); 
3282         if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) ) 
3285             if (!GTK_WIDGET_REALIZED(m_widget
)) 
3287                 // we can't set the focus to the widget now so we remember that 
3288                 // it should be focused and will do it later, during the idle 
3289                 // time, as soon as we can 
3290                 wxLogTrace(TRACE_FOCUS
, 
3291                            _T("Delaying setting focus to %s(%s)"), 
3292                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3294                 g_delayedFocus 
= this; 
3298                 wxLogTrace(TRACE_FOCUS
, 
3299                            _T("Setting focus to %s(%s)"), 
3300                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3302                 gtk_widget_grab_focus (m_widget
); 
3306         if (GTK_IS_CONTAINER(m_widget
)) 
3308             gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD 
); 
3312            wxLogTrace(TRACE_FOCUS
, 
3313                       _T("Can't set focus to %s(%s)"), 
3314                       GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3319 bool wxWindowGTK::AcceptsFocus() const 
3321     return m_acceptsFocus 
&& wxWindowBase::AcceptsFocus(); 
3324 bool wxWindowGTK::Reparent( wxWindowBase 
*newParentBase 
) 
3326     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3328     wxWindowGTK 
*oldParent 
= m_parent
, 
3329              *newParent 
= (wxWindowGTK 
*)newParentBase
; 
3331     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3333     if ( !wxWindowBase::Reparent(newParent
) ) 
3336     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3338     /* prevent GTK from deleting the widget arbitrarily */ 
3339     gtk_widget_ref( m_widget 
); 
3343         gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget 
); 
3346     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3350         /* insert GTK representation */ 
3351         (*(newParent
->m_insertCallback
))(newParent
, this); 
3354     /* reverse: prevent GTK from deleting the widget arbitrarily */ 
3355     gtk_widget_unref( m_widget 
); 
3360 void wxWindowGTK::DoAddChild(wxWindowGTK 
*child
) 
3362     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3364     wxASSERT_MSG( (child 
!= NULL
), wxT("invalid child window") ); 
3366     wxASSERT_MSG( (m_insertCallback 
!= NULL
), wxT("invalid child insertion function") ); 
3371     /* insert GTK representation */ 
3372     (*m_insertCallback
)(this, child
); 
3375 void wxWindowGTK::Raise() 
3377     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3379     if (m_wxwindow 
&& m_wxwindow
->window
) 
3381         gdk_window_raise( m_wxwindow
->window 
); 
3383     else if (m_widget
->window
) 
3385         gdk_window_raise( m_widget
->window 
); 
3389 void wxWindowGTK::Lower() 
3391     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3393     if (m_wxwindow 
&& m_wxwindow
->window
) 
3395         gdk_window_lower( m_wxwindow
->window 
); 
3397     else if (m_widget
->window
) 
3399         gdk_window_lower( m_widget
->window 
); 
3403 bool wxWindowGTK::SetCursor( const wxCursor 
&cursor 
) 
3405     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3407     if ( cursor
.IsSameAs(m_cursor
) ) 
3411         wxapp_install_idle_handler(); 
3413     return wxWindowBase::SetCursor( cursor
.IsOk() ? cursor
 
3414                                                   : *wxSTANDARD_CURSOR 
); 
3417 void wxWindowGTK::WarpPointer( int x
, int y 
) 
3419     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3421     // We provide this function ourselves as it is 
3422     // missing in GDK (top of this file). 
3424     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3426         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3428         window 
= GetConnectWidget()->window
; 
3431         gdk_window_warp_pointer( window
, x
, y 
); 
3435 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect 
*rect 
) 
3439     if (!m_widget
->window
) 
3443         wxapp_install_idle_handler(); 
3446     if (m_wxwindow 
&& rect
) 
3448         myRect
.SetSize(wxSize( m_wxwindow
->allocation
.width
, 
3449                                m_wxwindow
->allocation
.height
)); 
3450         if ( myRect
.Intersect(*rect
).IsEmpty() ) 
3452             // nothing to do, rectangle is empty 
3459     // schedule the area for later updating in GtkUpdate() 
3460     if (eraseBackground 
&& m_wxwindow 
&& m_wxwindow
->window
) 
3464             m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3468             m_clearRegion
.Clear(); 
3469             m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3477             m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3481             GdkRectangle gdk_rect
; 
3482             gdk_rect
.x 
= rect
->x
; 
3483             gdk_rect
.y 
= rect
->y
; 
3484             gdk_rect
.width 
= rect
->width
; 
3485             gdk_rect
.height 
= rect
->height
; 
3486             gtk_widget_draw( m_widget
, &gdk_rect 
); 
3493             m_updateRegion
.Clear(); 
3494             m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3498             gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL 
); 
3503 void wxWindowGTK::Update() 
3507     // when we call Update() we really want to update the window immediately on 
3508     // screen, even if it means flushing the entire queue and hence slowing down 
3509     // everything -- but it should still be done, it's just that Update() should 
3510     // be called very rarely 
3514 void wxWindowGTK::GtkUpdate() 
3516     if (!m_updateRegion
.IsEmpty()) 
3517         GtkSendPaintEvents(); 
3519     // for consistency with other platforms (and also because it's convenient 
3520     // to be able to update an entire TLW by calling Update() only once), we 
3521     // should also update all our children here 
3522     for ( wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
3524           node 
= node
->GetNext() ) 
3526         node
->GetData()->GtkUpdate(); 
3530 void wxWindowGTK::GtkSendPaintEvents() 
3534         m_clearRegion
.Clear(); 
3535         m_updateRegion
.Clear(); 
3539     // Clip to paint region in wxClientDC 
3540     m_clipPaintRegion 
= true; 
3542     // widget to draw on 
3543     GtkPizza 
*pizza 
= GTK_PIZZA (m_wxwindow
); 
3545     if (GetThemeEnabled() && (GetBackgroundStyle() == wxBG_STYLE_SYSTEM
)) 
3547         // find ancestor from which to steal background 
3548         wxWindow 
*parent 
= wxGetTopLevelParent((wxWindow 
*)this); 
3550             parent 
= (wxWindow
*)this; 
3552         if (GTK_WIDGET_MAPPED(parent
->m_widget
)) 
3554             wxRegionIterator 
upd( m_updateRegion 
); 
3558                 rect
.x 
= upd
.GetX(); 
3559                 rect
.y 
= upd
.GetY(); 
3560                 rect
.width 
= upd
.GetWidth(); 
3561                 rect
.height 
= upd
.GetHeight(); 
3563                 gtk_paint_flat_box( parent
->m_widget
->style
, 
3565                             (GtkStateType
)GTK_WIDGET_STATE(m_wxwindow
), 
3578     // if (!m_clearRegion.IsEmpty())   // Always send an erase event under GTK 1.2 
3580         wxWindowDC 
dc( (wxWindow
*)this ); 
3581         if (m_clearRegion
.IsEmpty()) 
3582             dc
.SetClippingRegion( m_updateRegion 
); 
3584             dc
.SetClippingRegion( m_clearRegion 
); 
3586         wxEraseEvent 
erase_event( GetId(), &dc 
); 
3587         erase_event
.SetEventObject( this ); 
3589         if (!GetEventHandler()->ProcessEvent(erase_event
) && GetBackgroundStyle() != wxBG_STYLE_CUSTOM
) 
3593                 g_eraseGC 
= gdk_gc_new( pizza
->bin_window 
); 
3594                 gdk_gc_set_fill( g_eraseGC
, GDK_SOLID 
); 
3596             gdk_gc_set_foreground( g_eraseGC
, GetBackgroundColour().GetColor() ); 
3598             wxRegionIterator 
upd( m_clearRegion 
); 
3601                 gdk_draw_rectangle( pizza
->bin_window
, g_eraseGC
, 1, 
3602                                     upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() ); 
3606         m_clearRegion
.Clear(); 
3609     wxNcPaintEvent 
nc_paint_event( GetId() ); 
3610     nc_paint_event
.SetEventObject( this ); 
3611     GetEventHandler()->ProcessEvent( nc_paint_event 
); 
3613     wxPaintEvent 
paint_event( GetId() ); 
3614     paint_event
.SetEventObject( this ); 
3615     GetEventHandler()->ProcessEvent( paint_event 
); 
3617     m_clipPaintRegion 
= false; 
3619 #if !defined(__WXUNIVERSAL__) 
3620     // The following code will result in all window-less widgets 
3621     // being redrawn because the wxWidgets class is allowed to 
3622     // paint over the window-less widgets. 
3624     GList 
*children 
= pizza
->children
; 
3627         GtkPizzaChild 
*child 
= (GtkPizzaChild
*) children
->data
; 
3628         children 
= children
->next
; 
3630         if (GTK_WIDGET_NO_WINDOW (child
->widget
) && 
3631             GTK_WIDGET_DRAWABLE (child
->widget
)) 
3633             // Get intersection of widget area and update region 
3634             wxRegion 
region( m_updateRegion 
); 
3636             GdkEventExpose gdk_event
; 
3637             gdk_event
.type 
= GDK_EXPOSE
; 
3638             gdk_event
.window 
= pizza
->bin_window
; 
3639             gdk_event
.count 
= 0; 
3640             gdk_event
.send_event 
= TRUE
; 
3642             wxRegionIterator 
upd( m_updateRegion 
); 
3646                 rect
.x 
= upd
.GetX(); 
3647                 rect
.y 
= upd
.GetY(); 
3648                 rect
.width 
= upd
.GetWidth(); 
3649                 rect
.height 
= upd
.GetHeight(); 
3651                 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
)) 
3653                     gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
); 
3660 #endif // native GTK 1 
3662     m_updateRegion
.Clear(); 
3665 void wxWindowGTK::ClearBackground() 
3667     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3669     if (m_wxwindow 
&& m_wxwindow
->window
) 
3671         m_clearRegion
.Clear(); 
3672         wxSize 
size( GetClientSize() ); 
3673         m_clearRegion
.Union( 0,0,size
.x
,size
.y 
); 
3675         // Better do this in idle? 
3681 void wxWindowGTK::DoSetToolTip( wxToolTip 
*tip 
) 
3683     wxWindowBase::DoSetToolTip(tip
); 
3686         m_tooltip
->Apply( (wxWindow 
*)this ); 
3689 void wxWindowGTK::ApplyToolTip( GtkTooltips 
*tips
, const wxChar 
*tip 
) 
3691     wxString 
tmp( tip 
); 
3692     gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxGTK_CONV(tmp
), (gchar
*) NULL 
); 
3694 #endif // wxUSE_TOOLTIPS 
3696 bool wxWindowGTK::SetBackgroundColour( const wxColour 
&colour 
) 
3698     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3700     if (!wxWindowBase::SetBackgroundColour(colour
)) 
3705         // We need the pixel value e.g. for background clearing. 
3706         m_backgroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
3709     // apply style change (forceStyle=true so that new style is applied 
3710     // even if the bg colour changed from valid to wxNullColour) 
3711     if (GetBackgroundStyle() != wxBG_STYLE_CUSTOM
) 
3712         ApplyWidgetStyle(true); 
3717 bool wxWindowGTK::SetForegroundColour( const wxColour 
&colour 
) 
3719     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3721     if (!wxWindowBase::SetForegroundColour(colour
)) 
3728         // We need the pixel value e.g. for background clearing. 
3729         m_foregroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
3732     // apply style change (forceStyle=true so that new style is applied 
3733     // even if the bg colour changed from valid to wxNullColour): 
3734     ApplyWidgetStyle(true); 
3739 GtkRcStyle 
*wxWindowGTK::CreateWidgetStyle(bool forceStyle
) 
3741     // do we need to apply any changes at all? 
3744          !m_foregroundColour
.Ok() && !m_backgroundColour
.Ok() ) 
3749     GtkRcStyle 
*style 
= gtk_rc_style_new(); 
3753         wxString xfontname 
= m_font
.GetNativeFontInfo()->GetXFontName(); 
3754         style
->fontset_name 
= g_strdup(xfontname
.c_str()); 
3757     if ( m_foregroundColour
.Ok() ) 
3759         GdkColor 
*fg 
= m_foregroundColour
.GetColor(); 
3761         style
->fg
[GTK_STATE_NORMAL
] = *fg
; 
3762         style
->color_flags
[GTK_STATE_NORMAL
] = GTK_RC_FG
; 
3764         style
->fg
[GTK_STATE_PRELIGHT
] = *fg
; 
3765         style
->color_flags
[GTK_STATE_PRELIGHT
] = GTK_RC_FG
; 
3767         style
->fg
[GTK_STATE_ACTIVE
] = *fg
; 
3768         style
->color_flags
[GTK_STATE_ACTIVE
] = GTK_RC_FG
; 
3771     if ( m_backgroundColour
.Ok() ) 
3773         GdkColor 
*bg 
= m_backgroundColour
.GetColor(); 
3775         style
->bg
[GTK_STATE_NORMAL
] = *bg
; 
3776         style
->base
[GTK_STATE_NORMAL
] = *bg
; 
3777         style
->color_flags
[GTK_STATE_NORMAL
] = (GtkRcFlags
) 
3778             (style
->color_flags
[GTK_STATE_NORMAL
] | GTK_RC_BG 
| GTK_RC_BASE
); 
3780         style
->bg
[GTK_STATE_PRELIGHT
] = *bg
; 
3781         style
->base
[GTK_STATE_PRELIGHT
] = *bg
; 
3782         style
->color_flags
[GTK_STATE_PRELIGHT
] = (GtkRcFlags
) 
3783             (style
->color_flags
[GTK_STATE_PRELIGHT
] | GTK_RC_BG 
| GTK_RC_BASE
); 
3785         style
->bg
[GTK_STATE_ACTIVE
] = *bg
; 
3786         style
->base
[GTK_STATE_ACTIVE
] = *bg
; 
3787         style
->color_flags
[GTK_STATE_ACTIVE
] = (GtkRcFlags
) 
3788             (style
->color_flags
[GTK_STATE_ACTIVE
] | GTK_RC_BG 
| GTK_RC_BASE
); 
3790         style
->bg
[GTK_STATE_INSENSITIVE
] = *bg
; 
3791         style
->base
[GTK_STATE_INSENSITIVE
] = *bg
; 
3792         style
->color_flags
[GTK_STATE_INSENSITIVE
] = (GtkRcFlags
) 
3793             (style
->color_flags
[GTK_STATE_INSENSITIVE
] | GTK_RC_BG 
| GTK_RC_BASE
); 
3799 void wxWindowGTK::ApplyWidgetStyle(bool forceStyle
) 
3801     GtkRcStyle 
*style 
= CreateWidgetStyle(forceStyle
); 
3804         DoApplyWidgetStyle(style
); 
3805         gtk_rc_style_unref(style
); 
3808     // Style change may affect GTK+'s size calculation: 
3809     InvalidateBestSize(); 
3812 void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
3815         gtk_widget_modify_style(m_wxwindow
, style
); 
3817         gtk_widget_modify_style(m_widget
, style
); 
3820 bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style
) 
3822     wxWindowBase::SetBackgroundStyle(style
); 
3824     if (style 
== wxBG_STYLE_CUSTOM
) 
3826         GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3828             window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3830             window 
= GetConnectWidget()->window
; 
3834             // Make sure GDK/X11 doesn't refresh the window 
3836             gdk_window_set_back_pixmap( window
, None
, False 
); 
3838             Display
* display 
= GDK_WINDOW_DISPLAY(window
); 
3841             m_needsStyleChange 
= false; 
3844             // Do in OnIdle, because the window is not yet available 
3845             m_needsStyleChange 
= true; 
3847         // Don't apply widget style, or we get a grey background 
3851         // apply style change (forceStyle=true so that new style is applied 
3852         // even if the bg colour changed from valid to wxNullColour): 
3853         ApplyWidgetStyle(true); 
3858 #if wxUSE_DRAG_AND_DROP 
3860 void wxWindowGTK::SetDropTarget( wxDropTarget 
*dropTarget 
) 
3862     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3864     GtkWidget 
*dnd_widget 
= GetConnectWidget(); 
3866     if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget 
); 
3868     if (m_dropTarget
) delete m_dropTarget
; 
3869     m_dropTarget 
= dropTarget
; 
3871     if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget 
); 
3874 #endif // wxUSE_DRAG_AND_DROP 
3876 GtkWidget
* wxWindowGTK::GetConnectWidget() 
3878     GtkWidget 
*connect_widget 
= m_widget
; 
3879     if (m_wxwindow
) connect_widget 
= m_wxwindow
; 
3881     return connect_widget
; 
3884 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow 
*window 
) 
3887         return (window 
== GTK_PIZZA(m_wxwindow
)->bin_window
); 
3889     return (window 
== m_widget
->window
); 
3892 bool wxWindowGTK::SetFont( const wxFont 
&font 
) 
3894     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3896     if (!wxWindowBase::SetFont(font
)) 
3899     // apply style change (forceStyle=true so that new style is applied 
3900     // even if the font changed from valid to wxNullFont): 
3901     ApplyWidgetStyle(true); 
3906 void wxWindowGTK::DoCaptureMouse() 
3908     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3910     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3912         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3914         window 
= GetConnectWidget()->window
; 
3916     wxCHECK_RET( window
, _T("CaptureMouse() failed") ); 
3918     const wxCursor
* cursor 
= &m_cursor
; 
3920         cursor 
= wxSTANDARD_CURSOR
; 
3922     gdk_pointer_grab( window
, FALSE
, 
3924                          (GDK_BUTTON_PRESS_MASK 
| 
3925                           GDK_BUTTON_RELEASE_MASK 
| 
3926                           GDK_POINTER_MOTION_HINT_MASK 
| 
3927                           GDK_POINTER_MOTION_MASK
), 
3929                       cursor
->GetCursor(), 
3930                       (guint32
)GDK_CURRENT_TIME 
); 
3931     g_captureWindow 
= this; 
3932     g_captureWindowHasMouse 
= true; 
3935 void wxWindowGTK::DoReleaseMouse() 
3937     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3939     wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") ); 
3941     g_captureWindow 
= (wxWindowGTK
*) NULL
; 
3943     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3945         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3947         window 
= GetConnectWidget()->window
; 
3952     gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME 
); 
3956 wxWindow 
*wxWindowBase::GetCapture() 
3958     return (wxWindow 
*)g_captureWindow
; 
3961 bool wxWindowGTK::IsRetained() const 
3966 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
, 
3967       int range
, bool refresh 
) 
3969     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3971     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
3973     m_hasScrolling 
= true; 
3975     if (orient 
== wxHORIZONTAL
) 
3977         float fpos 
= (float)pos
; 
3978         float frange 
= (float)range
; 
3979         float fthumb 
= (float)thumbVisible
; 
3980         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
3981         if (fpos 
< 0.0) fpos 
= 0.0; 
3983         if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) && 
3984             (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2)) 
3986             SetScrollPos( orient
, pos
, refresh 
); 
3990         m_oldHorizontalPos 
= fpos
; 
3992         m_hAdjust
->lower 
= 0.0; 
3993         m_hAdjust
->upper 
= frange
; 
3994         m_hAdjust
->value 
= fpos
; 
3995         m_hAdjust
->step_increment 
= 1.0; 
3996         m_hAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
3997         m_hAdjust
->page_size 
= fthumb
; 
4001         float fpos 
= (float)pos
; 
4002         float frange 
= (float)range
; 
4003         float fthumb 
= (float)thumbVisible
; 
4004         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4005         if (fpos 
< 0.0) fpos 
= 0.0; 
4007         if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) && 
4008             (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2)) 
4010             SetScrollPos( orient
, pos
, refresh 
); 
4014         m_oldVerticalPos 
= fpos
; 
4016         m_vAdjust
->lower 
= 0.0; 
4017         m_vAdjust
->upper 
= frange
; 
4018         m_vAdjust
->value 
= fpos
; 
4019         m_vAdjust
->step_increment 
= 1.0; 
4020         m_vAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4021         m_vAdjust
->page_size 
= fthumb
; 
4024     if (orient 
== wxHORIZONTAL
) 
4025         gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
4027         gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
4030 void wxWindowGTK::GtkUpdateScrollbar(int orient
) 
4032     GtkAdjustment 
*adj 
= orient 
== wxHORIZONTAL 
? m_hAdjust 
: m_vAdjust
; 
4033     GtkSignalFunc fn 
= orient 
== wxHORIZONTAL
 
4034                         ? (GtkSignalFunc
)gtk_window_hscroll_callback
 
4035                         : (GtkSignalFunc
)gtk_window_vscroll_callback
; 
4037     gtk_signal_disconnect_by_func(GTK_OBJECT(adj
), fn
, (gpointer
)this); 
4038     gtk_signal_emit_by_name(GTK_OBJECT(adj
), "value_changed"); 
4039     gtk_signal_connect(GTK_OBJECT(adj
), "value_changed", fn
, (gpointer
)this); 
4042 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) ) 
4044     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4045     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4047     GtkAdjustment 
*adj 
= orient 
== wxHORIZONTAL 
? m_hAdjust 
: m_vAdjust
; 
4049     float fpos 
= (float)pos
; 
4050     if (fpos 
> adj
->upper 
- adj
->page_size
) 
4051         fpos 
= adj
->upper 
- adj
->page_size
; 
4054     *(orient 
== wxHORIZONTAL 
? &m_oldHorizontalPos 
: &m_oldVerticalPos
) = fpos
; 
4056     if (fabs(fpos
-adj
->value
) < 0.2) 
4060     if ( m_wxwindow
->window 
) 
4065 int wxWindowGTK::GetScrollThumb( int orient 
) const 
4067     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4069     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4071     if (orient 
== wxHORIZONTAL
) 
4072         return (int)(m_hAdjust
->page_size
+0.5); 
4074         return (int)(m_vAdjust
->page_size
+0.5); 
4077 int wxWindowGTK::GetScrollPos( int orient 
) const 
4079     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4081     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4083     if (orient 
== wxHORIZONTAL
) 
4084         return (int)(m_hAdjust
->value
+0.5); 
4086         return (int)(m_vAdjust
->value
+0.5); 
4089 int wxWindowGTK::GetScrollRange( int orient 
) const 
4091     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4093     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4095     if (orient 
== wxHORIZONTAL
) 
4096         return (int)(m_hAdjust
->upper
+0.5); 
4098         return (int)(m_vAdjust
->upper
+0.5); 
4101 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) ) 
4103     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4105     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4107     // No scrolling requested. 
4108     if ((dx 
== 0) && (dy 
== 0)) return; 
4110     if (!m_updateRegion
.IsEmpty()) 
4112         m_updateRegion
.Offset( dx
, dy 
); 
4116         GetClientSize( &cw
, &ch 
); 
4117         m_updateRegion
.Intersect( 0, 0, cw
, ch 
); 
4120     if (!m_clearRegion
.IsEmpty()) 
4122         m_clearRegion
.Offset( dx
, dy 
); 
4126         GetClientSize( &cw
, &ch 
); 
4127         m_clearRegion
.Intersect( 0, 0, cw
, ch 
); 
4130     m_clipPaintRegion 
= true; 
4132     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy 
); 
4134     m_clipPaintRegion 
= false; 
4137 void wxWindowGTK::SetWindowStyleFlag( long style 
) 
4139     // Updates the internal variable. NB: Now m_windowStyle bits carry the _new_ style values already 
4140     wxWindowBase::SetWindowStyleFlag(style
); 
4143 // Find the wxWindow at the current mouse position, also returning the mouse 
4145 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
4147     pt 
= wxGetMousePosition(); 
4148     wxWindow
* found 
= wxFindWindowAtPoint(pt
); 
4152 // Get the current mouse position. 
4153 wxPoint 
wxGetMousePosition() 
4155   /* This crashes when used within wxHelpContext, 
4156      so we have to use the X-specific implementation below. 
4158     GdkModifierType *mask; 
4159     (void) gdk_window_get_pointer(NULL, &x, &y, mask); 
4161     return wxPoint(x, y); 
4165     GdkWindow
* windowAtPtr 
= gdk_window_at_pointer(& x
, & y
); 
4167     Display 
*display 
= windowAtPtr 
? GDK_WINDOW_XDISPLAY(windowAtPtr
) : GDK_DISPLAY(); 
4168     Window rootWindow 
= RootWindowOfScreen (DefaultScreenOfDisplay(display
)); 
4169     Window rootReturn
, childReturn
; 
4170     int rootX
, rootY
, winX
, winY
; 
4171     unsigned int maskReturn
; 
4173     XQueryPointer (display
, 
4177                    &rootX
, &rootY
, &winX
, &winY
, &maskReturn
); 
4178     return wxPoint(rootX
, rootY
); 
4182 // Needed for implementing e.g. combobox on wxGTK within a modal dialog. 
4183 void wxAddGrab(wxWindow
* window
) 
4185     gtk_grab_add( (GtkWidget
*) window
->GetHandle() ); 
4188 void wxRemoveGrab(wxWindow
* window
) 
4190     gtk_grab_remove( (GtkWidget
*) window
->GetHandle() ); 
4193 // ---------------------------------------------------------------------------- 
4195 // ---------------------------------------------------------------------------- 
4197 class wxWinModule 
: public wxModule
 
4204     DECLARE_DYNAMIC_CLASS(wxWinModule
) 
4207 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
) 
4209 bool wxWinModule::OnInit() 
4211     // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() ); 
4212     // gdk_gc_set_fill( g_eraseGC, GDK_SOLID ); 
4217 void wxWinModule::OnExit() 
4220         gdk_gc_unref( g_eraseGC 
);