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
) || win
->HasFlag(wxBORDER_THEME
)) 
 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 
*WXUNUSED(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 
*WXUNUSED(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 
*WXUNUSED(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; 
 931    // this is not gtk1.x 
 932    event
.m_uniChar 
= gdk_keyval_to_unicode(gdk_event
->keyval
); 
 935     wxGetMousePosition( &x
, &y 
); 
 936     win
->ScreenToClient( &x
, &y 
); 
 939     event
.SetEventObject( win 
); 
 944 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
, 
 946                            GdkEventKey 
*gdk_event
) 
 948     // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string 
 949     //     but only event->keyval which is quite useless to us, so remember 
 950     //     the last character from GDK_KEY_PRESS and reuse it as last resort 
 952     // NB: should be MT-safe as we're always called from the main thread only 
 957     } s_lastKeyPress 
= { 0, 0 }; 
 959     KeySym keysym 
= gdk_event
->keyval
; 
 961     wxLogTrace(TRACE_KEYS
, _T("Key %s event: keysym = %ld"), 
 962                event
.GetEventType() == wxEVT_KEY_UP 
? _T("release") 
 966     long key_code 
= wxTranslateKeySymToWXKey(keysym
, false /* !isChar */); 
 970         // do we have the translation or is it a plain ASCII character? 
 971         if ( (gdk_event
->length 
== 1) || wxIsAsciiKeysym(keysym
) ) 
 973             // we should use keysym if it is ASCII as X does some translations 
 974             // like "I pressed while Control is down" => "Ctrl-I" == "TAB" 
 975             // which we don't want here (but which we do use for OnChar()) 
 976             if ( !wxIsAsciiKeysym(keysym
) ) 
 978                 keysym 
= (KeySym
)gdk_event
->string
[0]; 
 981             // we want to always get the same key code when the same key is 
 982             // pressed regardless of the state of the modifiers, i.e. on a 
 983             // standard US keyboard pressing '5' or '%' ('5' key with 
 984             // Shift) should result in the same key code in OnKeyDown(): 
 985             // '5' (although OnChar() will get either '5' or '%'). 
 987             // to do it we first translate keysym to keycode (== scan code) 
 988             // and then back but always using the lower register 
 989             Display 
*dpy 
= (Display 
*)wxGetDisplay(); 
 990             KeyCode keycode 
= XKeysymToKeycode(dpy
, keysym
); 
 992             wxLogTrace(TRACE_KEYS
, _T("\t-> keycode %d"), keycode
); 
 994             KeySym keysymNormalized 
= XKeycodeToKeysym(dpy
, keycode
, 0); 
 996             // use the normalized, i.e. lower register, keysym if we've 
 998             key_code 
= keysymNormalized 
? keysymNormalized 
: keysym
; 
1000             // as explained above, we want to have lower register key codes 
1001             // normally but for the letter keys we want to have the upper ones 
1003             // NB: don't use XConvertCase() here, we want to do it for letters 
1005             key_code 
= toupper(key_code
); 
1007         else // non ASCII key, what to do? 
1009             // by default, ignore it 
1012             // but if we have cached information from the last KEY_PRESS 
1013             if ( gdk_event
->type 
== GDK_KEY_RELEASE 
) 
1016                 if ( keysym 
== s_lastKeyPress
.keysym 
) 
1018                     key_code 
= s_lastKeyPress
.keycode
; 
1023         if ( gdk_event
->type 
== GDK_KEY_PRESS 
) 
1025             // remember it to be reused for KEY_UP event later 
1026             s_lastKeyPress
.keysym 
= keysym
; 
1027             s_lastKeyPress
.keycode 
= key_code
; 
1031     wxLogTrace(TRACE_KEYS
, _T("\t-> wxKeyCode %ld"), key_code
); 
1033     // sending unknown key events doesn't really make sense 
1037     // now fill all the other fields 
1038     wxFillOtherKeyEventFields(event
, win
, gdk_event
); 
1040     event
.m_keyCode 
= key_code
; 
1047 static gint 
gtk_window_key_press_callback( GtkWidget 
*widget
, 
1048                                            GdkEventKey 
*gdk_event
, 
1054         wxapp_install_idle_handler(); 
1058     if (g_blockEventsOnDrag
) 
1062     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
1064     bool return_after_IM 
= false; 
1066     if ( wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1068         // Emit KEY_DOWN event 
1069         ret 
= win
->HandleWindowEvent( event 
); 
1073         // Return after IM processing as we cannot do 
1074         // anything with it anyhow. 
1075         return_after_IM 
= true; 
1078     // This is for GTK+ 1.2 only. The char event generatation for GTK+ 2.0 is done 
1079     // in the "commit" handler. 
1081     // 2005.02.02 modified by Hong Jen Yee (hzysoft@sina.com.tw). 
1082     // In GTK+ 1.2, strings sent by IMs are also regarded as key_press events whose 
1083     // keyCodes cannot be recognized by wxWidgets. These MBCS strings, however, are 
1084     // composed of more than one character, which means gdk_event->length will always 
1085     // greater than one. When gtk_event->length == 1, this may be an ASCII character 
1086     // and can be translated by wx.  However, when MBCS characters are sent by IM, 
1087     // gdk_event->length will >= 2. So neither should we pass it to accelerator table, 
1088     // nor should we pass it to controls. The following explanation was excerpted 
1089     // from GDK documentation. 
1090     // gint length : the length of string. 
1091     // gchar *string : a null-terminated multi-byte string containing the composed 
1092     // characters resulting from the key press. When text is being input, in a GtkEntry 
1093     // for example, it is these characters which should be added to the input buffer. 
1094     // When using Input Methods to support internationalized text input, the composed 
1095     // characters appear here after the pre-editing has been completed. 
1097     if ( (!ret
) && (gdk_event
->length 
> 1) ) // If this event contains a pre-edited string from IM. 
1099         // We should translate this key event into wxEVT_CHAR not wxEVT_KEY_DOWN. 
1100         #if wxUSE_UNICODE   // GTK+ 1.2 is not UTF-8 based. 
1101             const wxWCharBuffer string 
= wxConvLocal
.cMB2WC( gdk_event
->string 
); 
1105             const char* string 
= gdk_event
->string
; 
1108         // Implement OnCharHook by checking ancestor top level windows 
1109         wxWindow 
*parent 
= win
; 
1110         while (parent 
&& !parent
->IsTopLevel()) 
1111             parent 
= parent
->GetParent(); 
1113         for( const wxChar
* pstr 
= string
; *pstr
; pstr
++ ) 
1116             event
.m_uniChar 
= *pstr
; 
1117             // Backward compatible for ISO-8859-1 
1118             event
.m_keyCode 
= *pstr 
< 256 ? event
.m_uniChar 
: 0; 
1120             event
.m_keyCode 
= *pstr
; 
1124                 event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1125                 ret 
= parent
->HandleWindowEvent( event 
); 
1129                 event
.SetEventType(wxEVT_CHAR
); 
1130                 win
->HandleWindowEvent( event 
); 
1136     if (return_after_IM
) 
1142         wxWindowGTK 
*ancestor 
= win
; 
1145             int command 
= ancestor
->GetAcceleratorTable()->GetCommand( event 
); 
1148                 wxCommandEvent 
command_event( wxEVT_COMMAND_MENU_SELECTED
, command 
); 
1149                 ret 
= ancestor
->HandleWindowEvent( command_event 
); 
1152             if (ancestor
->IsTopLevel()) 
1154             ancestor 
= ancestor
->GetParent(); 
1157 #endif // wxUSE_ACCEL 
1159     // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x 
1160     // will only be sent if it is not in an accelerator table. 
1164         KeySym keysym 
= gdk_event
->keyval
; 
1165         // Find key code for EVT_CHAR and EVT_CHAR_HOOK events 
1166         key_code 
= wxTranslateKeySymToWXKey(keysym
, true /* isChar */); 
1169             if ( wxIsAsciiKeysym(keysym
) ) 
1172                 key_code 
= (unsigned char)keysym
; 
1174             // gdk_event->string is actually deprecated 
1175             else if ( gdk_event
->length 
== 1 ) 
1177                 key_code 
= (unsigned char)gdk_event
->string
[0]; 
1183             wxLogTrace(TRACE_KEYS
, _T("Char event: %ld"), key_code
); 
1185             event
.m_keyCode 
= key_code
; 
1187             // Implement OnCharHook by checking ancestor top level windows 
1188             wxWindow 
*parent 
= win
; 
1189             while (parent 
&& !parent
->IsTopLevel()) 
1190                 parent 
= parent
->GetParent(); 
1193                 event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1194                 ret 
= parent
->HandleWindowEvent( event 
); 
1199                 event
.SetEventType(wxEVT_CHAR
); 
1200                 ret 
= win
->HandleWindowEvent( event 
); 
1209     // win is a control: tab can be propagated up 
1211          ((gdk_event
->keyval 
== GDK_Tab
) || (gdk_event
->keyval 
== GDK_ISO_Left_Tab
)) && 
1212 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here - the control may 
1213 //     have this style, yet choose not to process this particular TAB in which 
1214 //     case TAB must still work as a navigational character 
1215 // JS: enabling again to make consistent with other platforms 
1216 //     (with wxTE_PROCESS_TAB you have to call Navigate to get default 
1217 //     navigation behaviour) 
1219          (! (win
->HasFlag(wxTE_PROCESS_TAB
) && win
->IsKindOf(CLASSINFO(wxTextCtrl
)) )) && 
1221          win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) ) 
1223         wxNavigationKeyEvent new_event
; 
1224         new_event
.SetEventObject( win
->GetParent() ); 
1225         // GDK reports GDK_ISO_Left_Tab for SHIFT-TAB 
1226         new_event
.SetDirection( (gdk_event
->keyval 
== GDK_Tab
) ); 
1227         // CTRL-TAB changes the (parent) window, i.e. switch notebook page 
1228         new_event
.SetWindowChange( (gdk_event
->state 
& GDK_CONTROL_MASK
) ); 
1229         new_event
.SetCurrentFocus( win 
); 
1230         ret 
= win
->GetParent()->HandleWindowEvent( new_event 
); 
1233     // generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) 
1235          (gdk_event
->keyval 
== GDK_Escape
) ) 
1237         // however only do it if we have a Cancel button in the dialog, 
1238         // otherwise the user code may get confused by the events from a 
1239         // non-existing button and, worse, a wxButton might get button event 
1240         // from another button which is not really expected 
1241         wxWindow 
*winForCancel 
= win
, 
1243         while ( winForCancel 
) 
1245             btnCancel 
= winForCancel
->FindWindow(wxID_CANCEL
); 
1248                 // found a cancel button 
1252             if ( winForCancel
->IsTopLevel() ) 
1254                 // no need to look further 
1258             // maybe our parent has a cancel button? 
1259             winForCancel 
= winForCancel
->GetParent(); 
1264             wxCommandEvent 
eventClick(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
); 
1265             eventClick
.SetEventObject(btnCancel
); 
1266             ret 
= btnCancel
->HandleWindowEvent(eventClick
); 
1272         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" ); 
1280 //----------------------------------------------------------------------------- 
1281 // "key_release_event" from any window 
1282 //----------------------------------------------------------------------------- 
1285 static gint 
gtk_window_key_release_callback( GtkWidget 
*widget
, 
1286                                              GdkEventKey 
*gdk_event
, 
1292         wxapp_install_idle_handler(); 
1297     if (g_blockEventsOnDrag
) 
1300     wxKeyEvent 
event( wxEVT_KEY_UP 
); 
1301     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1303         // unknown key pressed, ignore (the event would be useless anyhow) 
1307     if ( !win
->HandleWindowEvent( event 
) ) 
1310     gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" ); 
1315 // ============================================================================ 
1317 // ============================================================================ 
1319 // ---------------------------------------------------------------------------- 
1320 // mouse event processing helpers 
1321 // ---------------------------------------------------------------------------- 
1323 // init wxMouseEvent with the info from GdkEventXXX struct 
1324 template<typename T
> void InitMouseEvent(wxWindowGTK 
*win
, 
1325                                          wxMouseEvent
& event
, 
1328     event
.SetTimestamp( gdk_event
->time 
); 
1329     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
); 
1330     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
); 
1331     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
); 
1332     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
); 
1333     event
.m_leftDown 
= (gdk_event
->state 
& GDK_BUTTON1_MASK
); 
1334     event
.m_middleDown 
= (gdk_event
->state 
& GDK_BUTTON2_MASK
); 
1335     event
.m_rightDown 
= (gdk_event
->state 
& GDK_BUTTON3_MASK
); 
1336     if (event
.GetEventType() == wxEVT_MOUSEWHEEL
) 
1338        event
.m_linesPerAction 
= 3; 
1339        event
.m_wheelDelta 
= 120; 
1340        if (((GdkEventButton
*)gdk_event
)->button 
== 4) 
1341            event
.m_wheelRotation 
= 120; 
1342        else if (((GdkEventButton
*)gdk_event
)->button 
== 5) 
1343            event
.m_wheelRotation 
= -120; 
1346     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1347     event
.m_x 
= (wxCoord
)gdk_event
->x 
- pt
.x
; 
1348     event
.m_y 
= (wxCoord
)gdk_event
->y 
- pt
.y
; 
1350     event
.SetEventObject( win 
); 
1351     event
.SetId( win
->GetId() ); 
1352     event
.SetTimestamp( gdk_event
->time 
); 
1355 static void AdjustEventButtonState(wxMouseEvent
& event
) 
1357     // GDK reports the old state of the button for a button press event, but 
1358     // for compatibility with MSW and common sense we want m_leftDown be true 
1359     // for a LEFT_DOWN event, not FALSE, so we will invert 
1360     // left/right/middleDown for the corresponding click events 
1362     if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) || 
1363         (event
.GetEventType() == wxEVT_LEFT_DCLICK
) || 
1364         (event
.GetEventType() == wxEVT_LEFT_UP
)) 
1366         event
.m_leftDown 
= !event
.m_leftDown
; 
1370     if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) || 
1371         (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) || 
1372         (event
.GetEventType() == wxEVT_MIDDLE_UP
)) 
1374         event
.m_middleDown 
= !event
.m_middleDown
; 
1378     if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) || 
1379         (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) || 
1380         (event
.GetEventType() == wxEVT_RIGHT_UP
)) 
1382         event
.m_rightDown 
= !event
.m_rightDown
; 
1387 // find the window to send the mouse event too 
1389 wxWindowGTK 
*FindWindowForMouseEvent(wxWindowGTK 
*win
, wxCoord
& x
, wxCoord
& y
) 
1394     if (win
->m_wxwindow
) 
1396         GtkPizza 
*pizza 
= GTK_PIZZA(win
->m_wxwindow
); 
1397         xx 
+= pizza
->xoffset
; 
1398         yy 
+= pizza
->yoffset
; 
1401     wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
1404         wxWindowGTK 
*child 
= node
->GetData(); 
1406         node 
= node
->GetNext(); 
1407         if (!child
->IsShown()) 
1410         if (child
->IsTransparentForMouse()) 
1412             // wxStaticBox is transparent in the box itself 
1413             int xx1 
= child
->m_x
; 
1414             int yy1 
= child
->m_y
; 
1415             int xx2 
= child
->m_x 
+ child
->m_width
; 
1416             int yy2 
= child
->m_y 
+ child
->m_height
; 
1419             if (((xx 
>= xx1
) && (xx 
<= xx1
+10) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1421                 ((xx 
>= xx2
-10) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1423                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy1
+10)) || 
1425                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy2
-1) && (yy 
<= yy2
))) 
1436             if ((child
->m_wxwindow 
== (GtkWidget
*) NULL
) && 
1437                 (child
->m_x 
<= xx
) && 
1438                 (child
->m_y 
<= yy
) && 
1439                 (child
->m_x
+child
->m_width  
>= xx
) && 
1440                 (child
->m_y
+child
->m_height 
>= yy
)) 
1453 //----------------------------------------------------------------------------- 
1454 // "button_press_event" 
1455 //----------------------------------------------------------------------------- 
1458 static gint 
gtk_window_button_press_callback( GtkWidget 
*widget
, 
1459                                               GdkEventButton 
*gdk_event
, 
1465         wxapp_install_idle_handler(); 
1468     wxPrintf( wxT("1) OnButtonPress from ") ); 
1469     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1470         wxPrintf( win->GetClassInfo()->GetClassName() ); 
1471     wxPrintf( wxT(".\n") ); 
1473     if (!win
->m_hasVMT
) return FALSE
; 
1474     if (g_blockEventsOnDrag
) return TRUE
; 
1475     if (g_blockEventsOnScroll
) return TRUE
; 
1477     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1479     g_lastButtonNumber 
= gdk_event
->button
; 
1481     if (win
->m_wxwindow 
&& (g_focusWindow 
!= win
) && win
->IsFocusable()) 
1483         gtk_widget_grab_focus( win
->m_wxwindow 
); 
1485         wxPrintf( wxT("GrabFocus from ") ); 
1486         if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1487             wxPrintf( win->GetClassInfo()->GetClassName() ); 
1488         wxPrintf( wxT(".\n") ); 
1492     // GDK sends surplus button down events 
1493     // before a double click event. We 
1494     // need to filter these out. 
1495     if (gdk_event
->type 
== GDK_BUTTON_PRESS
) 
1497         GdkEvent 
*peek_event 
= gdk_event_peek(); 
1500             if ((peek_event
->type 
== GDK_2BUTTON_PRESS
) || 
1501                 (peek_event
->type 
== GDK_3BUTTON_PRESS
)) 
1503                 gdk_event_free( peek_event 
); 
1508                 gdk_event_free( peek_event 
); 
1513     wxEventType event_type 
= wxEVT_NULL
; 
1515     if (gdk_event
->button 
== 1) 
1517         // note that GDK generates triple click events which are not supported 
1518         // by wxWidgets but still have to be passed to the app as otherwise 
1519         // clicks would simply go missing 
1520         switch (gdk_event
->type
) 
1522             // we shouldn't get triple clicks at all for GTK2 because we 
1523             // suppress them artificially using the code above but we still 
1524             // should map them to something for GTK1 and not just ignore them 
1525             // as this would lose clicks 
1526             case GDK_3BUTTON_PRESS
:     // we could also map this to DCLICK... 
1527             case GDK_BUTTON_PRESS
: 
1528                 event_type 
= wxEVT_LEFT_DOWN
; 
1531             case GDK_2BUTTON_PRESS
: 
1532                 event_type 
= wxEVT_LEFT_DCLICK
; 
1536                 // just to silence gcc warnings 
1540     else if (gdk_event
->button 
== 2) 
1542         switch (gdk_event
->type
) 
1544             case GDK_3BUTTON_PRESS
: 
1545             case GDK_BUTTON_PRESS
: 
1546                 event_type 
= wxEVT_MIDDLE_DOWN
; 
1549             case GDK_2BUTTON_PRESS
: 
1550                 event_type 
= wxEVT_MIDDLE_DCLICK
; 
1557     else if (gdk_event
->button 
== 3) 
1559         switch (gdk_event
->type
) 
1561             case GDK_3BUTTON_PRESS
: 
1562             case GDK_BUTTON_PRESS
: 
1563                 event_type 
= wxEVT_RIGHT_DOWN
; 
1566             case GDK_2BUTTON_PRESS
: 
1567                 event_type 
= wxEVT_RIGHT_DCLICK
; 
1574     else if (gdk_event
->button 
== 4 || gdk_event
->button 
== 5) 
1576         if (gdk_event
->type 
== GDK_BUTTON_PRESS 
) 
1578             event_type 
= wxEVT_MOUSEWHEEL
; 
1582     if ( event_type 
== wxEVT_NULL 
) 
1584         // unknown mouse button or click type 
1588     g_lastMouseEvent 
= (GdkEvent
*) gdk_event
; 
1590     wxMouseEvent 
event( event_type 
); 
1591     InitMouseEvent( win
, event
, gdk_event 
); 
1593     AdjustEventButtonState(event
); 
1595     // wxListBox actually gets mouse events from the item, so we need to give it 
1596     // a chance to correct this 
1597     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1599     // find the correct window to send the event to: it may be a different one 
1600     // from the one which got it at GTK+ level because some controls don't have 
1601     // their own X window and thus cannot get any events. 
1602     if ( !g_captureWindow 
) 
1603         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1605     wxGtkTimeLastClick 
= gdk_event
->time
; 
1607     if (event_type 
== wxEVT_LEFT_DCLICK
) 
1609         // GTK 1.2 crashes when intercepting double 
1610         // click events from both wxSpinButton and 
1612         if (GTK_IS_SPIN_BUTTON(win
->m_widget
)) 
1614             // Just disable this event for now. 
1619     if (win
->HandleWindowEvent( event 
)) 
1621         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" ); 
1622         g_lastMouseEvent 
= NULL
; 
1625     g_lastMouseEvent 
= NULL
; 
1627     if (event_type 
== wxEVT_RIGHT_DOWN
) 
1629         // generate a "context menu" event: this is similar to right mouse 
1630         // click under many GUIs except that it is generated differently 
1631         // (right up under MSW, ctrl-click under Mac, right down here) and 
1633         // (a) it's a command event and so is propagated to the parent 
1634         // (b) under some ports it can be generated from kbd too 
1635         // (c) it uses screen coords (because of (a)) 
1636         wxContextMenuEvent 
evtCtx( 
1639             win
->ClientToScreen(event
.GetPosition())); 
1640         evtCtx
.SetEventObject(win
); 
1641         return win
->HandleWindowEvent(evtCtx
); 
1648 //----------------------------------------------------------------------------- 
1649 // "button_release_event" 
1650 //----------------------------------------------------------------------------- 
1653 static gint 
gtk_window_button_release_callback( GtkWidget 
*widget
, 
1654                                                 GdkEventButton 
*gdk_event
, 
1660         wxapp_install_idle_handler(); 
1662     if (!win
->m_hasVMT
) return FALSE
; 
1663     if (g_blockEventsOnDrag
) return FALSE
; 
1664     if (g_blockEventsOnScroll
) return FALSE
; 
1666     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1668     g_lastButtonNumber 
= 0; 
1670     wxEventType event_type 
= wxEVT_NULL
; 
1672     switch (gdk_event
->button
) 
1675             event_type 
= wxEVT_LEFT_UP
; 
1679             event_type 
= wxEVT_MIDDLE_UP
; 
1683             event_type 
= wxEVT_RIGHT_UP
; 
1687             // unknwon button, don't process 
1691     g_lastMouseEvent 
= (GdkEvent
*) gdk_event
; 
1693     wxMouseEvent 
event( event_type 
); 
1694     InitMouseEvent( win
, event
, gdk_event 
); 
1696     AdjustEventButtonState(event
); 
1698     // same wxListBox hack as above 
1699     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1701     if ( !g_captureWindow 
) 
1702         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1704     if (win
->HandleWindowEvent( event 
)) 
1706         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" ); 
1714 //----------------------------------------------------------------------------- 
1715 // "motion_notify_event" 
1716 //----------------------------------------------------------------------------- 
1719 static gint 
gtk_window_motion_notify_callback( GtkWidget 
*widget
, 
1720                                                GdkEventMotion 
*gdk_event
, 
1726         wxapp_install_idle_handler(); 
1728     if (!win
->m_hasVMT
) return FALSE
; 
1729     if (g_blockEventsOnDrag
) return FALSE
; 
1730     if (g_blockEventsOnScroll
) return FALSE
; 
1732     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1734     if (gdk_event
->is_hint
) 
1738         GdkModifierType state
; 
1739         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1744     g_lastMouseEvent 
= (GdkEvent
*) gdk_event
; 
1747     printf( "OnMotion from " ); 
1748     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1749       printf( win->GetClassInfo()->GetClassName() ); 
1753     wxMouseEvent 
event( wxEVT_MOTION 
); 
1754     InitMouseEvent(win
, event
, gdk_event
); 
1756     if ( g_captureWindow 
) 
1758         // synthetize a mouse enter or leave event if needed 
1759         GdkWindow 
*winUnderMouse 
= gdk_window_at_pointer(NULL
, NULL
); 
1760         // This seems to be necessary and actually been added to 
1761         // GDK itself in version 2.0.X 
1764         bool hasMouse 
= winUnderMouse 
== gdk_event
->window
; 
1765         if ( hasMouse 
!= g_captureWindowHasMouse 
) 
1767             // the mouse changed window 
1768             g_captureWindowHasMouse 
= hasMouse
; 
1770             wxMouseEvent 
eventM(g_captureWindowHasMouse 
? wxEVT_ENTER_WINDOW
 
1771                                                         : wxEVT_LEAVE_WINDOW
); 
1772             InitMouseEvent(win
, eventM
, gdk_event
); 
1773             eventM
.SetEventObject(win
); 
1774             win
->HandleWindowEvent(eventM
); 
1779         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1782     bool ret 
= win
->HandleWindowEvent( event 
); 
1783     g_lastMouseEvent 
= NULL
; 
1787         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" ); 
1790     return ret 
? TRUE 
: FALSE
; 
1794 //----------------------------------------------------------------------------- 
1796 //----------------------------------------------------------------------------- 
1798 // send the wxChildFocusEvent and wxFocusEvent, common code of 
1799 // gtk_window_focus_in_callback() and SetFocus() 
1800 static bool DoSendFocusEvents(wxWindow 
*win
) 
1802     // Notify the parent keeping track of focus for the kbd navigation 
1803     // purposes that we got it. 
1804     wxChildFocusEvent 
eventChildFocus(win
); 
1805     (void)win
->HandleWindowEvent(eventChildFocus
); 
1807     wxFocusEvent 
eventFocus(wxEVT_SET_FOCUS
, win
->GetId()); 
1808     eventFocus
.SetEventObject(win
); 
1810     return win
->HandleWindowEvent(eventFocus
); 
1814 static gint 
gtk_window_focus_in_callback( GtkWidget 
*widget
, 
1815                                           GdkEvent 
*WXUNUSED(event
), 
1821         wxapp_install_idle_handler(); 
1824     g_focusWindow 
= win
; 
1826     wxLogTrace(TRACE_FOCUS
, 
1827                _T("%s: focus in"), win
->GetName().c_str()); 
1831         gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
); 
1835     // caret needs to be informed about focus change 
1836     wxCaret 
*caret 
= win
->GetCaret(); 
1839         caret
->OnSetFocus(); 
1841 #endif // wxUSE_CARET 
1843     // does the window itself think that it has the focus? 
1844     if ( !win
->m_hasFocus 
) 
1846         // not yet, notify it 
1847         win
->m_hasFocus 
= true; 
1849         if ( DoSendFocusEvents(win
) ) 
1851            gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" ); 
1860 //----------------------------------------------------------------------------- 
1861 // "focus_out_event" 
1862 //----------------------------------------------------------------------------- 
1865 static gint 
gtk_window_focus_out_callback( GtkWidget 
*WXUNUSED(widget
), 
1866                                            GdkEventFocus 
*WXUNUSED(gdk_event
), 
1872         wxapp_install_idle_handler(); 
1874     wxLogTrace( TRACE_FOCUS
, 
1875                 _T("%s: focus out"), win
->GetName().c_str() ); 
1878     wxWindowGTK 
*winFocus 
= wxFindFocusedChild(win
); 
1882     g_focusWindow 
= (wxWindowGTK 
*)NULL
; 
1890     // caret needs to be informed about focus change 
1891     wxCaret 
*caret 
= win
->GetCaret(); 
1894         caret
->OnKillFocus(); 
1896 #endif // wxUSE_CARET 
1898     // don't send the window a kill focus event if it thinks that it doesn't 
1899     // have focus already 
1900     if ( win
->m_hasFocus 
) 
1902         win
->m_hasFocus 
= false; 
1904         wxFocusEvent 
event( wxEVT_KILL_FOCUS
, win
->GetId() ); 
1905         event
.SetEventObject( win 
); 
1907         // even if we did process the event in wx code, still let GTK itself 
1908         // process it too as otherwise bad things happen, especially in GTK2 
1909         // where the text control simply aborts the program if it doesn't get 
1910         // the matching focus out event 
1911         (void)win
->HandleWindowEvent( event 
); 
1918 //----------------------------------------------------------------------------- 
1919 // "enter_notify_event" 
1920 //----------------------------------------------------------------------------- 
1924 gint 
gtk_window_enter_callback( GtkWidget 
*widget
, 
1925                                 GdkEventCrossing 
*gdk_event
, 
1931         wxapp_install_idle_handler(); 
1933     if (!win
->m_hasVMT
) return FALSE
; 
1934     if (g_blockEventsOnDrag
) return FALSE
; 
1936     // Event was emitted after a grab 
1937     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
1939     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1943     GdkModifierType state 
= (GdkModifierType
)0; 
1945     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
1947     wxMouseEvent 
event( wxEVT_ENTER_WINDOW 
); 
1948     InitMouseEvent(win
, event
, gdk_event
); 
1949     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1950     event
.m_x 
= x 
+ pt
.x
; 
1951     event
.m_y 
= y 
+ pt
.y
; 
1953     if (win
->HandleWindowEvent( event 
)) 
1955        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" ); 
1963 //----------------------------------------------------------------------------- 
1964 // "leave_notify_event" 
1965 //----------------------------------------------------------------------------- 
1968 static gint 
gtk_window_leave_callback( GtkWidget 
*widget
, GdkEventCrossing 
*gdk_event
, wxWindowGTK 
*win 
) 
1973         wxapp_install_idle_handler(); 
1975     if (!win
->m_hasVMT
) return FALSE
; 
1976     if (g_blockEventsOnDrag
) return FALSE
; 
1978     // Event was emitted after an ungrab 
1979     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
1981     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1983     wxMouseEvent 
event( wxEVT_LEAVE_WINDOW 
); 
1984     event
.SetTimestamp( gdk_event
->time 
); 
1985     event
.SetEventObject( win 
); 
1989     GdkModifierType state 
= (GdkModifierType
)0; 
1991     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
1993     event
.m_shiftDown 
= (state 
& GDK_SHIFT_MASK
) != 0; 
1994     event
.m_controlDown 
= (state 
& GDK_CONTROL_MASK
) != 0; 
1995     event
.m_altDown 
= (state 
& GDK_MOD1_MASK
) != 0; 
1996     event
.m_metaDown 
= (state 
& GDK_MOD2_MASK
) != 0; 
1997     event
.m_leftDown 
= (state 
& GDK_BUTTON1_MASK
) != 0; 
1998     event
.m_middleDown 
= (state 
& GDK_BUTTON2_MASK
) != 0; 
1999     event
.m_rightDown 
= (state 
& GDK_BUTTON3_MASK
) != 0; 
2001     wxPoint pt 
= win
->GetClientAreaOrigin(); 
2002     event
.m_x 
= x 
+ pt
.x
; 
2003     event
.m_y 
= y 
+ pt
.y
; 
2005     if (win
->HandleWindowEvent( event 
)) 
2007         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" ); 
2015 //----------------------------------------------------------------------------- 
2016 // "value_changed" from m_vAdjust 
2017 //----------------------------------------------------------------------------- 
2020 static void gtk_window_vscroll_callback( GtkAdjustment 
*adjust
, 
2027         wxapp_install_idle_handler(); 
2029     if (g_blockEventsOnDrag
) return; 
2031     if (!win
->m_hasVMT
) return; 
2033     float diff 
= adjust
->value 
- win
->m_oldVerticalPos
; 
2034     if (fabs(diff
) < 0.2) return; 
2036     win
->m_oldVerticalPos 
= adjust
->value
; 
2038     GtkScrolledWindow   
*sw 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
2039     wxEventType         command 
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->vscrollbar
)); 
2041     int value 
= (int)(adjust
->value
+0.5); 
2043     wxScrollWinEvent 
event( command
, value
, wxVERTICAL 
); 
2044     event
.SetEventObject( win 
); 
2045     win
->HandleWindowEvent( event 
); 
2049 //----------------------------------------------------------------------------- 
2050 // "value_changed" from m_hAdjust 
2051 //----------------------------------------------------------------------------- 
2054 static void gtk_window_hscroll_callback( GtkAdjustment 
*adjust
, 
2061         wxapp_install_idle_handler(); 
2063     if (g_blockEventsOnDrag
) return; 
2064     if (!win
->m_hasVMT
) return; 
2066     float diff 
= adjust
->value 
- win
->m_oldHorizontalPos
; 
2067     if (fabs(diff
) < 0.2) return; 
2069     GtkScrolledWindow   
*sw 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
2070     wxEventType         command 
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->hscrollbar
)); 
2072     win
->m_oldHorizontalPos 
= adjust
->value
; 
2074     int value 
= (int)(adjust
->value
+0.5); 
2076     wxScrollWinEvent 
event( command
, value
, wxHORIZONTAL 
); 
2077     event
.SetEventObject( win 
); 
2078     win
->HandleWindowEvent( event 
); 
2082 //----------------------------------------------------------------------------- 
2083 // "button_press_event" from scrollbar 
2084 //----------------------------------------------------------------------------- 
2087 static gint 
gtk_scrollbar_button_press_callback( GtkRange 
*widget
, 
2088                                                  GdkEventButton 
*gdk_event
, 
2094         wxapp_install_idle_handler(); 
2097     g_blockEventsOnScroll 
= true; 
2099     // FIXME: there is no 'slider' field in GTK+ 2.0 any more 
2100     win
->m_isScrolling 
= (gdk_event
->window 
== widget
->slider
); 
2106 //----------------------------------------------------------------------------- 
2107 // "button_release_event" from scrollbar 
2108 //----------------------------------------------------------------------------- 
2111 static gint 
gtk_scrollbar_button_release_callback( GtkRange 
*widget
, 
2112                                                    GdkEventButton 
*WXUNUSED(gdk_event
), 
2117 //  don't test here as we can release the mouse while being over 
2118 //  a different window than the slider 
2120 //    if (gdk_event->window != widget->slider) return FALSE; 
2122     g_blockEventsOnScroll 
= false; 
2124     if (win
->m_isScrolling
) 
2126         wxEventType command 
= wxEVT_SCROLLWIN_THUMBRELEASE
; 
2130         GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
2131         if (widget 
== GTK_RANGE(scrolledWindow
->hscrollbar
)) 
2133             value 
= (int)(win
->m_hAdjust
->value
+0.5); 
2136         if (widget 
== GTK_RANGE(scrolledWindow
->vscrollbar
)) 
2138             value 
= (int)(win
->m_vAdjust
->value
+0.5); 
2142         wxScrollWinEvent 
event( command
, value
, dir 
); 
2143         event
.SetEventObject( win 
); 
2144         win
->HandleWindowEvent( event 
); 
2147     win
->m_isScrolling 
= false; 
2153 // ---------------------------------------------------------------------------- 
2154 // this wxWindowBase function is implemented here (in platform-specific file) 
2155 // because it is static and so couldn't be made virtual 
2156 // ---------------------------------------------------------------------------- 
2158 wxWindow 
*wxWindowBase::DoFindFocus() 
2160     // the cast is necessary when we compile in wxUniversal mode 
2161     return (wxWindow 
*)g_focusWindow
; 
2164 //----------------------------------------------------------------------------- 
2165 // "realize" from m_widget 
2166 //----------------------------------------------------------------------------- 
2168 /* We cannot set colours and fonts before the widget has 
2169    been realized, so we do this directly after realization. */ 
2173 gtk_window_realized_callback( GtkWidget 
*WXUNUSED(widget
), wxWindow 
*win 
) 
2178         wxapp_install_idle_handler(); 
2180     wxWindowCreateEvent 
event( win 
); 
2181     event
.SetEventObject( win 
); 
2182     win
->HandleWindowEvent( event 
); 
2188 //----------------------------------------------------------------------------- 
2190 //----------------------------------------------------------------------------- 
2194 void gtk_window_size_callback( GtkWidget 
*WXUNUSED(widget
), 
2195                                GtkAllocation 
*WXUNUSED(alloc
), 
2199         wxapp_install_idle_handler(); 
2201     if (!win
->m_hasScrolling
) return; 
2203     int client_width 
= 0; 
2204     int client_height 
= 0; 
2205     win
->GetClientSize( &client_width
, &client_height 
); 
2206     if ((client_width 
== win
->m_oldClientWidth
) && (client_height 
== win
->m_oldClientHeight
)) 
2209     win
->m_oldClientWidth 
= client_width
; 
2210     win
->m_oldClientHeight 
= client_height
; 
2212     if (!win
->m_nativeSizeEvent
) 
2214         wxSizeEvent 
event( win
->GetSize(), win
->GetId() ); 
2215         event
.SetEventObject( win 
); 
2216         win
->HandleWindowEvent( event 
); 
2223     #define WXUNUSED_UNLESS_XIM(param)  param 
2225     #define WXUNUSED_UNLESS_XIM(param)  WXUNUSED(param) 
2228 /* Resize XIM window */ 
2232 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
), 
2233                                  GtkAllocation
* WXUNUSED(alloc
), 
2234                                  wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) ) 
2237         wxapp_install_idle_handler(); 
2243     if  (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
) 
2247         gdk_window_get_size (widget
->window
, &width
, &height
); 
2248         win
->m_icattr
->preedit_area
.width 
= width
; 
2249         win
->m_icattr
->preedit_area
.height 
= height
; 
2250         gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
); 
2256 //----------------------------------------------------------------------------- 
2257 // "realize" from m_wxwindow 
2258 //----------------------------------------------------------------------------- 
2260 /* Initialize XIM support */ 
2264 gtk_wxwindow_realized_callback( GtkWidget 
* WXUNUSED_UNLESS_XIM(widget
), 
2265                                 wxWindowGTK 
* WXUNUSED_UNLESS_XIM(win
) ) 
2268         wxapp_install_idle_handler(); 
2271     if (win
->m_ic
) return FALSE
; 
2272     if (!widget
) return FALSE
; 
2273     if (!gdk_im_ready()) return FALSE
; 
2275     win
->m_icattr 
= gdk_ic_attr_new(); 
2276     if (!win
->m_icattr
) return FALSE
; 
2280     GdkColormap 
*colormap
; 
2281     GdkICAttr 
*attr 
= win
->m_icattr
; 
2282     unsigned attrmask 
= GDK_IC_ALL_REQ
; 
2284     GdkIMStyle supported_style 
= (GdkIMStyle
) 
2285                                   (GDK_IM_PREEDIT_NONE 
| 
2286                                    GDK_IM_PREEDIT_NOTHING 
| 
2287                                    GDK_IM_PREEDIT_POSITION 
| 
2288                                    GDK_IM_STATUS_NONE 
| 
2289                                    GDK_IM_STATUS_NOTHING
); 
2291     if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2292         supported_style 
= (GdkIMStyle
)(supported_style 
& ~GDK_IM_PREEDIT_POSITION
); 
2294     attr
->style 
= style 
= gdk_im_decide_style (supported_style
); 
2295     attr
->client_window 
= widget
->window
; 
2297     if ((colormap 
= gtk_widget_get_colormap (widget
)) != 
2298             gtk_widget_get_default_colormap ()) 
2300         attrmask 
|= GDK_IC_PREEDIT_COLORMAP
; 
2301         attr
->preedit_colormap 
= colormap
; 
2304     attrmask 
|= GDK_IC_PREEDIT_FOREGROUND
; 
2305     attrmask 
|= GDK_IC_PREEDIT_BACKGROUND
; 
2306     attr
->preedit_foreground 
= widget
->style
->fg
[GTK_STATE_NORMAL
]; 
2307     attr
->preedit_background 
= widget
->style
->base
[GTK_STATE_NORMAL
]; 
2309     switch (style 
& GDK_IM_PREEDIT_MASK
) 
2311         case GDK_IM_PREEDIT_POSITION
: 
2312             if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2314                 g_warning ("over-the-spot style requires fontset"); 
2318             gdk_window_get_size (widget
->window
, &width
, &height
); 
2320             attrmask 
|= GDK_IC_PREEDIT_POSITION_REQ
; 
2321             attr
->spot_location
.x 
= 0; 
2322             attr
->spot_location
.y 
= height
; 
2323             attr
->preedit_area
.x 
= 0; 
2324             attr
->preedit_area
.y 
= 0; 
2325             attr
->preedit_area
.width 
= width
; 
2326             attr
->preedit_area
.height 
= height
; 
2327             attr
->preedit_fontset 
= widget
->style
->font
; 
2332       win
->m_ic 
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
); 
2334       if (win
->m_ic 
== NULL
) 
2335           g_warning ("Can't create input context."); 
2338           mask 
= gdk_window_get_events (widget
->window
); 
2339           mask 
= (GdkEventMask
)(mask 
| gdk_ic_get_events (win
->m_ic
)); 
2340           gdk_window_set_events (widget
->window
, mask
); 
2342           if (GTK_WIDGET_HAS_FOCUS(widget
)) 
2343               gdk_im_begin (win
->m_ic
, widget
->window
); 
2351 //----------------------------------------------------------------------------- 
2352 // InsertChild for wxWindowGTK. 
2353 //----------------------------------------------------------------------------- 
2355 /* Callback for wxWindowGTK. This very strange beast has to be used because 
2356  * C++ has no virtual methods in a constructor. We have to emulate a 
2357  * virtual function here as wxNotebook requires a different way to insert 
2358  * a child in it. I had opted for creating a wxNotebookPage window class 
2359  * which would have made this superfluous (such in the MDI window system), 
2360  * but no-one was listening to me... */ 
2362 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child 
) 
2364     /* the window might have been scrolled already, do we 
2365        have to adapt the position */ 
2366     GtkPizza 
*pizza 
= GTK_PIZZA(parent
->m_wxwindow
); 
2367     child
->m_x 
+= pizza
->xoffset
; 
2368     child
->m_y 
+= pizza
->yoffset
; 
2370     gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
), 
2371                      GTK_WIDGET(child
->m_widget
), 
2378 //----------------------------------------------------------------------------- 
2380 //----------------------------------------------------------------------------- 
2382 wxWindow 
*wxGetActiveWindow() 
2384     return wxWindow::FindFocus(); 
2388 wxMouseState 
wxGetMouseState() 
2394     GdkModifierType mask
; 
2396     gdk_window_get_pointer(NULL
, &x
, &y
, &mask
); 
2400     ms
.SetLeftDown(mask 
& GDK_BUTTON1_MASK
); 
2401     ms
.SetMiddleDown(mask 
& GDK_BUTTON2_MASK
); 
2402     ms
.SetRightDown(mask 
& GDK_BUTTON3_MASK
); 
2404     ms
.SetControlDown(mask 
& GDK_CONTROL_MASK
); 
2405     ms
.SetShiftDown(mask 
& GDK_SHIFT_MASK
); 
2406     ms
.SetAltDown(mask 
& GDK_MOD1_MASK
); 
2407     ms
.SetMetaDown(mask 
& GDK_MOD2_MASK
); 
2412 //----------------------------------------------------------------------------- 
2414 //----------------------------------------------------------------------------- 
2416 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
2418 #ifdef __WXUNIVERSAL__ 
2419     IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
) 
2421     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
2422 #endif // __WXUNIVERSAL__/__WXGTK__ 
2424 void wxWindowGTK::Init() 
2427     m_widget 
= (GtkWidget 
*) NULL
; 
2428     m_wxwindow 
= (GtkWidget 
*) NULL
; 
2429     m_focusWidget 
= (GtkWidget 
*) NULL
; 
2439     m_needParent 
= true; 
2440     m_isBeingDeleted 
= false; 
2443     m_nativeSizeEvent 
= false; 
2445     m_hasScrolling 
= false; 
2446     m_isScrolling 
= false; 
2448     m_hAdjust 
= (GtkAdjustment
*) NULL
; 
2449     m_vAdjust 
= (GtkAdjustment
*) NULL
; 
2450     m_oldHorizontalPos 
= 
2451     m_oldVerticalPos 
= 0.0; 
2453     m_oldClientHeight 
= 0; 
2457     m_insertCallback 
= (wxInsertChildFunction
) NULL
; 
2459     m_acceptsFocus 
= false; 
2462     m_clipPaintRegion 
= false; 
2464     m_needsStyleChange 
= false; 
2466     m_cursor 
= *wxSTANDARD_CURSOR
; 
2469     m_ic 
= (GdkIC
*) NULL
; 
2470     m_icattr 
= (GdkICAttr
*) NULL
; 
2474 wxWindowGTK::wxWindowGTK() 
2479 wxWindowGTK::wxWindowGTK( wxWindow 
*parent
, 
2484                           const wxString 
&name  
) 
2488     Create( parent
, id
, pos
, size
, style
, name 
); 
2491 bool wxWindowGTK::Create( wxWindow 
*parent
, 
2496                           const wxString 
&name  
) 
2498     // Get default border 
2499     wxBorder border 
= GetBorder(style
); 
2500     style 
&= ~wxBORDER_MASK
; 
2503     if (!PreCreation( parent
, pos
, size 
) || 
2504         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
2506         wxFAIL_MSG( wxT("wxWindowGTK creation failed") ); 
2510     m_insertCallback 
= wxInsertChildInWindow
; 
2512     m_widget 
= gtk_scrolled_window_new( (GtkAdjustment 
*) NULL
, (GtkAdjustment 
*) NULL 
); 
2513     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
2515     GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
2517     GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2518     scroll_class
->scrollbar_spacing 
= 0; 
2520     gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
2522     m_hAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) ); 
2523     m_vAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) ); 
2525     m_wxwindow 
= gtk_pizza_new(); 
2527 #ifndef __WXUNIVERSAL__ 
2528     GtkPizza 
*pizza 
= GTK_PIZZA(m_wxwindow
); 
2530     if (HasFlag(wxRAISED_BORDER
)) 
2532         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT 
); 
2534     else if (HasFlag(wxSUNKEN_BORDER
) || HasFlag(wxBORDER_THEME
)) 
2536         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN 
); 
2538     else if (HasFlag(wxSIMPLE_BORDER
)) 
2540         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN 
); 
2544         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE 
); 
2546 #endif // __WXUNIVERSAL__ 
2548     gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
2550     GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
2551     m_acceptsFocus 
= true; 
2553     // I _really_ don't want scrollbars in the beginning 
2554     m_vAdjust
->lower 
= 0.0; 
2555     m_vAdjust
->upper 
= 1.0; 
2556     m_vAdjust
->value 
= 0.0; 
2557     m_vAdjust
->step_increment 
= 1.0; 
2558     m_vAdjust
->page_increment 
= 1.0; 
2559     m_vAdjust
->page_size 
= 5.0; 
2560     gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
2561     m_hAdjust
->lower 
= 0.0; 
2562     m_hAdjust
->upper 
= 1.0; 
2563     m_hAdjust
->value 
= 0.0; 
2564     m_hAdjust
->step_increment 
= 1.0; 
2565     m_hAdjust
->page_increment 
= 1.0; 
2566     m_hAdjust
->page_size 
= 5.0; 
2567     gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
2569     // these handlers block mouse events to any window during scrolling such as 
2570     // motion events and prevent GTK and wxWidgets from fighting over where the 
2573     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event", 
2574           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
2576     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event", 
2577           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
2579     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event", 
2580           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
2582     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event", 
2583           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
2585     // these handlers get notified when screen updates are required either when 
2586     // scrolling or when the window size (and therefore scrollbar configuration) 
2589     gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
2590           (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
2591     gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
2592           (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
2594     gtk_widget_show( m_wxwindow 
); 
2597         m_parent
->DoAddChild( this ); 
2599     m_focusWidget 
= m_wxwindow
; 
2606 wxWindowGTK::~wxWindowGTK() 
2610     if (g_focusWindow 
== this) 
2611         g_focusWindow 
= NULL
; 
2613     if ( g_delayedFocus 
== this ) 
2614         g_delayedFocus 
= NULL
; 
2616     m_isBeingDeleted 
= true; 
2619     // destroy children before destroying this window itself 
2622     // unhook focus handlers to prevent stray events being 
2623     // propagated to this (soon to be) dead object 
2624     if (m_focusWidget 
!= NULL
) 
2626         gtk_signal_disconnect_by_func( GTK_OBJECT(m_focusWidget
), 
2627             (GtkSignalFunc
) gtk_window_focus_in_callback
, (gpointer
) this ); 
2628         gtk_signal_disconnect_by_func( GTK_OBJECT(m_focusWidget
), 
2629             (GtkSignalFunc
) gtk_window_focus_out_callback
, (gpointer
) this ); 
2637         gdk_ic_destroy (m_ic
); 
2639         gdk_ic_attr_destroy (m_icattr
); 
2644         gtk_widget_destroy( m_wxwindow 
); 
2645         m_wxwindow 
= (GtkWidget
*) NULL
; 
2650         gtk_widget_destroy( m_widget 
); 
2651         m_widget 
= (GtkWidget
*) NULL
; 
2655 bool wxWindowGTK::PreCreation( wxWindowGTK 
*parent
, const wxPoint 
&pos
,  const wxSize 
&size 
) 
2657     wxCHECK_MSG( !m_needParent 
|| parent
, false, wxT("Need complete parent.") ); 
2659     // Use either the given size, or the default if -1 is given. 
2660     // See wxWindowBase for these functions. 
2661     m_width 
= WidthDefault(size
.x
) ; 
2662     m_height 
= HeightDefault(size
.y
); 
2670 void wxWindowGTK::PostCreation() 
2672     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2678             // these get reported to wxWidgets -> wxPaintEvent 
2680             gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE 
); 
2682             gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event", 
2683                 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this ); 
2685             gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw", 
2686                 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this ); 
2688             if (!HasFlag(wxFULL_REPAINT_ON_RESIZE
)) 
2690                 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event", 
2691                     GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this ); 
2695         // these are called when the "sunken" or "raised" borders are drawn 
2696         gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event", 
2697           GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this ); 
2699         gtk_signal_connect( GTK_OBJECT(m_widget
), "draw", 
2700           GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this ); 
2705     if (!GTK_IS_WINDOW(m_widget
)) 
2707         if (m_focusWidget 
== NULL
) 
2708             m_focusWidget 
= m_widget
; 
2710         gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event", 
2711             GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this ); 
2713         gtk_signal_connect_after( GTK_OBJECT(m_focusWidget
), "focus_out_event", 
2714             GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this ); 
2717     // connect to the various key and mouse handlers 
2719     GtkWidget 
*connect_widget 
= GetConnectWidget(); 
2721     ConnectWidget( connect_widget 
); 
2723     /* We cannot set colours, fonts and cursors before the widget has 
2724        been realized, so we do this directly after realization */ 
2725     gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize", 
2726                             GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this ); 
2730         // Catch native resize events 
2731         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate", 
2732                             GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this ); 
2734         // Initialize XIM support 
2735         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize", 
2736                             GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this ); 
2738         // And resize XIM window 
2739         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate", 
2740                             GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this ); 
2743     if (GTK_IS_COMBO(m_widget
)) 
2745         GtkCombo 
*gcombo 
= GTK_COMBO(m_widget
); 
2747         gtk_signal_connect( GTK_OBJECT(gcombo
->entry
), "size_request", 
2748                             GTK_SIGNAL_FUNC(wxgtk_combo_size_request_callback
), 
2753         // This is needed if we want to add our windows into native 
2754         // GTK controls, such as the toolbar. With this callback, the 
2755         // toolbar gets to know the correct size (the one set by the 
2756         // programmer). Sadly, it misbehaves for wxComboBox. 
2757         gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request", 
2758                             GTK_SIGNAL_FUNC(wxgtk_window_size_request_callback
), 
2762     InheritAttributes(); 
2766     // unless the window was created initially hidden (i.e. Hide() had been 
2767     // called before Create()), we should show it at GTK+ level as well 
2769         gtk_widget_show( m_widget 
); 
2772 void wxWindowGTK::ConnectWidget( GtkWidget 
*widget 
) 
2774     gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event", 
2775       GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this ); 
2777     gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event", 
2778       GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this ); 
2780     gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event", 
2781       GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this ); 
2783     gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event", 
2784       GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this ); 
2786     gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event", 
2787       GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this ); 
2789     gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event", 
2790       GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this ); 
2792     gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event", 
2793       GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this ); 
2796 bool wxWindowGTK::Destroy() 
2798     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2802     return wxWindowBase::Destroy(); 
2805 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
) 
2807     gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height 
); 
2810 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
2812     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2813     wxASSERT_MSG( (m_parent 
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") ); 
2816     printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height ); 
2819     if (m_resizing
) return; /* I don't like recursions */ 
2822     int currentX
, currentY
; 
2823     GetPosition(¤tX
, ¤tY
); 
2824     if (x 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
2826     if (y 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
2828     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
2830     if (m_parent
->m_wxwindow 
== NULL
) /* i.e. wxNotebook */ 
2832         /* don't set the size for children of wxNotebook, just take the values. */ 
2840         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
2841         if ((sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) == 0) 
2843             if (x 
!= -1) m_x 
= x 
+ pizza
->xoffset
; 
2844             if (y 
!= -1) m_y 
= y 
+ pizza
->yoffset
; 
2848             m_x 
= x 
+ pizza
->xoffset
; 
2849             m_y 
= y 
+ pizza
->yoffset
; 
2852         // calculate the best size if we should auto size the window 
2853         if ( ((sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1) || 
2854                 ((sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1) ) 
2856             const wxSize sizeBest 
= GetBestSize(); 
2857             if ( (sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1 ) 
2859             if ( (sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1 ) 
2860                 height 
= sizeBest
.y
; 
2868         int minWidth 
= GetMinWidth(), 
2869             minHeight 
= GetMinHeight(), 
2870             maxWidth 
= GetMaxWidth(), 
2871             maxHeight 
= GetMaxHeight(); 
2873         if ((minWidth 
!= -1) && (m_width 
< minWidth
)) m_width 
= minWidth
; 
2874         if ((minHeight 
!= -1) && (m_height 
< minHeight
)) m_height 
= minHeight
; 
2875         if ((maxWidth 
!= -1) && (m_width 
> maxWidth
)) m_width 
= maxWidth
; 
2876         if ((maxHeight 
!= -1) && (m_height 
> maxHeight
)) m_height 
= maxHeight
; 
2878         int left_border 
= 0; 
2879         int right_border 
= 0; 
2881         int bottom_border 
= 0; 
2883         /* the default button has a border around it */ 
2884         if (GTK_WIDGET_CAN_DEFAULT(m_widget
)) 
2892         DoMoveWindow( m_x
-top_border
, 
2894                       m_width
+left_border
+right_border
, 
2895                       m_height
+top_border
+bottom_border 
); 
2900         /* Sometimes the client area changes size without the 
2901            whole windows's size changing, but if the whole 
2902            windows's size doesn't change, no wxSizeEvent will 
2903            normally be sent. Here we add an extra test if 
2904            the client test has been changed and this will 
2906         GetClientSize( &m_oldClientWidth
, &m_oldClientHeight 
); 
2910     wxPrintf( "OnSize sent from " ); 
2911     if (GetClassInfo() && GetClassInfo()->GetClassName()) 
2912         wxPrintf( GetClassInfo()->GetClassName() ); 
2913     wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height ); 
2916     if (!m_nativeSizeEvent
) 
2918         wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
2919         event
.SetEventObject( this ); 
2920         HandleWindowEvent( event 
); 
2926 void wxWindowGTK::OnInternalIdle() 
2928     // Update style if the window was not yet realized 
2929     // and SetBackgroundStyle(wxBG_STYLE_CUSTOM) was called 
2930     if (m_needsStyleChange
) 
2932         SetBackgroundStyle(GetBackgroundStyle()); 
2933         m_needsStyleChange 
= false; 
2936     // Update invalidated regions. 
2939     wxCursor cursor 
= m_cursor
; 
2940     if (g_globalCursor
.Ok()) cursor 
= g_globalCursor
; 
2944         /* I now set the cursor anew in every OnInternalIdle call 
2945            as setting the cursor in a parent window also effects the 
2946            windows above so that checking for the current cursor is 
2951             GdkWindow 
*window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
2953                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2955             if (!g_globalCursor
.Ok()) 
2956                 cursor 
= *wxSTANDARD_CURSOR
; 
2958             window 
= m_widget
->window
; 
2959             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
2960                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2963         else if ( m_widget 
) 
2965             GdkWindow 
*window 
= m_widget
->window
; 
2966             if ( window 
&& !GTK_WIDGET_NO_WINDOW(m_widget
) ) 
2967                gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2971     if (wxUpdateUIEvent::CanUpdate(this) && IsShown()) 
2972         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
2975 void wxWindowGTK::DoGetSize( int *width
, int *height 
) const 
2977     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2979     if (width
) (*width
) = m_width
; 
2980     if (height
) (*height
) = m_height
; 
2983 void wxWindowGTK::DoSetClientSize( int width
, int height 
) 
2985     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2989         SetSize( width
, height 
); 
2996 #ifndef __WXUNIVERSAL__ 
2997         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
) || HasFlag(wxBORDER_THEME
)) 
2999             /* when using GTK 1.2 we set the shadow border size to 2 */ 
3003         if (HasFlag(wxSIMPLE_BORDER
)) 
3005             /* when using GTK 1.2 we set the simple border size to 1 */ 
3009 #endif // __WXUNIVERSAL__ 
3013             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
3015             GtkRequisition vscroll_req
; 
3016             vscroll_req
.width 
= 2; 
3017             vscroll_req
.height 
= 2; 
3018             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
3019                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
3021             GtkRequisition hscroll_req
; 
3022             hscroll_req
.width 
= 2; 
3023             hscroll_req
.height 
= 2; 
3024             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
3025                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
3027             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
3029             if (scroll_window
->vscrollbar_visible
) 
3031                 dw 
+= vscroll_req
.width
; 
3032                 dw 
+= scroll_class
->scrollbar_spacing
; 
3035             if (scroll_window
->hscrollbar_visible
) 
3037                 dh 
+= hscroll_req
.height
; 
3038                 dh 
+= scroll_class
->scrollbar_spacing
; 
3042        SetSize( width
+dw
, height
+dh 
); 
3046 void wxWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
3048     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3052         if (width
) (*width
) = m_width
; 
3053         if (height
) (*height
) = m_height
; 
3060 #ifndef __WXUNIVERSAL__ 
3061         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
) || HasFlag(wxBORDER_THEME
)) 
3063             /* when using GTK 1.2 we set the shadow border size to 2 */ 
3067         if (HasFlag(wxSIMPLE_BORDER
)) 
3069             /* when using GTK 1.2 we set the simple border size to 1 */ 
3073 #endif // __WXUNIVERSAL__ 
3077             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
3079             GtkRequisition vscroll_req
; 
3080             vscroll_req
.width 
= 2; 
3081             vscroll_req
.height 
= 2; 
3082             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
3083                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
3085             GtkRequisition hscroll_req
; 
3086             hscroll_req
.width 
= 2; 
3087             hscroll_req
.height 
= 2; 
3088             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
3089                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
3091             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
3093             if (scroll_window
->vscrollbar_visible
) 
3095                 dw 
+= vscroll_req
.width
; 
3096                 dw 
+= scroll_class
->scrollbar_spacing
; 
3099             if (scroll_window
->hscrollbar_visible
) 
3101                 dh 
+= hscroll_req
.height
; 
3102                 dh 
+= scroll_class
->scrollbar_spacing
; 
3106         if (width
) (*width
) = m_width 
- dw
; 
3107         if (height
) (*height
) = m_height 
- dh
; 
3111     printf( "GetClientSize, name %s ", GetName().c_str() ); 
3112     if (width) printf( " width = %d", (*width) ); 
3113     if (height) printf( " height = %d", (*height) ); 
3118 void wxWindowGTK::DoGetPosition( int *x
, int *y 
) const 
3120     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3124     if (m_parent 
&& m_parent
->m_wxwindow
) 
3126         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
3127         dx 
= pizza
->xoffset
; 
3128         dy 
= pizza
->yoffset
; 
3131     if (x
) (*x
) = m_x 
- dx
; 
3132     if (y
) (*y
) = m_y 
- dy
; 
3135 void wxWindowGTK::DoClientToScreen( int *x
, int *y 
) const 
3137     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3139     if (!m_widget
->window
) return; 
3141     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3143         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3145         source 
= m_widget
->window
; 
3149     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3153         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3155             org_x 
+= m_widget
->allocation
.x
; 
3156             org_y 
+= m_widget
->allocation
.y
; 
3164 void wxWindowGTK::DoScreenToClient( int *x
, int *y 
) const 
3166     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3168     if (!m_widget
->window
) return; 
3170     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3172         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3174         source 
= m_widget
->window
; 
3178     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3182         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3184             org_x 
+= m_widget
->allocation
.x
; 
3185             org_y 
+= m_widget
->allocation
.y
; 
3193 bool wxWindowGTK::Show( bool show 
) 
3195     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3197     if (!wxWindowBase::Show(show
)) 
3204         gtk_widget_show( m_widget 
); 
3206         gtk_widget_hide( m_widget 
); 
3208     wxShowEvent 
eventShow(GetId(), show
); 
3209     eventShow
.SetEventObject(this); 
3211     HandleWindowEvent(eventShow
); 
3216 void wxWindowGTK::DoEnable( bool enable 
) 
3218     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3220     gtk_widget_set_sensitive( m_widget
, enable 
); 
3222         gtk_widget_set_sensitive( m_wxwindow
, enable 
); 
3225 int wxWindowGTK::GetCharHeight() const 
3227     wxCHECK_MSG( (m_widget 
!= NULL
), 12, wxT("invalid window") ); 
3229     wxFont font 
= GetFont(); 
3230     wxCHECK_MSG( font
.Ok(), 12, wxT("invalid font") ); 
3232     GdkFont 
*gfont 
= font
.GetInternalFont( 1.0 ); 
3234     return gfont
->ascent 
+ gfont
->descent
; 
3237 int wxWindowGTK::GetCharWidth() const 
3239     wxCHECK_MSG( (m_widget 
!= NULL
), 8, wxT("invalid window") ); 
3241     wxFont font 
= GetFont(); 
3242     wxCHECK_MSG( font
.Ok(), 8, wxT("invalid font") ); 
3244     GdkFont 
*gfont 
= font
.GetInternalFont( 1.0 ); 
3246     return gdk_string_width( gfont
, "g" ); 
3249 void wxWindowGTK::GetTextExtent( const wxString
& string
, 
3253                                  int *externalLeading
, 
3254                                  const wxFont 
*theFont 
) const 
3256     wxFont fontToUse 
= theFont 
? *theFont 
: GetFont(); 
3258     wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") ); 
3267     GdkFont 
*font 
= fontToUse
.GetInternalFont( 1.0 ); 
3268     if (x
) (*x
) = gdk_string_width( font
, wxGTK_CONV( string 
) ); 
3269     if (y
) (*y
) = font
->ascent 
+ font
->descent
; 
3270     if (descent
) (*descent
) = font
->descent
; 
3271     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3274 void wxWindowGTK::SetFocus() 
3276     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3279         // don't do anything if we already have focus 
3285         if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
)) 
3287             gtk_widget_grab_focus (m_wxwindow
); 
3292         if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) ) 
3295             if (!GTK_WIDGET_REALIZED(m_widget
)) 
3297                 // we can't set the focus to the widget now so we remember that 
3298                 // it should be focused and will do it later, during the idle 
3299                 // time, as soon as we can 
3300                 wxLogTrace(TRACE_FOCUS
, 
3301                            _T("Delaying setting focus to %s(%s)"), 
3302                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3304                 g_delayedFocus 
= this; 
3308                 wxLogTrace(TRACE_FOCUS
, 
3309                            _T("Setting focus to %s(%s)"), 
3310                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3312                 gtk_widget_grab_focus (m_widget
); 
3316         if (GTK_IS_CONTAINER(m_widget
)) 
3318             gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD 
); 
3322            wxLogTrace(TRACE_FOCUS
, 
3323                       _T("Can't set focus to %s(%s)"), 
3324                       GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3329 bool wxWindowGTK::AcceptsFocus() const 
3331     return m_acceptsFocus 
&& wxWindowBase::AcceptsFocus(); 
3334 bool wxWindowGTK::Reparent( wxWindowBase 
*newParentBase 
) 
3336     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3338     wxWindowGTK 
*oldParent 
= m_parent
, 
3339              *newParent 
= (wxWindowGTK 
*)newParentBase
; 
3341     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3343     if ( !wxWindowBase::Reparent(newParent
) ) 
3346     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3348     /* prevent GTK from deleting the widget arbitrarily */ 
3349     gtk_widget_ref( m_widget 
); 
3353         gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget 
); 
3356     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3360         /* insert GTK representation */ 
3361         (*(newParent
->m_insertCallback
))(newParent
, this); 
3364     /* reverse: prevent GTK from deleting the widget arbitrarily */ 
3365     gtk_widget_unref( m_widget 
); 
3370 void wxWindowGTK::DoAddChild(wxWindowGTK 
*child
) 
3372     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3374     wxASSERT_MSG( (child 
!= NULL
), wxT("invalid child window") ); 
3376     wxASSERT_MSG( (m_insertCallback 
!= NULL
), wxT("invalid child insertion function") ); 
3381     /* insert GTK representation */ 
3382     (*m_insertCallback
)(this, child
); 
3385 void wxWindowGTK::Raise() 
3387     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3389     if (m_wxwindow 
&& m_wxwindow
->window
) 
3391         gdk_window_raise( m_wxwindow
->window 
); 
3393     else if (m_widget
->window
) 
3395         gdk_window_raise( m_widget
->window 
); 
3399 void wxWindowGTK::Lower() 
3401     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3403     if (m_wxwindow 
&& m_wxwindow
->window
) 
3405         gdk_window_lower( m_wxwindow
->window 
); 
3407     else if (m_widget
->window
) 
3409         gdk_window_lower( m_widget
->window 
); 
3413 bool wxWindowGTK::SetCursor( const wxCursor 
&cursor 
) 
3415     wxCHECK_MSG( (m_widget 
!= NULL
), false, wxT("invalid window") ); 
3417     if ( cursor
.IsSameAs(m_cursor
) ) 
3421         wxapp_install_idle_handler(); 
3423     return wxWindowBase::SetCursor( cursor
.IsOk() ? cursor
 
3424                                                   : *wxSTANDARD_CURSOR 
); 
3427 void wxWindowGTK::WarpPointer( int x
, int y 
) 
3429     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3431     // We provide this function ourselves as it is 
3432     // missing in GDK (top of this file). 
3434     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3436         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3438         window 
= GetConnectWidget()->window
; 
3441         gdk_window_warp_pointer( window
, x
, y 
); 
3445 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect 
*rect 
) 
3449     if (!m_widget
->window
) 
3453         wxapp_install_idle_handler(); 
3456     if (m_wxwindow 
&& rect
) 
3458         myRect
.SetSize(wxSize( m_wxwindow
->allocation
.width
, 
3459                                m_wxwindow
->allocation
.height
)); 
3460         if ( myRect
.Intersect(*rect
).IsEmpty() ) 
3462             // nothing to do, rectangle is empty 
3469     // schedule the area for later updating in GtkUpdate() 
3470     if (eraseBackground 
&& m_wxwindow 
&& m_wxwindow
->window
) 
3474             m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3478             m_clearRegion
.Clear(); 
3479             m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3487             m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3491             GdkRectangle gdk_rect
; 
3492             gdk_rect
.x 
= rect
->x
; 
3493             gdk_rect
.y 
= rect
->y
; 
3494             gdk_rect
.width 
= rect
->width
; 
3495             gdk_rect
.height 
= rect
->height
; 
3496             gtk_widget_draw( m_widget
, &gdk_rect 
); 
3503             m_updateRegion
.Clear(); 
3504             m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3508             gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL 
); 
3513 void wxWindowGTK::Update() 
3517     // when we call Update() we really want to update the window immediately on 
3518     // screen, even if it means flushing the entire queue and hence slowing down 
3519     // everything -- but it should still be done, it's just that Update() should 
3520     // be called very rarely 
3524 void wxWindowGTK::GtkUpdate() 
3526     if (!m_updateRegion
.IsEmpty()) 
3527         GtkSendPaintEvents(); 
3529     // for consistency with other platforms (and also because it's convenient 
3530     // to be able to update an entire TLW by calling Update() only once), we 
3531     // should also update all our children here 
3532     for ( wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
3534           node 
= node
->GetNext() ) 
3536         node
->GetData()->GtkUpdate(); 
3540 void wxWindowGTK::GtkSendPaintEvents() 
3544         m_clearRegion
.Clear(); 
3545         m_updateRegion
.Clear(); 
3549     // Clip to paint region in wxClientDC 
3550     m_clipPaintRegion 
= true; 
3552     // widget to draw on 
3553     GtkPizza 
*pizza 
= GTK_PIZZA (m_wxwindow
); 
3555     if (GetThemeEnabled() && (GetBackgroundStyle() == wxBG_STYLE_SYSTEM
)) 
3557         // find ancestor from which to steal background 
3558         wxWindow 
*parent 
= wxGetTopLevelParent((wxWindow 
*)this); 
3560             parent 
= (wxWindow
*)this; 
3562         if (GTK_WIDGET_MAPPED(parent
->m_widget
)) 
3564             wxRegionIterator 
upd( m_updateRegion 
); 
3568                 rect
.x 
= upd
.GetX(); 
3569                 rect
.y 
= upd
.GetY(); 
3570                 rect
.width 
= upd
.GetWidth(); 
3571                 rect
.height 
= upd
.GetHeight(); 
3573                 gtk_paint_flat_box( parent
->m_widget
->style
, 
3575                             (GtkStateType
)GTK_WIDGET_STATE(m_wxwindow
), 
3588     // if (!m_clearRegion.IsEmpty())   // Always send an erase event under GTK 1.2 
3590         wxWindowDC 
dc( (wxWindow
*)this ); 
3591         if (m_clearRegion
.IsEmpty()) 
3592             dc
.SetClippingRegion( m_updateRegion 
); 
3594             dc
.SetClippingRegion( m_clearRegion 
); 
3596         wxEraseEvent 
erase_event( GetId(), &dc 
); 
3597         erase_event
.SetEventObject( this ); 
3599         if (!HandleWindowEvent(erase_event
) && GetBackgroundStyle() != wxBG_STYLE_CUSTOM
) 
3603                 g_eraseGC 
= gdk_gc_new( pizza
->bin_window 
); 
3604                 gdk_gc_set_fill( g_eraseGC
, GDK_SOLID 
); 
3606             gdk_gc_set_foreground( g_eraseGC
, GetBackgroundColour().GetColor() ); 
3608             wxRegionIterator 
upd( m_clearRegion 
); 
3611                 gdk_draw_rectangle( pizza
->bin_window
, g_eraseGC
, 1, 
3612                                     upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() ); 
3616         m_clearRegion
.Clear(); 
3619     wxNcPaintEvent 
nc_paint_event( GetId() ); 
3620     nc_paint_event
.SetEventObject( this ); 
3621     HandleWindowEvent( nc_paint_event 
); 
3623     wxPaintEvent 
paint_event( GetId() ); 
3624     paint_event
.SetEventObject( this ); 
3625     HandleWindowEvent( paint_event 
); 
3627     m_clipPaintRegion 
= false; 
3629 #if !defined(__WXUNIVERSAL__) 
3630     // The following code will result in all window-less widgets 
3631     // being redrawn because the wxWidgets class is allowed to 
3632     // paint over the window-less widgets. 
3634     GList 
*children 
= pizza
->children
; 
3637         GtkPizzaChild 
*child 
= (GtkPizzaChild
*) children
->data
; 
3638         children 
= children
->next
; 
3640         if (GTK_WIDGET_NO_WINDOW (child
->widget
) && 
3641             GTK_WIDGET_DRAWABLE (child
->widget
)) 
3643             // Get intersection of widget area and update region 
3644             wxRegion 
region( m_updateRegion 
); 
3646             GdkEventExpose gdk_event
; 
3647             gdk_event
.type 
= GDK_EXPOSE
; 
3648             gdk_event
.window 
= pizza
->bin_window
; 
3649             gdk_event
.count 
= 0; 
3650             gdk_event
.send_event 
= TRUE
; 
3652             wxRegionIterator 
upd( m_updateRegion 
); 
3656                 rect
.x 
= upd
.GetX(); 
3657                 rect
.y 
= upd
.GetY(); 
3658                 rect
.width 
= upd
.GetWidth(); 
3659                 rect
.height 
= upd
.GetHeight(); 
3661                 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
)) 
3663                     gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
); 
3670 #endif // native GTK 1 
3672     m_updateRegion
.Clear(); 
3675 void wxWindowGTK::ClearBackground() 
3677     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3679     if (m_wxwindow 
&& m_wxwindow
->window
) 
3681         m_clearRegion
.Clear(); 
3682         wxSize 
size( GetClientSize() ); 
3683         m_clearRegion
.Union( 0,0,size
.x
,size
.y 
); 
3685         // Better do this in idle? 
3691 void wxWindowGTK::DoSetToolTip( wxToolTip 
*tip 
) 
3693     wxWindowBase::DoSetToolTip(tip
); 
3696         m_tooltip
->Apply( (wxWindow 
*)this ); 
3699 void wxWindowGTK::ApplyToolTip( GtkTooltips 
*tips
, const wxChar 
*tip 
) 
3701     wxString 
tmp( tip 
); 
3702     gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxGTK_CONV(tmp
), (gchar
*) NULL 
); 
3704 #endif // wxUSE_TOOLTIPS 
3706 bool wxWindowGTK::SetBackgroundColour( const wxColour 
&colour 
) 
3708     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3710     if (!wxWindowBase::SetBackgroundColour(colour
)) 
3715         // We need the pixel value e.g. for background clearing. 
3716         m_backgroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
3719     // apply style change (forceStyle=true so that new style is applied 
3720     // even if the bg colour changed from valid to wxNullColour) 
3721     if (GetBackgroundStyle() != wxBG_STYLE_CUSTOM
) 
3722         ApplyWidgetStyle(true); 
3727 bool wxWindowGTK::SetForegroundColour( const wxColour 
&colour 
) 
3729     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3731     if (!wxWindowBase::SetForegroundColour(colour
)) 
3738         // We need the pixel value e.g. for background clearing. 
3739         m_foregroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
3742     // apply style change (forceStyle=true so that new style is applied 
3743     // even if the bg colour changed from valid to wxNullColour): 
3744     ApplyWidgetStyle(true); 
3749 GtkRcStyle 
*wxWindowGTK::CreateWidgetStyle(bool forceStyle
) 
3751     // do we need to apply any changes at all? 
3754          !m_foregroundColour
.Ok() && !m_backgroundColour
.Ok() ) 
3759     GtkRcStyle 
*style 
= gtk_rc_style_new(); 
3763         wxString xfontname 
= m_font
.GetNativeFontInfo()->GetXFontName(); 
3764         style
->fontset_name 
= g_strdup(xfontname
.c_str()); 
3767     if ( m_foregroundColour
.Ok() ) 
3769         GdkColor 
*fg 
= m_foregroundColour
.GetColor(); 
3771         style
->fg
[GTK_STATE_NORMAL
] = *fg
; 
3772         style
->color_flags
[GTK_STATE_NORMAL
] = GTK_RC_FG
; 
3774         style
->fg
[GTK_STATE_PRELIGHT
] = *fg
; 
3775         style
->color_flags
[GTK_STATE_PRELIGHT
] = GTK_RC_FG
; 
3777         style
->fg
[GTK_STATE_ACTIVE
] = *fg
; 
3778         style
->color_flags
[GTK_STATE_ACTIVE
] = GTK_RC_FG
; 
3781     if ( m_backgroundColour
.Ok() ) 
3783         GdkColor 
*bg 
= m_backgroundColour
.GetColor(); 
3785         style
->bg
[GTK_STATE_NORMAL
] = *bg
; 
3786         style
->base
[GTK_STATE_NORMAL
] = *bg
; 
3787         style
->color_flags
[GTK_STATE_NORMAL
] = (GtkRcFlags
) 
3788             (style
->color_flags
[GTK_STATE_NORMAL
] | GTK_RC_BG 
| GTK_RC_BASE
); 
3790         style
->bg
[GTK_STATE_PRELIGHT
] = *bg
; 
3791         style
->base
[GTK_STATE_PRELIGHT
] = *bg
; 
3792         style
->color_flags
[GTK_STATE_PRELIGHT
] = (GtkRcFlags
) 
3793             (style
->color_flags
[GTK_STATE_PRELIGHT
] | GTK_RC_BG 
| GTK_RC_BASE
); 
3795         style
->bg
[GTK_STATE_ACTIVE
] = *bg
; 
3796         style
->base
[GTK_STATE_ACTIVE
] = *bg
; 
3797         style
->color_flags
[GTK_STATE_ACTIVE
] = (GtkRcFlags
) 
3798             (style
->color_flags
[GTK_STATE_ACTIVE
] | GTK_RC_BG 
| GTK_RC_BASE
); 
3800         style
->bg
[GTK_STATE_INSENSITIVE
] = *bg
; 
3801         style
->base
[GTK_STATE_INSENSITIVE
] = *bg
; 
3802         style
->color_flags
[GTK_STATE_INSENSITIVE
] = (GtkRcFlags
) 
3803             (style
->color_flags
[GTK_STATE_INSENSITIVE
] | GTK_RC_BG 
| GTK_RC_BASE
); 
3809 void wxWindowGTK::ApplyWidgetStyle(bool forceStyle
) 
3811     GtkRcStyle 
*style 
= CreateWidgetStyle(forceStyle
); 
3814         DoApplyWidgetStyle(style
); 
3815         gtk_rc_style_unref(style
); 
3818     // Style change may affect GTK+'s size calculation: 
3819     InvalidateBestSize(); 
3822 void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
3825         gtk_widget_modify_style(m_wxwindow
, style
); 
3827         gtk_widget_modify_style(m_widget
, style
); 
3830 bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style
) 
3832     wxWindowBase::SetBackgroundStyle(style
); 
3834     if (style 
== wxBG_STYLE_CUSTOM
) 
3836         GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3838             window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3840             window 
= GetConnectWidget()->window
; 
3844             // Make sure GDK/X11 doesn't refresh the window 
3846             gdk_window_set_back_pixmap( window
, None
, False 
); 
3848             Display
* display 
= GDK_WINDOW_DISPLAY(window
); 
3851             m_needsStyleChange 
= false; 
3854             // Do in OnIdle, because the window is not yet available 
3855             m_needsStyleChange 
= true; 
3857         // Don't apply widget style, or we get a grey background 
3861         // apply style change (forceStyle=true so that new style is applied 
3862         // even if the bg colour changed from valid to wxNullColour): 
3863         ApplyWidgetStyle(true); 
3868 #if wxUSE_DRAG_AND_DROP 
3870 void wxWindowGTK::SetDropTarget( wxDropTarget 
*dropTarget 
) 
3872     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3874     GtkWidget 
*dnd_widget 
= GetConnectWidget(); 
3876     if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget 
); 
3878     if (m_dropTarget
) delete m_dropTarget
; 
3879     m_dropTarget 
= dropTarget
; 
3881     if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget 
); 
3884 #endif // wxUSE_DRAG_AND_DROP 
3886 GtkWidget
* wxWindowGTK::GetConnectWidget() 
3888     GtkWidget 
*connect_widget 
= m_widget
; 
3889     if (m_wxwindow
) connect_widget 
= m_wxwindow
; 
3891     return connect_widget
; 
3894 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow 
*window 
) 
3897         return (window 
== GTK_PIZZA(m_wxwindow
)->bin_window
); 
3899     return (window 
== m_widget
->window
); 
3902 bool wxWindowGTK::SetFont( const wxFont 
&font 
) 
3904     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
3906     if (!wxWindowBase::SetFont(font
)) 
3909     // apply style change (forceStyle=true so that new style is applied 
3910     // even if the font changed from valid to wxNullFont): 
3911     ApplyWidgetStyle(true); 
3916 void wxWindowGTK::DoCaptureMouse() 
3918     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3920     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3922         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3924         window 
= GetConnectWidget()->window
; 
3926     wxCHECK_RET( window
, _T("CaptureMouse() failed") ); 
3928     const wxCursor
* cursor 
= &m_cursor
; 
3930         cursor 
= wxSTANDARD_CURSOR
; 
3932     gdk_pointer_grab( window
, FALSE
, 
3934                          (GDK_BUTTON_PRESS_MASK 
| 
3935                           GDK_BUTTON_RELEASE_MASK 
| 
3936                           GDK_POINTER_MOTION_HINT_MASK 
| 
3937                           GDK_POINTER_MOTION_MASK
), 
3939                       cursor
->GetCursor(), 
3940                       (guint32
)GDK_CURRENT_TIME 
); 
3941     g_captureWindow 
= this; 
3942     g_captureWindowHasMouse 
= true; 
3945 void wxWindowGTK::DoReleaseMouse() 
3947     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3949     wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") ); 
3951     g_captureWindow 
= (wxWindowGTK
*) NULL
; 
3953     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3955         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3957         window 
= GetConnectWidget()->window
; 
3962     gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME 
); 
3966 wxWindow 
*wxWindowBase::GetCapture() 
3968     return (wxWindow 
*)g_captureWindow
; 
3971 bool wxWindowGTK::IsRetained() const 
3976 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
, 
3977       int range
, bool refresh 
) 
3979     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3981     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
3983     m_hasScrolling 
= true; 
3985     if (orient 
== wxHORIZONTAL
) 
3987         float fpos 
= (float)pos
; 
3988         float frange 
= (float)range
; 
3989         float fthumb 
= (float)thumbVisible
; 
3990         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
3991         if (fpos 
< 0.0) fpos 
= 0.0; 
3993         if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) && 
3994             (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2)) 
3996             SetScrollPos( orient
, pos
, refresh 
); 
4000         m_oldHorizontalPos 
= fpos
; 
4002         m_hAdjust
->lower 
= 0.0; 
4003         m_hAdjust
->upper 
= frange
; 
4004         m_hAdjust
->value 
= fpos
; 
4005         m_hAdjust
->step_increment 
= 1.0; 
4006         m_hAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4007         m_hAdjust
->page_size 
= fthumb
; 
4011         float fpos 
= (float)pos
; 
4012         float frange 
= (float)range
; 
4013         float fthumb 
= (float)thumbVisible
; 
4014         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4015         if (fpos 
< 0.0) fpos 
= 0.0; 
4017         if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) && 
4018             (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2)) 
4020             SetScrollPos( orient
, pos
, refresh 
); 
4024         m_oldVerticalPos 
= fpos
; 
4026         m_vAdjust
->lower 
= 0.0; 
4027         m_vAdjust
->upper 
= frange
; 
4028         m_vAdjust
->value 
= fpos
; 
4029         m_vAdjust
->step_increment 
= 1.0; 
4030         m_vAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4031         m_vAdjust
->page_size 
= fthumb
; 
4034     if (orient 
== wxHORIZONTAL
) 
4035         gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
4037         gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
4040 void wxWindowGTK::GtkUpdateScrollbar(int orient
) 
4042     GtkAdjustment 
*adj 
= orient 
== wxHORIZONTAL 
? m_hAdjust 
: m_vAdjust
; 
4043     GtkSignalFunc fn 
= orient 
== wxHORIZONTAL
 
