1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        gtk/window.cpp 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling, Julian Smart 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  12     #pragma implementation "window.h" 
  16 #define XWarpPointer XWARPPOINTER 
  20 #include "wx/window.h" 
  21 #include "wx/dcclient.h" 
  24 #include "wx/layout.h" 
  26 #include "wx/dialog.h" 
  27 #include "wx/msgdlg.h" 
  28 #include "wx/module.h" 
  30 #if wxUSE_DRAG_AND_DROP 
  35     #include "wx/tooltip.h" 
  43     #include "wx/textctrl.h" 
  47 #include "wx/statusbr.h" 
  49 #include "wx/settings.h" 
  51 #include "wx/fontutil.h" 
  54     #include "wx/thread.h" 
  60 #include "wx/gtk/private.h" 
  61 #include <gdk/gdkprivate.h> 
  62 #include <gdk/gdkkeysyms.h> 
  66 #include <gtk/gtkprivate.h> 
  68 #include "wx/gtk/win_gtk.h" 
  71 #include <pango/pangox.h> 
  75     #define SET_CONTAINER_FOCUS(w, d) gtk_widget_child_focus((w), (d)) 
  77     #define SET_CONTAINER_FOCUS(w, d) gtk_container_focus(GTK_CONTAINER(w), (d)) 
  87 extern GtkContainerClass 
