1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        gtk/window.cpp 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling, Julian Smart 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  11 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  12     #pragma implementation "window.h" 
  15 // For compilers that support precompilation, includes "wx.h". 
  16 #include "wx/wxprec.h" 
  19 #define XWarpPointer XWARPPOINTER 
  22 #include "wx/window.h" 
  23 #include "wx/dcclient.h" 
  26 #include "wx/layout.h" 
  28 #include "wx/dialog.h" 
  29 #include "wx/msgdlg.h" 
  30 #include "wx/module.h" 
  31 #include "wx/combobox.h" 
  33 #if wxUSE_DRAG_AND_DROP 
  38     #include "wx/tooltip.h" 
  46     #include "wx/textctrl.h" 
  50 #include "wx/statusbr.h" 
  52 #include "wx/settings.h" 
  54 #include "wx/fontutil.h" 
  57     #include "wx/thread.h" 
  63 #include "wx/gtk/private.h" 
  64 #include <gdk/gdkprivate.h> 
  65 #include <gdk/gdkkeysyms.h> 
  69 #include <gtk/gtkprivate.h> 
  71 #include "wx/gtk/win_gtk.h" 
  74 #include <pango/pangox.h> 
  85 extern GtkContainerClass 
*pizza_parent_class
; 
  88 //----------------------------------------------------------------------------- 
  89 // documentation on internals 
  90 //----------------------------------------------------------------------------- 
  93    I have been asked several times about writing some documentation about 
  94    the GTK port of wxWidgets, especially its internal structures. Obviously, 
  95    you cannot understand wxGTK without knowing a little about the GTK, but 
  96    some more information about what the wxWindow, which is the base class 
  97    for all other window classes, does seems required as well. 
 101    What does wxWindow do? It contains the common interface for the following 
 102    jobs of its descendants: 
 104    1) Define the rudimentary behaviour common to all window classes, such as 
 105    resizing, intercepting user input (so as to make it possible to use these 
 106    events for special purposes in a derived class), window names etc. 
 108    2) Provide the possibility to contain and manage children, if the derived 
 109    class is allowed to contain children, which holds true for those window 
 110    classes which do not display a native GTK widget. To name them, these 
 111    classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame- 
 112    work classes are a special case and are handled a bit differently from 
 113    the rest. The same holds true for the wxNotebook class. 
 115    3) Provide the possibility to draw into a client area of a window. This, 
 116    too, only holds true for classes that do not display a native GTK widget 
 119    4) Provide the entire mechanism for scrolling widgets. This actual inter- 
 120    face for this is usually in wxScrolledWindow, but the GTK implementation 
 123    5) A multitude of helper or extra methods for special purposes, such as 
 124    Drag'n'Drop, managing validators etc. 
 126    6) Display a border (sunken, raised, simple or none). 
 128    Normally one might expect, that one wxWidgets window would always correspond 
 129    to one GTK widget. Under GTK, there is no such allround widget that has all 
 130    the functionality. Moreover, the GTK defines a client area as a different 
 131    widget from the actual widget you are handling. Last but not least some 
 132    special classes (e.g. wxFrame) handle different categories of widgets and 
 133    still have the possibility to draw something in the client area. 
 134    It was therefore required to write a special purpose GTK widget, that would 
 135    represent a client area in the sense of wxWidgets capable to do the jobs 
 136    2), 3) and 4). I have written this class and it resides in win_gtk.c of 
 139    All windows must have a widget, with which they interact with other under- 
 140    lying GTK widgets. It is this widget, e.g. that has to be resized etc and 
 141    thw wxWindow class has a member variable called m_widget which holds a 
 142    pointer to this widget. When the window class represents a GTK native widget, 
 143    this is (in most cases) the only GTK widget the class manages. E.g. the 
 144    wxStaticText class handles only a GtkLabel widget a pointer to which you 
 145    can find in m_widget (defined in wxWindow) 
 147    When the class has a client area for drawing into and for containing children 
 148    it has to handle the client area widget (of the type GtkPizza, defined in 
 149    win_gtk.c), but there could be any number of widgets, handled by a class 
 150    The common rule for all windows is only, that the widget that interacts with 
 151    the rest of GTK must be referenced in m_widget and all other widgets must be 
 152    children of this widget on the GTK level. The top-most widget, which also 
 153    represents the client area, must be in the m_wxwindow field and must be of 
 156    As I said, the window classes that display a GTK native widget only have 
 157    one widget, so in the case of e.g. the wxButton class m_widget holds a 
 158    pointer to a GtkButton widget. But windows with client areas (for drawing 
 159    and children) have a m_widget field that is a pointer to a GtkScrolled- 
 160    Window and a m_wxwindow field that is pointer to a GtkPizza and this 
 161    one is (in the GTK sense) a child of the GtkScrolledWindow. 
 163    If the m_wxwindow field is set, then all input to this widget is inter- 
 164    cepted and sent to the wxWidgets class. If not, all input to the widget 
 165    that gets pointed to by m_widget gets intercepted and sent to the class. 
 169    The design of scrolling in wxWidgets is markedly different from that offered 
 170    by the GTK itself and therefore we cannot simply take it as it is. In GTK, 
 171    clicking on a scrollbar belonging to scrolled window will inevitably move 
 172    the window. In wxWidgets, the scrollbar will only emit an event, send this 
 173    to (normally) a wxScrolledWindow and that class will call ScrollWindow() 
 174    which actually moves the window and its subchildren. Note that GtkPizza 
 175    memorizes how much it has been scrolled but that wxWidgets forgets this 
 176    so that the two coordinates systems have to be kept in synch. This is done 
 177    in various places using the pizza->xoffset and pizza->yoffset values. 
 181    Singularily the most broken code in GTK is the code that is supposes to 
 182    inform subwindows (child windows) about new positions. Very often, duplicate 
 183    events are sent without changes in size or position, equally often no 
 184    events are sent at all (All this is due to a bug in the GtkContainer code 
 185    which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores 
 186    GTK's own system and it simply waits for size events for toplevel windows 
 187    and then iterates down the respective size events to all window. This has 
 188    the disadvantage, that windows might get size events before the GTK widget 
 189    actually has the reported size. This doesn't normally pose any problem, but 
 190    the OpenGl drawing routines rely on correct behaviour. Therefore, I have 
 191    added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas, 
 192    i.e. the wxGLCanvas will emit a size event, when (and not before) the X11 
 193    window that is used for OpenGl output really has that size (as reported by 
 198    If someone at some point of time feels the immense desire to have a look at, 
 199    change or attempt to optimse the Refresh() logic, this person will need an 
 200    intimate understanding of what a "draw" and what an "expose" events are and 
 201    what there are used for, in particular when used in connection with GTK's 
 202    own windowless widgets. Beware. 
 206    Cursors, too, have been a constant source of pleasure. The main difficulty 
 207    is that a GdkWindow inherits a cursor if the programmer sets a new cursor 
 208    for the parent. To prevent this from doing too much harm, I use idle time 
 209    to set the cursor over and over again, starting from the toplevel windows 
 210    and ending with the youngest generation (speaking of parent and child windows). 
 211    Also don't forget that cursors (like much else) are connected to GdkWindows, 
 212    not GtkWidgets and that the "window" field of a GtkWidget might very well 
 213    point to the GdkWindow of the parent widget (-> "window less widget") and 
 214    that the two obviously have very different meanings. 
 218 //----------------------------------------------------------------------------- 
 220 //----------------------------------------------------------------------------- 
 222 extern wxList     wxPendingDelete
; 
 223 extern bool       g_blockEventsOnDrag
; 
 224 extern bool       g_blockEventsOnScroll
; 
 225 extern wxCursor   g_globalCursor
; 
 227 static GdkGC 
*g_eraseGC 
= NULL
; 
 229 // mouse capture state: the window which has it and if the mouse is currently 
 231 static wxWindowGTK  
*g_captureWindow 
= (wxWindowGTK
*) NULL
; 
 232 static bool g_captureWindowHasMouse 
= FALSE
; 
 234 wxWindowGTK  
*g_focusWindow 
= (wxWindowGTK
*) NULL
; 
 236 // the last window which had the focus - this is normally never NULL (except 
 237 // if we never had focus at all) as even when g_focusWindow is NULL it still 
 238 // keeps its previous value 
 239 wxWindowGTK 
*g_focusWindowLast 
= (wxWindowGTK
*) NULL
; 
 241 // If a window get the focus set but has not been realized 
 242 // yet, defer setting the focus to idle time. 
 243 wxWindowGTK 
*g_delayedFocus 
= (wxWindowGTK
*) NULL
; 
 245 // hack: we need something to pass to gtk_menu_popup, so we store the time of 
 246 // the last click here 
 247 static guint32 gs_timeLastClick 
= 0;  
 249 extern bool g_mainThreadLocked
; 
 251 //----------------------------------------------------------------------------- 
 253 //----------------------------------------------------------------------------- 
 258 #   define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance"); 
 260 #   define DEBUG_MAIN_THREAD 
 263 #define DEBUG_MAIN_THREAD 
 266 // the trace mask used for the focus debugging messages 
 267 #define TRACE_FOCUS _T("focus") 
 269 //----------------------------------------------------------------------------- 
 270 // missing gdk functions 
 271 //----------------------------------------------------------------------------- 
 274 gdk_window_warp_pointer (GdkWindow      
*window
, 
 279   GdkWindowPrivate 
*priv
; 
 283     window 
= GDK_ROOT_PARENT(); 
 286   if (!GDK_WINDOW_DESTROYED(window
)) 
 288       XWarpPointer (GDK_WINDOW_XDISPLAY(window
), 
 289                     None
,              /* not source window -> move from anywhere */ 
 290                     GDK_WINDOW_XID(window
),  /* dest window */ 
 291                     0, 0, 0, 0,        /* not source window -> move from anywhere */ 
 295   priv 
= (GdkWindowPrivate
*) window
; 
 297   if (!priv
->destroyed
) 
 299       XWarpPointer (priv
->xdisplay
, 
 300                     None
,              /* not source window -> move from anywhere */ 
 301                     priv
->xwindow
,  /* dest window */ 
 302                     0, 0, 0, 0,        /* not source window -> move from anywhere */ 
 308 //----------------------------------------------------------------------------- 
 310 //----------------------------------------------------------------------------- 
 312 extern void wxapp_install_idle_handler(); 
 313 extern bool g_isIdle
; 
 315 //----------------------------------------------------------------------------- 
 316 // local code (see below) 
 317 //----------------------------------------------------------------------------- 
 319 // returns the child of win which currently has focus or NULL if not found 
 321 // Note: can't be static, needed by textctrl.cpp. 
 322 wxWindow 
*wxFindFocusedChild(wxWindowGTK 
*win
) 
 324     wxWindow 
*winFocus 
= wxWindowGTK::FindFocus(); 
 326         return (wxWindow 
*)NULL
; 
 328     if ( winFocus 
== win 
) 
 329         return (wxWindow 
*)win
; 
 331     for ( wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
 333           node 
= node
->GetNext() ) 
 335         wxWindow 
*child 
= wxFindFocusedChild(node
->GetData()); 
 340     return (wxWindow 
*)NULL
; 
 343 static void draw_frame( GtkWidget 
*widget
, wxWindowGTK 
*win 
) 
 345     // wxUniversal widgets draw the borders and scrollbars themselves 
 346 #ifndef __WXUNIVERSAL__ 
 353     if (win
->m_hasScrolling
) 
 355         GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(widget
); 
 357         GtkRequisition vscroll_req
; 
 358         vscroll_req
.width 
= 2; 
 359         vscroll_req
.height 
= 2; 
 360         (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
 361             (scroll_window
->vscrollbar
, &vscroll_req 
); 
 363         GtkRequisition hscroll_req
; 
 364         hscroll_req
.width 
= 2; 
 365         hscroll_req
.height 
= 2; 
 366         (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
 367             (scroll_window
->hscrollbar
, &hscroll_req 
); 
 369         GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) ); 
 371         if (scroll_window
->vscrollbar_visible
) 
 373             dw 
+= vscroll_req
.width
; 
 374             dw 
+= scroll_class
->scrollbar_spacing
; 
 377         if (scroll_window
->hscrollbar_visible
) 
 379             dh 
+= hscroll_req
.height
; 
 380             dh 
+= scroll_class
->scrollbar_spacing
; 
 386     if (GTK_WIDGET_NO_WINDOW (widget
)) 
 388         dx 
+= widget
->allocation
.x
; 
 389         dy 
+= widget
->allocation
.y
; 
 392     if (win
->HasFlag(wxRAISED_BORDER
)) 
 394         gtk_draw_shadow( widget
->style
, 
 399                          widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh 
); 
 403     if (win
->HasFlag(wxSUNKEN_BORDER
)) 
 405         gtk_draw_shadow( widget
->style
, 
 410                          widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh 
); 
 414     if (win
->HasFlag(wxSIMPLE_BORDER
)) 
 417         gc 
= gdk_gc_new( widget
->window 
); 
 418         gdk_gc_set_foreground( gc
, &widget
->style
->black 
); 
 419         gdk_draw_rectangle( widget
->window
, gc
, FALSE
, 
 421                          widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 ); 
 425 #endif // __WXUNIVERSAL__ 
 428 //----------------------------------------------------------------------------- 
 429 // "expose_event" of m_widget 
 430 //----------------------------------------------------------------------------- 
 433 static gint 
gtk_window_own_expose_callback( GtkWidget 
*widget
, GdkEventExpose 
*gdk_event
, wxWindowGTK 
*win 
) 
 435     if (gdk_event
->count 
> 0) return FALSE
; 
 437     draw_frame( widget
, win 
); 
 441     (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
); 
 448 //----------------------------------------------------------------------------- 
 449 // "draw" of m_widget 
 450 //----------------------------------------------------------------------------- 
 455 static void gtk_window_own_draw_callback( GtkWidget 
*widget
, GdkRectangle 
*WXUNUSED(rect
), wxWindowGTK 
*win 
) 
 457     draw_frame( widget
, win 
); 
 463 //----------------------------------------------------------------------------- 
 464 // "size_request" of m_widget 
 465 //----------------------------------------------------------------------------- 
 467 // make it extern because wxStaticText needs to disconnect this one 
 469 void wxgtk_window_size_request_callback(GtkWidget 
*widget
, 
 470                                         GtkRequisition 
*requisition
, 
 474     win
->GetSize( &w
, &h 
); 
 480     requisition
->height 
= h
; 
 481     requisition
->width 
= w
; 
 487 void wxgtk_combo_size_request_callback(GtkWidget 
*widget
, 
 488                                        GtkRequisition 
*requisition
, 
 491     // This callback is actually hooked into the text entry 
 492     // of the combo box, not the GtkHBox. 
 495     win
->GetSize( &w
, &h 
); 
 501     GtkCombo 
*gcombo 
= GTK_COMBO(win
->m_widget
); 
 503     GtkRequisition entry_req
; 
 505     entry_req
.height 
= 2; 
 506     (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(gcombo
->button
) )->size_request 
) 
 507         (gcombo
->button
, &entry_req 
); 
 509     requisition
->width 
= w 
- entry_req
.width
; 
 510     requisition
->height 
= entry_req
.height
+4;  // TODO: why +4? 
 514 //----------------------------------------------------------------------------- 
 515 // "expose_event" of m_wxwindow 
 516 //----------------------------------------------------------------------------- 
 519 static int gtk_window_expose_callback( GtkWidget 
*widget
, 
 520                                        GdkEventExpose 
*gdk_event
, 
 526         wxapp_install_idle_handler(); 
 529     // This callback gets called in drawing-idle time under 
 530     // GTK 2.0, so we don't need to defer anything to idle 
 533     GtkPizza 
*pizza 
= GTK_PIZZA( widget 
); 
 534     if (gdk_event
->window 
!= pizza
->bin_window
) return FALSE
; 
 539         wxPrintf( wxT("OnExpose from ") ); 
 540         if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName()) 
 541             wxPrintf( win
->GetClassInfo()->GetClassName() ); 
 542         wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event
->area
.x
, 
 543                                          (int)gdk_event
->area
.y
, 
 544                                          (int)gdk_event
->area
.width
, 
 545                                          (int)gdk_event
->area
.height 
); 
 550         win
->m_wxwindow
->style
, 
 554         (GdkRectangle
*) NULL
, 
 556         (char *)"button", // const_cast 
 561     win
->GetUpdateRegion() = wxRegion( gdk_event
->region 
); 
 563     win
->GtkSendPaintEvents(); 
 566     // Let parent window draw window less widgets 
 567     (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
); 
 569     // This gets called immediately after an expose event 
 570     // under GTK 1.2 so we collect the calls and wait for 
 571     // the idle handler to pick things up. 
 573     win
->GetUpdateRegion().Union( gdk_event
->area
.x
, 
 575                                   gdk_event
->area
.width
, 
 576                                   gdk_event
->area
.height 
); 
 577     win
->m_clearRegion
.Union( gdk_event
->area
.x
, 
 579                                   gdk_event
->area
.width
, 
 580                                   gdk_event
->area
.height 
); 
 582     // Actual redrawing takes place in idle time. 
 590 //----------------------------------------------------------------------------- 
 591 // "event" of m_wxwindow 
 592 //----------------------------------------------------------------------------- 
 596 // GTK thinks it is clever and filters out a certain amount of "unneeded" 
 597 // expose events. We need them, of course, so we override the main event 
 598 // procedure in GtkWidget by giving our own handler for all system events. 
 599 // There, we look for expose events ourselves whereas all other events are 
 604 gint 
gtk_window_event_event_callback( GtkWidget 
*widget
, 
 605                                       GdkEventExpose 
*event
, 
 608     if (event
->type 
== GDK_EXPOSE
) 
 610         gint ret 
= gtk_window_expose_callback( widget
, event
, win 
); 
 620 //----------------------------------------------------------------------------- 
 621 // "draw" of m_wxwindow 
 622 //----------------------------------------------------------------------------- 
 626 // This callback is a complete replacement of the gtk_pizza_draw() function, 
 627 // which is disabled. 
 630 static void gtk_window_draw_callback( GtkWidget 
*widget
, 
 637         wxapp_install_idle_handler(); 
 639     // if there are any children we must refresh everything 
 642     if ( !win
->HasFlag(wxFULL_REPAINT_ON_RESIZE
) && 
 643             win
->GetChildren().IsEmpty() ) 
 651         wxPrintf( wxT("OnDraw from ") ); 
 652         if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName()) 
 653             wxPrintf( win
->GetClassInfo()->GetClassName() ); 
 654         wxPrintf( wxT(" %d %d %d %d\n"), (int)rect
->x
, 
 661 #ifndef __WXUNIVERSAL__ 
 662     GtkPizza 
*pizza 
= GTK_PIZZA (widget
); 
 664     if (win
->GetThemeEnabled() && win
->GetBackgroundStyle() == wxBG_STYLE_SYSTEM
) 
 666         wxWindow 
*parent 
= win
->GetParent(); 
 667         while (parent 
&& !parent
->IsTopLevel()) 
 668             parent 
= parent
->GetParent(); 
 672         gtk_paint_flat_box (parent
->m_widget
->style
, 
 683     win
->m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
 684     win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
 686     // Update immediately, not in idle time. 
 689 #ifndef __WXUNIVERSAL__ 
 690     // Redraw child widgets 
 691     GList 
*children 
= pizza
->children
; 
 694         GtkPizzaChild 
*child 
= (GtkPizzaChild
*) children
->data
; 
 695         children 
= children
->next
; 
 697         GdkRectangle child_area
; 
 698         if (gtk_widget_intersect (child
->widget
, rect
, &child_area
)) 
 700             gtk_widget_draw (child
->widget
, &child_area 
/* (GdkRectangle*) NULL*/ ); 
 709 //----------------------------------------------------------------------------- 
 710 // "key_press_event" from any window 
 711 //----------------------------------------------------------------------------- 
 713 // set WXTRACE to this to see the key event codes on the console 
 714 #define TRACE_KEYS  _T("keyevent") 
 716 // translates an X key symbol to WXK_XXX value 
 718 // if isChar is true it means that the value returned will be used for EVT_CHAR 
 719 // event and then we choose the logical WXK_XXX, i.e. '/' for GDK_KP_Divide, 
 720 // for example, while if it is false it means that the value is going to be 
 721 // used for KEY_DOWN/UP events and then we translate GDK_KP_Divide to 
 723 static long wxTranslateKeySymToWXKey(KeySym keysym
, bool isChar
) 
 729         // Shift, Control and Alt don't generate the CHAR events at all 
 732             key_code 
= isChar 
? 0 : WXK_SHIFT
; 
 736             key_code 
= isChar 
? 0 : WXK_CONTROL
; 
 744             key_code 
= isChar 
? 0 : WXK_ALT
; 
 747         // neither do the toggle modifies 
 748         case GDK_Scroll_Lock
: 
 749             key_code 
= isChar 
? 0 : WXK_SCROLL
; 
 753             key_code 
= isChar 
? 0 : WXK_CAPITAL
; 
 757             key_code 
= isChar 
? 0 : WXK_NUMLOCK
; 
 761         // various other special keys 
 774         case GDK_ISO_Left_Tab
: 
 781             key_code 
= WXK_RETURN
; 
 785             key_code 
= WXK_CLEAR
; 
 789             key_code 
= WXK_PAUSE
; 
 793             key_code 
= WXK_SELECT
; 
 797             key_code 
= WXK_PRINT
; 
 801             key_code 
= WXK_EXECUTE
; 
 805             key_code 
= WXK_ESCAPE
; 
 808         // cursor and other extended keyboard keys 
 810             key_code 
= WXK_DELETE
; 
 826             key_code 
= WXK_RIGHT
; 
 833         case GDK_Prior
:     // == GDK_Page_Up 
 834             key_code 
= WXK_PRIOR
; 
 837         case GDK_Next
:      // == GDK_Page_Down 
 850             key_code 
= WXK_INSERT
; 
 865             key_code 
= (isChar 
? '0' : WXK_NUMPAD0
) + keysym 
- GDK_KP_0
; 
 869             key_code 
= isChar 
? ' ' : WXK_NUMPAD_SPACE
; 
 873             key_code 
= isChar 
? WXK_TAB 
: WXK_NUMPAD_TAB
; 
 877             key_code 
= isChar 
? WXK_RETURN 
: WXK_NUMPAD_ENTER
; 
 881             key_code 
= isChar 
? WXK_F1 
: WXK_NUMPAD_F1
; 
 885             key_code 
= isChar 
? WXK_F2 
: WXK_NUMPAD_F2
; 
 889             key_code 
= isChar 
? WXK_F3 
: WXK_NUMPAD_F3
; 
 893             key_code 
= isChar 
? WXK_F4 
: WXK_NUMPAD_F4
; 
 897             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_HOME
; 
 901             key_code 
= isChar 
? WXK_LEFT 
: WXK_NUMPAD_LEFT
; 
 905             key_code 
= isChar 
? WXK_UP 
: WXK_NUMPAD_UP
; 
 909             key_code 
= isChar 
? WXK_RIGHT 
: WXK_NUMPAD_RIGHT
; 
 913             key_code 
= isChar 
? WXK_DOWN 
: WXK_NUMPAD_DOWN
; 
 916         case GDK_KP_Prior
: // == GDK_KP_Page_Up 
 917             key_code 
= isChar 
? WXK_PRIOR 
: WXK_NUMPAD_PRIOR
; 
 920         case GDK_KP_Next
: // == GDK_KP_Page_Down 
 921             key_code 
= isChar 
? WXK_NEXT 
: WXK_NUMPAD_NEXT
; 
 925             key_code 
= isChar 
? WXK_END 
: WXK_NUMPAD_END
; 
 929             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_BEGIN
; 
 933             key_code 
= isChar 
? WXK_INSERT 
: WXK_NUMPAD_INSERT
; 
 937             key_code 
= isChar 
? WXK_DELETE 
: WXK_NUMPAD_DELETE
; 
 941             key_code 
= isChar 
? '=' : WXK_NUMPAD_EQUAL
; 
 944         case GDK_KP_Multiply
: 
 945             key_code 
= isChar 
? '*' : WXK_NUMPAD_MULTIPLY
; 
 949             key_code 
= isChar 
? '+' : WXK_NUMPAD_ADD
; 
 952         case GDK_KP_Separator
: 
 953             // FIXME: what is this? 
 954             key_code 
= isChar 
? '.' : WXK_NUMPAD_SEPARATOR
; 
 957         case GDK_KP_Subtract
: 
 958             key_code 
= isChar 
? '-' : WXK_NUMPAD_SUBTRACT
; 
 962             key_code 
= isChar 
? '.' : WXK_NUMPAD_DECIMAL
; 
 966             key_code 
= isChar 
? '/' : WXK_NUMPAD_DIVIDE
; 
 983             key_code 
= WXK_F1 
+ keysym 
- GDK_F1
; 
 993 static inline bool wxIsAsciiKeysym(KeySym ks
) 
 998 static void wxFillOtherKeyEventFields(wxKeyEvent
& event
, 
1000                                       GdkEventKey 
*gdk_event
) 
1004     GdkModifierType state
; 
1005     if (gdk_event
->window
) 
1006         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1008     event
.SetTimestamp( gdk_event
->time 
); 
1009     event
.SetId(win
->GetId()); 
1010     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
) != 0; 
1011     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
) != 0; 
1012     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
) != 0; 
1013     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
) != 0; 
1014     event
.m_scanCode 
= gdk_event
->keyval
; 
1015     event
.m_rawCode 
= (wxUint32
) gdk_event
->keyval
; 
1016     event
.m_rawFlags 
= 0; 
1018     event
.m_uniChar 
= gdk_keyval_to_unicode(gdk_event
->keyval
); 
1020     wxGetMousePosition( &x
, &y 
); 
1021     win
->ScreenToClient( &x
, &y 
); 
1024     event
.SetEventObject( win 
); 
1029 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
, 
1031                            GdkEventKey 
*gdk_event
) 
1033     // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string 
1034     //     but only event->keyval which is quite useless to us, so remember 
1035     //     the last character from GDK_KEY_PRESS and reuse it as last resort 
1037     // NB: should be MT-safe as we're always called from the main thread only 
1042     } s_lastKeyPress 
= { 0, 0 }; 
1044     KeySym keysym 
= gdk_event
->keyval
; 
1046     wxLogTrace(TRACE_KEYS
, _T("Key %s event: keysym = %ld"), 
1047                event
.GetEventType() == wxEVT_KEY_UP 
? _T("release") 
1051     long key_code 
= wxTranslateKeySymToWXKey(keysym
, FALSE 
/* !isChar */); 
1055         // do we have the translation or is it a plain ASCII character? 
1056         if ( (gdk_event
->length 
== 1) || wxIsAsciiKeysym(keysym
) ) 
1058             // we should use keysym if it is ASCII as X does some translations 
1059             // like "I pressed while Control is down" => "Ctrl-I" == "TAB" 
1060             // which we don't want here (but which we do use for OnChar()) 
1061             if ( !wxIsAsciiKeysym(keysym
) ) 
1063                 keysym 
= (KeySym
)gdk_event
->string
[0]; 
1066             // we want to always get the same key code when the same key is 
1067             // pressed regardless of the state of the modifies, i.e. on a 
1068             // standard US keyboard pressing '5' or '%' ('5' key with 
1069             // Shift) should result in the same key code in OnKeyDown(): 
1070             // '5' (although OnChar() will get either '5' or '%'). 
1072             // to do it we first translate keysym to keycode (== scan code) 
1073             // and then back but always using the lower register 
1074             Display 
*dpy 
= (Display 
*)wxGetDisplay(); 
1075             KeyCode keycode 
= XKeysymToKeycode(dpy
, keysym
); 
1077             wxLogTrace(TRACE_KEYS
, _T("\t-> keycode %d"), keycode
); 
1079             KeySym keysymNormalized 
= XKeycodeToKeysym(dpy
, keycode
, 0); 
1081             // use the normalized, i.e. lower register, keysym if we've 
1083             key_code 
= keysymNormalized 
? keysymNormalized 
: keysym
; 
1085             // as explained above, we want to have lower register key codes 
1086             // normally but for the letter keys we want to have the upper ones 
1088             // NB: don't use XConvertCase() here, we want to do it for letters 
1090             key_code 
= toupper(key_code
); 
1092         else // non ASCII key, what to do? 
1094             // by default, ignore it 
1097             // but if we have cached information from the last KEY_PRESS 
1098             if ( gdk_event
->type 
== GDK_KEY_RELEASE 
) 
1101                 if ( keysym 
== s_lastKeyPress
.keysym 
) 
1103                     key_code 
= s_lastKeyPress
.keycode
; 
1108         if ( gdk_event
->type 
== GDK_KEY_PRESS 
) 
1110             // remember it to be reused for KEY_UP event later 
1111             s_lastKeyPress
.keysym 
= keysym
; 
1112             s_lastKeyPress
.keycode 
= key_code
; 
1116     wxLogTrace(TRACE_KEYS
, _T("\t-> wxKeyCode %ld"), key_code
); 
1118     // sending unknown key events doesn't really make sense 
1122     // now fill all the other fields 
1123     wxFillOtherKeyEventFields(event
, win
, gdk_event
); 
1125     event
.m_keyCode 
= key_code
; 
1134     GtkIMContext 
*context
; 
1135     GdkEventKey  
*lastKeyEvent
; 
1139         context 
= gtk_im_multicontext_new(); 
1140         lastKeyEvent 
= NULL
; 
1144         g_object_unref(context
); 
1150 static gint 
gtk_window_key_press_callback( GtkWidget 
*widget
, 
1151                                            GdkEventKey 
*gdk_event
, 
1157         wxapp_install_idle_handler(); 
1161     if (g_blockEventsOnDrag
) 
1165     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
1167     bool return_after_IM 
= false; 
1169     if( wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1171         // Emit KEY_DOWN event 
1172         ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1176         // Return after IM processing as we cannot do 
1177         // anything with it anyhow. 
1178         return_after_IM 
= true; 
1182     // 2005.01.26 modified by Hong Jen Yee (hzysoft@sina.com.tw): 
1183     // When we get a key_press event here, it could be originate 
1184     // from the current widget or its child widgets.  However, only the widget 
1185     // with the INPUT FOCUS can generate the INITIAL key_press event.  That is,  
1186     // if the CURRENT widget doesn't have the FOCUS at all, this event definitely 
1187     // originated from its child widgets and shouldn't be passed to IM context. 
1188     // In fact, what a GTK+ IM should do is filtering keyEvents and convert them 
1189     // into text input ONLY WHEN THE WIDGET HAS INPUT FOCUS.  Besides, when current 
1190     // widgets has both IM context and input focus, the event should be filtered  
1191     // by gtk_im_context_filter_keypress(). 
1192     // Then, we should, according to GTK+ 2.0 API doc, return whatever it returns. 
1193     if ((!ret
) && (win
->m_imData 
!= NULL
) && ( wxWindow::FindFocus() == win 
)) 
1195         // We should let GTK+ IM filter key event first. According to GTK+ 2.0 API 
1196         // docs, if IM filter returns true, no further processing should be done. 
1197         // we should send the key_down event anyway.  
1198         bool intercepted_by_IM 
= gtk_im_context_filter_keypress(win
->m_imData
->context
, gdk_event
); 
1199         win
->m_imData
->lastKeyEvent 
= NULL
; 
1200         if (intercepted_by_IM
) 
1202             wxLogTrace(TRACE_KEYS
, _T("Key event intercepted by IM")); 
1207     if (return_after_IM
) 
1211     // This is for GTK+ 1.2 only. The char event generatation for GTK+ 2.0 is done 
1212     // in the "commit" handler. 
1214     // 2005.02.02 modified by Hong Jen Yee (hzysoft@sina.com.tw). 
1215     // In GTK+ 1.2, strings sent by IMs are also regarded as key_press events whose  
1216     // keyCodes cannot be recognized by wxWidgets. These MBCS strings, however, are  
1217     // composed of more than one character, which means gdk_event->length will always  
1218     // greater than one. When gtk_event->length == 1, this may be an ASCII character 
1219     // and can be translated by wx.  However, when MBCS characters are sent by IM,  
1220     // gdk_event->length will >= 2. So neither should we pass it to accelerator table, 
1221     // nor should we pass it to controls. The following explanation was excerpted 
1222     // from GDK documentation. 
1223     // gint length : the length of string. 
1224     // gchar *string : a null-terminated multi-byte string containing the composed 
1225     // characters resulting from the key press. When text is being input, in a GtkEntry 
1226     // for example, it is these characters which should be added to the input buffer. 
1227     // When using Input Methods to support internationalized text input, the composed 
1228     // characters appear here after the pre-editing has been completed. 
1230     if ( (!ret
) && (gdk_event
->length 
> 1) ) // If this event contains a pre-edited string from IM. 
1232         // We should translate this key event into wxEVT_CHAR not wxEVT_KEY_DOWN. 
1233         #if wxUSE_UNICODE   // GTK+ 1.2 is not UTF-8 based. 
1234             const wxWCharBuffer string 
= wxConvLocal
.cMB2WC( gdk_event
->string 
); 
1238             const char* string 
= gdk_event
->string
; 
1241         // Implement OnCharHook by checking ancesteror top level windows 
1242         wxWindow 
*parent 
= win
; 
1243         while (parent 
&& !parent
->IsTopLevel()) 
1244             parent 
= parent
->GetParent(); 
1246         for( const wxChar
* pstr 
= string
; *pstr
; pstr
++ ) 
1249             event
.m_uniChar 
= *pstr
; 
1250             // Backward compatible for ISO-8859-1 
1251             event
.m_keyCode 
= *pstr 
< 256 ? event
.m_uniChar 
: 0; 
1253             event
.m_keyCode 
= *pstr
; 
1257                 event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1258                 ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1262                 event
.SetEventType(wxEVT_CHAR
); 
1263                 win
->GetEventHandler()->ProcessEvent( event 
); 
1269 #endif  // #ifndef  __WXGTK20__ 
1274         wxWindowGTK 
*ancestor 
= win
; 
1277             int command 
= ancestor
->GetAcceleratorTable()->GetCommand( event 
); 
1280                 wxCommandEvent 
command_event( wxEVT_COMMAND_MENU_SELECTED
, command 
); 
1281                 ret 
= ancestor
->GetEventHandler()->ProcessEvent( command_event 
); 
1284             if (ancestor
->IsTopLevel()) 
1286             ancestor 
= ancestor
->GetParent(); 
1289 #endif // wxUSE_ACCEL 
1291     // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x 
1292     // will only be sent if it is not in an accelerator table. 
1296         KeySym keysym 
= gdk_event
->keyval
; 
1297         // Find key code for EVT_CHAR and EVT_CHAR_HOOK events 
1298         key_code 
= wxTranslateKeySymToWXKey(keysym
, TRUE 
/* isChar */); 
1301             if ( wxIsAsciiKeysym(keysym
) ) 
1304                 key_code 
= (unsigned char)keysym
; 
1306             // gdk_event->string is actually deprecated 
1307             else if ( gdk_event
->length 
== 1 ) 
1309                 key_code 
= (unsigned char)gdk_event
->string
[0]; 
1315             wxLogTrace(TRACE_KEYS
, _T("Char event: %ld"), key_code
); 
1317             event
.m_keyCode 
= key_code
; 
1319             // Implement OnCharHook by checking ancesteror top level windows 
1320             wxWindow 
*parent 
= win
; 
1321             while (parent 
&& !parent
->IsTopLevel()) 
1322                 parent 
= parent
->GetParent(); 
1325                 event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1326                 ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1331                 event
.SetEventType(wxEVT_CHAR
); 
1332                 ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1341     // win is a control: tab can be propagated up 
1343          ((gdk_event
->keyval 
== GDK_Tab
) || (gdk_event
->keyval 
== GDK_ISO_Left_Tab
)) && 
1344 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may 
1345 //     have this style, yet choose not to process this particular TAB in which 
1346 //     case TAB must still work as a navigational character 
1347 // JS: enabling again to make consistent with other platforms 
1348 //     (with wxTE_PROCESS_TAB you have to call Navigate to get default 
1349 //     navigation behaviour) 
1351          (! (win
->HasFlag(wxTE_PROCESS_TAB
) && win
->IsKindOf(CLASSINFO(wxTextCtrl
)) )) && 
1353          win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) ) 
1355         wxNavigationKeyEvent new_event
; 
1356         new_event
.SetEventObject( win
->GetParent() ); 
1357         // GDK reports GDK_ISO_Left_Tab for SHIFT-TAB 
1358         new_event
.SetDirection( (gdk_event
->keyval 
== GDK_Tab
) ); 
1359         // CTRL-TAB changes the (parent) window, i.e. switch notebook page 
1360         new_event
.SetWindowChange( (gdk_event
->state 
& GDK_CONTROL_MASK
) ); 
1361         new_event
.SetCurrentFocus( win 
); 
1362         ret 
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event 
); 
1365     // generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) 
1367          (gdk_event
->keyval 
== GDK_Escape
) ) 
1369         // however only do it if we have a Cancel button in the dialog, 
1370         // otherwise the user code may get confused by the events from a 
1371         // non-existing button and, worse, a wxButton might get button event 
1372         // from another button which is not really expected 
1373         wxWindow 
*winForCancel 
= win
, 
1375         while ( winForCancel 
) 
1377             btnCancel 
= winForCancel
->FindWindow(wxID_CANCEL
); 
1380                 // found a cancel button 
1384             if ( winForCancel
->IsTopLevel() ) 
1386                 // no need to look further 
1390             // maybe our parent has a cancel button? 
1391             winForCancel 
= winForCancel
->GetParent(); 
1396             wxCommandEvent 
event(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
); 
1397             event
.SetEventObject(btnCancel
); 
1398             ret 
= btnCancel
->GetEventHandler()->ProcessEvent(event
); 
1404         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" ); 
1414 static void gtk_wxwindow_commit_cb (GtkIMContext 
*context
, 
1418     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
1420     // take modifiers, cursor position, timestamp etc. from the last 
1421     // key_press_event that was fed into Input Method: 
1422     if (window
->m_imData
->lastKeyEvent
) 
1424         wxFillOtherKeyEventFields(event
, 
1425                                   window
, window
->m_imData
->lastKeyEvent
); 
1429     const wxWCharBuffer data 
= wxConvUTF8
.cMB2WC( (char*)str 
); 
1431     const wxWCharBuffer wdata 
= wxConvUTF8
.cMB2WC( (char*)str 
); 
1432     const wxCharBuffer data 
= wxConvLocal
.cWC2MB( wdata 
); 
1433 #endif // wxUSE_UNICODE 
1434     if( !(const wxChar
*)data 
) 
1439     // Implement OnCharHook by checking ancestor top level windows 
1440     wxWindow 
*parent 
= window
; 
1441     while (parent 
&& !parent
->IsTopLevel()) 
1442         parent 
= parent
->GetParent(); 
1444     for( const wxChar
* pstr 
= data
; *pstr
; pstr
++ ) 
1447         event
.m_uniChar 
= *pstr
; 
1448         // Backward compatible for ISO-8859-1 
1449         event
.m_keyCode 
= *pstr 
< 256 ? event
.m_uniChar 
: 0; 
1450         wxLogTrace(TRACE_KEYS
, _T("IM sent character '%c'"), event
.m_uniChar
); 
1452         event
.m_keyCode 
= *pstr
; 
1453 #endif  // wxUSE_UNICODE 
1456             event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1457             ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1462             event
.SetEventType(wxEVT_CHAR
); 
1463             ret 
= window
->GetEventHandler()->ProcessEvent( event 
); 
1471 //----------------------------------------------------------------------------- 
1472 // "key_release_event" from any window 
1473 //----------------------------------------------------------------------------- 
1476 static gint 
gtk_window_key_release_callback( GtkWidget 
*widget
, 
1477                                              GdkEventKey 
*gdk_event
, 
1483         wxapp_install_idle_handler(); 
1488     if (g_blockEventsOnDrag
) 
1491     wxKeyEvent 
event( wxEVT_KEY_UP 
); 
1492     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1494         // unknown key pressed, ignore (the event would be useless anyhow 
1498     if ( !win
->GetEventHandler()->ProcessEvent( event 
) ) 
1501     gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" ); 
1506 // ============================================================================ 
1508 // ============================================================================ 
1510 // ---------------------------------------------------------------------------- 
1511 // mouse event processing helpers 
1512 // ---------------------------------------------------------------------------- 
1514 // init wxMouseEvent with the info from GdkEventXXX struct 
1515 template<typename T
> void InitMouseEvent(wxWindowGTK 
*win
, 
1516                                          wxMouseEvent
& event
, 
1519     event
.SetTimestamp( gdk_event
->time 
); 
1520     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
); 
1521     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
); 
1522     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
); 
1523     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
); 
1524     event
.m_leftDown 
= (gdk_event
->state 
& GDK_BUTTON1_MASK
); 
1525     event
.m_middleDown 
= (gdk_event
->state 
& GDK_BUTTON2_MASK
); 
1526     event
.m_rightDown 
= (gdk_event
->state 
& GDK_BUTTON3_MASK
); 
1527     if (event
.GetEventType() == wxEVT_MOUSEWHEEL
) 
1529        event
.m_linesPerAction 
= 3; 
1530        event
.m_wheelDelta 
= 120; 
1531        if (((GdkEventButton
*)gdk_event
)->button 
== 4) 
1532            event
.m_wheelRotation 
= 120; 
1533        else if (((GdkEventButton
*)gdk_event
)->button 
== 5) 
1534            event
.m_wheelRotation 
= -120; 
1537     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1538     event
.m_x 
= (wxCoord
)gdk_event
->x 
- pt
.x
; 
1539     event
.m_y 
= (wxCoord
)gdk_event
->y 
- pt
.y
; 
1541     event
.SetEventObject( win 
); 
1542     event
.SetId( win
->GetId() ); 
1543     event
.SetTimestamp( gdk_event
->time 
); 
1546 static void AdjustEventButtonState(wxMouseEvent
& event
) 
1548     // GDK reports the old state of the button for a button press event, but 
1549     // for compatibility with MSW and common sense we want m_leftDown be TRUE 
1550     // for a LEFT_DOWN event, not FALSE, so we will invert 
1551     // left/right/middleDown for the corresponding click events 
1553     if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) || 
1554         (event
.GetEventType() == wxEVT_LEFT_DCLICK
) || 
1555         (event
.GetEventType() == wxEVT_LEFT_UP
)) 
1557         event
.m_leftDown 
= !event
.m_leftDown
; 
1561     if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) || 
1562         (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) || 
1563         (event
.GetEventType() == wxEVT_MIDDLE_UP
)) 
1565         event
.m_middleDown 
= !event
.m_middleDown
; 
1569     if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) || 
1570         (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) || 
1571         (event
.GetEventType() == wxEVT_RIGHT_UP
)) 
1573         event
.m_rightDown 
= !event
.m_rightDown
; 
1578 // find the window to send the mouse event too 
1580 wxWindowGTK 
*FindWindowForMouseEvent(wxWindowGTK 
*win
, wxCoord
& x
, wxCoord
& y
) 
1585     if (win
->m_wxwindow
) 
1587         GtkPizza 
*pizza 
= GTK_PIZZA(win
->m_wxwindow
); 
1588         xx 
+= pizza
->xoffset
; 
1589         yy 
+= pizza
->yoffset
; 
1592     wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
1595         wxWindowGTK 
*child 
= node
->GetData(); 
1597         node 
= node
->GetNext(); 
1598         if (!child
->IsShown()) 
1601         if (child
->IsTransparentForMouse()) 
1603             // wxStaticBox is transparent in the box itself 
1604             int xx1 
= child
->m_x
; 
1605             int yy1 
= child
->m_y
; 
1606             int xx2 
= child
->m_x 
+ child
->m_width
; 
1607             int yy2 
= child
->m_y 
+ child
->m_height
; 
1610             if (((xx 
>= xx1
) && (xx 
<= xx1
+10) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1612                 ((xx 
>= xx2
-10) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1614                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy1
+10)) || 
1616                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy2
-1) && (yy 
<= yy2
))) 
1627             if ((child
->m_wxwindow 
== (GtkWidget
*) NULL
) && 
1628                 (child
->m_x 
<= xx
) && 
1629                 (child
->m_y 
<= yy
) && 
1630                 (child
->m_x
+child
->m_width  
>= xx
) && 
1631                 (child
->m_y
+child
->m_height 
>= yy
)) 
1644 //----------------------------------------------------------------------------- 
1645 // "button_press_event" 
1646 //----------------------------------------------------------------------------- 
1649 static gint 
gtk_window_button_press_callback( GtkWidget 
*widget
, 
1650                                               GdkEventButton 
*gdk_event
, 
1656         wxapp_install_idle_handler(); 
1659     wxPrintf( wxT("1) OnButtonPress from ") ); 
1660     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1661         wxPrintf( win->GetClassInfo()->GetClassName() ); 
1662     wxPrintf( wxT(".\n") ); 
1664     if (!win
->m_hasVMT
) return FALSE
; 
1665     if (g_blockEventsOnDrag
) return TRUE
; 
1666     if (g_blockEventsOnScroll
) return TRUE
; 
1668     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1670     if (win
->m_wxwindow 
&& (g_focusWindow 
!= win
) && win
->AcceptsFocus()) 
1672         gtk_widget_grab_focus( win
->m_wxwindow 
); 
1674         wxPrintf( wxT("GrabFocus from ") ); 
1675         if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1676             wxPrintf( win->GetClassInfo()->GetClassName() ); 
1677         wxPrintf( wxT(".\n") ); 
1681     // GDK sends surplus button down event 
1682     // before a double click event. We 
1683     // need to filter these out. 
1684     if (gdk_event
->type 
== GDK_BUTTON_PRESS
) 
1686         GdkEvent 
*peek_event 
= gdk_event_peek(); 
1689             if ((peek_event
->type 
== GDK_2BUTTON_PRESS
) || 
1690                 (peek_event
->type 
== GDK_3BUTTON_PRESS
)) 
1692                 gdk_event_free( peek_event 
); 
1697                 gdk_event_free( peek_event 
); 
1702     wxEventType event_type 
= wxEVT_NULL
; 
1704     // GdkDisplay is a GTK+ 2.2.0 thing 
1705 #if defined(__WXGTK20__) && GTK_CHECK_VERSION(2, 2, 0) 
1706     if ( gdk_event
->type 
== GDK_2BUTTON_PRESS 
&& 
1707             gdk_event
->button 
>= 1 && gdk_event
->button 
<= 3 ) 
1709         // Reset GDK internal timestamp variables in order to disable GDK 
1710         // triple click events. GDK will then next time believe no button has 
1711         // been clicked just before, and send a normal button click event. 
1712         GdkDisplay
* display 
= gtk_widget_get_display (widget
); 
1713         display
->button_click_time
[1] = 0; 
1714         display
->button_click_time
[0] = 0; 
1718     if (gdk_event
->button 
== 1) 
1720         // note that GDK generates triple click events which are not supported 
1721         // by wxWidgets but still have to be passed to the app as otherwise 
1722         // clicks would simply go missing 
1723         switch (gdk_event
->type
) 
1725             // we shouldn't get triple clicks at all for GTK2 because we 
1726             // suppress them artificially using the code above but we still 
1727             // should map them to something for GTK1 and not just ignore them 
1728             // as this would lose clicks 
1729             case GDK_3BUTTON_PRESS
:     // we could also map this to DCLICK... 
1730             case GDK_BUTTON_PRESS
: 
1731                 event_type 
= wxEVT_LEFT_DOWN
; 
1734             case GDK_2BUTTON_PRESS
: 
1735                 event_type 
= wxEVT_LEFT_DCLICK
; 
1739                 // just to silence gcc warnings 
1743     else if (gdk_event
->button 
== 2) 
1745         switch (gdk_event
->type
) 
1747             case GDK_3BUTTON_PRESS
: 
1748             case GDK_BUTTON_PRESS
: 
1749                 event_type 
= wxEVT_MIDDLE_DOWN
; 
1752             case GDK_2BUTTON_PRESS
: 
1753                 event_type 
= wxEVT_MIDDLE_DCLICK
; 
1760     else if (gdk_event
->button 
== 3) 
1762         switch (gdk_event
->type
) 
1764             case GDK_3BUTTON_PRESS
: 
1765             case GDK_BUTTON_PRESS
: 
1766                 event_type 
= wxEVT_RIGHT_DOWN
; 
1769             case GDK_2BUTTON_PRESS
: 
1770                 event_type 
= wxEVT_RIGHT_DCLICK
; 
1777     else if (gdk_event
->button 
== 4 || gdk_event
->button 
== 5) 
1779         if (gdk_event
->type 
== GDK_BUTTON_PRESS 
) 
1781             event_type 
= wxEVT_MOUSEWHEEL
; 
1785     if ( event_type 
== wxEVT_NULL 
) 
1787         // unknown mouse button or click type 
1791     wxMouseEvent 
event( event_type 
); 
1792     InitMouseEvent( win
, event
, gdk_event 
); 
1794     AdjustEventButtonState(event
); 
1796     // wxListBox actually get mouse events from the item, so we need to give it 
1797     // a chance to correct this 
1798     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1800     // find the correct window to send the event too: it may be a different one 
1801     // from the one which got it at GTK+ level because some control don't have 
1802     // their own X window and thus cannot get any events. 
1803     if ( !g_captureWindow 
) 
1804         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1806     gs_timeLastClick 
= gdk_event
->time
; 
1809     if (event_type 
== wxEVT_LEFT_DCLICK
) 
1811         // GTK 1.2 crashes when intercepting double 
1812         // click events from both wxSpinButton and 
1814         if (GTK_IS_SPIN_BUTTON(win
->m_widget
)) 
1816             // Just disable this event for now. 
1822     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1824         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" ); 
1828     if (event_type 
== wxEVT_RIGHT_DOWN
) 
1830         // generate a "context menu" event: this is similar to right mouse 
1831         // click under many GUIs except that it is generated differently 
1832         // (right up under MSW, ctrl-click under Mac, right down here) and 
1834         // (a) it's a command event and so is propagated to the parent 
1835         // (b) under some ports it can be generated from kbd too 
1836         // (c) it uses screen coords (because of (a)) 
1837         wxContextMenuEvent 
evtCtx( 
1840             win
->ClientToScreen(event
.GetPosition())); 
1841         evtCtx
.SetEventObject(win
); 
1842         return win
->GetEventHandler()->ProcessEvent(evtCtx
); 
1849 //----------------------------------------------------------------------------- 
1850 // "button_release_event" 
1851 //----------------------------------------------------------------------------- 
1854 static gint 
gtk_window_button_release_callback( GtkWidget 
*widget
, 
1855                                                 GdkEventButton 
*gdk_event
, 
1861         wxapp_install_idle_handler(); 
1863     if (!win
->m_hasVMT
) return FALSE
; 
1864     if (g_blockEventsOnDrag
) return FALSE
; 
1865     if (g_blockEventsOnScroll
) return FALSE
; 
1867     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1869     wxEventType event_type 
= wxEVT_NULL
; 
1871     switch (gdk_event
->button
) 
1874             event_type 
= wxEVT_LEFT_UP
; 
1878             event_type 
= wxEVT_MIDDLE_UP
; 
1882             event_type 
= wxEVT_RIGHT_UP
; 
1886             // unknwon button, don't process 
1890     wxMouseEvent 
event( event_type 
); 
1891     InitMouseEvent( win
, event
, gdk_event 
); 
1893     AdjustEventButtonState(event
); 
1895     // same wxListBox hack as above 
1896     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1898     if ( !g_captureWindow 
) 
1899         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1901     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1903         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" ); 
1911 //----------------------------------------------------------------------------- 
1912 // "motion_notify_event" 
1913 //----------------------------------------------------------------------------- 
1916 static gint 
gtk_window_motion_notify_callback( GtkWidget 
*widget
, 
1917                                                GdkEventMotion 
*gdk_event
, 
1923         wxapp_install_idle_handler(); 
1925     if (!win
->m_hasVMT
) return FALSE
; 
1926     if (g_blockEventsOnDrag
) return FALSE
; 
1927     if (g_blockEventsOnScroll
) return FALSE
; 
1929     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1931     if (gdk_event
->is_hint
) 
1935         GdkModifierType state
; 
1936         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1942     printf( "OnMotion from " ); 
1943     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1944       printf( win->GetClassInfo()->GetClassName() ); 
1948     wxMouseEvent 
event( wxEVT_MOTION 
); 
1949     InitMouseEvent(win
, event
, gdk_event
); 
1951     if ( g_captureWindow 
) 
1953         // synthetize a mouse enter or leave event if needed 
1954         GdkWindow 
*winUnderMouse 
= gdk_window_at_pointer(NULL
, NULL
); 
1955         // This seems to be necessary and actually been added to 
1956         // GDK itself in version 2.0.X 
1959         bool hasMouse 
= winUnderMouse 
== gdk_event
->window
; 
1960         if ( hasMouse 
!= g_captureWindowHasMouse 
) 
1962             // the mouse changed window 
1963             g_captureWindowHasMouse 
= hasMouse
; 
1965             wxMouseEvent 
event(g_captureWindowHasMouse 
? wxEVT_ENTER_WINDOW
 
1966                                                        : wxEVT_LEAVE_WINDOW
); 
1967             InitMouseEvent(win
, event
, gdk_event
); 
1968             event
.SetEventObject(win
); 
1969             win
->GetEventHandler()->ProcessEvent(event
); 
1974         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1977     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1979         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" ); 
1988 //----------------------------------------------------------------------------- 
1989 // "mouse_wheel_event" 
1990 //----------------------------------------------------------------------------- 
1993 static gint 
gtk_window_wheel_callback (GtkWidget 
* widget
, 
1994                                        GdkEventScroll 
* gdk_event
, 
2000         wxapp_install_idle_handler(); 
2002     wxEventType event_type 
= wxEVT_NULL
; 
2003     if (gdk_event
->direction 
== GDK_SCROLL_UP
) 
2004         event_type 
= wxEVT_MOUSEWHEEL
; 
2005     else if (gdk_event
->direction 
== GDK_SCROLL_DOWN
) 
2006         event_type 
= wxEVT_MOUSEWHEEL
; 
2010     wxMouseEvent 
event( event_type 
); 
2011     // Can't use InitMouse macro because scroll events don't have button 
2012     event
.SetTimestamp( gdk_event
->time 
); 
2013     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
); 
2014     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
); 
2015     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
); 
2016     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
); 
2017     event
.m_leftDown 
= (gdk_event
->state 
& GDK_BUTTON1_MASK
); 
2018     event
.m_middleDown 
= (gdk_event
->state 
& GDK_BUTTON2_MASK
); 
2019     event
.m_rightDown 
= (gdk_event
->state 
& GDK_BUTTON3_MASK
); 
2020     event
.m_linesPerAction 
= 3; 
2021     event
.m_wheelDelta 
= 120; 
2022     if (gdk_event
->direction 
== GDK_SCROLL_UP
) 
2023         event
.m_wheelRotation 
= 120; 
2025         event
.m_wheelRotation 
= -120; 
2027     wxPoint pt 
= win
->GetClientAreaOrigin(); 
2028     event
.m_x 
= (wxCoord
)gdk_event
->x 
- pt
.x
; 
2029     event
.m_y 
= (wxCoord
)gdk_event
->y 
- pt
.y
; 
2031     event
.SetEventObject( win 
); 
2032     event
.SetId( win
->GetId() ); 
2033     event
.SetTimestamp( gdk_event
->time 
); 
2035     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
2037         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "scroll_event" ); 
2045 //----------------------------------------------------------------------------- 
2047 //----------------------------------------------------------------------------- 
2049 static gboolean 
wxgtk_window_popup_menu_callback(GtkWidget
*, wxWindowGTK
* win
) 
2051     wxContextMenuEvent 
event( 
2055     event
.SetEventObject(win
); 
2056     return win
->GetEventHandler()->ProcessEvent(event
); 
2059 #endif // __WXGTK20__ 
2061 //----------------------------------------------------------------------------- 
2063 //----------------------------------------------------------------------------- 
2065 // send the wxChildFocusEvent and wxFocusEvent, common code of 
2066 // gtk_window_focus_in_callback() and SetFocus() 
2067 static bool DoSendFocusEvents(wxWindow 
*win
) 
2069     // Notify the parent keeping track of focus for the kbd navigation 
2070     // purposes that we got it. 
2071     wxChildFocusEvent 
eventChildFocus(win
); 
2072     (void)win
->GetEventHandler()->ProcessEvent(eventChildFocus
); 
2074     wxFocusEvent 
eventFocus(wxEVT_SET_FOCUS
, win
->GetId()); 
2075     eventFocus
.SetEventObject(win
); 
2077     return win
->GetEventHandler()->ProcessEvent(eventFocus
); 
2081 static gint 
gtk_window_focus_in_callback( GtkWidget 
*widget
, 
2082                                           GdkEvent 
*WXUNUSED(event
), 
2088         wxapp_install_idle_handler(); 
2092         gtk_im_context_focus_in(win
->m_imData
->context
); 
2096     g_focusWindow 
= win
; 
2098     wxLogTrace(TRACE_FOCUS
, 
2099                _T("%s: focus in"), win
->GetName().c_str()); 
2103         gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
); 
2107     // caret needs to be informed about focus change 
2108     wxCaret 
*caret 
= win
->GetCaret(); 
2111         caret
->OnSetFocus(); 
2113 #endif // wxUSE_CARET 
2115     // does the window itself think that it has the focus? 
2116     if ( !win
->m_hasFocus 
) 
2118         // not yet, notify it 
2119         win
->m_hasFocus 
= TRUE
; 
2121         if ( DoSendFocusEvents(win
) ) 
2123            gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" ); 
2132 //----------------------------------------------------------------------------- 
2133 // "focus_out_event" 
2134 //----------------------------------------------------------------------------- 
2137 static gint 
gtk_window_focus_out_callback( GtkWidget 
*widget
, GdkEventFocus 
*gdk_event
, wxWindowGTK 
*win 
) 
2142         wxapp_install_idle_handler(); 
2146         gtk_im_context_focus_out(win
->m_imData
->context
); 
2149     wxLogTrace( TRACE_FOCUS
, 
2150                 _T("%s: focus out"), win
->GetName().c_str() ); 
2153     wxWindowGTK 
*winFocus 
= wxFindFocusedChild(win
); 
2157     g_focusWindow 
= (wxWindowGTK 
*)NULL
; 
2165     // caret needs to be informed about focus change 
2166     wxCaret 
*caret 
= win
->GetCaret(); 
2169         caret
->OnKillFocus(); 
2171 #endif // wxUSE_CARET 
2173     // don't send the window a kill focus event if it thinks that it doesn't 
2174     // have focus already 
2175     if ( win
->m_hasFocus 
) 
2177         win
->m_hasFocus 
= FALSE
; 
2179         wxFocusEvent 
event( wxEVT_KILL_FOCUS
, win
->GetId() ); 
2180         event
.SetEventObject( win 
); 
2182         // even if we did process the event in wx code, still let GTK itself 
2183         // process it too as otherwise bad things happen, especially in GTK2 
2184         // where the text control simply aborts the program if it doesn't get 
2185         // the matching focus out event 
2186         (void)win
->GetEventHandler()->ProcessEvent( event 
); 
2193 //----------------------------------------------------------------------------- 
2194 // "enter_notify_event" 
2195 //----------------------------------------------------------------------------- 
2199 gint 
gtk_window_enter_callback( GtkWidget 
*widget
, 
2200                                 GdkEventCrossing 
*gdk_event
, 
2206         wxapp_install_idle_handler(); 
2208     if (!win
->m_hasVMT
) return FALSE
; 
2209     if (g_blockEventsOnDrag
) return FALSE
; 
2211     // Event was emitted after a grab 
2212     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
2214     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
2218     GdkModifierType state 
= (GdkModifierType
)0; 
2220     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
2222     wxMouseEvent 
event( wxEVT_ENTER_WINDOW 
); 
2223     InitMouseEvent(win
, event
, gdk_event
); 
2224     wxPoint pt 
= win
->GetClientAreaOrigin(); 
2225     event
.m_x 
= x 
+ pt
.x
; 
2226     event
.m_y 
= y 
+ pt
.y
; 
2228     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
2230        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" ); 
2238 //----------------------------------------------------------------------------- 
2239 // "leave_notify_event" 
2240 //----------------------------------------------------------------------------- 
2243 static gint 
gtk_window_leave_callback( GtkWidget 
*widget
, GdkEventCrossing 
*gdk_event
, wxWindowGTK 
*win 
) 
2248         wxapp_install_idle_handler(); 
2250     if (!win
->m_hasVMT
) return FALSE
; 
2251     if (g_blockEventsOnDrag
) return FALSE
; 
2253     // Event was emitted after an ungrab 
2254     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
2256     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
2258     wxMouseEvent 
event( wxEVT_LEAVE_WINDOW 
); 
2259     event
.SetTimestamp( gdk_event
->time 
); 
2260     event
.SetEventObject( win 
); 
2264     GdkModifierType state 
= (GdkModifierType
)0; 
2266     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
2268     event
.m_shiftDown 
= (state 
& GDK_SHIFT_MASK
) != 0; 
2269     event
.m_controlDown 
= (state 
& GDK_CONTROL_MASK
) != 0; 
2270     event
.m_altDown 
= (state 
& GDK_MOD1_MASK
) != 0; 
2271     event
.m_metaDown 
= (state 
& GDK_MOD2_MASK
) != 0; 
2272     event
.m_leftDown 
= (state 
& GDK_BUTTON1_MASK
) != 0; 
2273     event
.m_middleDown 
= (state 
& GDK_BUTTON2_MASK
) != 0; 
2274     event
.m_rightDown 
= (state 
& GDK_BUTTON3_MASK
) != 0; 
2276     wxPoint pt 
= win
->GetClientAreaOrigin(); 
2277     event
.m_x 
= x 
+ pt
.x
; 
2278     event
.m_y 
= y 
+ pt
.y
; 
2280     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
2282         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" ); 
2290 //----------------------------------------------------------------------------- 
2291 // "value_changed" from m_vAdjust 
2292 //----------------------------------------------------------------------------- 
2295 static void gtk_window_vscroll_callback( GtkAdjustment 
*adjust
, 
2302         wxapp_install_idle_handler(); 
2304     if (g_blockEventsOnDrag
) return; 
2306     if (!win
->m_hasVMT
) return; 
2308     float diff 
= adjust
->value 
- win
->m_oldVerticalPos
; 
2309     if (fabs(diff
) < 0.2) return; 
2311     win
->m_oldVerticalPos 
= adjust
->value
; 
2314     GtkScrolledWindow   
*sw 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
2316     wxEventType         command 
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->vscrollbar
)); 
2318     int value 
= (int)(adjust
->value
+0.5); 
2320     wxScrollWinEvent 
event( command
, value
, wxVERTICAL 
); 
2321     event
.SetEventObject( win 
); 
2322     win
->GetEventHandler()->ProcessEvent( event 
); 
2326 //----------------------------------------------------------------------------- 
2327 // "value_changed" from m_hAdjust 
2328 //----------------------------------------------------------------------------- 
2331 static void gtk_window_hscroll_callback( GtkAdjustment 
*adjust
, 
2338         wxapp_install_idle_handler(); 
2340     if (g_blockEventsOnDrag
) return; 
2341     if (!win
->m_hasVMT
) return; 
2343     float diff 
= adjust
->value 
- win
->m_oldHorizontalPos
; 
2344     if (fabs(diff
) < 0.2) return; 
2347     GtkScrolledWindow   
*sw 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
2349     wxEventType         command 
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->hscrollbar
)); 
2351     win
->m_oldHorizontalPos 
= adjust
->value
; 
2353     int value 
= (int)(adjust
->value
+0.5); 
2355     wxScrollWinEvent 
event( command
, value
, wxHORIZONTAL 
); 
2356     event
.SetEventObject( win 
); 
2357     win
->GetEventHandler()->ProcessEvent( event 
); 
2361 //----------------------------------------------------------------------------- 
2362 // "button_press_event" from scrollbar 
2363 //----------------------------------------------------------------------------- 
2366 static gint 
gtk_scrollbar_button_press_callback( GtkRange 
*widget
, 
2367                                                  GdkEventButton 
*gdk_event
, 
2373         wxapp_install_idle_handler(); 
2376     g_blockEventsOnScroll 
= TRUE
; 
2378     // FIXME: there is no 'slider' field in GTK+ 2.0 any more 
2380     win
->m_isScrolling 
= (gdk_event
->window 
== widget
->slider
); 
2387 //----------------------------------------------------------------------------- 
2388 // "button_release_event" from scrollbar 
2389 //----------------------------------------------------------------------------- 
2392 static gint 
gtk_scrollbar_button_release_callback( GtkRange 
*widget
, 
2393                                                    GdkEventButton 
*WXUNUSED(gdk_event
), 
2398 //  don't test here as we can release the mouse while being over 
2399 //  a different window than the slider 
2401 //    if (gdk_event->window != widget->slider) return FALSE; 
2403     g_blockEventsOnScroll 
= FALSE
; 
2405     if (win
->m_isScrolling
) 
2407         wxEventType command 
= wxEVT_SCROLLWIN_THUMBRELEASE
; 
2411         GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
2412         if (widget 
== GTK_RANGE(scrolledWindow
->hscrollbar
)) 
2414             value 
= (int)(win
->m_hAdjust
->value
+0.5); 
2417         if (widget 
== GTK_RANGE(scrolledWindow
->vscrollbar
)) 
2419             value 
= (int)(win
->m_vAdjust
->value
+0.5); 
2423         wxScrollWinEvent 
event( command
, value
, dir 
); 
2424         event
.SetEventObject( win 
); 
2425         win
->GetEventHandler()->ProcessEvent( event 
); 
2428     win
->m_isScrolling 
= FALSE
; 
2434 // ---------------------------------------------------------------------------- 
2435 // this wxWindowBase function is implemented here (in platform-specific file) 
2436 // because it is static and so couldn't be made virtual 
2437 // ---------------------------------------------------------------------------- 
2439 wxWindow 
*wxWindowBase::DoFindFocus() 
2441     // the cast is necessary when we compile in wxUniversal mode 
2442     return (wxWindow 
*)g_focusWindow
; 
2445 //----------------------------------------------------------------------------- 
2446 // "realize" from m_widget 
2447 //----------------------------------------------------------------------------- 
2449 /* We cannot set colours and fonts before the widget has 
2450    been realized, so we do this directly after realization. */ 
2454 gtk_window_realized_callback( GtkWidget 
*m_widget
, wxWindow 
*win 
) 
2459         wxapp_install_idle_handler(); 
2464         GtkPizza 
*pizza 
= GTK_PIZZA( m_widget 
); 
2465         gtk_im_context_set_client_window( win
->m_imData
->context
, 
2466                                           pizza
->bin_window 
); 
2470     wxWindowCreateEvent 
event( win 
); 
2471     event
.SetEventObject( win 
); 
2472     win
->GetEventHandler()->ProcessEvent( event 
); 
2478 //----------------------------------------------------------------------------- 
2480 //----------------------------------------------------------------------------- 
2484 void gtk_window_size_callback( GtkWidget 
*WXUNUSED(widget
), 
2485                                GtkAllocation 
*WXUNUSED(alloc
), 
2489         wxapp_install_idle_handler(); 
2491     if (!win
->m_hasScrolling
) return; 
2493     int client_width 
= 0; 
2494     int client_height 
= 0; 
2495     win
->GetClientSize( &client_width
, &client_height 
); 
2496     if ((client_width 
== win
->m_oldClientWidth
) && (client_height 
== win
->m_oldClientHeight
)) 
2499     win
->m_oldClientWidth 
= client_width
; 
2500     win
->m_oldClientHeight 
= client_height
; 
2502     if (!win
->m_nativeSizeEvent
) 
2504         wxSizeEvent 
event( win
->GetSize(), win
->GetId() ); 
2505         event
.SetEventObject( win 
); 
2506         win
->GetEventHandler()->ProcessEvent( event 
); 
2513     #define WXUNUSED_UNLESS_XIM(param)  param 
2515     #define WXUNUSED_UNLESS_XIM(param)  WXUNUSED(param) 
2518 /* Resize XIM window */ 
2522 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
), 
2523                                  GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
), 
2524                                  wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) ) 
2527         wxapp_install_idle_handler(); 
2533     if  (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
) 
2537         gdk_window_get_size (widget
->window
, &width
, &height
); 
2538         win
->m_icattr
->preedit_area
.width 
= width
; 
2539         win
->m_icattr
->preedit_area
.height 
= height
; 
2540         gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
); 
2546 //----------------------------------------------------------------------------- 
2547 // "realize" from m_wxwindow 
2548 //----------------------------------------------------------------------------- 
2550 /* Initialize XIM support */ 
2554 gtk_wxwindow_realized_callback( GtkWidget 
* WXUNUSED_UNLESS_XIM(widget
), 
2555                                 wxWindowGTK 
* WXUNUSED_UNLESS_XIM(win
) ) 
2558         wxapp_install_idle_handler(); 
2561     if (win
->m_ic
) return FALSE
; 
2562     if (!widget
) return FALSE
; 
2563     if (!gdk_im_ready()) return FALSE
; 
2565     win
->m_icattr 
= gdk_ic_attr_new(); 
2566     if (!win
->m_icattr
) return FALSE
; 
2570     GdkColormap 
*colormap
; 
2571     GdkICAttr 
*attr 
= win
->m_icattr
; 
2572     unsigned attrmask 
= GDK_IC_ALL_REQ
; 
2574     GdkIMStyle supported_style 
= (GdkIMStyle
) 
2575                                   (GDK_IM_PREEDIT_NONE 
| 
2576                                    GDK_IM_PREEDIT_NOTHING 
| 
2577                                    GDK_IM_PREEDIT_POSITION 
| 
2578                                    GDK_IM_STATUS_NONE 
| 
2579                                    GDK_IM_STATUS_NOTHING
); 
2581     if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2582         supported_style 
= (GdkIMStyle
)(supported_style 
& ~GDK_IM_PREEDIT_POSITION
); 
2584     attr
->style 
= style 
= gdk_im_decide_style (supported_style
); 
2585     attr
->client_window 
= widget
->window
; 
2587     if ((colormap 
= gtk_widget_get_colormap (widget
)) != 
2588             gtk_widget_get_default_colormap ()) 
2590         attrmask 
|= GDK_IC_PREEDIT_COLORMAP
; 
2591         attr
->preedit_colormap 
= colormap
; 
2594     attrmask 
|= GDK_IC_PREEDIT_FOREGROUND
; 
2595     attrmask 
|= GDK_IC_PREEDIT_BACKGROUND
; 
2596     attr
->preedit_foreground 
= widget
->style
->fg
[GTK_STATE_NORMAL
]; 
2597     attr
->preedit_background 
= widget
->style
->base
[GTK_STATE_NORMAL
]; 
2599     switch (style 
& GDK_IM_PREEDIT_MASK
) 
2601         case GDK_IM_PREEDIT_POSITION
: 
2602             if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2604                 g_warning ("over-the-spot style requires fontset"); 
2608             gdk_window_get_size (widget
->window
, &width
, &height
); 
2610             attrmask 
|= GDK_IC_PREEDIT_POSITION_REQ
; 
2611             attr
->spot_location
.x 
= 0; 
2612             attr
->spot_location
.y 
= height
; 
2613             attr
->preedit_area
.x 
= 0; 
2614             attr
->preedit_area
.y 
= 0; 
2615             attr
->preedit_area
.width 
= width
; 
2616             attr
->preedit_area
.height 
= height
; 
2617             attr
->preedit_fontset 
= widget
->style
->font
; 
2622       win
->m_ic 
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
); 
2624       if (win
->m_ic 
== NULL
) 
2625           g_warning ("Can't create input context."); 
2628           mask 
= gdk_window_get_events (widget
->window
); 
2629           mask 
= (GdkEventMask
)(mask 
| gdk_ic_get_events (win
->m_ic
)); 
2630           gdk_window_set_events (widget
->window
, mask
); 
2632           if (GTK_WIDGET_HAS_FOCUS(widget
)) 
2633               gdk_im_begin (win
->m_ic
, widget
->window
); 
2641 //----------------------------------------------------------------------------- 
2642 // InsertChild for wxWindowGTK. 
2643 //----------------------------------------------------------------------------- 
2645 /* Callback for wxWindowGTK. This very strange beast has to be used because 
2646  * C++ has no virtual methods in a constructor. We have to emulate a 
2647  * virtual function here as wxNotebook requires a different way to insert 
2648  * a child in it. I had opted for creating a wxNotebookPage window class 
2649  * which would have made this superfluous (such in the MDI window system), 
2650  * but no-one was listening to me... */ 
2652 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child 
) 
2654     /* the window might have been scrolled already, do we 
2655        have to adapt the position */ 
2656     GtkPizza 
*pizza 
= GTK_PIZZA(parent
->m_wxwindow
); 
2657     child
->m_x 
+= pizza
->xoffset
; 
2658     child
->m_y 
+= pizza
->yoffset
; 
2660     gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
), 
2661                      GTK_WIDGET(child
->m_widget
), 
2668 //----------------------------------------------------------------------------- 
2670 //----------------------------------------------------------------------------- 
2672 wxWindow 
*wxGetActiveWindow() 
2674     return wxWindow::FindFocus(); 
2677 //----------------------------------------------------------------------------- 
2679 //----------------------------------------------------------------------------- 
2681 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
2683 #ifdef __WXUNIVERSAL__ 
2684     IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
) 
2686     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
2687 #endif // __WXUNIVERSAL__/__WXGTK__ 
2689 void wxWindowGTK::Init() 
2692     m_widget 
= (GtkWidget 
*) NULL
; 
2693     m_wxwindow 
= (GtkWidget 
*) NULL
; 
2694     m_focusWidget 
= (GtkWidget 
*) NULL
; 
2704     m_needParent 
= TRUE
; 
2705     m_isBeingDeleted 
= FALSE
; 
2708     m_nativeSizeEvent 
= FALSE
; 
2710     m_hasScrolling 
= FALSE
; 
2711     m_isScrolling 
= FALSE
; 
2713     m_hAdjust 
= (GtkAdjustment
*) NULL
; 
2714     m_vAdjust 
= (GtkAdjustment
*) NULL
; 
2715     m_oldHorizontalPos 
= 
2716     m_oldVerticalPos 
= 0.0; 
2718     m_oldClientHeight 
= 0; 
2722     m_insertCallback 
= (wxInsertChildFunction
) NULL
; 
2724     m_acceptsFocus 
= FALSE
; 
2727     m_clipPaintRegion 
= FALSE
; 
2729     m_needsStyleChange 
= false; 
2731     m_cursor 
= *wxSTANDARD_CURSOR
; 
2735     m_x11Context 
= NULL
; 
2736     m_dirtyTabOrder 
= false; 
2739     m_ic 
= (GdkIC
*) NULL
; 
2740     m_icattr 
= (GdkICAttr
*) NULL
; 
2745 wxWindowGTK::wxWindowGTK() 
2750 wxWindowGTK::wxWindowGTK( wxWindow 
*parent
, 
2755                           const wxString 
&name  
) 
2759     Create( parent
, id
, pos
, size
, style
, name 
); 
2762 bool wxWindowGTK::Create( wxWindow 
*parent
, 
2767                           const wxString 
&name  
) 
2769     if (!PreCreation( parent
, pos
, size 
) || 
2770         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
2772         wxFAIL_MSG( wxT("wxWindowGTK creation failed") ); 
2776     m_insertCallback 
= wxInsertChildInWindow
; 
2778     m_widget 
= gtk_scrolled_window_new( (GtkAdjustment 
*) NULL
, (GtkAdjustment 
*) NULL 
); 
2779     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
2781     GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
2783     GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2784     scroll_class
->scrollbar_spacing 
= 0; 
2786     gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
2788     m_hAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) ); 
2789     m_vAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) ); 
2791     m_wxwindow 
= gtk_pizza_new(); 
2793 #ifndef __WXUNIVERSAL__ 
2794     GtkPizza 
*pizza 
= GTK_PIZZA(m_wxwindow
); 
2796     if (HasFlag(wxRAISED_BORDER
)) 
2798         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT 
); 
2800     else if (HasFlag(wxSUNKEN_BORDER
)) 
2802         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN 
); 
2804     else if (HasFlag(wxSIMPLE_BORDER
)) 
2806         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN 
); 
2810         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE 
); 
2812 #endif // __WXUNIVERSAL__ 
2814     gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
2816     GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
2817     m_acceptsFocus 
= TRUE
; 
2819     // I _really_ don't want scrollbars in the beginning 
2820     m_vAdjust
->lower 
= 0.0; 
2821     m_vAdjust
->upper 
= 1.0; 
2822     m_vAdjust
->value 
= 0.0; 
2823     m_vAdjust
->step_increment 
= 1.0; 
2824     m_vAdjust
->page_increment 
= 1.0; 
2825     m_vAdjust
->page_size 
= 5.0; 
2826     gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
2827     m_hAdjust
->lower 
= 0.0; 
2828     m_hAdjust
->upper 
= 1.0; 
2829     m_hAdjust
->value 
= 0.0; 
2830     m_hAdjust
->step_increment 
= 1.0; 
2831     m_hAdjust
->page_increment 
= 1.0; 
2832     m_hAdjust
->page_size 
= 5.0; 
2833     gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
2835     // these handlers block mouse events to any window during scrolling such as 
2836     // motion events and prevent GTK and wxWidgets from fighting over where the 
2839     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event", 
2840           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
2842     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event", 
2843           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
2845     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event", 
2846           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
2848     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event", 
2849           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
2851     // these handlers get notified when screen updates are required either when 
2852     // scrolling or when the window size (and therefore scrollbar configuration) 
2855     gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
2856           (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
2857     gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
2858           (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
2860     gtk_widget_show( m_wxwindow 
); 
2863         m_parent
->DoAddChild( this ); 
2865     m_focusWidget 
= m_wxwindow
; 
2872 wxWindowGTK::~wxWindowGTK() 
2876     if (g_focusWindow 
== this) 
2877         g_focusWindow 
= NULL
; 
2879     if ( g_delayedFocus 
== this ) 
2880         g_delayedFocus 
= NULL
; 
2882     m_isBeingDeleted 
= TRUE
; 
2892         gdk_ic_destroy (m_ic
); 
2894         gdk_ic_attr_destroy (m_icattr
); 
2899         gtk_widget_destroy( m_wxwindow 
); 
2900         m_wxwindow 
= (GtkWidget
*) NULL
; 
2905         gtk_widget_destroy( m_widget 
); 
2906         m_widget 
= (GtkWidget
*) NULL
; 
2914 bool wxWindowGTK::PreCreation( wxWindowGTK 
*parent
, const wxPoint 
&pos
,  const wxSize 
&size 
) 
2916     wxCHECK_MSG( !m_needParent 
|| parent
, FALSE
, wxT("Need complete parent.") ); 
2918     // Use either the given size, or the default if -1 is given. 
2919     // See wxWindowBase for these functions. 
2920     m_width 
= WidthDefault(size
.x
) ; 
2921     m_height 
= HeightDefault(size
.y
); 
2929 void wxWindowGTK::PostCreation() 
2931     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2937             // these get reported to wxWidgets -> wxPaintEvent 
2939             gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE 
); 
2941             gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event", 
2942                 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this ); 
2945             gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw", 
2946                 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this ); 
2948             if (!HasFlag(wxFULL_REPAINT_ON_RESIZE
)) 
2950                 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event", 
2951                     GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this ); 
2954             // gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), !HasFlag( wxFULL_REPAINT_ON_RESIZE ) ); 
2959         // Create input method handler 
2960         m_imData 
= new wxGtkIMData
; 
2962         // Cannot handle drawing preedited text yet 
2963         gtk_im_context_set_use_preedit( m_imData
->context
, FALSE 
); 
2965         g_signal_connect (G_OBJECT (m_imData
->context
), "commit", 
2966                           G_CALLBACK (gtk_wxwindow_commit_cb
), this); 
2969         // these are called when the "sunken" or "raised" borders are drawn 
2970         gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event", 
2971           GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this ); 
2974         gtk_signal_connect( GTK_OBJECT(m_widget
), "draw", 
2975           GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this ); 
2981     if (!GTK_IS_WINDOW(m_widget
)) 
2983         if (m_focusWidget 
== NULL
) 
2984             m_focusWidget 
= m_widget
; 
2986         gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event", 
2987             GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this ); 
2989         gtk_signal_connect_after( GTK_OBJECT(m_focusWidget
), "focus_out_event", 
2990             GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this ); 
2993     // connect to the various key and mouse handlers 
2995     GtkWidget 
*connect_widget 
= GetConnectWidget(); 
2997     ConnectWidget( connect_widget 
); 
2999     /* We cannot set colours, fonts and cursors before the widget has 
3000        been realized, so we do this directly after realization */ 
3001     gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize", 
3002                             GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this ); 
3006         // Catch native resize events 
3007         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate", 
3008                             GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this ); 
3010         // Initialize XIM support 
3011         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize", 
3012                             GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this ); 
3014         // And resize XIM window 
3015         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate", 
3016                             GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this ); 
3019     if (GTK_IS_COMBO(m_widget
)) 
3021         GtkCombo 
*gcombo 
= GTK_COMBO(m_widget
); 
3023         gtk_signal_connect( GTK_OBJECT(gcombo
->entry
), "size_request", 
3024                             GTK_SIGNAL_FUNC(wxgtk_combo_size_request_callback
), 
3029         // This is needed if we want to add our windows into native 
3030         // GTK controls, such as the toolbar. With this callback, the 
3031         // toolbar gets to know the correct size (the one set by the 
3032         // programmer). Sadly, it misbehaves for wxComboBox. 
3033         gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request", 
3034                             GTK_SIGNAL_FUNC(wxgtk_window_size_request_callback
), 
3038     InheritAttributes(); 
3042     // unless the window was created initially hidden (i.e. Hide() had been 
3043     // called before Create()), we should show it at GTK+ level as well 
3045         gtk_widget_show( m_widget 
); 
3048 void wxWindowGTK::ConnectWidget( GtkWidget 
*widget 
) 
3050     gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event", 
3051       GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this ); 
3053     gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event", 
3054       GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this ); 
3056     gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event", 
3057       GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this ); 
3059     gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event", 
3060       GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this ); 
3062     gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event", 
3063       GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this ); 
3066     gtk_signal_connect( GTK_OBJECT(widget
), "scroll_event", 
3067       GTK_SIGNAL_FUNC(gtk_window_wheel_callback
), (gpointer
)this ); 
3068     g_signal_connect(widget
, "popup_menu", 
3069         G_CALLBACK(wxgtk_window_popup_menu_callback
), this); 
3072     gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event", 
3073       GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this ); 
3075     gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event", 
3076       GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this ); 
3079 bool wxWindowGTK::Destroy() 
3081     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3085     return wxWindowBase::Destroy(); 
3088 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
) 
3090     gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height 
); 
3093 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
3095     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3096     wxASSERT_MSG( (m_parent 
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") ); 
3099     printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height ); 
3102     if (m_resizing
) return; /* I don't like recursions */ 
3105     int currentX
, currentY
; 
3106     GetPosition(¤tX
, ¤tY
); 
3107     if (x 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
3109     if (y 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
3111     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
3113     if (m_parent
->m_wxwindow 
== NULL
) /* i.e. wxNotebook */ 
3115         /* don't set the size for children of wxNotebook, just take the values. */ 
3123         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
3124         if ((sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) == 0) 
3126             if (x 
!= -1) m_x 
= x 
+ pizza
->xoffset
; 
3127             if (y 
!= -1) m_y 
= y 
+ pizza
->yoffset
; 
3131             m_x 
= x 
+ pizza
->xoffset
; 
3132             m_y 
= y 
+ pizza
->yoffset
; 
3135         // calculate the best size if we should auto size the window 
3136         if ( ((sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1) || 
3137                 ((sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1) ) 
3139             const wxSize sizeBest 
= GetBestSize(); 
3140             if ( (sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1 ) 
3142             if ( (sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1 ) 
3143                 height 
= sizeBest
.y
; 
3151         int minWidth 
= GetMinWidth(), 
3152             minHeight 
= GetMinHeight(), 
3153             maxWidth 
= GetMaxWidth(), 
3154             maxHeight 
= GetMaxHeight(); 
3156         if ((minWidth 
!= -1) && (m_width 
< minWidth
)) m_width 
= minWidth
; 
3157         if ((minHeight 
!= -1) && (m_height 
< minHeight
)) m_height 
= minHeight
; 
3158         if ((maxWidth 
!= -1) && (m_width 
> maxWidth
)) m_width 
= maxWidth
; 
3159         if ((maxHeight 
!= -1) && (m_height 
> maxHeight
)) m_height 
= maxHeight
; 
3161         int left_border 
= 0; 
3162         int right_border 
= 0; 
3164         int bottom_border 
= 0; 
3166         /* the default button has a border around it */ 
3167         if (GTK_WIDGET_CAN_DEFAULT(m_widget
)) 
3170             GtkBorder 
*default_border 
= NULL
; 
3171             gtk_widget_style_get( m_widget
, "default_border", &default_border
, NULL 
); 
3174                 left_border 
+= default_border
->left
; 
3175                 right_border 
+= default_border
->right
; 
3176                 top_border 
+= default_border
->top
; 
3177                 bottom_border 
+= default_border
->bottom
; 
3178                 g_free( default_border 
); 
3188         DoMoveWindow( m_x
-top_border
, 
3190                       m_width
+left_border
+right_border
, 
3191                       m_height
+top_border
+bottom_border 
); 
3196         /* Sometimes the client area changes size without the 
3197            whole windows's size changing, but if the whole 
3198            windows's size doesn't change, no wxSizeEvent will 
3199            normally be sent. Here we add an extra test if 
3200            the client test has been changed and this will 
3202         GetClientSize( &m_oldClientWidth
, &m_oldClientHeight 
); 
3206     wxPrintf( "OnSize sent from " ); 
3207     if (GetClassInfo() && GetClassInfo()->GetClassName()) 
3208         wxPrintf( GetClassInfo()->GetClassName() ); 
3209     wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height ); 
3212     if (!m_nativeSizeEvent
) 
3214         wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
3215         event
.SetEventObject( this ); 
3216         GetEventHandler()->ProcessEvent( event 
); 
3222 void wxWindowGTK::OnInternalIdle() 
3225     if ( m_dirtyTabOrder 
) 
3228     // Update style if the window was not yet realized 
3229     // and SetBackgroundStyle(wxBG_STYLE_CUSTOM) was called 
3230     if (m_needsStyleChange
) 
3232         SetBackgroundStyle(GetBackgroundStyle()); 
3233         m_needsStyleChange 
= false; 
3236     // Update invalidated regions. 
3239     wxCursor cursor 
= m_cursor
; 
3240     if (g_globalCursor
.Ok()) cursor 
= g_globalCursor
; 
3244         /* I now set the cursor anew in every OnInternalIdle call 
3245            as setting the cursor in a parent window also effects the 
3246            windows above so that checking for the current cursor is 
3251             GdkWindow 
*window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3253                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3255             if (!g_globalCursor
.Ok()) 
3256                 cursor 
= *wxSTANDARD_CURSOR
; 
3258             window 
= m_widget
->window
; 
3259             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
3260                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3266             GdkWindow 
*window 
= m_widget
->window
; 
3267             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
3268                gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3273     if (wxUpdateUIEvent::CanUpdate(this)) 
3274         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
3277 void wxWindowGTK::DoGetSize( int *width
, int *height 
) const 
3279     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3281     if (width
) (*width
) = m_width
; 
3282     if (height
) (*height
) = m_height
; 
3285 void wxWindowGTK::DoSetClientSize( int width
, int height 
) 
3287     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3291         SetSize( width
, height 
); 
3298 #ifndef __WXUNIVERSAL__ 
3299         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
3301             /* when using GTK 1.2 we set the shadow border size to 2 */ 
3305         if (HasFlag(wxSIMPLE_BORDER
)) 
3307             /* when using GTK 1.2 we set the simple border size to 1 */ 
3311 #endif // __WXUNIVERSAL__ 
3315             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
3317             GtkRequisition vscroll_req
; 
3318             vscroll_req
.width 
= 2; 
3319             vscroll_req
.height 
= 2; 
3320             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
3321                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
3323             GtkRequisition hscroll_req
; 
3324             hscroll_req
.width 
= 2; 
3325             hscroll_req
.height 
= 2; 
3326             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
3327                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
3329             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
3331             if (scroll_window
->vscrollbar_visible
) 
3333                 dw 
+= vscroll_req
.width
; 
3334                 dw 
+= scroll_class
->scrollbar_spacing
; 
3337             if (scroll_window
->hscrollbar_visible
) 
3339                 dh 
+= hscroll_req
.height
; 
3340                 dh 
+= scroll_class
->scrollbar_spacing
; 
3344        SetSize( width
+dw
, height
+dh 
); 
3348 void wxWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
3350     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3354         if (width
) (*width
) = m_width
; 
3355         if (height
) (*height
) = m_height
; 
3362 #ifndef __WXUNIVERSAL__ 
3363         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
3365             /* when using GTK 1.2 we set the shadow border size to 2 */ 
3369         if (HasFlag(wxSIMPLE_BORDER
)) 
3371             /* when using GTK 1.2 we set the simple border size to 1 */ 
3375 #endif // __WXUNIVERSAL__ 
3379             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
3381             GtkRequisition vscroll_req
; 
3382             vscroll_req
.width 
= 2; 
3383             vscroll_req
.height 
= 2; 
3384             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
3385                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
3387             GtkRequisition hscroll_req
; 
3388             hscroll_req
.width 
= 2; 
3389             hscroll_req
.height 
= 2; 
3390             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
3391                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
3393             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
3395             if (scroll_window
->vscrollbar_visible
) 
3397                 dw 
+= vscroll_req
.width
; 
3398                 dw 
+= scroll_class
->scrollbar_spacing
; 
3401             if (scroll_window
->hscrollbar_visible
) 
3403                 dh 
+= hscroll_req
.height
; 
3404                 dh 
+= scroll_class
->scrollbar_spacing
; 
3408         if (width
) (*width
) = m_width 
- dw
; 
3409         if (height
) (*height
) = m_height 
- dh
; 
3413     printf( "GetClientSize, name %s ", GetName().c_str() ); 
3414     if (width) printf( " width = %d", (*width) ); 
3415     if (height) printf( " height = %d", (*height) ); 
3420 void wxWindowGTK::DoGetPosition( int *x
, int *y 
) const 
3422     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3426     if (m_parent 
&& m_parent
->m_wxwindow
) 
3428         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
3429         dx 
= pizza
->xoffset
; 
3430         dy 
= pizza
->yoffset
; 
3433     if (x
) (*x
) = m_x 
- dx
; 
3434     if (y
) (*y
) = m_y 
- dy
; 
3437 void wxWindowGTK::DoClientToScreen( int *x
, int *y 
) const 
3439     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3441     if (!m_widget
->window
) return; 
3443     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3445         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3447         source 
= m_widget
->window
; 
3451     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3455         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3457             org_x 
+= m_widget
->allocation
.x
; 
3458             org_y 
+= m_widget
->allocation
.y
; 
3466 void wxWindowGTK::DoScreenToClient( int *x
, int *y 
) const 
3468     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3470     if (!m_widget
->window
) return; 
3472     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3474         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3476         source 
= m_widget
->window
; 
3480     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3484         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3486             org_x 
+= m_widget
->allocation
.x
; 
3487             org_y 
+= m_widget
->allocation
.y
; 
3495 bool wxWindowGTK::Show( bool show 
) 
3497     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3499     if (!wxWindowBase::Show(show
)) 
3506         gtk_widget_show( m_widget 
); 
3508         gtk_widget_hide( m_widget 
); 
3510     wxShowEvent 
eventShow(GetId(), show
); 
3511     eventShow
.SetEventObject(this); 
3513     GetEventHandler()->ProcessEvent(eventShow
); 
3518 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
) 
3520     win
->OnParentEnable(enable
); 
3522     // Recurse, so that children have the opportunity to Do The Right Thing 
3523     // and reset colours that have been messed up by a parent's (really ancestor's) 
3525     for ( wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
3527           node 
= node
->GetNext() ) 
3529         wxWindow 
*child 
= node
->GetData(); 
3530         if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
))) 
3531             wxWindowNotifyEnable(child
, enable
); 
3535 bool wxWindowGTK::Enable( bool enable 
) 
3537     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3539     if (!wxWindowBase::Enable(enable
)) 
3545     gtk_widget_set_sensitive( m_widget
, enable 
); 
3547         gtk_widget_set_sensitive( m_wxwindow
, enable 
); 
3549     wxWindowNotifyEnable(this, enable
); 
3554 int wxWindowGTK::GetCharHeight() const 
3556     wxCHECK_MSG( (m_widget 
!= NULL
), 12, wxT("invalid window") ); 
3558     wxFont font 
= GetFont(); 
3559     wxCHECK_MSG( font
.Ok(), 12, wxT("invalid font") ); 
3562     PangoContext 
*context 
= NULL
; 
3564         context 
= gtk_widget_get_pango_context( m_widget 
); 
3569     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
3570     PangoLayout 
*layout 
= pango_layout_new(context
); 
3571     pango_layout_set_font_description(layout
, desc
); 
3572     pango_layout_set_text(layout
, "H", 1); 
3573     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
3575     PangoRectangle rect
; 
3576     pango_layout_line_get_extents(line
, NULL
, &rect
); 
3578     g_object_unref( G_OBJECT( layout 
) ); 
3580     return (int) PANGO_PIXELS(rect
.height
); 
3582     GdkFont 
*gfont 
= font
.GetInternalFont( 1.0 ); 
3584     return gfont
->ascent 
+ gfont
->descent
; 
3588 int wxWindowGTK::GetCharWidth() const 
3590     wxCHECK_MSG( (m_widget 
!= NULL
), 8, wxT("invalid window") ); 
3592     wxFont font 
= GetFont(); 
3593     wxCHECK_MSG( font
.Ok(), 8, wxT("invalid font") ); 
3596     PangoContext 
*context 
= NULL
; 
3598         context 
= gtk_widget_get_pango_context( m_widget 
); 
3603     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
3604     PangoLayout 
*layout 
= pango_layout_new(context
); 
3605     pango_layout_set_font_description(layout
, desc
); 
3606     pango_layout_set_text(layout
, "g", 1); 
3607     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
3609     PangoRectangle rect
; 
3610     pango_layout_line_get_extents(line
, NULL
, &rect
); 
3612     g_object_unref( G_OBJECT( layout 
) ); 
3614     return (int) PANGO_PIXELS(rect
.width
); 
3616     GdkFont 
*gfont 
= font
.GetInternalFont( 1.0 ); 
3618     return gdk_string_width( gfont
, "g" ); 
3622 void wxWindowGTK::GetTextExtent( const wxString
& string
, 
3626                               int *externalLeading
, 
3627                               const wxFont 
*theFont 
) const 
3629     wxFont fontToUse 
= theFont 
? *theFont 
: GetFont(); 
3631     wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") ); 
3633     if (string
.IsEmpty()) 
3641     PangoContext 
*context 
= NULL
; 
3643         context 
= gtk_widget_get_pango_context( m_widget 
); 
3652     PangoFontDescription 
*desc 
= fontToUse
.GetNativeFontInfo()->description
; 
3653     PangoLayout 
*layout 
= pango_layout_new(context
); 
3654     pango_layout_set_font_description(layout
, desc
); 
3657         const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( string 
); 
3658         pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data 
)); 
3660         const wxWCharBuffer wdata 
= wxConvLocal
.cMB2WC( string 
); 
3661         const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( wdata 
); 
3662         pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data 
)); 
3666     PangoRectangle rect
; 
3667     pango_layout_get_extents(layout
, NULL
, &rect
); 
3669     if (x
) (*x
) = (wxCoord
) PANGO_PIXELS(rect
.width
); 
3670     if (y
) (*y
) = (wxCoord
) PANGO_PIXELS(rect
.height
); 
3673         PangoLayoutIter 
*iter 
= pango_layout_get_iter(layout
); 
3674         int baseline 
= pango_layout_iter_get_baseline(iter
); 
3675         pango_layout_iter_free(iter
); 
3676         *descent 
= *y 
- PANGO_PIXELS(baseline
); 
3678     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3680     g_object_unref( G_OBJECT( layout 
) ); 
3682     GdkFont 
*font 
= fontToUse
.GetInternalFont( 1.0 ); 
3683     if (x
) (*x
) = gdk_string_width( font
, wxGTK_CONV( string 
) ); 
3684     if (y
) (*y
) = font
->ascent 
+ font
->descent
; 
3685     if (descent
) (*descent
) = font
->descent
; 
3686     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3690 void wxWindowGTK::SetFocus() 
3692     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3695         // don't do anything if we already have focus 
3701         if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
)) 
3703             gtk_widget_grab_focus (m_wxwindow
); 
3709         if (GTK_IS_CONTAINER(m_widget
)) 
3711             gtk_widget_child_focus( m_widget
, GTK_DIR_TAB_FORWARD 
); 
3715         if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) ) 
3718             if (!GTK_WIDGET_REALIZED(m_widget
)) 
3720                 // we can't set the focus to the widget now so we remember that 
3721                 // it should be focused and will do it later, during the idle 
3722                 // time, as soon as we can 
3723                 wxLogTrace(TRACE_FOCUS
, 
3724                            _T("Delaying setting focus to %s(%s)"), 
3725                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3727                 g_delayedFocus 
= this; 
3731                 wxLogTrace(TRACE_FOCUS
, 
3732                            _T("Setting focus to %s(%s)"), 
3733                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3735                 gtk_widget_grab_focus (m_widget
); 
3740         if (GTK_IS_CONTAINER(m_widget
)) 
3742             gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD 
); 
3747            wxLogTrace(TRACE_FOCUS
, 
3748                       _T("Can't set focus to %s(%s)"), 
3749                       GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3754 bool wxWindowGTK::AcceptsFocus() const 
3756     return m_acceptsFocus 
&& wxWindowBase::AcceptsFocus(); 
3759 bool wxWindowGTK::Reparent( wxWindowBase 
*newParentBase 
) 
3761     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3763     wxWindowGTK 
*oldParent 
= m_parent
, 
3764              *newParent 
= (wxWindowGTK 
*)newParentBase
; 
3766     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3768     if ( !wxWindowBase::Reparent(newParent
) ) 
3771     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3773     /* prevent GTK from deleting the widget arbitrarily */ 
3774     gtk_widget_ref( m_widget 
); 
3778         gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget 
); 
3781     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3785         /* insert GTK representation */ 
3786         (*(newParent
->m_insertCallback
))(newParent
, this); 
3789     /* reverse: prevent GTK from deleting the widget arbitrarily */ 
3790     gtk_widget_unref( m_widget 
); 
3795 void wxWindowGTK::DoAddChild(wxWindowGTK 
*child
) 
3797     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3799     wxASSERT_MSG( (child 
!= NULL
), wxT("invalid child window") ); 
3801     wxASSERT_MSG( (m_insertCallback 
!= NULL
), wxT("invalid child insertion function") ); 
3806     /* insert GTK representation */ 
3807     (*m_insertCallback
)(this, child
); 
3812 void wxWindowGTK::AddChild(wxWindowBase 
*child
) 
3814     wxWindowBase::AddChild(child
); 
3815     m_dirtyTabOrder 
= true; 
3817         wxapp_install_idle_handler(); 
3820 void wxWindowGTK::RemoveChild(wxWindowBase 
*child
) 
3822     wxWindowBase::RemoveChild(child
); 
3823     m_dirtyTabOrder 
= true; 
3825         wxapp_install_idle_handler(); 
3828 void wxWindowGTK::DoMoveInTabOrder(wxWindow 
*win
, MoveKind move
) 
3830     wxWindowBase::DoMoveInTabOrder(win
, move
); 
3831     m_dirtyTabOrder 
= true; 
3833         wxapp_install_idle_handler(); 
3836 void wxWindowGTK::RealizeTabOrder() 
3840         if (m_children
.size() > 0) 
3842             GList 
*chain 
= NULL
; 
3844             for (wxWindowList::const_iterator i 
= m_children
.begin(); 
3845                     i 
!= m_children
.end(); ++i
) 
3847                 chain 
= g_list_prepend(chain
, (*i
)->m_widget
); 
3850             chain 
= g_list_reverse(chain
); 
3852             gtk_container_set_focus_chain(GTK_CONTAINER(m_wxwindow
), chain
); 
3857             gtk_container_unset_focus_chain(GTK_CONTAINER(m_wxwindow
)); 
3861     m_dirtyTabOrder 
= false; 
3864 #endif // __WXGTK20__ 
3866 void wxWindowGTK::Raise() 
3868     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3870     if (m_wxwindow 
&& m_wxwindow
->window
) 
3872         gdk_window_raise( m_wxwindow
->window 
); 
3874      else if (m_widget
->window
) 
3876         gdk_window_raise( m_widget
->window 
); 
3880 void wxWindowGTK::Lower() 
3882     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3884     if (m_wxwindow 
&& m_wxwindow
->window
) 
3886         gdk_window_lower( m_wxwindow
->window 
); 
3888      else if (m_widget
->window
) 
3890         gdk_window_lower( m_widget
->window 
); 
3894 bool wxWindowGTK::SetCursor( const wxCursor 
&cursor 
) 
3896     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3898     if (cursor 
== m_cursor
) 
3902         wxapp_install_idle_handler(); 
3904     if (cursor 
== wxNullCursor
) 
3905        return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR 
); 
3907        return wxWindowBase::SetCursor( cursor 
); 
3910 void wxWindowGTK::WarpPointer( int x
, int y 
) 
3912     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3914     // We provide this function ourselves as it is 
3915     // missing in GDK (top of this file). 
3917     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3919         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3921         window 
= GetConnectWidget()->window
; 
3924         gdk_window_warp_pointer( window
, x
, y 
); 
3928 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect 
*rect 
) 
3932     if (!m_widget
->window
) 
3937         wxapp_install_idle_handler(); 
3940     if (m_wxwindow 
&& rect
) 
3942         myRect
.SetSize(wxSize( m_wxwindow
->allocation
.width
, 
3943                                m_wxwindow
->allocation
.height
)); 
3944         if ( myRect
.Intersect(*rect
).IsEmpty() ) 
3946             // nothing to do, rectangle is empty 
3953     // schedule the area for later updating in GtkUpdate() 
3954     if (eraseBackground 
&& m_wxwindow 
&& m_wxwindow
->window
) 
3958             m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3962             m_clearRegion
.Clear(); 
3963             m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3971             m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3975             GdkRectangle gdk_rect
; 
3976             gdk_rect
.x 
= rect
->x
; 
3977             gdk_rect
.y 
= rect
->y
; 
3978             gdk_rect
.width 
= rect
->width
; 
3979             gdk_rect
.height 
= rect
->height
; 
3980             gtk_widget_draw( m_widget
, &gdk_rect 
); 
3987             m_updateRegion
.Clear(); 
3988             m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3992             gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL 
); 
3998         GdkRectangle gdk_rect
, 
4002             gdk_rect
.x 
= rect
->x
; 
4003             gdk_rect
.y 
= rect
->y
; 
4004             gdk_rect
.width 
= rect
->width
; 
4005             gdk_rect
.height 
= rect
->height
; 
4008         else // invalidate everything 
4013         gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, p
, TRUE 
); 
4018 void wxWindowGTK::Update() 
4022     // when we call Update() we really want to update the window immediately on 
4023     // screen, even if itmeans flushing the entire queue and hence slowing down 
4024     // everything -- but it should still be done, it's just that Update() should 
4025     // be called very rarely 
4029 void wxWindowGTK::GtkUpdate() 
4032     if (m_wxwindow 
&& GTK_PIZZA(m_wxwindow
)->bin_window
) 
4033         gdk_window_process_updates( GTK_PIZZA(m_wxwindow
)->bin_window
, FALSE 
); 
4035     if (!m_updateRegion
.IsEmpty()) 
4036         GtkSendPaintEvents(); 
4039     // for consistency with other platforms (and also because it's convenient 
4040     // to be able to update an entire TLW by calling Update() only once), we 
4041     // should also update all our children here 
4042     for ( wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
4044           node 
= node
->GetNext() ) 
4046         node
->GetData()->GtkUpdate(); 
4050 void wxWindowGTK::GtkSendPaintEvents() 
4055         m_clearRegion
.Clear(); 
4057         m_updateRegion
.Clear(); 
4061     // Clip to paint region in wxClientDC 
4062     m_clipPaintRegion 
= TRUE
; 
4064     // widget to draw on 
4065     GtkPizza 
*pizza 
= GTK_PIZZA (m_wxwindow
); 
4067     if (GetThemeEnabled() && (GetBackgroundStyle() == wxBG_STYLE_SYSTEM
)) 
4069         // find ancestor from which to steal background 
4070         wxWindow 
*parent 
= wxGetTopLevelParent((wxWindow 
*)this); 
4072             parent 
= (wxWindow
*)this; 
4074         if (GTK_WIDGET_MAPPED(parent
->m_widget
)) 
4076             wxRegionIterator 
upd( m_updateRegion 
); 
4080                 rect
.x 
= upd
.GetX(); 
4081                 rect
.y 
= upd
.GetY(); 
4082                 rect
.width 
= upd
.GetWidth(); 
4083                 rect
.height 
= upd
.GetHeight(); 
4085                 gtk_paint_flat_box( parent
->m_widget
->style
, 
4087                             (GtkStateType
)GTK_WIDGET_STATE(m_wxwindow
), 
4102         wxWindowDC 
dc( (wxWindow
*)this ); 
4103         dc
.SetClippingRegion( m_updateRegion 
); 
4105         wxEraseEvent 
erase_event( GetId(), &dc 
); 
4106         erase_event
.SetEventObject( this ); 
4108         GetEventHandler()->ProcessEvent(erase_event
); 
4111     // if (!m_clearRegion.IsEmpty())   // Always send an erase event under GTK 1.2 
4113         wxWindowDC 
dc( (wxWindow
*)this ); 
4114         if (m_clearRegion
.IsEmpty()) 
4115             dc
.SetClippingRegion( m_updateRegion 
); 
4117             dc
.SetClippingRegion( m_clearRegion 
); 
4119         wxEraseEvent 
erase_event( GetId(), &dc 
); 
4120         erase_event
.SetEventObject( this ); 
4122         if (!GetEventHandler()->ProcessEvent(erase_event
) && GetBackgroundStyle() != wxBG_STYLE_CUSTOM
) 
4126                 g_eraseGC 
= gdk_gc_new( pizza
->bin_window 
); 
4127                 gdk_gc_set_fill( g_eraseGC
, GDK_SOLID 
); 
4129             gdk_gc_set_foreground( g_eraseGC
, GetBackgroundColour().GetColor() ); 
4131             wxRegionIterator 
upd( m_clearRegion 
); 
4134                 gdk_draw_rectangle( pizza
->bin_window
, g_eraseGC
, 1, 
4135                                     upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() ); 
4139         m_clearRegion
.Clear(); 
4143     wxNcPaintEvent 
nc_paint_event( GetId() ); 
4144     nc_paint_event
.SetEventObject( this ); 
4145     GetEventHandler()->ProcessEvent( nc_paint_event 
); 
4147     wxPaintEvent 
paint_event( GetId() ); 
4148     paint_event
.SetEventObject( this ); 
4149     GetEventHandler()->ProcessEvent( paint_event 
); 
4151     m_clipPaintRegion 
= FALSE
; 
4153 #ifndef __WXUNIVERSAL__ 
4155     // The following code will result in all window-less widgets 
4156     // being redrawn because the wxWidgets class is allowed to 
4157     // paint over the window-less widgets. 
4159     GList 
*children 
= pizza
->children
; 
4162         GtkPizzaChild 
*child 
= (GtkPizzaChild
*) children
->data
; 
4163         children 
= children
->next
; 
4165         if (GTK_WIDGET_NO_WINDOW (child
->widget
) && 
4166             GTK_WIDGET_DRAWABLE (child
->widget
)) 
4168             // Get intersection of widget area and update region 
4169             wxRegion 
region( m_updateRegion 
); 
4171             GdkEventExpose gdk_event
; 
4172             gdk_event
.type 
= GDK_EXPOSE
; 
4173             gdk_event
.window 
= pizza
->bin_window
; 
4174             gdk_event
.count 
= 0; 
4176             wxRegionIterator 
upd( m_updateRegion 
); 
4180                 rect
.x 
= upd
.GetX(); 
4181                 rect
.y 
= upd
.GetY(); 
4182                 rect
.width 
= upd
.GetWidth(); 
4183                 rect
.height 
= upd
.GetHeight(); 
4185                 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
)) 
4187                     gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
); 
4197     m_updateRegion
.Clear(); 
4200 void wxWindowGTK::ClearBackground() 
4202     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4205     if (m_wxwindow 
&& m_wxwindow
->window
) 
4207         m_clearRegion
.Clear(); 
4208         wxSize 
size( GetClientSize() ); 
4209         m_clearRegion
.Union( 0,0,size
.x
,size
.y 
); 
4211         // Better do this in idle? 
4218 void wxWindowGTK::DoSetToolTip( wxToolTip 
*tip 
) 
4220     wxWindowBase::DoSetToolTip(tip
); 
4223         m_tooltip
->Apply( (wxWindow 
*)this ); 
4226 void wxWindowGTK::ApplyToolTip( GtkTooltips 
*tips
, const wxChar 
*tip 
) 
4228     wxString 
tmp( tip 
); 
4229     gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxGTK_CONV(tmp
), (gchar
*) NULL 
); 
4231 #endif // wxUSE_TOOLTIPS 
4233 bool wxWindowGTK::SetBackgroundColour( const wxColour 
&colour 
) 
4235     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
4237     if (!wxWindowBase::SetBackgroundColour(colour
)) 
4242         // We need the pixel value e.g. for background clearing. 
4243         m_backgroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
4246     // apply style change (forceStyle=true so that new style is applied 
4247     // even if the bg colour changed from valid to wxNullColour) 
4248     if (GetBackgroundStyle() != wxBG_STYLE_CUSTOM
) 
4249         ApplyWidgetStyle(true); 
4254 bool wxWindowGTK::SetForegroundColour( const wxColour 
&colour 
) 
4256     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
4258     if (!wxWindowBase::SetForegroundColour(colour
)) 
4265         // We need the pixel value e.g. for background clearing. 
4266         m_foregroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
4269     // apply style change (forceStyle=true so that new style is applied 
4270     // even if the bg colour changed from valid to wxNullColour): 
4271     ApplyWidgetStyle(true); 
4277 PangoContext 
*wxWindowGTK::GtkGetPangoDefaultContext() 
4279     return gtk_widget_get_pango_context( m_widget 
); 
4282 PangoContext 
*wxWindowGTK::GtkGetPangoX11Context() 
4285         m_x11Context 
= pango_x_get_context( gdk_display 
); 
4287     return m_x11Context
; 
4291 GtkRcStyle 
*wxWindowGTK::CreateWidgetStyle(bool forceStyle
) 
4293     // do we need to apply any changes at all? 
4296          !m_foregroundColour
.Ok() && !m_backgroundColour
.Ok() ) 
4301     GtkRcStyle 
*style 
= gtk_rc_style_new(); 
4307             pango_font_description_copy( m_font
.GetNativeFontInfo()->description 
); 
4309         wxString xfontname 
= m_font
.GetNativeFontInfo()->GetXFontName(); 
4310         style
->fontset_name 
= g_strdup(xfontname
.c_str()); 
4314     if ( m_foregroundColour
.Ok() ) 
4316         GdkColor 
*fg 
= m_foregroundColour
.GetColor(); 
4318         style
->fg
[GTK_STATE_NORMAL
] = *fg
; 
4319         style
->color_flags
[GTK_STATE_NORMAL
] = GTK_RC_FG
; 
4321         style
->fg
[GTK_STATE_PRELIGHT
] = *fg
; 
4322         style
->color_flags
[GTK_STATE_PRELIGHT
] = GTK_RC_FG
; 
4324         style
->fg
[GTK_STATE_ACTIVE
] = *fg
; 
4325         style
->color_flags
[GTK_STATE_ACTIVE
] = GTK_RC_FG
; 
4328     if ( m_backgroundColour
.Ok() ) 
4330         GdkColor 
*bg 
= m_backgroundColour
.GetColor(); 
4332         style
->bg
[GTK_STATE_NORMAL
] = *bg
; 
4333         style
->base
[GTK_STATE_NORMAL
] = *bg
; 
4334         style
->color_flags
[GTK_STATE_NORMAL
] = (GtkRcFlags
) 
4335             (style
->color_flags
[GTK_STATE_NORMAL
] | GTK_RC_BG 
| GTK_RC_BASE
); 
4337         style
->bg
[GTK_STATE_PRELIGHT
] = *bg
; 
4338         style
->base
[GTK_STATE_PRELIGHT
] = *bg
; 
4339         style
->color_flags
[GTK_STATE_PRELIGHT
] = (GtkRcFlags
) 
4340             (style
->color_flags
[GTK_STATE_PRELIGHT
] | GTK_RC_BG 
| GTK_RC_BASE
); 
4342         style
->bg
[GTK_STATE_ACTIVE
] = *bg
; 
4343         style
->base
[GTK_STATE_ACTIVE
] = *bg
; 
4344         style
->color_flags
[GTK_STATE_ACTIVE
] = (GtkRcFlags
) 
4345             (style
->color_flags
[GTK_STATE_ACTIVE
] | GTK_RC_BG 
| GTK_RC_BASE
); 
4347         style
->bg
[GTK_STATE_INSENSITIVE
] = *bg
; 
4348         style
->base
[GTK_STATE_INSENSITIVE
] = *bg
; 
4349         style
->color_flags
[GTK_STATE_INSENSITIVE
] = (GtkRcFlags
) 
4350             (style
->color_flags
[GTK_STATE_INSENSITIVE
] | GTK_RC_BG 
| GTK_RC_BASE
); 
4356 void wxWindowGTK::ApplyWidgetStyle(bool forceStyle
) 
4358     GtkRcStyle 
*style 
= CreateWidgetStyle(forceStyle
); 
4361         DoApplyWidgetStyle(style
); 
4362         gtk_rc_style_unref(style
); 
4365     // Style change may affect GTK+'s size calculation: 
4366     InvalidateBestSize(); 
4369 void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
4372         gtk_widget_modify_style(m_wxwindow
, style
); 
4373     gtk_widget_modify_style(m_widget
, style
); 
4376 bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style
) 
4378     wxWindowBase::SetBackgroundStyle(style
); 
4380     if (style 
== wxBG_STYLE_CUSTOM
) 
4382         GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4384             window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4386             window 
= GetConnectWidget()->window
; 
4390             // Make sure GDK/X11 doesn't refresh the window 
4392             gdk_window_set_back_pixmap( window
, None
, False 
); 
4394             Display
* display 
= GDK_WINDOW_DISPLAY(window
); 
4397             m_needsStyleChange 
= false; 
4400             // Do in OnIdle, because the window is not yet available 
4401             m_needsStyleChange 
= true; 
4403         // Don't apply widget style, or we get a grey background 
4407         // apply style change (forceStyle=true so that new style is applied 
4408         // even if the bg colour changed from valid to wxNullColour): 
4409         ApplyWidgetStyle(true); 
4414 //----------------------------------------------------------------------------- 
4415 // Pop-up menu stuff 
4416 //----------------------------------------------------------------------------- 
4418 #if wxUSE_MENUS_NATIVE 
4421 void gtk_pop_hide_callback( GtkWidget 
*WXUNUSED(widget
), bool* is_waiting  
) 
4423     *is_waiting 
= FALSE
; 
4426 void SetInvokingWindow( wxMenu 
*menu
, wxWindow
* win 
) 
4428     menu
->SetInvokingWindow( win 
); 
4430     wxMenuItemList::compatibility_iterator node 
= menu
->GetMenuItems().GetFirst(); 
4433         wxMenuItem 
*menuitem 
= node
->GetData(); 
4434         if (menuitem
->IsSubMenu()) 
4436             SetInvokingWindow( menuitem
->GetSubMenu(), win 
); 
4439         node 
= node
->GetNext(); 
4443 extern "C" void wxPopupMenuPositionCallback( GtkMenu 
*menu
, 
4446                                              gboolean 
* WXUNUSED(whatever
), 
4448                                              gpointer user_data 
) 
4450     // ensure that the menu appears entirely on screen 
4452     gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
); 
4454     wxSize sizeScreen 
= wxGetDisplaySize(); 
4455     wxPoint 
*pos 
= (wxPoint
*)user_data
; 
4457     gint xmax 
= sizeScreen
.x 
- req
.width
, 
4458          ymax 
= sizeScreen
.y 
- req
.height
; 
4460     *x 
= pos
->x 
< xmax 
? pos
->x 
: xmax
; 
4461     *y 
= pos
->y 
< ymax 
? pos
->y 
: ymax
; 
4464 bool wxWindowGTK::DoPopupMenu( wxMenu 
*menu
, int x
, int y 
) 
4466     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
4468     wxCHECK_MSG( menu 
!= NULL
, false, wxT("invalid popup-menu") ); 
4470     // NOTE: if you change this code, you need to update 
4471     //       the same code in taskbar.cpp as well. This 
4472     //       is ugly code duplication, I know, 
4474     SetInvokingWindow( menu
, this ); 
4478     bool is_waiting 
= true; 
4480     gulong handler 
= gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), 
4482                                          GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), 
4483                                          (gpointer
)&is_waiting 
); 
4487     GtkMenuPositionFunc posfunc
; 
4488     if ( x 
== -1 && y 
== -1 ) 
4490         // use GTK's default positioning algorithm 
4496         pos 
= ClientToScreen(wxPoint(x
, y
)); 
4498         posfunc 
= wxPopupMenuPositionCallback
; 
4502                   GTK_MENU(menu
->m_menu
), 
4503                   (GtkWidget 
*) NULL
,           // parent menu shell 
4504                   (GtkWidget 
*) NULL
,           // parent menu item 
4505                   posfunc
,                      // function to position it 
4506                   userdata
,                     // client data 
4507                   0,                            // button used to activate it 
4509                   gtk_get_current_event_time() 
4511                   gs_timeLastClick              
// the time of activation 
4517         gtk_main_iteration(); 
4520     gtk_signal_disconnect(GTK_OBJECT(menu
->m_menu
), handler
); 
4525 #endif // wxUSE_MENUS_NATIVE 
4527 #if wxUSE_DRAG_AND_DROP 
4529 void wxWindowGTK::SetDropTarget( wxDropTarget 
*dropTarget 
) 
4531     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4533     GtkWidget 
*dnd_widget 
= GetConnectWidget(); 
4535     if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget 
); 
4537     if (m_dropTarget
) delete m_dropTarget
; 
4538     m_dropTarget 
= dropTarget
; 
4540     if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget 
); 
4543 #endif // wxUSE_DRAG_AND_DROP 
4545 GtkWidget
* wxWindowGTK::GetConnectWidget() 
4547     GtkWidget 
*connect_widget 
= m_widget
; 
4548     if (m_wxwindow
) connect_widget 
= m_wxwindow
; 
4550     return connect_widget
; 
4553 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow 
*window 
) 
4556         return (window 
== GTK_PIZZA(m_wxwindow
)->bin_window
); 
4558     return (window 
== m_widget
->window
); 
4561 bool wxWindowGTK::SetFont( const wxFont 
&font 
) 
4563     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
4565     if (!wxWindowBase::SetFont(font
)) 
4568     // apply style change (forceStyle=true so that new style is applied 
4569     // even if the font changed from valid to wxNullFont): 
4570     ApplyWidgetStyle(true);     
4575 void wxWindowGTK::DoCaptureMouse() 
4577     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4579     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4581         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4583         window 
= GetConnectWidget()->window
; 
4585     wxCHECK_RET( window
, _T("CaptureMouse() failed") ); 
4587     wxCursor
* cursor 
= & m_cursor
; 
4589         cursor 
= wxSTANDARD_CURSOR
; 
4591     gdk_pointer_grab( window
, FALSE
, 
4593                          (GDK_BUTTON_PRESS_MASK 
| 
4594                           GDK_BUTTON_RELEASE_MASK 
| 
4595                           GDK_POINTER_MOTION_HINT_MASK 
| 
4596                           GDK_POINTER_MOTION_MASK
), 
4598                       cursor
->GetCursor(), 
4599                       (guint32
)GDK_CURRENT_TIME 
); 
4600     g_captureWindow 
= this; 
4601     g_captureWindowHasMouse 
= TRUE
; 
4604 void wxWindowGTK::DoReleaseMouse() 
4606     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4608     wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") ); 
4610     g_captureWindow 
= (wxWindowGTK
*) NULL
; 
4612     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4614         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4616         window 
= GetConnectWidget()->window
; 
4621     gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME 
); 
4625 wxWindow 
*wxWindowBase::GetCapture() 
4627     return (wxWindow 
*)g_captureWindow
; 
4630 bool wxWindowGTK::IsRetained() const 
4635 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
, 
4636       int range
, bool refresh 
) 
4638     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4640     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4642     m_hasScrolling 
= TRUE
; 
4644     if (orient 
== wxHORIZONTAL
) 
4646         float fpos 
= (float)pos
; 
4647         float frange 
= (float)range
; 
4648         float fthumb 
= (float)thumbVisible
; 
4649         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4650         if (fpos 
< 0.0) fpos 
= 0.0; 
4652         if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) && 
4653             (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2)) 
4655             SetScrollPos( orient
, pos
, refresh 
); 
4659         m_oldHorizontalPos 
= fpos
; 
4661         m_hAdjust
->lower 
= 0.0; 
4662         m_hAdjust
->upper 
= frange
; 
4663         m_hAdjust
->value 
= fpos
; 
4664         m_hAdjust
->step_increment 
= 1.0; 
4665         m_hAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4666         m_hAdjust
->page_size 
= fthumb
; 
4670         float fpos 
= (float)pos
; 
4671         float frange 
= (float)range
; 
4672         float fthumb 
= (float)thumbVisible
; 
4673         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4674         if (fpos 
< 0.0) fpos 
= 0.0; 
4676         if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) && 
4677             (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2)) 
4679             SetScrollPos( orient
, pos
, refresh 
); 
4683         m_oldVerticalPos 
= fpos
; 
4685         m_vAdjust
->lower 
= 0.0; 
4686         m_vAdjust
->upper 
= frange
; 
4687         m_vAdjust
->value 
= fpos
; 
4688         m_vAdjust
->step_increment 
= 1.0; 
4689         m_vAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4690         m_vAdjust
->page_size 
= fthumb
; 
4693     if (orient 
== wxHORIZONTAL
) 
4694         gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
4696         gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
4699 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) ) 
4701     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4703     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4705     if (orient 
== wxHORIZONTAL
) 
4707         float fpos 
= (float)pos
; 
4708         if (fpos 
> m_hAdjust
->upper 
- m_hAdjust
->page_size
) fpos 
= m_hAdjust
->upper 
- m_hAdjust
->page_size
; 
4709         if (fpos 
< 0.0) fpos 
= 0.0; 
4710         m_oldHorizontalPos 
= fpos
; 
4712         if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return; 
4713         m_hAdjust
->value 
= fpos
; 
4717         float fpos 
= (float)pos
; 
4718         if (fpos 
> m_vAdjust
->upper 
- m_vAdjust
->page_size
) fpos 
= m_vAdjust
->upper 
- m_vAdjust
->page_size
; 
4719         if (fpos 
< 0.0) fpos 
= 0.0; 
4720         m_oldVerticalPos 
= fpos
; 
4722         if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return; 
4723         m_vAdjust
->value 
= fpos
; 
4726     if (m_wxwindow
->window
) 
4728         if (orient 
== wxHORIZONTAL
) 
4730             gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
), 
4731                 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
4733             gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" ); 
4735             gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
4736                 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
4740             gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
), 
4741                 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
4743             gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" ); 
4745             gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
4746                 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
4751 int wxWindowGTK::GetScrollThumb( int orient 
) const 
4753     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4755     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4757     if (orient 
== wxHORIZONTAL
) 
4758         return (int)(m_hAdjust
->page_size
+0.5); 
4760         return (int)(m_vAdjust
->page_size
+0.5); 
4763 int wxWindowGTK::GetScrollPos( int orient 
) const 
4765     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4767     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4769     if (orient 
== wxHORIZONTAL
) 
4770         return (int)(m_hAdjust
->value
+0.5); 
4772         return (int)(m_vAdjust
->value
+0.5); 
4775 int wxWindowGTK::GetScrollRange( int orient 
) const 
4777     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4779     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4781     if (orient 
== wxHORIZONTAL
) 
4782         return (int)(m_hAdjust
->upper
+0.5); 
4784         return (int)(m_vAdjust
->upper
+0.5); 
4787 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) ) 
4789     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4791     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4793     // No scrolling requested. 
4794     if ((dx 
== 0) && (dy 
== 0)) return; 
4797     if (!m_updateRegion
.IsEmpty()) 
4799         m_updateRegion
.Offset( dx
, dy 
); 
4803         GetClientSize( &cw
, &ch 
); 
4804         m_updateRegion
.Intersect( 0, 0, cw
, ch 
); 
4807     if (!m_clearRegion
.IsEmpty()) 
4809         m_clearRegion
.Offset( dx
, dy 
); 
4813         GetClientSize( &cw
, &ch 
); 
4814         m_clearRegion
.Intersect( 0, 0, cw
, ch 
); 
4818     m_clipPaintRegion 
= TRUE
; 
4820     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy 
); 
4822     m_clipPaintRegion 
= FALSE
; 
4826 // Find the wxWindow at the current mouse position, also returning the mouse 
4828 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
4830     pt 
= wxGetMousePosition(); 
4831     wxWindow
* found 
= wxFindWindowAtPoint(pt
); 
4835 // Get the current mouse position. 
4836 wxPoint 
wxGetMousePosition() 
4838   /* This crashes when used within wxHelpContext, 
4839      so we have to use the X-specific implementation below. 
4841     GdkModifierType *mask; 
4842     (void) gdk_window_get_pointer(NULL, &x, &y, mask); 
4844     return wxPoint(x, y); 
4848     GdkWindow
* windowAtPtr 
= gdk_window_at_pointer(& x
, & y
); 
4850     Display 
*display 
= windowAtPtr 
? GDK_WINDOW_XDISPLAY(windowAtPtr
) : GDK_DISPLAY(); 
4851     Window rootWindow 
= RootWindowOfScreen (DefaultScreenOfDisplay(display
)); 
4852     Window rootReturn
, childReturn
; 
4853     int rootX
, rootY
, winX
, winY
; 
4854     unsigned int maskReturn
; 
4856     XQueryPointer (display
, 
4860                    &rootX
, &rootY
, &winX
, &winY
, &maskReturn
); 
4861     return wxPoint(rootX
, rootY
); 
4865 // ---------------------------------------------------------------------------- 
4867 // ---------------------------------------------------------------------------- 
4869 class wxWinModule 
: public wxModule
 
4876     DECLARE_DYNAMIC_CLASS(wxWinModule
) 
4879 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
) 
4881 bool wxWinModule::OnInit() 
4883     // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() ); 
4884     // gdk_gc_set_fill( g_eraseGC, GDK_SOLID ); 
4889 void wxWinModule::OnExit() 
4892         gdk_gc_unref( g_eraseGC 
);