4044                         ? (GtkSignalFunc
)gtk_window_hscroll_callback
 
4045                         : (GtkSignalFunc
)gtk_window_vscroll_callback
; 
4047     gtk_signal_disconnect_by_func(GTK_OBJECT(adj
), fn
, (gpointer
)this); 
4048     gtk_signal_emit_by_name(GTK_OBJECT(adj
), "value_changed"); 
4049     gtk_signal_connect(GTK_OBJECT(adj
), "value_changed", fn
, (gpointer
)this); 
4052 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) ) 
4054     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4055     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4057     GtkAdjustment 
*adj 
= orient 
== wxHORIZONTAL 
? m_hAdjust 
: m_vAdjust
; 
4059     float fpos 
= (float)pos
; 
4060     if (fpos 
> adj
->upper 
- adj
->page_size
) 
4061         fpos 
= adj
->upper 
- adj
->page_size
; 
4064     *(orient 
== wxHORIZONTAL 
? &m_oldHorizontalPos 
: &m_oldVerticalPos
) = fpos
; 
4066     if (fabs(fpos
-adj
->value
) < 0.2) 
4070     if ( m_wxwindow
->window 
) 
4075 int wxWindowGTK::GetScrollThumb( int orient 
) const 
4077     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4079     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4081     if (orient 
== wxHORIZONTAL
) 
4082         return (int)(m_hAdjust
->page_size
+0.5); 
4084         return (int)(m_vAdjust
->page_size
+0.5); 
4087 int wxWindowGTK::GetScrollPos( int orient 
) const 
4089     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4091     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4093     if (orient 
== wxHORIZONTAL
) 
4094         return (int)(m_hAdjust
->value
+0.5); 
4096         return (int)(m_vAdjust
->value
+0.5); 
4099 int wxWindowGTK::GetScrollRange( int orient 
) const 
4101     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4103     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4105     if (orient 
== wxHORIZONTAL
) 
4106         return (int)(m_hAdjust
->upper
+0.5); 
4108         return (int)(m_vAdjust
->upper
+0.5); 
4111 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) ) 
4113     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4115     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4117     // No scrolling requested. 
4118     if ((dx 
== 0) && (dy 
== 0)) return; 
4120     if (!m_updateRegion
.IsEmpty()) 
4122         m_updateRegion
.Offset( dx
, dy 
); 
4126         GetClientSize( &cw
, &ch 
); 
4127         m_updateRegion
.Intersect( 0, 0, cw
, ch 
); 
4130     if (!m_clearRegion
.IsEmpty()) 
4132         m_clearRegion
.Offset( dx
, dy 
); 
4136         GetClientSize( &cw
, &ch 
); 
4137         m_clearRegion
.Intersect( 0, 0, cw
, ch 
); 
4140     m_clipPaintRegion 
= true; 
4142     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy 
); 
4144     m_clipPaintRegion 
= false; 
4147 void wxWindowGTK::SetWindowStyleFlag( long style 
) 
4149     // Updates the internal variable. NB: Now m_windowStyle bits carry the _new_ style values already 
4150     wxWindowBase::SetWindowStyleFlag(style
); 
4153 // Find the wxWindow at the current mouse position, also returning the mouse 
4155 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
4157     pt 
= wxGetMousePosition(); 
4158     wxWindow
* found 
= wxFindWindowAtPoint(pt
); 
4162 // Get the current mouse position. 
4163 wxPoint 
wxGetMousePosition() 
4165   /* This crashes when used within wxHelpContext, 
4166      so we have to use the X-specific implementation below. 
4168     GdkModifierType *mask; 
4169     (void) gdk_window_get_pointer(NULL, &x, &y, mask); 
4171     return wxPoint(x, y); 
4175     GdkWindow
* windowAtPtr 
= gdk_window_at_pointer(& x
, & y
); 
4177     Display 
*display 
= windowAtPtr 
? GDK_WINDOW_XDISPLAY(windowAtPtr
) : GDK_DISPLAY(); 
4178     Window rootWindow 
= RootWindowOfScreen (DefaultScreenOfDisplay(display
)); 
4179     Window rootReturn
, childReturn
; 
4180     int rootX
, rootY
, winX
, winY
; 
4181     unsigned int maskReturn
; 
4183     XQueryPointer (display
, 
4187                    &rootX
, &rootY
, &winX
, &winY
, &maskReturn
); 
4188     return wxPoint(rootX
, rootY
); 
4192 // Needed for implementing e.g. combobox on wxGTK within a modal dialog. 
4193 void wxAddGrab(wxWindow
* window
) 
4195     gtk_grab_add( (GtkWidget
*) window
->GetHandle() ); 
4198 void wxRemoveGrab(wxWindow
* window
) 
4200     gtk_grab_remove( (GtkWidget
*) window
->GetHandle() ); 
4203 // ---------------------------------------------------------------------------- 
4205 // ---------------------------------------------------------------------------- 
4207 class wxWinModule 
: public wxModule
 
4214     DECLARE_DYNAMIC_CLASS(wxWinModule
) 
4217 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
) 
4219 bool wxWinModule::OnInit() 
4221     // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() ); 
4222     // gdk_gc_set_fill( g_eraseGC, GDK_SOLID ); 
4227 void wxWinModule::OnExit() 
4230         gdk_gc_unref( g_eraseGC 
); 
4233 GdkWindow
* wxWindowGTK::GTKGetDrawingWindow() const 
4235     GdkWindow
* window 
= NULL
; 
4237         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
;