*pizza_parent_class
; 
  90 //----------------------------------------------------------------------------- 
  91 // documentation on internals 
  92 //----------------------------------------------------------------------------- 
  95    I have been asked several times about writing some documentation about 
  96    the GTK port of wxWindows, especially its internal structures. Obviously, 
  97    you cannot understand wxGTK without knowing a little about the GTK, but 
  98    some more information about what the wxWindow, which is the base class 
  99    for all other window classes, does seems required as well. 
 103    What does wxWindow do? It contains the common interface for the following 
 104    jobs of its descendants: 
 106    1) Define the rudimentary behaviour common to all window classes, such as 
 107    resizing, intercepting user input (so as to make it possible to use these 
 108    events for special purposes in a derived class), window names etc. 
 110    2) Provide the possibility to contain and manage children, if the derived 
 111    class is allowed to contain children, which holds true for those window 
 112    classes which do not display a native GTK widget. To name them, these 
 113    classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame- 
 114    work classes are a special case and are handled a bit differently from 
 115    the rest. The same holds true for the wxNotebook class. 
 117    3) Provide the possibility to draw into a client area of a window. This, 
 118    too, only holds true for classes that do not display a native GTK widget 
 121    4) Provide the entire mechanism for scrolling widgets. This actual inter- 
 122    face for this is usually in wxScrolledWindow, but the GTK implementation 
 125    5) A multitude of helper or extra methods for special purposes, such as 
 126    Drag'n'Drop, managing validators etc. 
 128    6) Display a border (sunken, raised, simple or none). 
 130    Normally one might expect, that one wxWindows window would always correspond 
 131    to one GTK widget. Under GTK, there is no such allround widget that has all 
 132    the functionality. Moreover, the GTK defines a client area as a different 
 133    widget from the actual widget you are handling. Last but not least some 
 134    special classes (e.g. wxFrame) handle different categories of widgets and 
 135    still have the possibility to draw something in the client area. 
 136    It was therefore required to write a special purpose GTK widget, that would 
 137    represent a client area in the sense of wxWindows capable to do the jobs 
 138    2), 3) and 4). I have written this class and it resides in win_gtk.c of 
 141    All windows must have a widget, with which they interact with other under- 
 142    lying GTK widgets. It is this widget, e.g. that has to be resized etc and 
 143    thw wxWindow class has a member variable called m_widget which holds a 
 144    pointer to this widget. When the window class represents a GTK native widget, 
 145    this is (in most cases) the only GTK widget the class manages. E.g. the 
 146    wxStatitText class handles only a GtkLabel widget a pointer to which you 
 147    can find in m_widget (defined in wxWindow) 
 149    When the class has a client area for drawing into and for containing children 
 150    it has to handle the client area widget (of the type GtkPizza, defined in 
 151    win_gtk.c), but there could be any number of widgets, handled by a class 
 152    The common rule for all windows is only, that the widget that interacts with 
 153    the rest of GTK must be referenced in m_widget and all other widgets must be 
 154    children of this widget on the GTK level. The top-most widget, which also 
 155    represents the client area, must be in the m_wxwindow field and must be of 
 158    As I said, the window classes that display a GTK native widget only have 
 159    one widget, so in the case of e.g. the wxButton class m_widget holds a 
 160    pointer to a GtkButton widget. But windows with client areas (for drawing 
 161    and children) have a m_widget field that is a pointer to a GtkScrolled- 
 162    Window and a m_wxwindow field that is pointer to a GtkPizza and this 
 163    one is (in the GTK sense) a child of the GtkScrolledWindow. 
 165    If the m_wxwindow field is set, then all input to this widget is inter- 
 166    cepted and sent to the wxWindows class. If not, all input to the widget 
 167    that gets pointed to by m_widget gets intercepted and sent to the class. 
 171    The design of scrolling in wxWindows is markedly different from that offered 
 172    by the GTK itself and therefore we cannot simply take it as it is. In GTK, 
 173    clicking on a scrollbar belonging to scrolled window will inevitably move 
 174    the window. In wxWindows, the scrollbar will only emit an event, send this 
 175    to (normally) a wxScrolledWindow and that class will call ScrollWindow() 
 176    which actually moves the window and its subchildren. Note that GtkPizza 
 177    memorizes how much it has been scrolled but that wxWindows forgets this 
 178    so that the two coordinates systems have to be kept in synch. This is done 
 179    in various places using the pizza->xoffset and pizza->yoffset values. 
 183    Singularily the most broken code in GTK is the code that is supposes to 
 184    inform subwindows (child windows) about new positions. Very often, duplicate 
 185    events are sent without changes in size or position, equally often no 
 186    events are sent at all (All this is due to a bug in the GtkContainer code 
 187    which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores 
 188    GTK's own system and it simply waits for size events for toplevel windows 
 189    and then iterates down the respective size events to all window. This has 
 190    the disadvantage, that windows might get size events before the GTK widget 
 191    actually has the reported size. This doesn't normally pose any problem, but 
 192    the OpenGl drawing routines rely on correct behaviour. Therefore, I have 
 193    added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas, 
 194    i.e. the wxGLCanvas will emit a size event, when (and not before) the X11 
 195    window that is used for OpenGl output really has that size (as reported by 
 200    If someone at some point of time feels the immense desire to have a look at, 
 201    change or attempt to optimse the Refresh() logic, this person will need an 
 202    intimate understanding of what a "draw" and what an "expose" events are and 
 203    what there are used for, in particular when used in connection with GTK's 
 204    own windowless widgets. Beware. 
 208    Cursors, too, have been a constant source of pleasure. The main difficulty 
 209    is that a GdkWindow inherits a cursor if the programmer sets a new cursor 
 210    for the parent. To prevent this from doing too much harm, I use idle time 
 211    to set the cursor over and over again, starting from the toplevel windows 
 212    and ending with the youngest generation (speaking of parent and child windows). 
 213    Also don't forget that cursors (like much else) are connected to GdkWindows, 
 214    not GtkWidgets and that the "window" field of a GtkWidget might very well 
 215    point to the GdkWindow of the parent widget (-> "window less widget") and 
 216    that the two obviously have very different meanings. 
 220 //----------------------------------------------------------------------------- 
 222 //----------------------------------------------------------------------------- 
 224 extern wxList     wxPendingDelete
; 
 225 extern bool       g_blockEventsOnDrag
; 
 226 extern bool       g_blockEventsOnScroll
; 
 227 extern wxCursor   g_globalCursor
; 
 229 static GdkGC 
*g_eraseGC 
= NULL
; 
 231 // mouse capture state: the window which has it and if the mouse is currently 
 233 static wxWindowGTK  
*g_captureWindow 
= (wxWindowGTK
*) NULL
; 
 234 static bool g_captureWindowHasMouse 
= FALSE
; 
 236 /* extern */ wxWindowGTK  
*g_focusWindow 
= (wxWindowGTK
*) NULL
; 
 238 // the last window which had the focus - this is normally never NULL (except 
 239 // if we never had focus at all) as even when g_focusWindow is NULL it still 
 240 // keeps its previous value 
 241 static wxWindowGTK 
*g_focusWindowLast 
= (wxWindowGTK
*) NULL
; 
 243 // the frame that is currently active (i.e. its child has focus). It is 
 244 // used to generate wxActivateEvents 
 245 static wxWindowGTK 
*g_activeFrame 
= (wxWindowGTK
*) NULL
; 
 246 static bool g_activeFrameLostFocus 
= FALSE
; 
 248 // If a window get the focus set but has not been realized 
 249 // yet, defer setting the focus to idle time. 
 250 wxWindowGTK 
*g_delayedFocus 
= (wxWindowGTK
*) NULL
; 
 252 // if we detect that the app has got/lost the focus, we set this variable to 
 253 // either TRUE or FALSE and an activate event will be sent during the next 
 254 // OnIdle() call and it is reset to -1: this value means that we shouldn't 
 255 // send any activate events at all 
 256 static int        g_sendActivateEvent 
= -1; 
 258 /* hack: we need something to pass to gtk_menu_popup, so we store the time of 
 259    the last click here */ 
 260 static guint32 gs_timeLastClick 
= 0; 
 262 extern bool g_mainThreadLocked
; 
 264 //----------------------------------------------------------------------------- 
 266 //----------------------------------------------------------------------------- 
 269 #define DISABLE_STYLE_IF_BROKEN_THEME 0 
 275 #   define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance"); 
 277 #   define DEBUG_MAIN_THREAD 
 280 #define DEBUG_MAIN_THREAD 
 283 // the trace mask used for the focus debugging messages 
 284 #define TRACE_FOCUS _T("focus") 
 286 //----------------------------------------------------------------------------- 
 287 // missing gdk functions 
 288 //----------------------------------------------------------------------------- 
 291 gdk_window_warp_pointer (GdkWindow      
*window
, 
 296   GdkWindowPrivate 
*priv
; 
 300     window 
= GDK_ROOT_PARENT(); 
 303   if (!GDK_WINDOW_DESTROYED(window
)) 
 305       XWarpPointer (GDK_WINDOW_XDISPLAY(window
), 
 306                     None
,              /* not source window -> move from anywhere */ 
 307                     GDK_WINDOW_XID(window
),  /* dest window */ 
 308                     0, 0, 0, 0,        /* not source window -> move from anywhere */ 
 312   priv 
= (GdkWindowPrivate
*) window
; 
 314   if (!priv
->destroyed
) 
 316       XWarpPointer (priv
->xdisplay
, 
 317                     None
,              /* not source window -> move from anywhere */ 
 318                     priv
->xwindow
,  /* dest window */ 
 319                     0, 0, 0, 0,        /* not source window -> move from anywhere */ 
 325 //----------------------------------------------------------------------------- 
 327 //----------------------------------------------------------------------------- 
 329 extern void wxapp_install_idle_handler(); 
 330 extern bool g_isIdle
; 
 332 //----------------------------------------------------------------------------- 
 333 // local code (see below) 
 334 //----------------------------------------------------------------------------- 
 336 // returns the child of win which currently has focus or NULL if not found 
 338 // Note: can't be static, needed by textctrl.cpp. 
 339 wxWindow 
*wxFindFocusedChild(wxWindowGTK 
*win
) 
 341     wxWindow 
*winFocus 
= wxWindowGTK::FindFocus(); 
 343         return (wxWindow 
*)NULL
; 
 345     if ( winFocus 
== win 
) 
 346         return (wxWindow 
*)win
; 
 348     for ( wxWindowList::Node 
*node 
= win
->GetChildren().GetFirst(); 
 350           node 
= node
->GetNext() ) 
 352         wxWindow 
*child 
= wxFindFocusedChild(node
->GetData()); 
 357     return (wxWindow 
*)NULL
; 
 360 static void draw_frame( GtkWidget 
*widget
, wxWindowGTK 
*win 
) 
 362     // wxUniversal widgets draw the borders and scrollbars themselves 
 363 #ifndef __WXUNIVERSAL__ 
 370     if (win
->m_hasScrolling
) 
 372         GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(widget
); 
 374         GtkRequisition vscroll_req
; 
 375         vscroll_req
.width 
= 2; 
 376         vscroll_req
.height 
= 2; 
 377         (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
 378             (scroll_window
->vscrollbar
, &vscroll_req 
); 
 380         GtkRequisition hscroll_req
; 
 381         hscroll_req
.width 
= 2; 
 382         hscroll_req
.height 
= 2; 
 383         (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
 384             (scroll_window
->hscrollbar
, &hscroll_req 
); 
 386         GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) ); 
 388         if (scroll_window
->vscrollbar_visible
) 
 390             dw 
+= vscroll_req
.width
; 
 391             dw 
+= scroll_class
->scrollbar_spacing
; 
 394         if (scroll_window
->hscrollbar_visible
) 
 396             dh 
+= hscroll_req
.height
; 
 397             dh 
+= scroll_class
->scrollbar_spacing
; 
 403     if (GTK_WIDGET_NO_WINDOW (widget
)) 
 405         dx 
+= widget
->allocation
.x
; 
 406         dy 
+= widget
->allocation
.y
; 
 409     if (win
->HasFlag(wxRAISED_BORDER
)) 
 411         gtk_draw_shadow( widget
->style
, 
 416                          widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh 
); 
 420     if (win
->HasFlag(wxSUNKEN_BORDER
)) 
 422         gtk_draw_shadow( widget
->style
, 
 427                          widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh 
); 
 431     if (win
->HasFlag(wxSIMPLE_BORDER
)) 
 434         gc 
= gdk_gc_new( widget
->window 
); 
 435         gdk_gc_set_foreground( gc
, &widget
->style
->black 
); 
 436         gdk_draw_rectangle( widget
->window
, gc
, FALSE
, 
 438                          widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 ); 
 442 #endif // __WXUNIVERSAL__ 
 445 //----------------------------------------------------------------------------- 
 446 // "expose_event" of m_widget 
 447 //----------------------------------------------------------------------------- 
 449 gint 
gtk_window_own_expose_callback( GtkWidget 
*widget
, GdkEventExpose 
*gdk_event
, wxWindowGTK 
*win 
) 
 451     if (gdk_event
->count 
> 0) return FALSE
; 
 453     draw_frame( widget
, win 
); 
 457     (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
); 
 463 //----------------------------------------------------------------------------- 
 464 // "draw" of m_widget 
 465 //----------------------------------------------------------------------------- 
 469 static void gtk_window_own_draw_callback( GtkWidget 
*widget
, GdkRectangle 
*WXUNUSED(rect
), wxWindowGTK 
*win 
) 
 471     draw_frame( widget
, win 
); 
 476 //----------------------------------------------------------------------------- 
 477 // "size_request" of m_widget 
 478 //----------------------------------------------------------------------------- 
 480 static void gtk_window_size_request_callback( GtkWidget 
*widget
, GtkRequisition 
*requisition
, wxWindow 
*win 
) 
 483     win
->GetSize( &w
, &h 
); 
 487     requisition
->height 
= h
; 
 488     requisition
->width 
= w
; 
 491 //----------------------------------------------------------------------------- 
 492 // "expose_event" of m_wxwindow 
 493 //----------------------------------------------------------------------------- 
 495 static int gtk_window_expose_callback( GtkWidget 
*widget
, 
 496                                        GdkEventExpose 
*gdk_event
, 
 502         wxapp_install_idle_handler(); 
 505     // This callback gets called in drawing-idle time under 
 506     // GTK 2.0, so we don't need to defer anything to idle 
 509     GtkPizza 
*pizza 
= GTK_PIZZA( widget 
); 
 510     if (gdk_event
->window 
!= pizza
->bin_window
) return FALSE
; 
 515         wxPrintf( wxT("OnExpose from ") ); 
 516         if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName()) 
 517             wxPrintf( win
->GetClassInfo()->GetClassName() ); 
 518         wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event
->area
.x
, 
 519                                          (int)gdk_event
->area
.y
, 
 520                                          (int)gdk_event
->area
.width
, 
 521                                          (int)gdk_event
->area
.height 
); 
 525     win
->GetUpdateRegion() = wxRegion( gdk_event
->region 
); 
 527     win
->GtkSendPaintEvents(); 
 530     // Let parent window draw window less widgets 
 531     (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
); 
 533     // This gets called immediately after an expose event 
 534     // under GTK 1.2 so we collect the calls and wait for 
 535     // the idle handler to pick things up. 
 537     win
->GetUpdateRegion().Union( gdk_event
->area
.x
, 
 539                                   gdk_event
->area
.width
, 
 540                                   gdk_event
->area
.height 
); 
 541     win
->m_clearRegion
.Union( gdk_event
->area
.x
, 
 543                                   gdk_event
->area
.width
, 
 544                                   gdk_event
->area
.height 
); 
 546     // Actual redrawing takes place in idle time. 
 553 //----------------------------------------------------------------------------- 
 554 // "event" of m_wxwindow 
 555 //----------------------------------------------------------------------------- 
 557 // GTK thinks it is clever and filters out a certain amount of "unneeded" 
 558 // expose events. We need them, of course, so we override the main event 
 559 // procedure in GtkWidget by giving our own handler for all system events. 
 560 // There, we look for expose events ourselves whereas all other events are 
 563 gint 
gtk_window_event_event_callback( GtkWidget 
*widget
, 
 564                                       GdkEventExpose 
*event
, 
 567     if (event
->type 
== GDK_EXPOSE
) 
 569         gint ret 
= gtk_window_expose_callback( widget
, event
, win 
); 
 576 //----------------------------------------------------------------------------- 
 577 // "draw" of m_wxwindow 
 578 //----------------------------------------------------------------------------- 
 582 // This callback is a complete replacement of the gtk_pizza_draw() function, 
 583 // which is disabled. 
 585 static void gtk_window_draw_callback( GtkWidget 
*widget
, 
 592         wxapp_install_idle_handler(); 
 594     // The wxNO_FULL_REPAINT_ON_RESIZE flag only works if 
 595     // there are no child windows. 
 596     if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) && 
 597         (win
->GetChildren().GetCount() == 0)) 
 605         wxPrintf( wxT("OnDraw from ") ); 
 606         if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName()) 
 607             wxPrintf( win
->GetClassInfo()->GetClassName() ); 
 608         wxPrintf( wxT(" %d %d %d %d\n"), (int)rect
->x
, 
 615 #ifndef __WXUNIVERSAL__ 
 616     GtkPizza 
*pizza 
= GTK_PIZZA (widget
); 
 618     if (win
->GetThemeEnabled()) 
 620         wxWindow 
*parent 
= win
->GetParent(); 
 621         while (parent 
&& !parent
->IsTopLevel()) 
 622             parent 
= parent
->GetParent(); 
 626         gtk_paint_flat_box (parent
->m_widget
->style
, 
 637     win
->m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
 638     win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
 640     // Update immediately, not in idle time. 
 643 #ifndef __WXUNIVERSAL__ 
 644     // Redraw child widgets 
 645     GList 
*children 
= pizza
->children
; 
 648         GtkPizzaChild 
*child 
= (GtkPizzaChild
*) children
->data
; 
 649         children 
= children
->next
; 
 651         GdkRectangle child_area
; 
 652         if (gtk_widget_intersect (child
->widget
, rect
, &child_area
)) 
 654             gtk_widget_draw (child
->widget
, &child_area 
/* (GdkRectangle*) NULL*/ ); 
 662 //----------------------------------------------------------------------------- 
 663 // "key_press_event" from any window 
 664 //----------------------------------------------------------------------------- 
 666 // set WXTRACE to this to see the key event codes on the console 
 667 #define TRACE_KEYS  _T("keyevent") 
 669 // translates an X key symbol to WXK_XXX value 
 671 // if isChar is true it means that the value returned will be used for EVT_CHAR 
 672 // event and then we choose the logical WXK_XXX, i.e. '/' for GDK_KP_Divide, 
 673 // for example, while if it is false it means that the value is going to be 
 674 // used for KEY_DOWN/UP events and then we translate GDK_KP_Divide to 
 676 static long wxTranslateKeySymToWXKey(KeySym keysym
, bool isChar
) 
 682         // Shift, Control and Alt don't generate the CHAR events at all 
 685             key_code 
= isChar 
? 0 : WXK_SHIFT
; 
 689             key_code 
= isChar 
? 0 : WXK_CONTROL
; 
 697             key_code 
= isChar 
? 0 : WXK_ALT
; 
 700         // neither do the toggle modifies 
 701         case GDK_Scroll_Lock
: 
 702             key_code 
= isChar 
? 0 : WXK_SCROLL
; 
 706             key_code 
= isChar 
? 0 : WXK_CAPITAL
; 
 710             key_code 
= isChar 
? 0 : WXK_NUMLOCK
; 
 714         // various other special keys 
 727         case GDK_ISO_Left_Tab
: 
 734             key_code 
= WXK_RETURN
; 
 738             key_code 
= WXK_CLEAR
; 
 742             key_code 
= WXK_PAUSE
; 
 746             key_code 
= WXK_SELECT
; 
 750             key_code 
= WXK_PRINT
; 
 754             key_code 
= WXK_EXECUTE
; 
 758             key_code 
= WXK_ESCAPE
; 
 761         // cursor and other extended keyboard keys 
 763             key_code 
= WXK_DELETE
; 
 779             key_code 
= WXK_RIGHT
; 
 786         case GDK_Prior
:     // == GDK_Page_Up 
 787             key_code 
= WXK_PRIOR
; 
 790         case GDK_Next
:      // == GDK_Page_Down 
 803             key_code 
= WXK_INSERT
; 
 818             key_code 
= (isChar 
? '0' : WXK_NUMPAD0
) + keysym 
- GDK_KP_0
; 
 822             key_code 
= isChar 
? ' ' : WXK_NUMPAD_SPACE
; 
 826             key_code 
= isChar 
? WXK_TAB 
: WXK_NUMPAD_TAB
; 
 830             key_code 
= isChar 
? WXK_RETURN 
: WXK_NUMPAD_ENTER
; 
 834             key_code 
= isChar 
? WXK_F1 
: WXK_NUMPAD_F1
; 
 838             key_code 
= isChar 
? WXK_F2 
: WXK_NUMPAD_F2
; 
 842             key_code 
= isChar 
? WXK_F3 
: WXK_NUMPAD_F3
; 
 846             key_code 
= isChar 
? WXK_F4 
: WXK_NUMPAD_F4
; 
 850             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_HOME
; 
 854             key_code 
= isChar 
? WXK_LEFT 
: WXK_NUMPAD_LEFT
; 
 858             key_code 
= isChar 
? WXK_UP 
: WXK_NUMPAD_UP
; 
 862             key_code 
= isChar 
? WXK_RIGHT 
: WXK_NUMPAD_RIGHT
; 
 866             key_code 
= isChar 
? WXK_DOWN 
: WXK_NUMPAD_DOWN
; 
 869         case GDK_KP_Prior
: // == GDK_KP_Page_Up 
 870             key_code 
= isChar 
? WXK_PRIOR 
: WXK_NUMPAD_PRIOR
; 
 873         case GDK_KP_Next
: // == GDK_KP_Page_Down 
 874             key_code 
= isChar 
? WXK_NEXT 
: WXK_NUMPAD_NEXT
; 
 878             key_code 
= isChar 
? WXK_END 
: WXK_NUMPAD_END
; 
 882             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_BEGIN
; 
 886             key_code 
= isChar 
? WXK_INSERT 
: WXK_NUMPAD_INSERT
; 
 890             key_code 
= isChar 
? WXK_DELETE 
: WXK_NUMPAD_DELETE
; 
 894             key_code 
= isChar 
? '=' : WXK_NUMPAD_EQUAL
; 
 897         case GDK_KP_Multiply
: 
 898             key_code 
= isChar 
? '*' : WXK_NUMPAD_MULTIPLY
; 
 902             key_code 
= isChar 
? '+' : WXK_NUMPAD_ADD
; 
 905         case GDK_KP_Separator
: 
 906             // FIXME: what is this? 
 907             key_code 
= isChar 
? '.' : WXK_NUMPAD_SEPARATOR
; 
 910         case GDK_KP_Subtract
: 
 911             key_code 
= isChar 
? '-' : WXK_NUMPAD_SUBTRACT
; 
 915             key_code 
= isChar 
? '.' : WXK_NUMPAD_DECIMAL
; 
 919             key_code 
= isChar 
? '/' : WXK_NUMPAD_DIVIDE
; 
 936             key_code 
= WXK_F1 
+ keysym 
- GDK_F1
; 
 946 static inline bool wxIsAsciiKeysym(KeySym ks
) 
 952 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
, 
 954                            GdkEventKey 
*gdk_event
) 
 956     // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string 
 957     //     but only event->keyval which is quite useless to us, so remember 
 958     //     the last character from GDK_KEY_PRESS and reuse it as last resort 
 960     // NB: should be MT-safe as we're always called from the main thread only 
 965     } s_lastKeyPress 
= { 0, 0 }; 
 967     KeySym keysym 
= gdk_event
->keyval
; 
 969     wxLogTrace(TRACE_KEYS
, _T("Key %s event: keysym = %ld"), 
 970                event
.GetEventType() == wxEVT_KEY_UP 
? _T("release") 
 974     long key_code 
= wxTranslateKeySymToWXKey(keysym
, FALSE 
/* !isChar */); 
 978         // do we have the translation or is it a plain ASCII character? 
 979         if ( (gdk_event
->length 
== 1) || wxIsAsciiKeysym(keysym
) ) 
 981             // we should use keysym if it is ASCII as X does some translations 
 982             // like "I pressed while Control is down" => "Ctrl-I" == "TAB" 
 983             // which we don't want here (but which we do use for OnChar()) 
 984             if ( !wxIsAsciiKeysym(keysym
) ) 
 986                 keysym 
= (KeySym
)gdk_event
->string
[0]; 
 989             // we want to always get the same key code when the same key is 
 990             // pressed regardless of the state of the modifies, i.e. on a 
 991             // standard US keyboard pressing '5' or '%' ('5' key with 
 992             // Shift) should result in the same key code in OnKeyDown(): 
 993             // '5' (although OnChar() will get either '5' or '%'). 
 995             // to do it we first translate keysym to keycode (== scan code) 
 996             // and then back but always using the lower register 
 997             Display 
*dpy 
= (Display 
*)wxGetDisplay(); 
 998             KeyCode keycode 
= XKeysymToKeycode(dpy
, keysym
); 
1000             wxLogTrace(TRACE_KEYS
, _T("\t-> keycode %d"), keycode
); 
1002             KeySym keysymNormalized 
= XKeycodeToKeysym(dpy
, keycode
, 0); 
1004             // use the normalized, i.e. lower register, keysym if we've 
1006             key_code 
= keysymNormalized 
? keysymNormalized 
: keysym
; 
1008             // as explained above, we want to have lower register key codes 
1009             // normally but for the letter keys we want to have the upper ones 
1011             // NB: don't use XConvertCase() here, we want to do it for letters 
1013             key_code 
= toupper(key_code
); 
1015         else // non ASCII key, what to do? 
1017             // by default, ignore it 
1020             // but if we have cached information from the last KEY_PRESS 
1021             if ( gdk_event
->type 
== GDK_KEY_RELEASE 
) 
1024                 if ( keysym 
== s_lastKeyPress
.keysym 
) 
1026                     key_code 
= s_lastKeyPress
.keycode
; 
1031         if ( gdk_event
->type 
== GDK_KEY_PRESS 
) 
1033             // remember it to be reused for KEY_UP event later 
1034             s_lastKeyPress
.keysym 
= keysym
; 
1035             s_lastKeyPress
.keycode 
= key_code
; 
1039     wxLogTrace(TRACE_KEYS
, _T("\t-> wxKeyCode %ld"), key_code
); 
1041     // sending unknown key events doesn't really make sense 
1045     // now fill all the other fields 
1048     GdkModifierType state
; 
1049     if (gdk_event
->window
) 
1050         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1052     event
.SetTimestamp( gdk_event
->time 
); 
1053     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
) != 0; 
1054     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
) != 0; 
1055     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
) != 0; 
1056     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
) != 0; 
1057     event
.m_keyCode 
= key_code
; 
1058     event
.m_scanCode 
= gdk_event
->keyval
; 
1059     event
.m_rawCode 
= (wxUint32
) gdk_event
->keyval
; 
1060     event
.m_rawFlags 
= 0; 
1063     event
.SetEventObject( win 
); 
1069 static gint 
gtk_window_key_press_callback( GtkWidget 
*widget
, 
1070                                            GdkEventKey 
*gdk_event
, 
1076         wxapp_install_idle_handler(); 
1080     if (g_blockEventsOnDrag
) 
1084     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
1085     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1087         // unknown key pressed, ignore (the event would be useless anyhow) 
1091     // Emit KEY_DOWN event 
1092     bool ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1097         wxWindowGTK 
*ancestor 
= win
; 
1100             int command 
= ancestor
->GetAcceleratorTable()->GetCommand( event 
); 
1103                 wxCommandEvent 
command_event( wxEVT_COMMAND_MENU_SELECTED
, command 
); 
1104                 ret 
= ancestor
->GetEventHandler()->ProcessEvent( command_event 
); 
1107             if (ancestor
->IsTopLevel()) 
1109             ancestor 
= ancestor
->GetParent(); 
1112 #endif // wxUSE_ACCEL 
1114     // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x 
1115     // will only be sent if it is not in an accelerator table. 
1118         // Find key code for EVT_CHAR and EVT_CHAR_HOOK events 
1119         KeySym keysym 
= gdk_event
->keyval
; 
1120         long key_code 
= wxTranslateKeySymToWXKey(keysym
, TRUE 
/* isChar */); 
1123             if ( gdk_event
->length 
== 1 ) 
1125                 key_code 
= (unsigned char)gdk_event
->string
[0]; 
1127             else if ( wxIsAsciiKeysym(keysym
) ) 
1130                 key_code 
= (unsigned char)keysym
; 
1136             wxLogTrace(TRACE_KEYS
, _T("Char event: %ld"), key_code
); 
1138             event
.m_keyCode 
= key_code
; 
1140             // Implement OnCharHook by checking ancesteror top level windows 
1141             wxWindow 
*parent 
= win
; 
1142             while (parent 
&& !parent
->IsTopLevel()) 
1143             parent 
= parent
->GetParent(); 
1146                 event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1147                 ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1152                 event
.SetEventType(wxEVT_CHAR
); 
1153                 ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1158     // win is a control: tab can be propagated up 
1160          ((gdk_event
->keyval 
== GDK_Tab
) || (gdk_event
->keyval 
== GDK_ISO_Left_Tab
)) && 
1161 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may 
1162 //     have this style, yet choose not to process this particular TAB in which 
1163 //     case TAB must still work as a navigational character 
1165          !win
->HasFlag(wxTE_PROCESS_TAB
) && 
1167          win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) ) 
1169         wxNavigationKeyEvent new_event
; 
1170         new_event
.SetEventObject( win
->GetParent() ); 
1171         // GDK reports GDK_ISO_Left_Tab for SHIFT-TAB 
1172         new_event
.SetDirection( (gdk_event
->keyval 
== GDK_Tab
) ); 
1173         // CTRL-TAB changes the (parent) window, i.e. switch notebook page 
1174         new_event
.SetWindowChange( (gdk_event
->state 
& GDK_CONTROL_MASK
) ); 
1175         new_event
.SetCurrentFocus( win 
); 
1176         ret 
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event 
); 
1179     // generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) 
1181          (gdk_event
->keyval 
== GDK_Escape
) ) 
1183         // however only do it if we have a Cancel button in the dialog, 
1184         // otherwise the user code may get confused by the events from a 
1185         // non-existing button and, worse, a wxButton might get button event 
1186         // from another button which is not really expected 
1187         wxWindow 
*winForCancel 
= win
, 
1189         while ( winForCancel 
) 
1191             btnCancel 
= winForCancel
->FindWindow(wxID_CANCEL
); 
1194                 // found a cancel button 
1198             if ( winForCancel
->IsTopLevel() ) 
1200                 // no need to look further 
1204             // maybe our parent has a cancel button? 
1205             winForCancel 
= winForCancel
->GetParent(); 
1210             wxCommandEvent 
event(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
); 
1211             event
.SetEventObject(btnCancel
); 
1212             ret 
= btnCancel
->GetEventHandler()->ProcessEvent(event
); 
1218         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" ); 
1227 static gint 
gtk_window_key_press_callback( GtkWidget 
*widget
, 
1228                                            GdkEventKey 
*gdk_event
, 
1232         wxapp_install_idle_handler(); 
1236     if (g_blockEventsOnDrag
) 
1240     bool dont_use_IM 
= FALSE
; 
1242     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
1243     long keycode 
= wxTranslateKeySymToWXKey( gdk_event
->keyval
, FALSE 
); 
1246         // We were able to decode the key press without 
1247         // any input method, so don't use it. 
1250         // now fill all the other fields 
1253         GdkModifierType state
; 
1254         if (gdk_event
->window
) 
1255             gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1257         event
.SetTimestamp( gdk_event
->time 
); 
1258         event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
) != 0; 
1259         event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
) != 0; 
1260         event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
) != 0; 
1261         event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
) != 0; 
1262         event
.m_keyCode 
= keycode
; 
1263         event
.m_scanCode 
= gdk_event
->keyval
; 
1264         event
.m_rawCode 
= (wxUint32
) gdk_event
->keyval
; 
1265         event
.m_rawFlags 
= 0; 
1268         event
.SetEventObject( win 
); 
1270         // send key down event 
1271         ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1275             // Implement OnCharHook by checking ancesteror top level windows 
1276             wxWindow 
*parent 
= win
; 
1277             while (parent 
&& !parent
->IsTopLevel()) 
1278             parent 
= parent
->GetParent(); 
1281                 event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1282                 ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1287                 event
.SetEventType(wxEVT_CHAR
); 
1288                 ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1292         // win is a control: tab can be propagated up 
1294              ((gdk_event
->keyval 
== GDK_Tab
) || (gdk_event
->keyval 
== GDK_ISO_Left_Tab
)) && 
1295             win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) ) 
1297             wxNavigationKeyEvent new_event
; 
1298             new_event
.SetEventObject( win
->GetParent() ); 
1299             // GDK reports GDK_ISO_Left_Tab for SHIFT-TAB 
1300             new_event
.SetDirection( (gdk_event
->keyval 
== GDK_Tab
) ); 
1301             // CTRL-TAB changes the (parent) window, i.e. switch notebook page 
1302             new_event
.SetWindowChange( (gdk_event
->state 
& GDK_CONTROL_MASK
) ); 
1303             new_event
.SetCurrentFocus( win 
); 
1304             ret 
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event 
); 
1308              (gdk_event
->keyval 
== GDK_Escape
) ) 
1310             wxWindow 
*winForCancel 
= win
, *btnCancel 
= NULL
; 
1311             while ( winForCancel 
) 
1313                 btnCancel 
= winForCancel
->FindWindow(wxID_CANCEL
); 
1314                 if ( btnCancel 
) break; 
1316                 if ( winForCancel
->IsTopLevel() ) break; 
1318                 winForCancel 
= winForCancel
->GetParent(); 
1323                 wxCommandEvent 
event(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
); 
1324                 event
.SetEventObject(btnCancel
); 
1325                 ret 
= btnCancel
->GetEventHandler()->ProcessEvent(event
); 
1332         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" ); 
1336     if (!dont_use_IM 
&& win
->m_imContext
) 
1338         // In GTK 2.0, we need to hand over the key 
1339         // event to an input method and the IM will 
1340         // emit a "commit" event containing the 
1341         // actual utf8 character. 
1342         gtk_im_context_filter_keypress ( (GtkIMContext
*) win
->m_imContext
, gdk_event 
); 
1350 static void gtk_wxwindow_commit_cb (GtkIMContext 
*context
, 
1356     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
1359     event
.m_uniChar 
= g_utf8_get_char( str 
); 
1361     // Backward compatible for ISO-8859 
1362     if (event
.m_uniChar 
< 256) 
1363         event
.m_keyCode 
= event
.m_uniChar
; 
1365     gunichar uniChar 
= g_utf8_get_char( str 
); 
1366     // We cannot handle Unicode in non-Unicode mode 
1367     if (uniChar 
> 255) return; 
1369     event
.m_keyCode 
= uniChar
; 
1374         // Implement OnCharHook by checking ancesteror top level windows 
1375         wxWindow 
*parent 
= window
; 
1376         while (parent 
&& !parent
->IsTopLevel()) 
1377         parent 
= parent
->GetParent(); 
1380             event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1381             ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1386             event
.SetEventType(wxEVT_CHAR
); 
1387             ret 
= window
->GetEventHandler()->ProcessEvent( event 
); 
1394 //----------------------------------------------------------------------------- 
1395 // "key_release_event" from any window 
1396 //----------------------------------------------------------------------------- 
1398 static gint 
gtk_window_key_release_callback( GtkWidget 
*widget
, 
1399                                              GdkEventKey 
*gdk_event
, 
1405         wxapp_install_idle_handler(); 
1410     if (g_blockEventsOnDrag
) 
1413     wxKeyEvent 
event( wxEVT_KEY_UP 
); 
1414     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1416         // unknown key pressed, ignore (the event would be useless anyhow 
1420     if ( !win
->GetEventHandler()->ProcessEvent( event 
) ) 
1423     gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" ); 
1427 // ============================================================================ 
1429 // ============================================================================ 
1431 // ---------------------------------------------------------------------------- 
1432 // mouse event processing helpers 
1433 // ---------------------------------------------------------------------------- 
1435 // init wxMouseEvent with the info from gdk_event 
1437 // NB: this has to be a macro as gdk_event type is different for different 
1438 //     events we're used with 
1439 #define InitMouseEvent(/* wxWindowGTK * */ win,                               \ 
1440                        /* wxMouseEvent& */ event,                             \ 
1441                        /* GdkEventXXX * */ gdk_event)                         \ 
1443     event.SetTimestamp( gdk_event->time );                                    \ 
1444     event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);                  \ 
1445     event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);              \ 
1446     event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);                     \ 
1447     event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);                    \ 
1448     event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);                 \ 
1449     event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);               \ 
1450     event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);                \ 
1451     if (event.GetEventType()==wxEVT_MOUSEWHEEL)                               \ 
1453        if (((GdkEventButton*)gdk_event)->button == 4)                         \ 
1454            event.m_wheelRotation = 120;                                       \ 
1455        else if (((GdkEventButton*)gdk_event)->button == 5)                    \ 
1456            event.m_wheelRotation = -120;                                      \ 
1459     wxPoint pt = win->GetClientAreaOrigin();                                  \ 
1460     event.m_x = (wxCoord)gdk_event->x - pt.x;                                 \ 
1461     event.m_y = (wxCoord)gdk_event->y - pt.y;                                 \ 
1463     event.SetEventObject( win );                                              \ 
1464     event.SetId( win->GetId() );                                              \ 
1465     event.SetTimestamp( gdk_event->time );                                    \ 
1468 static void AdjustEventButtonState(wxMouseEvent& event) 
1470     // GDK reports the old state of the button for a button press event, but 
1471     // for compatibility with MSW and common sense we want m_leftDown be TRUE 
1472     // for a LEFT_DOWN event, not FALSE, so we will invert 
1473     // left/right/middleDown for the corresponding click events 
1475     if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) || 
1476         (event
.GetEventType() == wxEVT_LEFT_DCLICK
) || 
1477         (event
.GetEventType() == wxEVT_LEFT_UP
)) 
1479         event
.m_leftDown 
= !event
.m_leftDown
; 
1483     if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) || 
1484         (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) || 
1485         (event
.GetEventType() == wxEVT_MIDDLE_UP
)) 
1487         event
.m_middleDown 
= !event
.m_middleDown
; 
1491     if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) || 
1492         (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) || 
1493         (event
.GetEventType() == wxEVT_RIGHT_UP
)) 
1495         event
.m_rightDown 
= !event
.m_rightDown
; 
1500 // find the window to send the mouse event too 
1502 wxWindowGTK 
*FindWindowForMouseEvent(wxWindowGTK 
*win
, wxCoord
& x
, wxCoord
& y
) 
1507     if (win
->m_wxwindow
) 
1509         GtkPizza 
*pizza 
= GTK_PIZZA(win
->m_wxwindow
); 
1510         xx 
+= pizza
->xoffset
; 
1511         yy 
+= pizza
->yoffset
; 
1514     wxNode 
*node 
= win
->GetChildren().First(); 
1517         wxWindowGTK 
*child 
= (wxWindowGTK
*)node
->Data(); 
1519         node 
= node
->Next(); 
1520         if (!child
->IsShown()) 
1523         if (child
->IsTransparentForMouse()) 
1525             // wxStaticBox is transparent in the box itself 
1526             int xx1 
= child
->m_x
; 
1527             int yy1 
= child
->m_y
; 
1528             int xx2 
= child
->m_x 
+ child
->m_width
; 
1529             int yy2 
= child
->m_x 
+ child
->m_height
; 
1532             if (((xx 
>= xx1
) && (xx 
<= xx1
+10) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1534                 ((xx 
>= xx2
-10) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1536                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy1
+10)) || 
1538                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy2
-1) && (yy 
<= yy2
))) 
1549             if ((child
->m_wxwindow 
== (GtkWidget
*) NULL
) && 
1550                 (child
->m_x 
<= xx
) && 
1551                 (child
->m_y 
<= yy
) && 
1552                 (child
->m_x
+child
->m_width  
>= xx
) && 
1553                 (child
->m_y
+child
->m_height 
>= yy
)) 
1566 //----------------------------------------------------------------------------- 
1567 // "button_press_event" 
1568 //----------------------------------------------------------------------------- 
1570 static gint 
gtk_window_button_press_callback( GtkWidget 
*widget
, 
1571                                               GdkEventButton 
*gdk_event
, 
1577         wxapp_install_idle_handler(); 
1580     wxPrintf( wxT("1) OnButtonPress from ") ); 
1581     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1582         wxPrintf( win->GetClassInfo()->GetClassName() ); 
1583     wxPrintf( wxT(".\n") ); 
1585     if (!win
->m_hasVMT
) return FALSE
; 
1586     if (g_blockEventsOnDrag
) return TRUE
; 
1587     if (g_blockEventsOnScroll
) return TRUE
; 
1589     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1591     if (win
->m_wxwindow 
&& (g_focusWindow 
!= win
) && win
->AcceptsFocus()) 
1593         gtk_widget_grab_focus( win
->m_wxwindow 
); 
1595         wxPrintf( wxT("GrabFocus from ") ); 
1596         if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1597             wxPrintf( win->GetClassInfo()->GetClassName() ); 
1598         wxPrintf( wxT(".\n") ); 
1602     // GDK sends surplus button down event 
1603     // before a double click event. We 
1604     // need to filter these out. 
1605     if (gdk_event
->type 
== GDK_BUTTON_PRESS
) 
1607         GdkEvent 
*peek_event 
= gdk_event_peek(); 
1610             if (peek_event
->type 
== GDK_2BUTTON_PRESS
) 
1612                 gdk_event_free( peek_event 
); 
1617                 gdk_event_free( peek_event 
); 
1622     wxEventType event_type 
= wxEVT_NULL
; 
1624     if (gdk_event
->button 
== 1) 
1626         switch (gdk_event
->type
) 
1628             case GDK_BUTTON_PRESS
: event_type 
= wxEVT_LEFT_DOWN
; break; 
1629             case GDK_2BUTTON_PRESS
: event_type 
= wxEVT_LEFT_DCLICK
; break; 
1633     else if (gdk_event
->button 
== 2) 
1635         switch (gdk_event
->type
) 
1637             case GDK_BUTTON_PRESS
: event_type 
= wxEVT_MIDDLE_DOWN
; break; 
1638             case GDK_2BUTTON_PRESS
: event_type 
= wxEVT_MIDDLE_DCLICK
; break; 
1642     else if (gdk_event
->button 
== 3) 
1644         switch (gdk_event
->type
) 
1646             case GDK_BUTTON_PRESS
: event_type 
= wxEVT_RIGHT_DOWN
; break; 
1647             case GDK_2BUTTON_PRESS
: event_type 
= wxEVT_RIGHT_DCLICK
; break; 
1651     else if (gdk_event
->button 
== 4) 
1653         switch (gdk_event
->type
) 
1655             case GDK_BUTTON_PRESS
: event_type 
= wxEVT_MOUSEWHEEL
; break; 
1659     else if (gdk_event
->button 
== 5) 
1661         switch (gdk_event
->type
) 
1663             case GDK_BUTTON_PRESS
: event_type 
= wxEVT_MOUSEWHEEL
; break; 
1668     if ( event_type 
== wxEVT_NULL 
) 
1670         // unknown mouse button or click type 
1674     wxMouseEvent 
event( event_type 
); 
1675     InitMouseEvent( win
, event
, gdk_event 
); 
1677     AdjustEventButtonState(event
); 
1679     // wxListBox actually get mouse events from the item, so we need to give it 
1680     // a chance to correct this 
1681     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1683     // find the correct window to send the event too: it may be a different one 
1684     // from the one which got it at GTK+ level because some control don't have 
1685     // their own X window and thus cannot get any events. 
1686     if ( !g_captureWindow 
) 
1687         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1689     gs_timeLastClick 
= gdk_event
->time
; 
1692     wxPrintf( wxT("2) OnButtonPress from ") ); 
1693     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1694         wxPrintf( win->GetClassInfo()->GetClassName() ); 
1695     wxPrintf( wxT(".\n") ); 
1699     if (event_type 
== wxEVT_LEFT_DCLICK
) 
1701         // GTK 1.2 crashes when intercepting double 
1702         // click events from both wxSpinButton and 
1704         if (GTK_IS_SPIN_BUTTON(win
->m_widget
)) 
1706             // Just disable this event for now. 
1712     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1714         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" ); 
1721 //----------------------------------------------------------------------------- 
1722 // "button_release_event" 
1723 //----------------------------------------------------------------------------- 
1725 static gint 
gtk_window_button_release_callback( GtkWidget 
*widget
, 
1726                                                 GdkEventButton 
*gdk_event
, 
1732         wxapp_install_idle_handler(); 
1734     if (!win
->m_hasVMT
) return FALSE
; 
1735     if (g_blockEventsOnDrag
) return FALSE
; 
1736     if (g_blockEventsOnScroll
) return FALSE
; 
1738     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1740     wxEventType event_type 
= wxEVT_NULL
; 
1742     switch (gdk_event
->button
) 
1745             event_type 
= wxEVT_LEFT_UP
; 
1749             event_type 
= wxEVT_MIDDLE_UP
; 
1753             event_type 
= wxEVT_RIGHT_UP
; 
1757             // unknwon button, don't process 
1761     wxMouseEvent 
event( event_type 
); 
1762     InitMouseEvent( win
, event
, gdk_event 
); 
1764     AdjustEventButtonState(event
); 
1766     // same wxListBox hack as above 
1767     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1769     if ( event_type 
== wxEVT_RIGHT_UP 
) 
1771         // generate a "context menu" event: this is similar to wxEVT_RIGHT_UP 
1774         // (a) it's a command event and so is propagated to the parent 
1775         // (b) under MSW it can be generated from kbd too 
1776         // (c) it uses screen coords (because of (a)) 
1777         wxContextMenuEvent 
evtCtx(wxEVT_CONTEXT_MENU
, 
1779                                   win
->ClientToScreen(event
.GetPosition())); 
1780         (void)win
->GetEventHandler()->ProcessEvent(evtCtx
); 
1783     if ( !g_captureWindow 
) 
1784         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1786     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1788         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" ); 
1795 //----------------------------------------------------------------------------- 
1796 // "motion_notify_event" 
1797 //----------------------------------------------------------------------------- 
1799 static gint 
gtk_window_motion_notify_callback( GtkWidget 
*widget
, 
1800                                                GdkEventMotion 
*gdk_event
, 
1806         wxapp_install_idle_handler(); 
1808     if (!win
->m_hasVMT
) return FALSE
; 
1809     if (g_blockEventsOnDrag
) return FALSE
; 
1810     if (g_blockEventsOnScroll
) return FALSE
; 
1812     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1814     if (gdk_event
->is_hint
) 
1818         GdkModifierType state
; 
1819         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1825     printf( "OnMotion from " ); 
1826     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1827       printf( win->GetClassInfo()->GetClassName() ); 
1831     wxMouseEvent 
event( wxEVT_MOTION 
); 
1832     InitMouseEvent(win
, event
, gdk_event
); 
1834     if ( g_captureWindow 
) 
1836         // synthetize a mouse enter or leave event if needed 
1837         GdkWindow 
*winUnderMouse 
= gdk_window_at_pointer(NULL
, NULL
); 
1838         bool hasMouse 
= winUnderMouse 
== gdk_event
->window
; 
1839         if ( hasMouse 
!= g_captureWindowHasMouse 
) 
1841             // the mouse changed window 
1842             g_captureWindowHasMouse 
= hasMouse
; 
1844             wxMouseEvent 
event(g_captureWindowHasMouse 
? wxEVT_ENTER_WINDOW
 
1845                                                        : wxEVT_LEAVE_WINDOW
); 
1846             InitMouseEvent(win
, event
, gdk_event
); 
1847             event
.SetEventObject(win
); 
1848             win
->GetEventHandler()->ProcessEvent(event
); 
1853         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1856     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1858         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" ); 
1865 //----------------------------------------------------------------------------- 
1867 //----------------------------------------------------------------------------- 
1869 // send the wxChildFocusEvent and wxFocusEvent, common code of 
1870 // gtk_window_focus_in_callback() and SetFocus() 
1871 static bool DoSendFocusEvents(wxWindow 
*win
) 
1873     // Notify the parent keeping track of focus for the kbd navigation 
1874     // purposes that we got it. 
1875     wxChildFocusEvent 
eventChildFocus(win
); 
1876     (void)win
->GetEventHandler()->ProcessEvent(eventChildFocus
); 
1878     wxFocusEvent 
eventFocus(wxEVT_SET_FOCUS
, win
->GetId()); 
1879     eventFocus
.SetEventObject(win
); 
1881     return win
->GetEventHandler()->ProcessEvent(eventFocus
); 
1884 static gint 
gtk_window_focus_in_callback( GtkWidget 
*widget
, 
1885                                           GdkEvent 
*WXUNUSED(event
), 
1891         wxapp_install_idle_handler(); 
1893     if (!win
->m_hasVMT
) return FALSE
; 
1894     if (g_blockEventsOnDrag
) return FALSE
; 
1896     switch ( g_sendActivateEvent 
) 
1899             // we've got focus from outside, synthetize wxActivateEvent 
1900             g_sendActivateEvent 
= 1; 
1904             // another our window just lost focus, it was already ours before 
1905             // - don't send any wxActivateEvent 
1906             g_sendActivateEvent 
= -1; 
1911     g_focusWindow 
= win
; 
1913     wxLogTrace(TRACE_FOCUS
, 
1914                _T("%s: focus in"), win
->GetName().c_str()); 
1918         gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
); 
1922     // caret needs to be informed about focus change 
1923     wxCaret 
*caret 
= win
->GetCaret(); 
1926         caret
->OnSetFocus(); 
1928 #endif // wxUSE_CARET 
1930     g_activeFrameLostFocus 
= FALSE
; 
1932     wxWindowGTK 
*active 
= wxGetTopLevelParent(win
); 
1933     if ( active 
!= g_activeFrame 
) 
1935         if ( g_activeFrame 
) 
1937             wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
); 
1938             wxActivateEvent 
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId()); 
1939             event
.SetEventObject(g_activeFrame
); 
1940             g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
1943         wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
); 
1944         g_activeFrame 
= active
; 
1945         wxActivateEvent 
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId()); 
1946         event
.SetEventObject(g_activeFrame
); 
1947         g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
1949         // Don't send focus events in addition to activate 
1950         // if (win == g_activeFrame) 
1954     // does the window itself think that it has the focus? 
1955     if ( !win
->m_hasFocus 
) 
1957         // not yet, notify it 
1958         win
->m_hasFocus 
= TRUE
; 
1960         if ( DoSendFocusEvents(win
) ) 
1962            gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" ); 
1970 //----------------------------------------------------------------------------- 
1971 // "focus_out_event" 
1972 //----------------------------------------------------------------------------- 
1974 static gint 
gtk_window_focus_out_callback( GtkWidget 
*widget
, GdkEventFocus 
*gdk_event
, wxWindowGTK 
*win 
) 
1979         wxapp_install_idle_handler(); 
1981     if (!win
->m_hasVMT
) return FALSE
; 
1982     if (g_blockEventsOnDrag
) return FALSE
; 
1984     wxLogTrace( TRACE_FOCUS
, 
1985                 _T("%s: focus out"), win
->GetName().c_str() ); 
1987     if ( !g_activeFrameLostFocus 
&& g_activeFrame 
) 
1989         // VZ: commenting this out because it does happen (although not easy 
1990         //     to reproduce, I only see it when using wxMiniFrame and not 
1991         //     always) and makes using Mahogany quite annoying 
1993         wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
, 
1994                         wxT("unfocusing window that hasn't gained focus properly") ); 
1997         g_activeFrameLostFocus 
= TRUE
; 
2000     // if the focus goes out of our app alltogether, OnIdle() will send 
2001     // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset 
2002     // g_sendActivateEvent to -1 
2003     g_sendActivateEvent 
= 0; 
2005     wxWindowGTK 
*winFocus 
= wxFindFocusedChild(win
); 
2009     g_focusWindow 
= (wxWindowGTK 
*)NULL
; 
2017     // caret needs to be informed about focus change 
2018     wxCaret 
*caret 
= win
->GetCaret(); 
2021         caret
->OnKillFocus(); 
2023 #endif // wxUSE_CARET 
2025     // don't send the window a kill focus event if it thinks that it doesn't 
2026     // have focus already 
2027     if ( win
->m_hasFocus 
) 
2029         win
->m_hasFocus 
= FALSE
; 
2031         wxFocusEvent 
event( wxEVT_KILL_FOCUS
, win
->GetId() ); 
2032         event
.SetEventObject( win 
); 
2034         if (win
->GetEventHandler()->ProcessEvent( event 
)) 
2036             gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" ); 
2044 //----------------------------------------------------------------------------- 
2045 // "enter_notify_event" 
2046 //----------------------------------------------------------------------------- 
2049 gint 
gtk_window_enter_callback( GtkWidget 
*widget
, 
2050                                 GdkEventCrossing 
*gdk_event
, 
2056         wxapp_install_idle_handler(); 
2058     if (!win
->m_hasVMT
) return FALSE
; 
2059     if (g_blockEventsOnDrag
) return FALSE
; 
2061     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
2065     GdkModifierType state 
= (GdkModifierType
)0; 
2067     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
2069     wxMouseEvent 
event( wxEVT_ENTER_WINDOW 
); 
2070     InitMouseEvent(win
, event
, gdk_event
); 
2071     wxPoint pt 
= win
->GetClientAreaOrigin(); 
2072     event
.m_x 
= x 
+ pt
.x
; 
2073     event
.m_y 
= y 
+ pt
.y
; 
2075     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
2077        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" ); 
2084 //----------------------------------------------------------------------------- 
2085 // "leave_notify_event" 
2086 //----------------------------------------------------------------------------- 
2088 static gint 
gtk_window_leave_callback( GtkWidget 
*widget
, GdkEventCrossing 
*gdk_event
, wxWindowGTK 
*win 
) 
2093         wxapp_install_idle_handler(); 
2095     if (!win
->m_hasVMT
) return FALSE
; 
2096     if (g_blockEventsOnDrag
) return FALSE
; 
2098     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
2100     wxMouseEvent 
event( wxEVT_LEAVE_WINDOW 
); 
2101     event
.SetTimestamp( gdk_event
->time 
); 
2102     event
.SetEventObject( win 
); 
2106     GdkModifierType state 
= (GdkModifierType
)0; 
2108     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
2110     event
.m_shiftDown 
= (state 
& GDK_SHIFT_MASK
) != 0; 
2111     event
.m_controlDown 
= (state 
& GDK_CONTROL_MASK
) != 0; 
2112     event
.m_altDown 
= (state 
& GDK_MOD1_MASK
) != 0; 
2113     event
.m_metaDown 
= (state 
& GDK_MOD2_MASK
) != 0; 
2114     event
.m_leftDown 
= (state 
& GDK_BUTTON1_MASK
) != 0; 
2115     event
.m_middleDown 
= (state 
& GDK_BUTTON2_MASK
) != 0; 
2116     event
.m_rightDown 
= (state 
& GDK_BUTTON3_MASK
) != 0; 
2118     wxPoint pt 
= win
->GetClientAreaOrigin(); 
2119     event
.m_x 
= x 
+ pt
.x
; 
2120     event
.m_y 
= y 
+ pt
.y
; 
2122     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
2124         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" ); 
2131 //----------------------------------------------------------------------------- 
2132 // "value_changed" from m_vAdjust 
2133 //----------------------------------------------------------------------------- 
2135 static void gtk_window_vscroll_callback( GtkAdjustment 
*adjust
, 
2142         wxapp_install_idle_handler(); 
2144     if (g_blockEventsOnDrag
) return; 
2146     if (!win
->m_hasVMT
) return; 
2148     float diff 
= adjust
->value 
- win
->m_oldVerticalPos
; 
2149     if (fabs(diff
) < 0.2) return; 
2151     win
->m_oldVerticalPos 
= adjust
->value
; 
2154     GtkScrolledWindow   
*sw 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
2156     wxEventType         command 
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->vscrollbar
)); 
2158     int value 
= (int)(adjust
->value
+0.5); 
2160     wxScrollWinEvent 
event( command
, value
, wxVERTICAL 
); 
2161     event
.SetEventObject( win 
); 
2162     win
->GetEventHandler()->ProcessEvent( event 
); 
2165 //----------------------------------------------------------------------------- 
2166 // "value_changed" from m_hAdjust 
2167 //----------------------------------------------------------------------------- 
2169 static void gtk_window_hscroll_callback( GtkAdjustment 
*adjust
, 
2176         wxapp_install_idle_handler(); 
2178     if (g_blockEventsOnDrag
) return; 
2179     if (!win
->m_hasVMT
) return; 
2181     float diff 
= adjust
->value 
- win
->m_oldHorizontalPos
; 
2182     if (fabs(diff
) < 0.2) return; 
2185     GtkScrolledWindow   
*sw 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
2187     wxEventType         command 
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->hscrollbar
)); 
2189     win
->m_oldHorizontalPos 
= adjust
->value
; 
2191     int value 
= (int)(adjust
->value
+0.5); 
2193     wxScrollWinEvent 
event( command
, value
, wxHORIZONTAL 
); 
2194     event
.SetEventObject( win 
); 
2195     win
->GetEventHandler()->ProcessEvent( event 
); 
2198 //----------------------------------------------------------------------------- 
2199 // "button_press_event" from scrollbar 
2200 //----------------------------------------------------------------------------- 
2202 static gint 
gtk_scrollbar_button_press_callback( GtkRange 
*widget
, 
2203                                                  GdkEventButton 
*gdk_event
, 
2209         wxapp_install_idle_handler(); 
2212     g_blockEventsOnScroll 
= TRUE
; 
2214     // FIXME: there is no 'slider' field in GTK+ 2.0 any more 
2216     win
->m_isScrolling 
= (gdk_event
->window 
== widget
->slider
); 
2222 //----------------------------------------------------------------------------- 
2223 // "button_release_event" from scrollbar 
2224 //----------------------------------------------------------------------------- 
2226 static gint 
gtk_scrollbar_button_release_callback( GtkRange 
*widget
, 
2227                                                    GdkEventButton 
*WXUNUSED(gdk_event
), 
2232 //  don't test here as we can release the mouse while being over 
2233 //  a different window than the slider 
2235 //    if (gdk_event->window != widget->slider) return FALSE; 
2237     g_blockEventsOnScroll 
= FALSE
; 
2239     if (win
->m_isScrolling
) 
2241         wxEventType command 
= wxEVT_SCROLLWIN_THUMBRELEASE
; 
2245         GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
2246         if (widget 
== GTK_RANGE(scrolledWindow
->hscrollbar
)) 
2248             value 
= (int)(win
->m_hAdjust
->value
+0.5); 
2251         if (widget 
== GTK_RANGE(scrolledWindow
->vscrollbar
)) 
2253             value 
= (int)(win
->m_vAdjust
->value
+0.5); 
2257         wxScrollWinEvent 
event( command
, value
, dir 
); 
2258         event
.SetEventObject( win 
); 
2259         win
->GetEventHandler()->ProcessEvent( event 
); 
2262     win
->m_isScrolling 
= FALSE
; 
2267 // ---------------------------------------------------------------------------- 
2268 // this wxWindowBase function is implemented here (in platform-specific file) 
2269 // because it is static and so couldn't be made virtual 
2270 // ---------------------------------------------------------------------------- 
2272 wxWindow 
*wxWindowBase::FindFocus() 
2274     // the cast is necessary when we compile in wxUniversal mode 
2275     return (wxWindow 
*)g_focusWindow
; 
2278 //----------------------------------------------------------------------------- 
2280 //----------------------------------------------------------------------------- 
2282 // VZ: Robert commented the code using out so it generates warnings: should 
2283 //     be either fixed or removed completely 
2286 static void gtk_window_destroy_callback( GtkWidget
* widget
, wxWindow 
*win 
) 
2288     wxWindowDestroyEvent 
event(win
); 
2289     win
->GetEventHandler()->ProcessEvent(event
); 
2294 //----------------------------------------------------------------------------- 
2295 // "realize" from m_widget 
2296 //----------------------------------------------------------------------------- 
2298 /* We cannot set colours and fonts before the widget has 
2299    been realized, so we do this directly after realization. */ 
2302 gtk_window_realized_callback( GtkWidget 
*m_widget
, wxWindow 
*win 
) 
2307         wxapp_install_idle_handler(); 
2309     if (win
->m_delayedBackgroundColour
) 
2310         win
->GtkSetBackgroundColour( win
->GetBackgroundColour() ); 
2312     if (win
->m_delayedForegroundColour
) 
2313         win
->GtkSetForegroundColour( win
->GetForegroundColour() ); 
2316     if (win
->m_imContext
) 
2318         GtkPizza 
*pizza 
= GTK_PIZZA( m_widget 
); 
2319         gtk_im_context_set_client_window( (GtkIMContext
*) win
->m_imContext
, pizza
->bin_window 
); 
2323     wxWindowCreateEvent 
event( win 
); 
2324     event
.SetEventObject( win 
); 
2325     win
->GetEventHandler()->ProcessEvent( event 
); 
2330 //----------------------------------------------------------------------------- 
2332 //----------------------------------------------------------------------------- 
2335 void gtk_window_size_callback( GtkWidget 
*WXUNUSED(widget
), 
2336                                GtkAllocation 
*WXUNUSED(alloc
), 
2340         wxapp_install_idle_handler(); 
2342     if (!win
->m_hasScrolling
) return; 
2344     int client_width 
= 0; 
2345     int client_height 
= 0; 
2346     win
->GetClientSize( &client_width
, &client_height 
); 
2347     if ((client_width 
== win
->m_oldClientWidth
) && (client_height 
== win
->m_oldClientHeight
)) 
2350     win
->m_oldClientWidth 
= client_width
; 
2351     win
->m_oldClientHeight 
= client_height
; 
2353     if (!win
->m_nativeSizeEvent
) 
2355         wxSizeEvent 
event( win
->GetSize(), win
->GetId() ); 
2356         event
.SetEventObject( win 
); 
2357         win
->GetEventHandler()->ProcessEvent( event 
); 
2363     #define WXUNUSED_UNLESS_XIM(param)  param 
2365     #define WXUNUSED_UNLESS_XIM(param)  WXUNUSED(param) 
2368 /* Resize XIM window */ 
2371 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
), 
2372                                  GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
), 
2373                                  wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) ) 
2376         wxapp_install_idle_handler(); 
2382     if  (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
) 
2386         gdk_window_get_size (widget
->window
, &width
, &height
); 
2387         win
->m_icattr
->preedit_area
.width 
= width
; 
2388         win
->m_icattr
->preedit_area
.height 
= height
; 
2389         gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
); 
2394 //----------------------------------------------------------------------------- 
2395 // "realize" from m_wxwindow 
2396 //----------------------------------------------------------------------------- 
2398 /* Initialize XIM support */ 
2401 gtk_wxwindow_realized_callback( GtkWidget 
* WXUNUSED_UNLESS_XIM(widget
), 
2402                                 wxWindowGTK 
* WXUNUSED_UNLESS_XIM(win
) ) 
2405         wxapp_install_idle_handler(); 
2408     if (win
->m_ic
) return FALSE
; 
2409     if (!widget
) return FALSE
; 
2410     if (!gdk_im_ready()) return FALSE
; 
2412     win
->m_icattr 
= gdk_ic_attr_new(); 
2413     if (!win
->m_icattr
) return FALSE
; 
2417     GdkColormap 
*colormap
; 
2418     GdkICAttr 
*attr 
= win
->m_icattr
; 
2419     unsigned attrmask 
= GDK_IC_ALL_REQ
; 
2421     GdkIMStyle supported_style 
= (GdkIMStyle
) 
2422                                   (GDK_IM_PREEDIT_NONE 
| 
2423                                    GDK_IM_PREEDIT_NOTHING 
| 
2424                                    GDK_IM_PREEDIT_POSITION 
| 
2425                                    GDK_IM_STATUS_NONE 
| 
2426                                    GDK_IM_STATUS_NOTHING
); 
2428     if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2429         supported_style 
= (GdkIMStyle
)(supported_style 
& ~GDK_IM_PREEDIT_POSITION
); 
2431     attr
->style 
= style 
= gdk_im_decide_style (supported_style
); 
2432     attr
->client_window 
= widget
->window
; 
2434     if ((colormap 
= gtk_widget_get_colormap (widget
)) != 
2435             gtk_widget_get_default_colormap ()) 
2437         attrmask 
|= GDK_IC_PREEDIT_COLORMAP
; 
2438         attr
->preedit_colormap 
= colormap
; 
2441     attrmask 
|= GDK_IC_PREEDIT_FOREGROUND
; 
2442     attrmask 
|= GDK_IC_PREEDIT_BACKGROUND
; 
2443     attr
->preedit_foreground 
= widget
->style
->fg
[GTK_STATE_NORMAL
]; 
2444     attr
->preedit_background 
= widget
->style
->base
[GTK_STATE_NORMAL
]; 
2446     switch (style 
& GDK_IM_PREEDIT_MASK
) 
2448         case GDK_IM_PREEDIT_POSITION
: 
2449             if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2451                 g_warning ("over-the-spot style requires fontset"); 
2455             gdk_window_get_size (widget
->window
, &width
, &height
); 
2457             attrmask 
|= GDK_IC_PREEDIT_POSITION_REQ
; 
2458             attr
->spot_location
.x 
= 0; 
2459             attr
->spot_location
.y 
= height
; 
2460             attr
->preedit_area
.x 
= 0; 
2461             attr
->preedit_area
.y 
= 0; 
2462             attr
->preedit_area
.width 
= width
; 
2463             attr
->preedit_area
.height 
= height
; 
2464             attr
->preedit_fontset 
= widget
->style
->font
; 
2469       win
->m_ic 
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
); 
2471       if (win
->m_ic 
== NULL
) 
2472           g_warning ("Can't create input context."); 
2475           mask 
= gdk_window_get_events (widget
->window
); 
2476           mask 
= (GdkEventMask
)(mask 
| gdk_ic_get_events (win
->m_ic
)); 
2477           gdk_window_set_events (widget
->window
, mask
); 
2479           if (GTK_WIDGET_HAS_FOCUS(widget
)) 
2480               gdk_im_begin (win
->m_ic
, widget
->window
); 
2487 //----------------------------------------------------------------------------- 
2488 // InsertChild for wxWindowGTK. 
2489 //----------------------------------------------------------------------------- 
2491 /* Callback for wxWindowGTK. This very strange beast has to be used because 
2492  * C++ has no virtual methods in a constructor. We have to emulate a 
2493  * virtual function here as wxNotebook requires a different way to insert 
2494  * a child in it. I had opted for creating a wxNotebookPage window class 
2495  * which would have made this superfluous (such in the MDI window system), 
2496  * but no-one was listening to me... */ 
2498 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child 
) 
2500     /* the window might have been scrolled already, do we 
2501        have to adapt the position */ 
2502     GtkPizza 
*pizza 
= GTK_PIZZA(parent
->m_wxwindow
); 
2503     child
->m_x 
+= pizza
->xoffset
; 
2504     child
->m_y 
+= pizza
->yoffset
; 
2506     gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
), 
2507                      GTK_WIDGET(child
->m_widget
), 
2514 //----------------------------------------------------------------------------- 
2516 //----------------------------------------------------------------------------- 
2518 wxWindow 
*wxGetActiveWindow() 
2520     return wxWindow::FindFocus(); 
2523 //----------------------------------------------------------------------------- 
2525 //----------------------------------------------------------------------------- 
2527 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
2529 #ifdef __WXUNIVERSAL__ 
2530     IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
) 
2532     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
2533 #endif // __WXUNIVERSAL__/__WXGTK__ 
2535 void wxWindowGTK::Init() 
2541     m_widget 
= (GtkWidget 
*) NULL
; 
2542     m_wxwindow 
= (GtkWidget 
*) NULL
; 
2543     m_focusWidget 
= (GtkWidget 
*) NULL
; 
2553     m_needParent 
= TRUE
; 
2554     m_isBeingDeleted 
= FALSE
; 
2557     m_nativeSizeEvent 
= FALSE
; 
2559     m_hasScrolling 
= FALSE
; 
2560     m_isScrolling 
= FALSE
; 
2562     m_hAdjust 
= (GtkAdjustment
*) NULL
; 
2563     m_vAdjust 
= (GtkAdjustment
*) NULL
; 
2564     m_oldHorizontalPos 
= 0.0; 
2565     m_oldVerticalPos 
= 0.0; 
2568     m_widgetStyle 
= (GtkStyle
*) NULL
; 
2570     m_insertCallback 
= (wxInsertChildFunction
) NULL
; 
2572     m_acceptsFocus 
= FALSE
; 
2575     m_clipPaintRegion 
= FALSE
; 
2577     m_cursor 
= *wxSTANDARD_CURSOR
; 
2579     m_delayedForegroundColour 
= FALSE
; 
2580     m_delayedBackgroundColour 
= FALSE
; 
2584     m_x11Context 
= NULL
; 
2587     m_ic 
= (GdkIC
*) NULL
; 
2588     m_icattr 
= (GdkICAttr
*) NULL
; 
2593 wxWindowGTK::wxWindowGTK() 
2598 wxWindowGTK::wxWindowGTK( wxWindow 
*parent
, 
2603                           const wxString 
&name  
) 
2607     Create( parent
, id
, pos
, size
, style
, name 
); 
2610 bool wxWindowGTK::Create( wxWindow 
*parent
, 
2615                           const wxString 
&name  
) 
2617     if (!PreCreation( parent
, pos
, size 
) || 
2618         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
2620         wxFAIL_MSG( wxT("wxWindowGTK creation failed") ); 
2624     m_insertCallback 
= wxInsertChildInWindow
; 
2626     // always needed for background clearing 
2627     m_delayedBackgroundColour 
= TRUE
; 
2629     m_widget 
= gtk_scrolled_window_new( (GtkAdjustment 
*) NULL
, (GtkAdjustment 
*) NULL 
); 
2630     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
2632     GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
2634     GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2635     scroll_class
->scrollbar_spacing 
= 0; 
2637     gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
2639     m_hAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) ); 
2640     m_vAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) ); 
2642     m_wxwindow 
= gtk_pizza_new(); 
2644 #ifndef __WXUNIVERSAL__ 
2645     GtkPizza 
*pizza 
= GTK_PIZZA(m_wxwindow
); 
2647     if (HasFlag(wxRAISED_BORDER
)) 
2649         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT 
); 
2651     else if (HasFlag(wxSUNKEN_BORDER
)) 
2653         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN 
); 
2655     else if (HasFlag(wxSIMPLE_BORDER
)) 
2657         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN 
); 
2661         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE 
); 
2663 #endif // __WXUNIVERSAL__ 
2665     gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
2667     GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
2668     m_acceptsFocus 
= TRUE
; 
2670     // I _really_ don't want scrollbars in the beginning 
2671     m_vAdjust
->lower 
= 0.0; 
2672     m_vAdjust
->upper 
= 1.0; 
2673     m_vAdjust
->value 
= 0.0; 
2674     m_vAdjust
->step_increment 
= 1.0; 
2675     m_vAdjust
->page_increment 
= 1.0; 
2676     m_vAdjust
->page_size 
= 5.0; 
2677     gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
2678     m_hAdjust
->lower 
= 0.0; 
2679     m_hAdjust
->upper 
= 1.0; 
2680     m_hAdjust
->value 
= 0.0; 
2681     m_hAdjust
->step_increment 
= 1.0; 
2682     m_hAdjust
->page_increment 
= 1.0; 
2683     m_hAdjust
->page_size 
= 5.0; 
2684     gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
2686     // these handlers block mouse events to any window during scrolling such as 
2687     // motion events and prevent GTK and wxWindows from fighting over where the 
2690     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event", 
2691           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
2693     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event", 
2694           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
2696     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event", 
2697           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
2699     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event", 
2700           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
2702     // these handlers get notified when screen updates are required either when 
2703     // scrolling or when the window size (and therefore scrollbar configuration) 
2706     gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
2707           (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
2708     gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
2709           (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
2712     // Create input method handler 
2713     m_imContext 
= (GtkIMMulticontext
*) gtk_im_multicontext_new (); 
2715     // Cannot handle drawing preedited text yet 
2716     gtk_im_context_set_use_preedit( (GtkIMContext
*) m_imContext
, FALSE 
); 
2718     g_signal_connect (G_OBJECT (m_imContext
), "commit", 
2719         G_CALLBACK (gtk_wxwindow_commit_cb
), this); 
2722     gtk_widget_show( m_wxwindow 
); 
2725         m_parent
->DoAddChild( this ); 
2727     m_focusWidget 
= m_wxwindow
; 
2736 wxWindowGTK::~wxWindowGTK() 
2738     if (g_focusWindow 
== this) 
2739         g_focusWindow 
= NULL
; 
2741     if (g_activeFrame 
== this) 
2742         g_activeFrame 
= NULL
; 
2744     if ( g_delayedFocus 
== this ) 
2745         g_delayedFocus 
= NULL
; 
2747     m_isBeingDeleted 
= TRUE
; 
2756         m_parent
->RemoveChild( this ); 
2760         gdk_ic_destroy (m_ic
); 
2762         gdk_ic_attr_destroy (m_icattr
); 
2767 #if DISABLE_STYLE_IF_BROKEN_THEME 
2768         // don't delete if it's a pixmap theme style 
2769         if (!m_widgetStyle
->engine_data
) 
2770             gtk_style_unref( m_widgetStyle 
); 
2772         m_widgetStyle 
= (GtkStyle
*) NULL
; 
2777         gtk_widget_destroy( m_wxwindow 
); 
2778         m_wxwindow 
= (GtkWidget
*) NULL
; 
2783         gtk_widget_destroy( m_widget 
); 
2784         m_widget 
= (GtkWidget
*) NULL
; 
2788 bool wxWindowGTK::PreCreation( wxWindowGTK 
*parent
, const wxPoint 
&pos
,  const wxSize 
&size 
) 
2790     wxCHECK_MSG( !m_needParent 
|| parent
, FALSE
, wxT("Need complete parent.") ); 
2792     // This turns -1 into 30 so that a minimal window is 
2793     // visible even although -1,-1 has been given as the 
2794     // size of the window. the same trick is used in other 
2795     // ports and should make debugging easier. 
2796     m_width 
= WidthDefault(size
.x
) ; 
2797     m_height 
= HeightDefault(size
.y
); 
2802     // some reasonable defaults 
2807             m_x 
= (gdk_screen_width () - m_width
) / 2; 
2808             if (m_x 
< 10) m_x 
= 10; 
2812             m_y 
= (gdk_screen_height () - m_height
) / 2; 
2813             if (m_y 
< 10) m_y 
= 10; 
2820 void wxWindowGTK::PostCreation() 
2822     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2828             // these get reported to wxWindows -> wxPaintEvent 
2830             gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE 
); 
2832             gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event", 
2833                 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this ); 
2836             gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw", 
2837                 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this ); 
2839             if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) 
2841                 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event", 
2842                     GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this ); 
2845             // gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), HasFlag( wxNO_FULL_REPAINT_ON_RESIZE ) ); 
2849         // Create input method handler 
2850         m_imContext 
= (GtkIMMulticontext
*) gtk_im_multicontext_new (); 
2852         // Cannot handle drawing preedited text yet 
2853         gtk_im_context_set_use_preedit( (GtkIMContext
*) m_imContext
, FALSE 
); 
2855         g_signal_connect (G_OBJECT (m_imContext
), "commit", 
2856             G_CALLBACK (gtk_wxwindow_commit_cb
), this); 
2860         // these are called when the "sunken" or "raised" borders are drawn 
2861         gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event", 
2862           GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this ); 
2865         gtk_signal_connect( GTK_OBJECT(m_widget
), "draw", 
2866           GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this ); 
2872     if (m_focusWidget 
== NULL
) 
2873         m_focusWidget 
= m_widget
; 
2875     gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event", 
2876         GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this ); 
2878     gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event", 
2879          GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this ); 
2881     // connect to the various key and mouse handlers 
2883     GtkWidget 
*connect_widget 
= GetConnectWidget(); 
2885     ConnectWidget( connect_widget 
); 
2887     /* We cannot set colours, fonts and cursors before the widget has 
2888        been realized, so we do this directly after realization */ 
2889     gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize", 
2890                             GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this ); 
2894         // Catch native resize events 
2895         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate", 
2896                             GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this ); 
2898         // Initialize XIM support 
2899         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize", 
2900                             GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this ); 
2902         // And resize XIM window 
2903         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate", 
2904                             GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this ); 
2907     if (!GTK_IS_COMBO(m_widget
)) 
2909         // This is needed if we want to add our windows into native 
2910         // GTK control, such as the toolbar. With this callback, the 
2911         // toolbar gets to know the correct size (the one set by the 
2912         // programmer). Sadly, it misbehaves for wxComboBox. FIXME 
2913         // when moving to GTK 2.0. 
2914         gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request", 
2915                             GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this ); 
2921 void wxWindowGTK::ConnectWidget( GtkWidget 
*widget 
) 
2923     gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event", 
2924       GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this ); 
2926     gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event", 
2927       GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this ); 
2929     gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event", 
2930       GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this ); 
2932     gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event", 
2933       GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this ); 
2935     gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event", 
2936       GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this ); 
2938     gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event", 
2939       GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this ); 
2941     gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event", 
2942       GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this ); 
2944     // This keeps crashing on me. RR. 
2946     // gtk_signal_connect( GTK_OBJECT(widget), "destroy", 
2947     //  GTK_SIGNAL_FUNC(gtk_window_destroy_callback), (gpointer)this ); 
2950 bool wxWindowGTK::Destroy() 
2952     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2956     return wxWindowBase::Destroy(); 
2959 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
) 
2961     gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height 
); 
2964 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
2966     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2967     wxASSERT_MSG( (m_parent 
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") ); 
2970     printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height ); 
2973     if (m_resizing
) return; /* I don't like recursions */ 
2976     int currentX
, currentY
; 
2977     GetPosition(¤tX
, ¤tY
); 
2982     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
2984     if (m_parent
->m_wxwindow 
== NULL
) /* i.e. wxNotebook */ 
2986         /* don't set the size for children of wxNotebook, just take the values. */ 
2994         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
2995         if ((sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) == 0) 
2997             if (x 
!= -1) m_x 
= x 
+ pizza
->xoffset
; 
2998             if (y 
!= -1) m_y 
= y 
+ pizza
->yoffset
; 
3002             m_x 
= x 
+ pizza
->xoffset
; 
3003             m_y 
= y 
+ pizza
->yoffset
; 
3005         if (width 
!= -1) m_width 
= width
; 
3006         if (height 
!= -1) m_height 
= height
; 
3008         if ((sizeFlags 
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
) 
3010              if (width 
== -1) m_width 
= 80; 
3013         if ((sizeFlags 
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
) 
3015              if (height 
== -1) m_height 
= 26; 
3018         int minWidth 
= GetMinWidth(), 
3019             minHeight 
= GetMinHeight(), 
3020             maxWidth 
= GetMaxWidth(), 
3021             maxHeight 
= GetMaxHeight(); 
3023         if ((minWidth 
!= -1) && (m_width 
< minWidth
)) m_width 
= minWidth
; 
3024         if ((minHeight 
!= -1) && (m_height 
< minHeight
)) m_height 
= minHeight
; 
3025         if ((maxWidth 
!= -1) && (m_width 
> maxWidth
)) m_width 
= maxWidth
; 
3026         if ((maxHeight 
!= -1) && (m_height 
> maxHeight
)) m_height 
= maxHeight
; 
3029         int bottom_border 
= 0; 
3032         if (GTK_WIDGET_CAN_DEFAULT(m_widget
)) 
3034             /* the default button has a border around it */ 
3040         DoMoveWindow( m_x
-border
, 
3043                       m_height
+border
+bottom_border 
); 
3048         /* Sometimes the client area changes size without the 
3049            whole windows's size changing, but if the whole 
3050            windows's size doesn't change, no wxSizeEvent will 
3051            normally be sent. Here we add an extra test if 
3052            the client test has been changed and this will 
3054         GetClientSize( &m_oldClientWidth
, &m_oldClientHeight 
); 
3058     wxPrintf( "OnSize sent from " ); 
3059     if (GetClassInfo() && GetClassInfo()->GetClassName()) 
3060         wxPrintf( GetClassInfo()->GetClassName() ); 
3061     wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height ); 
3064     if (!m_nativeSizeEvent
) 
3066         wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
3067         event
.SetEventObject( this ); 
3068         GetEventHandler()->ProcessEvent( event 
); 
3074 void wxWindowGTK::OnInternalIdle() 
3076     // Update invalidated regions. 
3079     // Synthetize activate events. 
3080     if ( g_sendActivateEvent 
!= -1 ) 
3082         bool activate 
= g_sendActivateEvent 
!= 0; 
3085         g_sendActivateEvent 
= -1; 
3087         wxTheApp
->SetActive(activate
, (wxWindow 
*)g_focusWindowLast
); 
3090     if ( g_activeFrameLostFocus 
) 
3092         if ( g_activeFrame 
) 
3094             wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
); 
3095             wxActivateEvent 
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId()); 
3096             event
.SetEventObject(g_activeFrame
); 
3097             g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
3098             g_activeFrame 
= NULL
; 
3100         g_activeFrameLostFocus 
= FALSE
; 
3103     wxCursor cursor 
= m_cursor
; 
3104     if (g_globalCursor
.Ok()) cursor 
= g_globalCursor
; 
3108         /* I now set the cursor anew in every OnInternalIdle call 
3109            as setting the cursor in a parent window also effects the 
3110            windows above so that checking for the current cursor is 
3115             GdkWindow 
*window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3117                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3119             if (!g_globalCursor
.Ok()) 
3120                 cursor 
= *wxSTANDARD_CURSOR
; 
3122             window 
= m_widget
->window
; 
3123             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
3124                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3130             GdkWindow 
*window 
= m_widget
->window
; 
3131             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
3132                gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3140 void wxWindowGTK::DoGetSize( int *width
, int *height 
) const 
3142     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3144     if (width
) (*width
) = m_width
; 
3145     if (height
) (*height
) = m_height
; 
3148 void wxWindowGTK::DoSetClientSize( int width
, int height 
) 
3150     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3154         SetSize( width
, height 
); 
3161 #ifndef __WXUNIVERSAL__ 
3162         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
3164             /* when using GTK 1.2 we set the shadow border size to 2 */ 
3168         if (HasFlag(wxSIMPLE_BORDER
)) 
3170             /* when using GTK 1.2 we set the simple border size to 1 */ 
3174 #endif // __WXUNIVERSAL__ 
3178             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
3180             GtkRequisition vscroll_req
; 
3181             vscroll_req
.width 
= 2; 
3182             vscroll_req
.height 
= 2; 
3183             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
3184                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
3186             GtkRequisition hscroll_req
; 
3187             hscroll_req
.width 
= 2; 
3188             hscroll_req
.height 
= 2; 
3189             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
3190                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
3192             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
3194             if (scroll_window
->vscrollbar_visible
) 
3196                 dw 
+= vscroll_req
.width
; 
3197                 dw 
+= scroll_class
->scrollbar_spacing
; 
3200             if (scroll_window
->hscrollbar_visible
) 
3202                 dh 
+= hscroll_req
.height
; 
3203                 dh 
+= scroll_class
->scrollbar_spacing
; 
3207        SetSize( width
+dw
, height
+dh 
); 
3211 void wxWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
3213     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3217         if (width
) (*width
) = m_width
; 
3218         if (height
) (*height
) = m_height
; 
3225 #ifndef __WXUNIVERSAL__ 
3226         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
3228             /* when using GTK 1.2 we set the shadow border size to 2 */ 
3232         if (HasFlag(wxSIMPLE_BORDER
)) 
3234             /* when using GTK 1.2 we set the simple border size to 1 */ 
3238 #endif // __WXUNIVERSAL__ 
3242             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
3244             GtkRequisition vscroll_req
; 
3245             vscroll_req
.width 
= 2; 
3246             vscroll_req
.height 
= 2; 
3247             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
3248                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
3250             GtkRequisition hscroll_req
; 
3251             hscroll_req
.width 
= 2; 
3252             hscroll_req
.height 
= 2; 
3253             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
3254                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
3256             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
3258             if (scroll_window
->vscrollbar_visible
) 
3260                 dw 
+= vscroll_req
.width
; 
3261                 dw 
+= scroll_class
->scrollbar_spacing
; 
3264             if (scroll_window
->hscrollbar_visible
) 
3266                 dh 
+= hscroll_req
.height
; 
3267                 dh 
+= scroll_class
->scrollbar_spacing
; 
3271         if (width
) (*width
) = m_width 
- dw
; 
3272         if (height
) (*height
) = m_height 
- dh
; 
3276     printf( "GetClientSize, name %s ", GetName().c_str() ); 
3277     if (width) printf( " width = %d", (*width) ); 
3278     if (height) printf( " height = %d", (*height) ); 
3283 void wxWindowGTK::DoGetPosition( int *x
, int *y 
) const 
3285     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3289     if (m_parent 
&& m_parent
->m_wxwindow
) 
3291         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
3292         dx 
= pizza
->xoffset
; 
3293         dy 
= pizza
->yoffset
; 
3296     if (x
) (*x
) = m_x 
- dx
; 
3297     if (y
) (*y
) = m_y 
- dy
; 
3300 void wxWindowGTK::DoClientToScreen( int *x
, int *y 
) const 
3302     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3304     if (!m_widget
->window
) return; 
3306     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3308         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3310         source 
= m_widget
->window
; 
3314     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3318         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3320             org_x 
+= m_widget
->allocation
.x
; 
3321             org_y 
+= m_widget
->allocation
.y
; 
3329 void wxWindowGTK::DoScreenToClient( int *x
, int *y 
) const 
3331     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3333     if (!m_widget
->window
) return; 
3335     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3337         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3339         source 
= m_widget
->window
; 
3343     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3347         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3349             org_x 
+= m_widget
->allocation
.x
; 
3350             org_y 
+= m_widget
->allocation
.y
; 
3358 bool wxWindowGTK::Show( bool show 
) 
3360     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3362     if (!wxWindowBase::Show(show
)) 
3369         gtk_widget_show( m_widget 
); 
3371         gtk_widget_hide( m_widget 
); 
3373     wxShowEvent 
eventShow(GetId(), show
); 
3374     eventShow
.m_eventObject 
= this; 
3376     GetEventHandler()->ProcessEvent(eventShow
); 
3381 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
) 
3383     win
->OnParentEnable(enable
); 
3385     // Recurse, so that children have the opportunity to Do The Right Thing 
3386     // and reset colours that have been messed up by a parent's (really ancestor's) 
3388     for ( wxWindowList::Node 
*node 
= win
->GetChildren().GetFirst(); 
3390           node 
= node
->GetNext() ) 
3392         wxWindow 
*child 
= node
->GetData(); 
3393         if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
))) 
3394             wxWindowNotifyEnable(child
, enable
); 
3398 bool wxWindowGTK::Enable( bool enable 
) 
3400     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3402     if (!wxWindowBase::Enable(enable
)) 
3408     gtk_widget_set_sensitive( m_widget
, enable 
); 
3410         gtk_widget_set_sensitive( m_wxwindow
, enable 
); 
3412     wxWindowNotifyEnable(this, enable
); 
3417 int wxWindowGTK::GetCharHeight() const 
3419     wxCHECK_MSG( (m_widget 
!= NULL
), 12, wxT("invalid window") ); 
3421     wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") ); 
3424     PangoContext 
*context 
= NULL
; 
3426         context 
= gtk_widget_get_pango_context( m_widget 
); 
3431     PangoFontDescription 
*desc 
= m_font
.GetNativeFontInfo()->description
; 
3432     PangoLayout 
*layout 
= pango_layout_new(context
); 
3433     pango_layout_set_font_description(layout
, desc
); 
3434     pango_layout_set_text(layout
, "H", 1); 
3435     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
3437     PangoRectangle rect
; 
3438     pango_layout_line_get_extents(line
, NULL
, &rect
); 
3440     g_object_unref( G_OBJECT( layout 
) ); 
3442     return (int) (rect
.height 
/ PANGO_SCALE
); 
3444     GdkFont 
*font 
= m_font
.GetInternalFont( 1.0 ); 
3446     return font
->ascent 
+ font
->descent
; 
3450 int wxWindowGTK::GetCharWidth() const 
3452     wxCHECK_MSG( (m_widget 
!= NULL
), 8, wxT("invalid window") ); 
3454     wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") ); 
3457     PangoContext 
*context 
= NULL
; 
3459         context 
= gtk_widget_get_pango_context( m_widget 
); 
3464     PangoFontDescription 
*desc 
= m_font
.GetNativeFontInfo()->description
; 
3465     PangoLayout 
*layout 
= pango_layout_new(context
); 
3466     pango_layout_set_font_description(layout
, desc
); 
3467     pango_layout_set_text(layout
, "H", 1); 
3468     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
3470     PangoRectangle rect
; 
3471     pango_layout_line_get_extents(line
, NULL
, &rect
); 
3473     g_object_unref( G_OBJECT( layout 
) ); 
3475     return (int) (rect
.width 
/ PANGO_SCALE
); 
3477     GdkFont 
*font 
= m_font
.GetInternalFont( 1.0 ); 
3479     return gdk_string_width( font
, "H" ); 
3483 void wxWindowGTK::GetTextExtent( const wxString
& string
, 
3487                               int *externalLeading
, 
3488                               const wxFont 
*theFont 
) const 
3490     wxFont fontToUse 
= m_font
; 
3491     if (theFont
) fontToUse 
= *theFont
; 
3493     wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") ); 
3495     if (string
.IsEmpty()) 
3503     PangoContext 
*context 
= NULL
; 
3505         context 
= gtk_widget_get_pango_context( m_widget 
); 
3514     PangoFontDescription 
*desc 
= fontToUse
.GetNativeFontInfo()->description
; 
3515     PangoLayout 
*layout 
= pango_layout_new(context
); 
3516     pango_layout_set_font_description(layout
, desc
); 
3519         const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( string 
); 
3520         pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data 
)); 
3522         const wxWCharBuffer wdata 
= wxConvLocal
.cMB2WC( string 
); 
3523         const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( wdata 
); 
3524         pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data 
)); 
3527     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
3529     PangoRectangle rect
; 
3530     pango_layout_line_get_extents(line
, NULL
, &rect
); 
3532     if (x
) (*x
) = (wxCoord
) (rect
.width 
/ PANGO_SCALE
); 
3533     if (y
) (*y
) = (wxCoord
) (rect
.height 
/ PANGO_SCALE
); 
3536         // Do something about metrics here 
3539     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3541     g_object_unref( G_OBJECT( layout 
) ); 
3543     GdkFont 
*font 
= fontToUse
.GetInternalFont( 1.0 ); 
3544     if (x
) (*x
) = gdk_string_width( font
, wxGTK_CONV( string 
) ); 
3545     if (y
) (*y
) = font
->ascent 
+ font
->descent
; 
3546     if (descent
) (*descent
) = font
->descent
; 
3547     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3551 void wxWindowGTK::SetFocus() 
3553     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3557         // don't do anything if we already have focus 
3563         if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
)) 
3565             gtk_widget_grab_focus (m_wxwindow
); 
3570         if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) ) 
3572             if (!GTK_WIDGET_REALIZED(m_widget
)) 
3574                 // we can't set the focus to the widget now so we remember that 
3575                 // it should be focused and will do it later, during the idle 
3576                 // time, as soon as we can 
3577                 wxLogTrace(TRACE_FOCUS
, 
3578                            _T("Delaying setting focus to %s(%s)"), 
3579                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3581                 g_delayedFocus 
= this; 
3585                 wxLogTrace(TRACE_FOCUS
, 
3586                            _T("Setting focus to %s(%s)"), 
3587                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3589                 gtk_widget_grab_focus (m_widget
); 
3592         else if (GTK_IS_CONTAINER(m_widget
)) 
3594             SET_CONTAINER_FOCUS( m_widget
, GTK_DIR_TAB_FORWARD 
); 
3598            wxLogTrace(TRACE_FOCUS
, 
3599                       _T("Can't set focus to %s(%s)"), 
3600                       GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3605 bool wxWindowGTK::AcceptsFocus() const 
3607     return m_acceptsFocus 
&& wxWindowBase::AcceptsFocus(); 
3610 bool wxWindowGTK::Reparent( wxWindowBase 
*newParentBase 
) 
3612     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3614     wxWindowGTK 
*oldParent 
= m_parent
, 
3615              *newParent 
= (wxWindowGTK 
*)newParentBase
; 
3617     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3619     if ( !wxWindowBase::Reparent(newParent
) ) 
3622     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3624     /* prevent GTK from deleting the widget arbitrarily */ 
3625     gtk_widget_ref( m_widget 
); 
3629         gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget 
); 
3632     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3636         /* insert GTK representation */ 
3637         (*(newParent
->m_insertCallback
))(newParent
, this); 
3640     /* reverse: prevent GTK from deleting the widget arbitrarily */ 
3641     gtk_widget_unref( m_widget 
); 
3646 void wxWindowGTK::DoAddChild(wxWindowGTK 
*child
) 
3648     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3650     wxASSERT_MSG( (child 
!= NULL
), wxT("invalid child window") ); 
3652     wxASSERT_MSG( (m_insertCallback 
!= NULL
), wxT("invalid child insertion function") ); 
3657     /* insert GTK representation */ 
3658     (*m_insertCallback
)(this, child
); 
3661 void wxWindowGTK::Raise() 
3663     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3665     if (!m_widget
->window
) return; 
3667     gdk_window_raise( m_widget
->window 
); 
3670 void wxWindowGTK::Lower() 
3672     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3674     if (!m_widget
->window
) return; 
3676     gdk_window_lower( m_widget
->window 
); 
3679 bool wxWindowGTK::SetCursor( const wxCursor 
&cursor 
) 
3681     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3683     if (cursor 
== m_cursor
) 
3687         wxapp_install_idle_handler(); 
3689     if (cursor 
== wxNullCursor
) 
3690        return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR 
); 
3692        return wxWindowBase::SetCursor( cursor 
); 
3695 void wxWindowGTK::WarpPointer( int x
, int y 
) 
3697     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3699     // We provide this function ourselves as it is 
3700     // missing in GDK (top of this file). 
3702     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3704         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3706         window 
= GetConnectWidget()->window
; 
3709         gdk_window_warp_pointer( window
, x
, y 
); 
3713 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect 
*rect 
) 
3715     if (!m_widget
) return; 
3716     if (!m_widget
->window
) return; 
3720         wxapp_install_idle_handler(); 
3722     if (eraseBackground 
&& m_wxwindow 
&& m_wxwindow
->window
) 
3726             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3727             m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3731             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3732             m_clearRegion
.Clear(); 
3733             m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3741             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3742             m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3746             GdkRectangle gdk_rect
; 
3747             gdk_rect
.x 
= rect
->x
; 
3748             gdk_rect
.y 
= rect
->y
; 
3749             gdk_rect
.width 
= rect
->width
; 
3750             gdk_rect
.height 
= rect
->height
; 
3751             gtk_widget_draw( m_widget
, &gdk_rect 
); 
3758             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3759             m_updateRegion
.Clear(); 
3760             m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3764             gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL 
); 
3772             GdkRectangle gdk_rect
; 
3773             gdk_rect
.x 
= rect
->x
; 
3774             gdk_rect
.y 
= rect
->y
; 
3775             gdk_rect
.width 
= rect
->width
; 
3776             gdk_rect
.height 
= rect
->height
; 
3777             gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, &gdk_rect
, TRUE 
); 
3781             gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, NULL
, TRUE 
); 
3787 void wxWindowGTK::Update() 
3792 void wxWindowGTK::GtkUpdate() 
3795     if (m_wxwindow 
&& GTK_PIZZA(m_wxwindow
)->bin_window
) 
3796         gdk_window_process_updates( GTK_PIZZA(m_wxwindow
)->bin_window
, FALSE 
); 
3798     if (!m_updateRegion
.IsEmpty()) 
3799         GtkSendPaintEvents(); 
3803 void wxWindowGTK::GtkSendPaintEvents() 
3808         m_clearRegion
.Clear(); 
3810         m_updateRegion
.Clear(); 
3814     // Clip to paint region in wxClientDC 
3815     m_clipPaintRegion 
= TRUE
; 
3818     // widget to draw on 
3819     GtkPizza 
*pizza 
= GTK_PIZZA (m_wxwindow
); 
3821     // later for GTK 2.0, too. 
3822     if (GetThemeEnabled()) 
3824         // find ancestor from which to steal background 
3825         wxWindow 
*parent 
= GetParent(); 
3826         while (parent 
&& !parent
->IsTopLevel()) 
3827             parent 
= parent
->GetParent(); 
3829             parent 
= (wxWindow
*)this; 
3831         wxRegionIterator 
upd( m_updateRegion 
); 
3835             rect
.x 
= upd
.GetX(); 
3836             rect
.y 
= upd
.GetY(); 
3837             rect
.width 
= upd
.GetWidth(); 
3838             rect
.height 
= upd
.GetHeight(); 
3840             gtk_paint_flat_box( parent
->m_widget
->style
, 
3857         wxWindowDC 
dc( (wxWindow
*)this ); 
3858         dc
.SetClippingRegion( m_updateRegion 
); 
3860         wxEraseEvent 
erase_event( GetId(), &dc 
); 
3861         erase_event
.SetEventObject( this ); 
3863         GetEventHandler()->ProcessEvent(erase_event
); 
3866     // if (!m_clearRegion.IsEmpty())   // Always send an erase event under GTK 1.2 
3868         wxWindowDC 
dc( (wxWindow
*)this ); 
3869         if (m_clearRegion
.IsEmpty()) 
3870             dc
.SetClippingRegion( m_updateRegion 
); 
3872             dc
.SetClippingRegion( m_clearRegion 
); 
3874         wxEraseEvent 
erase_event( GetId(), &dc 
); 
3875         erase_event
.SetEventObject( this ); 
3877         if (!GetEventHandler()->ProcessEvent(erase_event
)) 
3881                 g_eraseGC 
= gdk_gc_new( pizza
->bin_window 
); 
3882                 gdk_gc_set_fill( g_eraseGC
, GDK_SOLID 
); 
3884             gdk_gc_set_foreground( g_eraseGC
, m_backgroundColour
.GetColor() ); 
3886             wxRegionIterator 
upd( m_clearRegion 
); 
3889                 gdk_draw_rectangle( pizza
->bin_window
, g_eraseGC
, 1, 
3890                                     upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() ); 
3894         m_clearRegion
.Clear(); 
3898     wxNcPaintEvent 
nc_paint_event( GetId() ); 
3899     nc_paint_event
.SetEventObject( this ); 
3900     GetEventHandler()->ProcessEvent( nc_paint_event 
); 
3902     wxPaintEvent 
paint_event( GetId() ); 
3903     paint_event
.SetEventObject( this ); 
3904     GetEventHandler()->ProcessEvent( paint_event 
); 
3906     m_clipPaintRegion 
= FALSE
; 
3908 #ifndef __WXUNIVERSAL__ 
3910     // The following code will result in all window-less widgets 
3911     // being redrawn because the wxWindows class is allowed to 
3912     // paint over the window-less widgets. 
3914     GList 
*children 
= pizza
->children
; 
3917         GtkPizzaChild 
*child 
= (GtkPizzaChild
*) children
->data
; 
3918         children 
= children
->next
; 
3920         if (GTK_WIDGET_NO_WINDOW (child
->widget
) && 
3921             GTK_WIDGET_DRAWABLE (child
->widget
)) 
3923             // Get intersection of widget area and update region 
3924             wxRegion 
region( m_updateRegion 
); 
3926             GdkEventExpose gdk_event
; 
3927             gdk_event
.type 
= GDK_EXPOSE
; 
3928             gdk_event
.window 
= pizza
->bin_window
; 
3929             gdk_event
.count 
= 0; 
3931             wxRegionIterator 
upd( m_updateRegion 
); 
3935                 rect
.x 
= upd
.GetX(); 
3936                 rect
.y 
= upd
.GetY(); 
3937                 rect
.width 
= upd
.GetWidth(); 
3938                 rect
.height 
= upd
.GetHeight(); 
3940                 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
)) 
3942                     gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
); 
3952     m_updateRegion
.Clear(); 
3955 void wxWindowGTK::Clear() 
3957     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3960     if (m_wxwindow 
&& m_wxwindow
->window
) 
3962         m_clearRegion
.Clear(); 
3963         wxSize 
size( GetClientSize() ); 
3964         m_clearRegion
.Union( 0,0,size
.x
,size
.y 
); 
3966         // Better do this in idle? 
3973 void wxWindowGTK::DoSetToolTip( wxToolTip 
*tip 
) 
3975     wxWindowBase::DoSetToolTip(tip
); 
3978         m_tooltip
->Apply( (wxWindow 
*)this ); 
3981 void wxWindowGTK::ApplyToolTip( GtkTooltips 
*tips
, const wxChar 
*tip 
) 
3983     gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL 
); 
3985 #endif // wxUSE_TOOLTIPS 
3987 void wxWindowGTK::GtkSetBackgroundColour( const wxColour 
&colour 
) 
3989     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3991         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3993         window 
= GetConnectWidget()->window
; 
3997     // We need the pixel value e.g. for background clearing. 
3998     m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window 
) ); 
4002         // wxMSW doesn't clear the window here, either. 
4003         gdk_window_set_background( window
, m_backgroundColour
.GetColor() ); 
4009 bool wxWindowGTK::SetBackgroundColour( const wxColour 
&colour 
) 
4011     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
4013     if (!wxWindowBase::SetBackgroundColour(colour
)) 
4016     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4018         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4020         window 
= GetConnectWidget()->window
; 
4024         // indicate that a new style has been set 
4025         // but it couldn't get applied as the 
4026         // widget hasn't been realized yet. 
4027         m_delayedBackgroundColour 
= TRUE
; 
4032         GtkSetBackgroundColour( colour 
); 
4038 void wxWindowGTK::GtkSetForegroundColour( const wxColour 
&colour 
) 
4040     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4042         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4044         window 
= GetConnectWidget()->window
; 
4051 bool wxWindowGTK::SetForegroundColour( const wxColour 
&colour 
) 
4053     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
4055     if (!wxWindowBase::SetForegroundColour(colour
)) 
4057         // don't leave if the GTK widget has just 
4059         if (!m_delayedForegroundColour
) return FALSE
; 
4062     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4064         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4066         window 
= GetConnectWidget()->window
; 
4070         // indicate that a new style has been set 
4071         // but it couldn't get applied as the 
4072         // widget hasn't been realized yet. 
4073         m_delayedForegroundColour 
= TRUE
; 
4077        GtkSetForegroundColour( colour 
); 
4084 PangoContext 
*wxWindowGTK::GtkGetPangoDefaultContext() 
4086     return gtk_widget_get_pango_context( m_widget 
); 
4089 PangoContext 
*wxWindowGTK::GtkGetPangoX11Context() 
4092         m_x11Context 
= pango_x_get_context( gdk_display 
); 
4094     return m_x11Context
; 
4098 GtkStyle 
*wxWindowGTK::GetWidgetStyle() 
4102         GtkStyle 
*remake 
= gtk_style_copy( m_widgetStyle 
); 
4104         // FIXME: no more klass in 2.0 
4106         remake
->klass 
= m_widgetStyle
->klass
; 
4109         gtk_style_unref( m_widgetStyle 
); 
4110         m_widgetStyle 
= remake
; 
4114         GtkStyle 
*def 
= gtk_rc_get_style( m_widget 
); 
4117             def 
= gtk_widget_get_default_style(); 
4119         m_widgetStyle 
= gtk_style_copy( def 
); 
4121         // FIXME: no more klass in 2.0 
4123         m_widgetStyle
->klass 
= def
->klass
; 
4127     return m_widgetStyle
; 
4130 void wxWindowGTK::SetWidgetStyle() 
4132 #if DISABLE_STYLE_IF_BROKEN_THEME 
4133     if (m_widget
->style
->engine_data
) 
4135         static bool s_warningPrinted 
= FALSE
; 
4136         if (!s_warningPrinted
) 
4138             printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" ); 
4139             s_warningPrinted 
= TRUE
; 
4141         m_widgetStyle 
= m_widget
->style
; 
4146     GtkStyle 
*style 
= GetWidgetStyle(); 
4148     if (m_font 
!= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT 
)) 
4150         SET_STYLE_FONT(style
, m_font
.GetInternalFont( 1.0 )); 
4153     if (m_foregroundColour
.Ok()) 
4155         m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget 
) ); 
4156         if (m_foregroundColour 
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT
)) 
4158             style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor(); 
4159             style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor(); 
4160             style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor(); 
4164             // Try to restore the gtk default style.  This is still a little 
4165             // oversimplified for what is probably really needed here for controls 
4166             // other than buttons, but is better than not being able to (re)set a 
4167             // control's foreground colour to *wxBLACK -- RL 
4168             GtkStyle 
*def 
= gtk_rc_get_style( m_widget 
); 
4171                 def 
= gtk_widget_get_default_style(); 
4173             style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
]; 
4174             style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
]; 
4175             style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
]; 
4179     if (m_backgroundColour
.Ok()) 
4181         m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget 
) ); 
4182         if (m_backgroundColour 
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
)) 
4184             style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor(); 
4185             style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor(); 
4186             style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor(); 
4187             style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor(); 
4188             style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor(); 
4189             style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor(); 
4190             style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor(); 
4191             style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor(); 
4195             // Try to restore the gtk default style.  This is still a little 
4196             // oversimplified for what is probably really needed here for controls 
4197             // other than buttons, but is better than not being able to (re)set a 
4198             // control's background colour to default grey and means resetting a 
4199             // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting 
4201             GtkStyle 
*def 
= gtk_rc_get_style( m_widget 
); 
4204                 def 
= gtk_widget_get_default_style(); 
4206             style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
]; 
4207             style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
]; 
4208             style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
]; 
4209             style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
]; 
4210             style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
]; 
4211             style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
]; 
4212             style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
]; 
4213             style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
]; 
4218 void wxWindowGTK::ApplyWidgetStyle() 
4222 //----------------------------------------------------------------------------- 
4223 // Pop-up menu stuff 
4224 //----------------------------------------------------------------------------- 
4226 #if wxUSE_MENUS_NATIVE 
4229 void gtk_pop_hide_callback( GtkWidget 
*WXUNUSED(widget
), bool* is_waiting  
) 
4231     *is_waiting 
= FALSE
; 
4234 static void SetInvokingWindow( wxMenu 
*menu
, wxWindowGTK 
*win 
) 
4236     menu
->SetInvokingWindow( win 
); 
4237     wxMenuItemList::Node 
*node 
= menu
->GetMenuItems().GetFirst(); 
4240         wxMenuItem 
*menuitem 
= node
->GetData(); 
4241         if (menuitem
->IsSubMenu()) 
4243             SetInvokingWindow( menuitem
->GetSubMenu(), win 
); 
4246         node 
= node
->GetNext(); 
4250 // used to pass the coordinates from wxWindowGTK::DoPopupMenu() to 
4251 // wxPopupMenuPositionCallback() 
4253 // should be safe even in the MT case as the user can hardly popup 2 menus 
4254 // simultaneously, can he? 
4255 static gint gs_pop_x 
= 0; 
4256 static gint gs_pop_y 
= 0; 
4258 extern "C" void wxPopupMenuPositionCallback( GtkMenu 
*menu
, 
4261                                              gboolean 
* WXUNUSED(whatever
), 
4263                                              gpointer 
WXUNUSED(user_data
) ) 
4265     // ensure that the menu appears entirely on screen 
4267     gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
); 
4269     wxSize sizeScreen 
= wxGetDisplaySize(); 
4271     gint xmax 
= sizeScreen
.x 
- req
.width
, 
4272          ymax 
= sizeScreen
.y 
- req
.height
; 
4274     *x 
= gs_pop_x 
< xmax 
? gs_pop_x 
: xmax
; 
4275     *y 
= gs_pop_y 
< ymax 
? gs_pop_y 
: ymax
; 
4278 bool wxWindowGTK::DoPopupMenu( wxMenu 
*menu
, int x
, int y 
) 
4280     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
4282     wxCHECK_MSG( menu 
!= NULL
, FALSE
, wxT("invalid popup-menu") ); 
4284     SetInvokingWindow( menu
, this ); 
4290     ClientToScreen( &gs_pop_x
, &gs_pop_y 
); 
4292     bool is_waiting 
= TRUE
; 
4294     gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), 
4296                         GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), 
4297                         (gpointer
)&is_waiting 
); 
4300                   GTK_MENU(menu
->m_menu
), 
4301                   (GtkWidget 
*) NULL
,           // parent menu shell 
4302                   (GtkWidget 
*) NULL
,           // parent menu item 
4303                   wxPopupMenuPositionCallback
,  // function to position it 
4304                   NULL
,                         // client data 
4305                   0,                            // button used to activate it 
4306                   gs_timeLastClick              
// the time of activation 
4311         while (gtk_events_pending()) 
4312             gtk_main_iteration(); 
4318 #endif // wxUSE_MENUS_NATIVE 
4320 #if wxUSE_DRAG_AND_DROP 
4322 void wxWindowGTK::SetDropTarget( wxDropTarget 
*dropTarget 
) 
4324     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4326     GtkWidget 
*dnd_widget 
= GetConnectWidget(); 
4328     if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget 
); 
4330     if (m_dropTarget
) delete m_dropTarget
; 
4331     m_dropTarget 
= dropTarget
; 
4333     if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget 
); 
4336 #endif // wxUSE_DRAG_AND_DROP 
4338 GtkWidget
* wxWindowGTK::GetConnectWidget() 
4340     GtkWidget 
*connect_widget 
= m_widget
; 
4341     if (m_wxwindow
) connect_widget 
= m_wxwindow
; 
4343     return connect_widget
; 
4346 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow 
*window 
) 
4349         return (window 
== GTK_PIZZA(m_wxwindow
)->bin_window
); 
4351     return (window 
== m_widget
->window
); 
4354 bool wxWindowGTK::SetFont( const wxFont 
&font 
) 
4356     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
4358     if (!wxWindowBase::SetFont(font
)) 
4363     wxColour sysbg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE 
); 
4364     if ( sysbg 
== m_backgroundColour 
) 
4366         m_backgroundColour 
= wxNullColour
; 
4368         m_backgroundColour 
= sysbg
; 
4378 void wxWindowGTK::DoCaptureMouse() 
4380     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4382     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4384         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4386         window 
= GetConnectWidget()->window
; 
4388     wxCHECK_RET( window
, _T("CaptureMouse() failed") ); 
4390     wxCursor
* cursor 
= & m_cursor
; 
4392         cursor 
= wxSTANDARD_CURSOR
; 
4394     gdk_pointer_grab( window
, FALSE
, 
4396                          (GDK_BUTTON_PRESS_MASK 
| 
4397                           GDK_BUTTON_RELEASE_MASK 
| 
4398                           GDK_POINTER_MOTION_HINT_MASK 
| 
4399                           GDK_POINTER_MOTION_MASK
), 
4401                       cursor
->GetCursor(), 
4402                       (guint32
)GDK_CURRENT_TIME 
); 
4403     g_captureWindow 
= this; 
4404     g_captureWindowHasMouse 
= TRUE
; 
4407 void wxWindowGTK::DoReleaseMouse() 
4409     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4411     wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") ); 
4413     g_captureWindow 
= (wxWindowGTK
*) NULL
; 
4415     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4417         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4419         window 
= GetConnectWidget()->window
; 
4424     gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME 
); 
4428 wxWindow 
*wxWindowBase::GetCapture() 
4430     return (wxWindow 
*)g_captureWindow
; 
4433 bool wxWindowGTK::IsRetained() const 
4438 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
, 
4439       int range
, bool refresh 
) 
4441     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4443     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4445     m_hasScrolling 
= TRUE
; 
4447     if (orient 
== wxHORIZONTAL
) 
4449         float fpos 
= (float)pos
; 
4450         float frange 
= (float)range
; 
4451         float fthumb 
= (float)thumbVisible
; 
4452         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4453         if (fpos 
< 0.0) fpos 
= 0.0; 
4455         if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) && 
4456             (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2)) 
4458             SetScrollPos( orient
, pos
, refresh 
); 
4462         m_oldHorizontalPos 
= fpos
; 
4464         m_hAdjust
->lower 
= 0.0; 
4465         m_hAdjust
->upper 
= frange
; 
4466         m_hAdjust
->value 
= fpos
; 
4467         m_hAdjust
->step_increment 
= 1.0; 
4468         m_hAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4469         m_hAdjust
->page_size 
= fthumb
; 
4473         float fpos 
= (float)pos
; 
4474         float frange 
= (float)range
; 
4475         float fthumb 
= (float)thumbVisible
; 
4476         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4477         if (fpos 
< 0.0) fpos 
= 0.0; 
4479         if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) && 
4480             (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2)) 
4482             SetScrollPos( orient
, pos
, refresh 
); 
4486         m_oldVerticalPos 
= fpos
; 
4488         m_vAdjust
->lower 
= 0.0; 
4489         m_vAdjust
->upper 
= frange
; 
4490         m_vAdjust
->value 
= fpos
; 
4491         m_vAdjust
->step_increment 
= 1.0; 
4492         m_vAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4493         m_vAdjust
->page_size 
= fthumb
; 
4496     if (orient 
== wxHORIZONTAL
) 
4497         gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
4499         gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
4502 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) ) 
4504     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4506     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4508     if (orient 
== wxHORIZONTAL
) 
4510         float fpos 
= (float)pos
; 
4511         if (fpos 
> m_hAdjust
->upper 
- m_hAdjust
->page_size
) fpos 
= m_hAdjust
->upper 
- m_hAdjust
->page_size
; 
4512         if (fpos 
< 0.0) fpos 
= 0.0; 
4513         m_oldHorizontalPos 
= fpos
; 
4515         if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return; 
4516         m_hAdjust
->value 
= fpos
; 
4520         float fpos 
= (float)pos
; 
4521         if (fpos 
> m_vAdjust
->upper 
- m_vAdjust
->page_size
) fpos 
= m_vAdjust
->upper 
- m_vAdjust
->page_size
; 
4522         if (fpos 
< 0.0) fpos 
= 0.0; 
4523         m_oldVerticalPos 
= fpos
; 
4525         if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return; 
4526         m_vAdjust
->value 
= fpos
; 
4529     if (m_wxwindow
->window
) 
4531         if (orient 
== wxHORIZONTAL
) 
4533             gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
), 
4534                 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
4536             gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" ); 
4538             gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
4539                 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
4543             gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
), 
4544                 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
4546             gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" ); 
4548             gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
4549                 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
4554 int wxWindowGTK::GetScrollThumb( int orient 
) const 
4556     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4558     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4560     if (orient 
== wxHORIZONTAL
) 
4561         return (int)(m_hAdjust
->page_size
+0.5); 
4563         return (int)(m_vAdjust
->page_size
+0.5); 
4566 int wxWindowGTK::GetScrollPos( int orient 
) const 
4568     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4570     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4572     if (orient 
== wxHORIZONTAL
) 
4573         return (int)(m_hAdjust
->value
+0.5); 
4575         return (int)(m_vAdjust
->value
+0.5); 
4578 int wxWindowGTK::GetScrollRange( int orient 
) const 
4580     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4582     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4584     if (orient 
== wxHORIZONTAL
) 
4585         return (int)(m_hAdjust
->upper
+0.5); 
4587         return (int)(m_vAdjust
->upper
+0.5); 
4590 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) ) 
4592     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4594     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4596     // No scrolling requested. 
4597     if ((dx 
== 0) && (dy 
== 0)) return; 
4600     if (!m_updateRegion
.IsEmpty()) 
4602         m_updateRegion
.Offset( dx
, dy 
); 
4606         GetClientSize( &cw
, &ch 
); 
4607         m_updateRegion
.Intersect( 0, 0, cw
, ch 
); 
4610     if (!m_clearRegion
.IsEmpty()) 
4612         m_clearRegion
.Offset( dx
, dy 
); 
4616         GetClientSize( &cw
, &ch 
); 
4617         m_clearRegion
.Intersect( 0, 0, cw
, ch 
); 
4621     m_clipPaintRegion 
= TRUE
; 
4623     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy 
); 
4625     m_clipPaintRegion 
= FALSE
; 
4629 // Find the wxWindow at the current mouse position, also returning the mouse 
4631 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
4633     pt 
= wxGetMousePosition(); 
4634     wxWindow
* found 
= wxFindWindowAtPoint(pt
); 
4638 // Get the current mouse position. 
4639 wxPoint 
wxGetMousePosition() 
4641   /* This crashes when used within wxHelpContext, 
4642      so we have to use the X-specific implementation below. 
4644     GdkModifierType *mask; 
4645     (void) gdk_window_get_pointer(NULL, &x, &y, mask); 
4647     return wxPoint(x, y); 
4651     GdkWindow
* windowAtPtr 
= gdk_window_at_pointer(& x
, & y
); 
4653     Display 
*display 
= windowAtPtr 
? GDK_WINDOW_XDISPLAY(windowAtPtr
) : GDK_DISPLAY(); 
4654     Window rootWindow 
= RootWindowOfScreen (DefaultScreenOfDisplay(display
)); 
4655     Window rootReturn
, childReturn
; 
4656     int rootX
, rootY
, winX
, winY
; 
4657     unsigned int maskReturn
; 
4659     XQueryPointer (display
, 
4663                    &rootX
, &rootY
, &winX
, &winY
, &maskReturn
); 
4664     return wxPoint(rootX
, rootY
); 
4668 // ---------------------------------------------------------------------------- 
4670 // ---------------------------------------------------------------------------- 
4672 class wxWinModule 
: public wxModule
 
4679     DECLARE_DYNAMIC_CLASS(wxWinModule
) 
4682 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
) 
4684 bool wxWinModule::OnInit() 
4686     // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() ); 
4687     // gdk_gc_set_fill( g_eraseGC, GDK_SOLID ); 
4692 void wxWinModule::OnExit() 
4695         gdk_gc_unref( g_eraseGC 
);