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 //----------------------------------------------------------------------------- 
 432 gint 
gtk_window_own_expose_callback( GtkWidget 
*widget
, GdkEventExpose 
*gdk_event
, wxWindowGTK 
*win 
) 
 434     if (gdk_event
->count 
> 0) return FALSE
; 
 436     draw_frame( widget
, win 
); 
 440     (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
); 
 446 //----------------------------------------------------------------------------- 
 447 // "draw" of m_widget 
 448 //----------------------------------------------------------------------------- 
 452 static void gtk_window_own_draw_callback( GtkWidget 
*widget
, GdkRectangle 
*WXUNUSED(rect
), wxWindowGTK 
*win 
) 
 454     draw_frame( widget
, win 
); 
 459 //----------------------------------------------------------------------------- 
 460 // "size_request" of m_widget 
 461 //----------------------------------------------------------------------------- 
 463 // make it extern because wxStatitText needs to disconnect this one 
 465 void wxgtk_window_size_request_callback(GtkWidget 
*widget
, 
 466                                         GtkRequisition 
*requisition
, 
 470     win
->GetSize( &w
, &h 
); 
 476     requisition
->height 
= h
; 
 477     requisition
->width 
= w
; 
 482 void wxgtk_combo_size_request_callback(GtkWidget 
*widget
, 
 483                                        GtkRequisition 
*requisition
, 
 486     // This callback is actually hooked into the text entry 
 487     // of the combo box, not the GtkHBox. 
 490     win
->GetSize( &w
, &h 
); 
 496     GtkCombo 
*gcombo 
= GTK_COMBO(win
->m_widget
); 
 498     GtkRequisition entry_req
; 
 500     entry_req
.height 
= 2; 
 501     (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(gcombo
->button
) )->size_request 
) 
 502         (gcombo
->button
, &entry_req 
); 
 504     requisition
->width 
= w 
- entry_req
.width
; 
 505     requisition
->height 
= entry_req
.height
+4;  // TODO: why +4? 
 508 //----------------------------------------------------------------------------- 
 509 // "expose_event" of m_wxwindow 
 510 //----------------------------------------------------------------------------- 
 512 static int gtk_window_expose_callback( GtkWidget 
*widget
, 
 513                                        GdkEventExpose 
*gdk_event
, 
 519         wxapp_install_idle_handler(); 
 522     // This callback gets called in drawing-idle time under 
 523     // GTK 2.0, so we don't need to defer anything to idle 
 526     GtkPizza 
*pizza 
= GTK_PIZZA( widget 
); 
 527     if (gdk_event
->window 
!= pizza
->bin_window
) return FALSE
; 
 532         wxPrintf( wxT("OnExpose from ") ); 
 533         if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName()) 
 534             wxPrintf( win
->GetClassInfo()->GetClassName() ); 
 535         wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event
->area
.x
, 
 536                                          (int)gdk_event
->area
.y
, 
 537                                          (int)gdk_event
->area
.width
, 
 538                                          (int)gdk_event
->area
.height 
); 
 543         win
->m_wxwindow
->style
, 
 547         (GdkRectangle
*) NULL
, 
 549         (char *)"button", // const_cast 
 554     win
->GetUpdateRegion() = wxRegion( gdk_event
->region 
); 
 556     win
->GtkSendPaintEvents(); 
 559     // Let parent window draw window less widgets 
 560     (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
); 
 562     // This gets called immediately after an expose event 
 563     // under GTK 1.2 so we collect the calls and wait for 
 564     // the idle handler to pick things up. 
 566     win
->GetUpdateRegion().Union( gdk_event
->area
.x
, 
 568                                   gdk_event
->area
.width
, 
 569                                   gdk_event
->area
.height 
); 
 570     win
->m_clearRegion
.Union( gdk_event
->area
.x
, 
 572                                   gdk_event
->area
.width
, 
 573                                   gdk_event
->area
.height 
); 
 575     // Actual redrawing takes place in idle time. 
 582 //----------------------------------------------------------------------------- 
 583 // "event" of m_wxwindow 
 584 //----------------------------------------------------------------------------- 
 586 // GTK thinks it is clever and filters out a certain amount of "unneeded" 
 587 // expose events. We need them, of course, so we override the main event 
 588 // procedure in GtkWidget by giving our own handler for all system events. 
 589 // There, we look for expose events ourselves whereas all other events are 
 592 gint 
gtk_window_event_event_callback( GtkWidget 
*widget
, 
 593                                       GdkEventExpose 
*event
, 
 596     if (event
->type 
== GDK_EXPOSE
) 
 598         gint ret 
= gtk_window_expose_callback( widget
, event
, win 
); 
 605 //----------------------------------------------------------------------------- 
 606 // "draw" of m_wxwindow 
 607 //----------------------------------------------------------------------------- 
 611 // This callback is a complete replacement of the gtk_pizza_draw() function, 
 612 // which is disabled. 
 614 static void gtk_window_draw_callback( GtkWidget 
*widget
, 
 621         wxapp_install_idle_handler(); 
 623     // if there are any children we must refresh everything 
 626     if ( !win
->HasFlag(wxFULL_REPAINT_ON_RESIZE
) && 
 627             win
->GetChildren().IsEmpty() ) 
 635         wxPrintf( wxT("OnDraw from ") ); 
 636         if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName()) 
 637             wxPrintf( win
->GetClassInfo()->GetClassName() ); 
 638         wxPrintf( wxT(" %d %d %d %d\n"), (int)rect
->x
, 
 645 #ifndef __WXUNIVERSAL__ 
 646     GtkPizza 
*pizza 
= GTK_PIZZA (widget
); 
 648     if (win
->GetThemeEnabled() && win
->GetBackgroundStyle() == wxBG_STYLE_SYSTEM
) 
 650         wxWindow 
*parent 
= win
->GetParent(); 
 651         while (parent 
&& !parent
->IsTopLevel()) 
 652             parent 
= parent
->GetParent(); 
 656         gtk_paint_flat_box (parent
->m_widget
->style
, 
 667     win
->m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
 668     win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
 670     // Update immediately, not in idle time. 
 673 #ifndef __WXUNIVERSAL__ 
 674     // Redraw child widgets 
 675     GList 
*children 
= pizza
->children
; 
 678         GtkPizzaChild 
*child 
= (GtkPizzaChild
*) children
->data
; 
 679         children 
= children
->next
; 
 681         GdkRectangle child_area
; 
 682         if (gtk_widget_intersect (child
->widget
, rect
, &child_area
)) 
 684             gtk_widget_draw (child
->widget
, &child_area 
/* (GdkRectangle*) NULL*/ ); 
 692 //----------------------------------------------------------------------------- 
 693 // "key_press_event" from any window 
 694 //----------------------------------------------------------------------------- 
 696 // set WXTRACE to this to see the key event codes on the console 
 697 #define TRACE_KEYS  _T("keyevent") 
 699 // translates an X key symbol to WXK_XXX value 
 701 // if isChar is true it means that the value returned will be used for EVT_CHAR 
 702 // event and then we choose the logical WXK_XXX, i.e. '/' for GDK_KP_Divide, 
 703 // for example, while if it is false it means that the value is going to be 
 704 // used for KEY_DOWN/UP events and then we translate GDK_KP_Divide to 
 706 static long wxTranslateKeySymToWXKey(KeySym keysym
, bool isChar
) 
 712         // Shift, Control and Alt don't generate the CHAR events at all 
 715             key_code 
= isChar 
? 0 : WXK_SHIFT
; 
 719             key_code 
= isChar 
? 0 : WXK_CONTROL
; 
 727             key_code 
= isChar 
? 0 : WXK_ALT
; 
 730         // neither do the toggle modifies 
 731         case GDK_Scroll_Lock
: 
 732             key_code 
= isChar 
? 0 : WXK_SCROLL
; 
 736             key_code 
= isChar 
? 0 : WXK_CAPITAL
; 
 740             key_code 
= isChar 
? 0 : WXK_NUMLOCK
; 
 744         // various other special keys 
 757         case GDK_ISO_Left_Tab
: 
 764             key_code 
= WXK_RETURN
; 
 768             key_code 
= WXK_CLEAR
; 
 772             key_code 
= WXK_PAUSE
; 
 776             key_code 
= WXK_SELECT
; 
 780             key_code 
= WXK_PRINT
; 
 784             key_code 
= WXK_EXECUTE
; 
 788             key_code 
= WXK_ESCAPE
; 
 791         // cursor and other extended keyboard keys 
 793             key_code 
= WXK_DELETE
; 
 809             key_code 
= WXK_RIGHT
; 
 816         case GDK_Prior
:     // == GDK_Page_Up 
 817             key_code 
= WXK_PRIOR
; 
 820         case GDK_Next
:      // == GDK_Page_Down 
 833             key_code 
= WXK_INSERT
; 
 848             key_code 
= (isChar 
? '0' : WXK_NUMPAD0
) + keysym 
- GDK_KP_0
; 
 852             key_code 
= isChar 
? ' ' : WXK_NUMPAD_SPACE
; 
 856             key_code 
= isChar 
? WXK_TAB 
: WXK_NUMPAD_TAB
; 
 860             key_code 
= isChar 
? WXK_RETURN 
: WXK_NUMPAD_ENTER
; 
 864             key_code 
= isChar 
? WXK_F1 
: WXK_NUMPAD_F1
; 
 868             key_code 
= isChar 
? WXK_F2 
: WXK_NUMPAD_F2
; 
 872             key_code 
= isChar 
? WXK_F3 
: WXK_NUMPAD_F3
; 
 876             key_code 
= isChar 
? WXK_F4 
: WXK_NUMPAD_F4
; 
 880             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_HOME
; 
 884             key_code 
= isChar 
? WXK_LEFT 
: WXK_NUMPAD_LEFT
; 
 888             key_code 
= isChar 
? WXK_UP 
: WXK_NUMPAD_UP
; 
 892             key_code 
= isChar 
? WXK_RIGHT 
: WXK_NUMPAD_RIGHT
; 
 896             key_code 
= isChar 
? WXK_DOWN 
: WXK_NUMPAD_DOWN
; 
 899         case GDK_KP_Prior
: // == GDK_KP_Page_Up 
 900             key_code 
= isChar 
? WXK_PRIOR 
: WXK_NUMPAD_PRIOR
; 
 903         case GDK_KP_Next
: // == GDK_KP_Page_Down 
 904             key_code 
= isChar 
? WXK_NEXT 
: WXK_NUMPAD_NEXT
; 
 908             key_code 
= isChar 
? WXK_END 
: WXK_NUMPAD_END
; 
 912             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_BEGIN
; 
 916             key_code 
= isChar 
? WXK_INSERT 
: WXK_NUMPAD_INSERT
; 
 920             key_code 
= isChar 
? WXK_DELETE 
: WXK_NUMPAD_DELETE
; 
 924             key_code 
= isChar 
? '=' : WXK_NUMPAD_EQUAL
; 
 927         case GDK_KP_Multiply
: 
 928             key_code 
= isChar 
? '*' : WXK_NUMPAD_MULTIPLY
; 
 932             key_code 
= isChar 
? '+' : WXK_NUMPAD_ADD
; 
 935         case GDK_KP_Separator
: 
 936             // FIXME: what is this? 
 937             key_code 
= isChar 
? '.' : WXK_NUMPAD_SEPARATOR
; 
 940         case GDK_KP_Subtract
: 
 941             key_code 
= isChar 
? '-' : WXK_NUMPAD_SUBTRACT
; 
 945             key_code 
= isChar 
? '.' : WXK_NUMPAD_DECIMAL
; 
 949             key_code 
= isChar 
? '/' : WXK_NUMPAD_DIVIDE
; 
 966             key_code 
= WXK_F1 
+ keysym 
- GDK_F1
; 
 976 static inline bool wxIsAsciiKeysym(KeySym ks
) 
 981 static void wxFillOtherKeyEventFields(wxKeyEvent
& event
, 
 983                                       GdkEventKey 
*gdk_event
) 
 987     GdkModifierType state
; 
 988     if (gdk_event
->window
) 
 989         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
 991     event
.SetTimestamp( gdk_event
->time 
); 
 992     event
.SetId(win
->GetId()); 
 993     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
) != 0; 
 994     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
) != 0; 
 995     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
) != 0; 
 996     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
) != 0; 
 997     event
.m_scanCode 
= gdk_event
->keyval
; 
 998     event
.m_rawCode 
= (wxUint32
) gdk_event
->keyval
; 
 999     event
.m_rawFlags 
= 0; 
1001     event
.m_uniChar 
= gdk_keyval_to_unicode(gdk_event
->keyval
); 
1003     wxGetMousePosition( &x
, &y 
); 
1004     win
->ScreenToClient( &x
, &y 
); 
1007     event
.SetEventObject( win 
); 
1012 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
, 
1014                            GdkEventKey 
*gdk_event
) 
1016     // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string 
1017     //     but only event->keyval which is quite useless to us, so remember 
1018     //     the last character from GDK_KEY_PRESS and reuse it as last resort 
1020     // NB: should be MT-safe as we're always called from the main thread only 
1025     } s_lastKeyPress 
= { 0, 0 }; 
1027     KeySym keysym 
= gdk_event
->keyval
; 
1029     wxLogTrace(TRACE_KEYS
, _T("Key %s event: keysym = %ld"), 
1030                event
.GetEventType() == wxEVT_KEY_UP 
? _T("release") 
1034     long key_code 
= wxTranslateKeySymToWXKey(keysym
, FALSE 
/* !isChar */); 
1038         // do we have the translation or is it a plain ASCII character? 
1039         if ( (gdk_event
->length 
== 1) || wxIsAsciiKeysym(keysym
) ) 
1041             // we should use keysym if it is ASCII as X does some translations 
1042             // like "I pressed while Control is down" => "Ctrl-I" == "TAB" 
1043             // which we don't want here (but which we do use for OnChar()) 
1044             if ( !wxIsAsciiKeysym(keysym
) ) 
1046                 keysym 
= (KeySym
)gdk_event
->string
[0]; 
1049             // we want to always get the same key code when the same key is 
1050             // pressed regardless of the state of the modifies, i.e. on a 
1051             // standard US keyboard pressing '5' or '%' ('5' key with 
1052             // Shift) should result in the same key code in OnKeyDown(): 
1053             // '5' (although OnChar() will get either '5' or '%'). 
1055             // to do it we first translate keysym to keycode (== scan code) 
1056             // and then back but always using the lower register 
1057             Display 
*dpy 
= (Display 
*)wxGetDisplay(); 
1058             KeyCode keycode 
= XKeysymToKeycode(dpy
, keysym
); 
1060             wxLogTrace(TRACE_KEYS
, _T("\t-> keycode %d"), keycode
); 
1062             KeySym keysymNormalized 
= XKeycodeToKeysym(dpy
, keycode
, 0); 
1064             // use the normalized, i.e. lower register, keysym if we've 
1066             key_code 
= keysymNormalized 
? keysymNormalized 
: keysym
; 
1068             // as explained above, we want to have lower register key codes 
1069             // normally but for the letter keys we want to have the upper ones 
1071             // NB: don't use XConvertCase() here, we want to do it for letters 
1073             key_code 
= toupper(key_code
); 
1075         else // non ASCII key, what to do? 
1077             // by default, ignore it 
1080             // but if we have cached information from the last KEY_PRESS 
1081             if ( gdk_event
->type 
== GDK_KEY_RELEASE 
) 
1084                 if ( keysym 
== s_lastKeyPress
.keysym 
) 
1086                     key_code 
= s_lastKeyPress
.keycode
; 
1091         if ( gdk_event
->type 
== GDK_KEY_PRESS 
) 
1093             // remember it to be reused for KEY_UP event later 
1094             s_lastKeyPress
.keysym 
= keysym
; 
1095             s_lastKeyPress
.keycode 
= key_code
; 
1099     wxLogTrace(TRACE_KEYS
, _T("\t-> wxKeyCode %ld"), key_code
); 
1101     // sending unknown key events doesn't really make sense 
1105     // now fill all the other fields 
1106     wxFillOtherKeyEventFields(event
, win
, gdk_event
); 
1108     event
.m_keyCode 
= key_code
; 
1117     GtkIMContext 
*context
; 
1118     GdkEventKey  
*lastKeyEvent
; 
1122         context 
= gtk_im_multicontext_new(); 
1123         lastKeyEvent 
= NULL
; 
1127         g_object_unref(context
); 
1132 static gint 
gtk_window_key_press_callback( GtkWidget 
*widget
, 
1133                                            GdkEventKey 
*gdk_event
, 
1139         wxapp_install_idle_handler(); 
1143     if (g_blockEventsOnDrag
) 
1147     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
1149     bool return_after_IM 
= false; 
1151     if( wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1153         // Emit KEY_DOWN event 
1154         ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1158         // Return after IM processing as we cannot do 
1159         // anything with it anyhow. 
1160         return_after_IM 
= true; 
1164     // 2005.01.26 modified by Hong Jen Yee (hzysoft@sina.com.tw): 
1165     // When we get a key_press event here, it could be originate 
1166     // from the current widget or its child widgets.  However, only the widget 
1167     // with the INPUT FOCUS can generate the INITIAL key_press event.  That is,  
1168     // if the CURRENT widget doesn't have the FOCUS at all, this event definitely 
1169     // originated from its child widgets and shouldn't be passed to IM context. 
1170     // In fact, what a GTK+ IM should do is filtering keyEvents and convert them 
1171     // into text input ONLY WHEN THE WIDGET HAS INPUT FOCUS.  Besides, when current 
1172     // widgets has both IM context and input focus, the event should be filtered  
1173     // by gtk_im_context_filter_keypress(). 
1174     // Then, we should, according to GTK+ 2.0 API doc, return whatever it returns. 
1175     if ((!ret
) && (win
->m_imData 
!= NULL
) && ( wxWindow::FindFocus() == win 
)) 
1177         // We should let GTK+ IM filter key event first. According to GTK+ 2.0 API 
1178         // docs, if IM filter returns true, no further processing should be done. 
1179         // we should send the key_down event anyway.  
1180         bool intercepted_by_IM 
= gtk_im_context_filter_keypress(win
->m_imData
->context
, gdk_event
); 
1181         win
->m_imData
->lastKeyEvent 
= NULL
; 
1182         if (intercepted_by_IM
) 
1184             wxLogTrace(TRACE_KEYS
, _T("Key event intercepted by IM")); 
1189     if (return_after_IM
) 
1193     // This is for GTK+ 1.2 only. The char event generatation for GTK+ 2.0 is done 
1194     // in the "commit" handler. 
1196     // 2005.02.02 modified by Hong Jen Yee (hzysoft@sina.com.tw). 
1197     // In GTK+ 1.2, strings sent by IMs are also regarded as key_press events whose  
1198     // keyCodes cannot be recognized by wxWidgets. These MBCS strings, however, are  
1199     // composed of more than one character, which means gdk_event->length will always  
1200     // greater than one. When gtk_event->length == 1, this may be an ASCII character 
1201     // and can be translated by wx.  However, when MBCS characters are sent by IM,  
1202     // gdk_event->length will >= 2. So neither should we pass it to accelerator table, 
1203     // nor should we pass it to controls. The following explanation was excerpted 
1204     // from GDK documentation. 
1205     // gint length : the length of string. 
1206     // gchar *string : a null-terminated multi-byte string containing the composed 
1207     // characters resulting from the key press. When text is being input, in a GtkEntry 
1208     // for example, it is these characters which should be added to the input buffer. 
1209     // When using Input Methods to support internationalized text input, the composed 
1210     // characters appear here after the pre-editing has been completed. 
1212     if ( (!ret
) && (gdk_event
->length 
> 1) ) // If this event contains a pre-edited string from IM. 
1214         // We should translate this key event into wxEVT_CHAR not wxEVT_KEY_DOWN. 
1215         #if wxUSE_UNICODE   // GTK+ 1.2 is not UTF-8 based. 
1216             const wxWCharBuffer string 
= wxConvLocal
.cMB2WC( gdk_event
->string 
); 
1220             const char* string 
= gdk_event
->string
; 
1223         // Implement OnCharHook by checking ancesteror top level windows 
1224         wxWindow 
*parent 
= win
; 
1225         while (parent 
&& !parent
->IsTopLevel()) 
1226             parent 
= parent
->GetParent(); 
1228         for( const wxChar
* pstr 
= string
; *pstr
; pstr
++ ) 
1231             event
.m_uniChar 
= *pstr
; 
1232             // Backward compatible for ISO-8859-1 
1233             event
.m_keyCode 
= *pstr 
< 256 ? event
.m_uniChar 
: 0; 
1235             event
.m_keyCode 
= *pstr
; 
1239                 event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1240                 ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1244                 event
.SetEventType(wxEVT_CHAR
); 
1245                 win
->GetEventHandler()->ProcessEvent( event 
); 
1251 #endif  // #ifndef  __WXGTK20__ 
1256         wxWindowGTK 
*ancestor 
= win
; 
1259             int command 
= ancestor
->GetAcceleratorTable()->GetCommand( event 
); 
1262                 wxCommandEvent 
command_event( wxEVT_COMMAND_MENU_SELECTED
, command 
); 
1263                 ret 
= ancestor
->GetEventHandler()->ProcessEvent( command_event 
); 
1266             if (ancestor
->IsTopLevel()) 
1268             ancestor 
= ancestor
->GetParent(); 
1271 #endif // wxUSE_ACCEL 
1273     // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x 
1274     // will only be sent if it is not in an accelerator table. 
1278         KeySym keysym 
= gdk_event
->keyval
; 
1279         // Find key code for EVT_CHAR and EVT_CHAR_HOOK events 
1280         key_code 
= wxTranslateKeySymToWXKey(keysym
, TRUE 
/* isChar */); 
1283             if ( wxIsAsciiKeysym(keysym
) ) 
1286                 key_code 
= (unsigned char)keysym
; 
1288             // gdk_event->string is actually deprecated 
1289             else if ( gdk_event
->length 
== 1 ) 
1291                 key_code 
= (unsigned char)gdk_event
->string
[0]; 
1297             wxLogTrace(TRACE_KEYS
, _T("Char event: %ld"), key_code
); 
1299             event
.m_keyCode 
= key_code
; 
1301             // Implement OnCharHook by checking ancesteror top level windows 
1302             wxWindow 
*parent 
= win
; 
1303             while (parent 
&& !parent
->IsTopLevel()) 
1304                 parent 
= parent
->GetParent(); 
1307                 event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1308                 ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1313                 event
.SetEventType(wxEVT_CHAR
); 
1314                 ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1323     // win is a control: tab can be propagated up 
1325          ((gdk_event
->keyval 
== GDK_Tab
) || (gdk_event
->keyval 
== GDK_ISO_Left_Tab
)) && 
1326 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may 
1327 //     have this style, yet choose not to process this particular TAB in which 
1328 //     case TAB must still work as a navigational character 
1329 // JS: enabling again to make consistent with other platforms 
1330 //     (with wxTE_PROCESS_TAB you have to call Navigate to get default 
1331 //     navigation behaviour) 
1333          (! (win
->HasFlag(wxTE_PROCESS_TAB
) && win
->IsKindOf(CLASSINFO(wxTextCtrl
)) )) && 
1335          win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) ) 
1337         wxNavigationKeyEvent new_event
; 
1338         new_event
.SetEventObject( win
->GetParent() ); 
1339         // GDK reports GDK_ISO_Left_Tab for SHIFT-TAB 
1340         new_event
.SetDirection( (gdk_event
->keyval 
== GDK_Tab
) ); 
1341         // CTRL-TAB changes the (parent) window, i.e. switch notebook page 
1342         new_event
.SetWindowChange( (gdk_event
->state 
& GDK_CONTROL_MASK
) ); 
1343         new_event
.SetCurrentFocus( win 
); 
1344         ret 
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event 
); 
1347     // generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) 
1349          (gdk_event
->keyval 
== GDK_Escape
) ) 
1351         // however only do it if we have a Cancel button in the dialog, 
1352         // otherwise the user code may get confused by the events from a 
1353         // non-existing button and, worse, a wxButton might get button event 
1354         // from another button which is not really expected 
1355         wxWindow 
*winForCancel 
= win
, 
1357         while ( winForCancel 
) 
1359             btnCancel 
= winForCancel
->FindWindow(wxID_CANCEL
); 
1362                 // found a cancel button 
1366             if ( winForCancel
->IsTopLevel() ) 
1368                 // no need to look further 
1372             // maybe our parent has a cancel button? 
1373             winForCancel 
= winForCancel
->GetParent(); 
1378             wxCommandEvent 
event(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
); 
1379             event
.SetEventObject(btnCancel
); 
1380             ret 
= btnCancel
->GetEventHandler()->ProcessEvent(event
); 
1386         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" ); 
1394 static void gtk_wxwindow_commit_cb (GtkIMContext 
*context
, 
1398     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
1400     // take modifiers, cursor position, timestamp etc. from the last 
1401     // key_press_event that was fed into Input Method: 
1402     if (window
->m_imData
->lastKeyEvent
) 
1404         wxFillOtherKeyEventFields(event
, 
1405                                   window
, window
->m_imData
->lastKeyEvent
); 
1409     const wxWCharBuffer data 
= wxConvUTF8
.cMB2WC( (char*)str 
); 
1411     const wxWCharBuffer wdata 
= wxConvUTF8
.cMB2WC( (char*)str 
); 
1412     const wxCharBuffer data 
= wxConvLocal
.cWC2MB( wdata 
); 
1413 #endif // wxUSE_UNICODE 
1414     if( !(const wxChar
*)data 
) 
1419     // Implement OnCharHook by checking ancestor top level windows 
1420     wxWindow 
*parent 
= window
; 
1421     while (parent 
&& !parent
->IsTopLevel()) 
1422         parent 
= parent
->GetParent(); 
1424     for( const wxChar
* pstr 
= data
; *pstr
; pstr
++ ) 
1427         event
.m_uniChar 
= *pstr
; 
1428         // Backward compatible for ISO-8859-1 
1429         event
.m_keyCode 
= *pstr 
< 256 ? event
.m_uniChar 
: 0; 
1430         wxLogTrace(TRACE_KEYS
, _T("IM sent character '%c'"), event
.m_uniChar
); 
1432         event
.m_keyCode 
= *pstr
; 
1433 #endif  // wxUSE_UNICODE 
1436             event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1437             ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1442             event
.SetEventType(wxEVT_CHAR
); 
1443             ret 
= window
->GetEventHandler()->ProcessEvent( event 
); 
1450 //----------------------------------------------------------------------------- 
1451 // "key_release_event" from any window 
1452 //----------------------------------------------------------------------------- 
1454 static gint 
gtk_window_key_release_callback( GtkWidget 
*widget
, 
1455                                              GdkEventKey 
*gdk_event
, 
1461         wxapp_install_idle_handler(); 
1466     if (g_blockEventsOnDrag
) 
1469     wxKeyEvent 
event( wxEVT_KEY_UP 
); 
1470     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1472         // unknown key pressed, ignore (the event would be useless anyhow 
1476     if ( !win
->GetEventHandler()->ProcessEvent( event 
) ) 
1479     gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" ); 
1483 // ============================================================================ 
1485 // ============================================================================ 
1487 // ---------------------------------------------------------------------------- 
1488 // mouse event processing helpers 
1489 // ---------------------------------------------------------------------------- 
1491 // init wxMouseEvent with the info from GdkEventXXX struct 
1492 template<typename T
> void InitMouseEvent(wxWindowGTK 
*win
, 
1493                                          wxMouseEvent
& event
, 
1496     event
.SetTimestamp( gdk_event
->time 
); 
1497     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
); 
1498     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
); 
1499     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
); 
1500     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
); 
1501     event
.m_leftDown 
= (gdk_event
->state 
& GDK_BUTTON1_MASK
); 
1502     event
.m_middleDown 
= (gdk_event
->state 
& GDK_BUTTON2_MASK
); 
1503     event
.m_rightDown 
= (gdk_event
->state 
& GDK_BUTTON3_MASK
); 
1504     if (event
.GetEventType() == wxEVT_MOUSEWHEEL
) 
1506        event
.m_linesPerAction 
= 3; 
1507        event
.m_wheelDelta 
= 120; 
1508        if (((GdkEventButton
*)gdk_event
)->button 
== 4) 
1509            event
.m_wheelRotation 
= 120; 
1510        else if (((GdkEventButton
*)gdk_event
)->button 
== 5) 
1511            event
.m_wheelRotation 
= -120; 
1514     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1515     event
.m_x 
= (wxCoord
)gdk_event
->x 
- pt
.x
; 
1516     event
.m_y 
= (wxCoord
)gdk_event
->y 
- pt
.y
; 
1518     event
.SetEventObject( win 
); 
1519     event
.SetId( win
->GetId() ); 
1520     event
.SetTimestamp( gdk_event
->time 
); 
1523 static void AdjustEventButtonState(wxMouseEvent
& event
) 
1525     // GDK reports the old state of the button for a button press event, but 
1526     // for compatibility with MSW and common sense we want m_leftDown be TRUE 
1527     // for a LEFT_DOWN event, not FALSE, so we will invert 
1528     // left/right/middleDown for the corresponding click events 
1530     if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) || 
1531         (event
.GetEventType() == wxEVT_LEFT_DCLICK
) || 
1532         (event
.GetEventType() == wxEVT_LEFT_UP
)) 
1534         event
.m_leftDown 
= !event
.m_leftDown
; 
1538     if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) || 
1539         (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) || 
1540         (event
.GetEventType() == wxEVT_MIDDLE_UP
)) 
1542         event
.m_middleDown 
= !event
.m_middleDown
; 
1546     if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) || 
1547         (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) || 
1548         (event
.GetEventType() == wxEVT_RIGHT_UP
)) 
1550         event
.m_rightDown 
= !event
.m_rightDown
; 
1555 // find the window to send the mouse event too 
1557 wxWindowGTK 
*FindWindowForMouseEvent(wxWindowGTK 
*win
, wxCoord
& x
, wxCoord
& y
) 
1562     if (win
->m_wxwindow
) 
1564         GtkPizza 
*pizza 
= GTK_PIZZA(win
->m_wxwindow
); 
1565         xx 
+= pizza
->xoffset
; 
1566         yy 
+= pizza
->yoffset
; 
1569     wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
1572         wxWindowGTK 
*child 
= node
->GetData(); 
1574         node 
= node
->GetNext(); 
1575         if (!child
->IsShown()) 
1578         if (child
->IsTransparentForMouse()) 
1580             // wxStaticBox is transparent in the box itself 
1581             int xx1 
= child
->m_x
; 
1582             int yy1 
= child
->m_y
; 
1583             int xx2 
= child
->m_x 
+ child
->m_width
; 
1584             int yy2 
= child
->m_y 
+ child
->m_height
; 
1587             if (((xx 
>= xx1
) && (xx 
<= xx1
+10) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1589                 ((xx 
>= xx2
-10) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1591                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy1
+10)) || 
1593                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy2
-1) && (yy 
<= yy2
))) 
1604             if ((child
->m_wxwindow 
== (GtkWidget
*) NULL
) && 
1605                 (child
->m_x 
<= xx
) && 
1606                 (child
->m_y 
<= yy
) && 
1607                 (child
->m_x
+child
->m_width  
>= xx
) && 
1608                 (child
->m_y
+child
->m_height 
>= yy
)) 
1621 //----------------------------------------------------------------------------- 
1622 // "button_press_event" 
1623 //----------------------------------------------------------------------------- 
1625 static gint 
gtk_window_button_press_callback( GtkWidget 
*widget
, 
1626                                               GdkEventButton 
*gdk_event
, 
1632         wxapp_install_idle_handler(); 
1635     wxPrintf( wxT("1) OnButtonPress from ") ); 
1636     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1637         wxPrintf( win->GetClassInfo()->GetClassName() ); 
1638     wxPrintf( wxT(".\n") ); 
1640     if (!win
->m_hasVMT
) return FALSE
; 
1641     if (g_blockEventsOnDrag
) return TRUE
; 
1642     if (g_blockEventsOnScroll
) return TRUE
; 
1644     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1646     if (win
->m_wxwindow 
&& (g_focusWindow 
!= win
) && win
->AcceptsFocus()) 
1648         gtk_widget_grab_focus( win
->m_wxwindow 
); 
1650         wxPrintf( wxT("GrabFocus from ") ); 
1651         if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1652             wxPrintf( win->GetClassInfo()->GetClassName() ); 
1653         wxPrintf( wxT(".\n") ); 
1657     // GDK sends surplus button down event 
1658     // before a double click event. We 
1659     // need to filter these out. 
1660     if (gdk_event
->type 
== GDK_BUTTON_PRESS
) 
1662         GdkEvent 
*peek_event 
= gdk_event_peek(); 
1665             if ((peek_event
->type 
== GDK_2BUTTON_PRESS
) || 
1666                 (peek_event
->type 
== GDK_3BUTTON_PRESS
)) 
1668                 gdk_event_free( peek_event 
); 
1673                 gdk_event_free( peek_event 
); 
1678     wxEventType event_type 
= wxEVT_NULL
; 
1680     // GdkDisplay is a GTK+ 2.2.0 thing 
1681 #if defined(__WXGTK20__) && GTK_CHECK_VERSION(2, 2, 0) 
1682     if ( gdk_event
->type 
== GDK_2BUTTON_PRESS 
&& 
1683             gdk_event
->button 
>= 1 && gdk_event
->button 
<= 3 ) 
1685         // Reset GDK internal timestamp variables in order to disable GDK 
1686         // triple click events. GDK will then next time believe no button has 
1687         // been clicked just before, and send a normal button click event. 
1688         GdkDisplay
* display 
= gtk_widget_get_display (widget
); 
1689         display
->button_click_time
[1] = 0; 
1690         display
->button_click_time
[0] = 0; 
1694     if (gdk_event
->button 
== 1) 
1696         // note that GDK generates triple click events which are not supported 
1697         // by wxWidgets but still have to be passed to the app as otherwise 
1698         // clicks would simply go missing 
1699         switch (gdk_event
->type
) 
1701             // we shouldn't get triple clicks at all for GTK2 because we 
1702             // suppress them artificially using the code above but we still 
1703             // should map them to something for GTK1 and not just ignore them 
1704             // as this would lose clicks 
1705             case GDK_3BUTTON_PRESS
:     // we could also map this to DCLICK... 
1706             case GDK_BUTTON_PRESS
: 
1707                 event_type 
= wxEVT_LEFT_DOWN
; 
1710             case GDK_2BUTTON_PRESS
: 
1711                 event_type 
= wxEVT_LEFT_DCLICK
; 
1715                 // just to silence gcc warnings 
1719     else if (gdk_event
->button 
== 2) 
1721         switch (gdk_event
->type
) 
1723             case GDK_3BUTTON_PRESS
: 
1724             case GDK_BUTTON_PRESS
: 
1725                 event_type 
= wxEVT_MIDDLE_DOWN
; 
1728             case GDK_2BUTTON_PRESS
: 
1729                 event_type 
= wxEVT_MIDDLE_DCLICK
; 
1736     else if (gdk_event
->button 
== 3) 
1738         switch (gdk_event
->type
) 
1740             case GDK_3BUTTON_PRESS
: 
1741             case GDK_BUTTON_PRESS
: 
1742                 event_type 
= wxEVT_RIGHT_DOWN
; 
1745             case GDK_2BUTTON_PRESS
: 
1746                 event_type 
= wxEVT_RIGHT_DCLICK
; 
1753     else if (gdk_event
->button 
== 4 || gdk_event
->button 
== 5) 
1755         if (gdk_event
->type 
== GDK_BUTTON_PRESS 
) 
1757             event_type 
= wxEVT_MOUSEWHEEL
; 
1761     if ( event_type 
== wxEVT_NULL 
) 
1763         // unknown mouse button or click type 
1767     wxMouseEvent 
event( event_type 
); 
1768     InitMouseEvent( win
, event
, gdk_event 
); 
1770     AdjustEventButtonState(event
); 
1772     // wxListBox actually get mouse events from the item, so we need to give it 
1773     // a chance to correct this 
1774     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1776     // find the correct window to send the event too: it may be a different one 
1777     // from the one which got it at GTK+ level because some control don't have 
1778     // their own X window and thus cannot get any events. 
1779     if ( !g_captureWindow 
) 
1780         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1782     gs_timeLastClick 
= gdk_event
->time
; 
1785     if (event_type 
== wxEVT_LEFT_DCLICK
) 
1787         // GTK 1.2 crashes when intercepting double 
1788         // click events from both wxSpinButton and 
1790         if (GTK_IS_SPIN_BUTTON(win
->m_widget
)) 
1792             // Just disable this event for now. 
1798     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1800         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" ); 
1804     if (event_type 
== wxEVT_RIGHT_DOWN
) 
1806         // generate a "context menu" event: this is similar to right mouse 
1807         // click under many GUIs except that it is generated differently 
1808         // (right up under MSW, ctrl-click under Mac, right down here) and 
1810         // (a) it's a command event and so is propagated to the parent 
1811         // (b) under some ports it can be generated from kbd too 
1812         // (c) it uses screen coords (because of (a)) 
1813         wxContextMenuEvent 
evtCtx( 
1816             win
->ClientToScreen(event
.GetPosition())); 
1817         evtCtx
.SetEventObject(win
); 
1818         return win
->GetEventHandler()->ProcessEvent(evtCtx
); 
1824 //----------------------------------------------------------------------------- 
1825 // "button_release_event" 
1826 //----------------------------------------------------------------------------- 
1828 static gint 
gtk_window_button_release_callback( GtkWidget 
*widget
, 
1829                                                 GdkEventButton 
*gdk_event
, 
1835         wxapp_install_idle_handler(); 
1837     if (!win
->m_hasVMT
) return FALSE
; 
1838     if (g_blockEventsOnDrag
) return FALSE
; 
1839     if (g_blockEventsOnScroll
) return FALSE
; 
1841     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1843     wxEventType event_type 
= wxEVT_NULL
; 
1845     switch (gdk_event
->button
) 
1848             event_type 
= wxEVT_LEFT_UP
; 
1852             event_type 
= wxEVT_MIDDLE_UP
; 
1856             event_type 
= wxEVT_RIGHT_UP
; 
1860             // unknwon button, don't process 
1864     wxMouseEvent 
event( event_type 
); 
1865     InitMouseEvent( win
, event
, gdk_event 
); 
1867     AdjustEventButtonState(event
); 
1869     // same wxListBox hack as above 
1870     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1872     if ( !g_captureWindow 
) 
1873         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1875     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1877         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" ); 
1884 //----------------------------------------------------------------------------- 
1885 // "motion_notify_event" 
1886 //----------------------------------------------------------------------------- 
1888 static gint 
gtk_window_motion_notify_callback( GtkWidget 
*widget
, 
1889                                                GdkEventMotion 
*gdk_event
, 
1895         wxapp_install_idle_handler(); 
1897     if (!win
->m_hasVMT
) return FALSE
; 
1898     if (g_blockEventsOnDrag
) return FALSE
; 
1899     if (g_blockEventsOnScroll
) return FALSE
; 
1901     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1903     if (gdk_event
->is_hint
) 
1907         GdkModifierType state
; 
1908         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1914     printf( "OnMotion from " ); 
1915     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1916       printf( win->GetClassInfo()->GetClassName() ); 
1920     wxMouseEvent 
event( wxEVT_MOTION 
); 
1921     InitMouseEvent(win
, event
, gdk_event
); 
1923     if ( g_captureWindow 
) 
1925         // synthetize a mouse enter or leave event if needed 
1926         GdkWindow 
*winUnderMouse 
= gdk_window_at_pointer(NULL
, NULL
); 
1927         // This seems to be necessary and actually been added to 
1928         // GDK itself in version 2.0.X 
1931         bool hasMouse 
= winUnderMouse 
== gdk_event
->window
; 
1932         if ( hasMouse 
!= g_captureWindowHasMouse 
) 
1934             // the mouse changed window 
1935             g_captureWindowHasMouse 
= hasMouse
; 
1937             wxMouseEvent 
event(g_captureWindowHasMouse 
? wxEVT_ENTER_WINDOW
 
1938                                                        : wxEVT_LEAVE_WINDOW
); 
1939             InitMouseEvent(win
, event
, gdk_event
); 
1940             event
.SetEventObject(win
); 
1941             win
->GetEventHandler()->ProcessEvent(event
); 
1946         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1949     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1951         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" ); 
1959 //----------------------------------------------------------------------------- 
1960 // "mouse_wheel_event" 
1961 //----------------------------------------------------------------------------- 
1963 static gint 
gtk_window_wheel_callback (GtkWidget 
* widget
, 
1964                                         GdkEventScroll 
* gdk_event
, 
1970         wxapp_install_idle_handler(); 
1972     wxEventType event_type 
= wxEVT_NULL
; 
1973     if (gdk_event
->direction 
== GDK_SCROLL_UP
) 
1974         event_type 
= wxEVT_MOUSEWHEEL
; 
1975     else if (gdk_event
->direction 
== GDK_SCROLL_DOWN
) 
1976         event_type 
= wxEVT_MOUSEWHEEL
; 
1980     wxMouseEvent 
event( event_type 
); 
1981     // Can't use InitMouse macro because scroll events don't have button 
1982     event
.SetTimestamp( gdk_event
->time 
); 
1983     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
); 
1984     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
); 
1985     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
); 
1986     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
); 
1987     event
.m_leftDown 
= (gdk_event
->state 
& GDK_BUTTON1_MASK
); 
1988     event
.m_middleDown 
= (gdk_event
->state 
& GDK_BUTTON2_MASK
); 
1989     event
.m_rightDown 
= (gdk_event
->state 
& GDK_BUTTON3_MASK
); 
1990     event
.m_linesPerAction 
= 3; 
1991     event
.m_wheelDelta 
= 120; 
1992     if (gdk_event
->direction 
== GDK_SCROLL_UP
) 
1993         event
.m_wheelRotation 
= 120; 
1995         event
.m_wheelRotation 
= -120; 
1997     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1998     event
.m_x 
= (wxCoord
)gdk_event
->x 
- pt
.x
; 
1999     event
.m_y 
= (wxCoord
)gdk_event
->y 
- pt
.y
; 
2001     event
.SetEventObject( win 
); 
2002     event
.SetId( win
->GetId() ); 
2003     event
.SetTimestamp( gdk_event
->time 
); 
2005     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
2007         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "scroll_event" ); 
2014 //----------------------------------------------------------------------------- 
2016 //----------------------------------------------------------------------------- 
2017 static gboolean 
wxgtk_window_popup_menu_callback(GtkWidget
*, wxWindowGTK
* win
) 
2019     wxContextMenuEvent 
event( 
2023     event
.SetEventObject(win
); 
2024     return win
->GetEventHandler()->ProcessEvent(event
); 
2026 #endif // __WXGTK20__ 
2028 //----------------------------------------------------------------------------- 
2030 //----------------------------------------------------------------------------- 
2032 // send the wxChildFocusEvent and wxFocusEvent, common code of 
2033 // gtk_window_focus_in_callback() and SetFocus() 
2034 static bool DoSendFocusEvents(wxWindow 
*win
) 
2036     // Notify the parent keeping track of focus for the kbd navigation 
2037     // purposes that we got it. 
2038     wxChildFocusEvent 
eventChildFocus(win
); 
2039     (void)win
->GetEventHandler()->ProcessEvent(eventChildFocus
); 
2041     wxFocusEvent 
eventFocus(wxEVT_SET_FOCUS
, win
->GetId()); 
2042     eventFocus
.SetEventObject(win
); 
2044     return win
->GetEventHandler()->ProcessEvent(eventFocus
); 
2047 static gint 
gtk_window_focus_in_callback( GtkWidget 
*widget
, 
2048                                           GdkEvent 
*WXUNUSED(event
), 
2054         wxapp_install_idle_handler(); 
2058         gtk_im_context_focus_in(win
->m_imData
->context
); 
2062     g_focusWindow 
= win
; 
2064     wxLogTrace(TRACE_FOCUS
, 
2065                _T("%s: focus in"), win
->GetName().c_str()); 
2069         gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
); 
2073     // caret needs to be informed about focus change 
2074     wxCaret 
*caret 
= win
->GetCaret(); 
2077         caret
->OnSetFocus(); 
2079 #endif // wxUSE_CARET 
2081     // does the window itself think that it has the focus? 
2082     if ( !win
->m_hasFocus 
) 
2084         // not yet, notify it 
2085         win
->m_hasFocus 
= TRUE
; 
2087         if ( DoSendFocusEvents(win
) ) 
2089            gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" ); 
2097 //----------------------------------------------------------------------------- 
2098 // "focus_out_event" 
2099 //----------------------------------------------------------------------------- 
2101 static gint 
gtk_window_focus_out_callback( GtkWidget 
*widget
, GdkEventFocus 
*gdk_event
, wxWindowGTK 
*win 
) 
2106         wxapp_install_idle_handler(); 
2110         gtk_im_context_focus_out(win
->m_imData
->context
); 
2113     wxLogTrace( TRACE_FOCUS
, 
2114                 _T("%s: focus out"), win
->GetName().c_str() ); 
2117     wxWindowGTK 
*winFocus 
= wxFindFocusedChild(win
); 
2121     g_focusWindow 
= (wxWindowGTK 
*)NULL
; 
2129     // caret needs to be informed about focus change 
2130     wxCaret 
*caret 
= win
->GetCaret(); 
2133         caret
->OnKillFocus(); 
2135 #endif // wxUSE_CARET 
2137     // don't send the window a kill focus event if it thinks that it doesn't 
2138     // have focus already 
2139     if ( win
->m_hasFocus 
) 
2141         win
->m_hasFocus 
= FALSE
; 
2143         wxFocusEvent 
event( wxEVT_KILL_FOCUS
, win
->GetId() ); 
2144         event
.SetEventObject( win 
); 
2146         // even if we did process the event in wx code, still let GTK itself 
2147         // process it too as otherwise bad things happen, especially in GTK2 
2148         // where the text control simply aborts the program if it doesn't get 
2149         // the matching focus out event 
2150         (void)win
->GetEventHandler()->ProcessEvent( event 
); 
2156 //----------------------------------------------------------------------------- 
2157 // "enter_notify_event" 
2158 //----------------------------------------------------------------------------- 
2161 gint 
gtk_window_enter_callback( GtkWidget 
*widget
, 
2162                                 GdkEventCrossing 
*gdk_event
, 
2168         wxapp_install_idle_handler(); 
2170     if (!win
->m_hasVMT
) return FALSE
; 
2171     if (g_blockEventsOnDrag
) return FALSE
; 
2173     // Event was emitted after a grab 
2174     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
2176     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
2180     GdkModifierType state 
= (GdkModifierType
)0; 
2182     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
2184     wxMouseEvent 
event( wxEVT_ENTER_WINDOW 
); 
2185     InitMouseEvent(win
, event
, gdk_event
); 
2186     wxPoint pt 
= win
->GetClientAreaOrigin(); 
2187     event
.m_x 
= x 
+ pt
.x
; 
2188     event
.m_y 
= y 
+ pt
.y
; 
2190     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
2192        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" ); 
2199 //----------------------------------------------------------------------------- 
2200 // "leave_notify_event" 
2201 //----------------------------------------------------------------------------- 
2203 static gint 
gtk_window_leave_callback( GtkWidget 
*widget
, GdkEventCrossing 
*gdk_event
, wxWindowGTK 
*win 
) 
2208         wxapp_install_idle_handler(); 
2210     if (!win
->m_hasVMT
) return FALSE
; 
2211     if (g_blockEventsOnDrag
) return FALSE
; 
2213     // Event was emitted after an ungrab 
2214     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
2216     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
2218     wxMouseEvent 
event( wxEVT_LEAVE_WINDOW 
); 
2219     event
.SetTimestamp( gdk_event
->time 
); 
2220     event
.SetEventObject( win 
); 
2224     GdkModifierType state 
= (GdkModifierType
)0; 
2226     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
2228     event
.m_shiftDown 
= (state 
& GDK_SHIFT_MASK
) != 0; 
2229     event
.m_controlDown 
= (state 
& GDK_CONTROL_MASK
) != 0; 
2230     event
.m_altDown 
= (state 
& GDK_MOD1_MASK
) != 0; 
2231     event
.m_metaDown 
= (state 
& GDK_MOD2_MASK
) != 0; 
2232     event
.m_leftDown 
= (state 
& GDK_BUTTON1_MASK
) != 0; 
2233     event
.m_middleDown 
= (state 
& GDK_BUTTON2_MASK
) != 0; 
2234     event
.m_rightDown 
= (state 
& GDK_BUTTON3_MASK
) != 0; 
2236     wxPoint pt 
= win
->GetClientAreaOrigin(); 
2237     event
.m_x 
= x 
+ pt
.x
; 
2238     event
.m_y 
= y 
+ pt
.y
; 
2240     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
2242         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" ); 
2249 //----------------------------------------------------------------------------- 
2250 // "value_changed" from m_vAdjust 
2251 //----------------------------------------------------------------------------- 
2253 static void gtk_window_vscroll_callback( GtkAdjustment 
*adjust
, 
2260         wxapp_install_idle_handler(); 
2262     if (g_blockEventsOnDrag
) return; 
2264     if (!win
->m_hasVMT
) return; 
2266     float diff 
= adjust
->value 
- win
->m_oldVerticalPos
; 
2267     if (fabs(diff
) < 0.2) return; 
2269     win
->m_oldVerticalPos 
= adjust
->value
; 
2272     GtkScrolledWindow   
*sw 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
2274     wxEventType         command 
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->vscrollbar
)); 
2276     int value 
= (int)(adjust
->value
+0.5); 
2278     wxScrollWinEvent 
event( command
, value
, wxVERTICAL 
); 
2279     event
.SetEventObject( win 
); 
2280     win
->GetEventHandler()->ProcessEvent( event 
); 
2283 //----------------------------------------------------------------------------- 
2284 // "value_changed" from m_hAdjust 
2285 //----------------------------------------------------------------------------- 
2287 static void gtk_window_hscroll_callback( GtkAdjustment 
*adjust
, 
2294         wxapp_install_idle_handler(); 
2296     if (g_blockEventsOnDrag
) return; 
2297     if (!win
->m_hasVMT
) return; 
2299     float diff 
= adjust
->value 
- win
->m_oldHorizontalPos
; 
2300     if (fabs(diff
) < 0.2) return; 
2303     GtkScrolledWindow   
*sw 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
2305     wxEventType         command 
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->hscrollbar
)); 
2307     win
->m_oldHorizontalPos 
= adjust
->value
; 
2309     int value 
= (int)(adjust
->value
+0.5); 
2311     wxScrollWinEvent 
event( command
, value
, wxHORIZONTAL 
); 
2312     event
.SetEventObject( win 
); 
2313     win
->GetEventHandler()->ProcessEvent( event 
); 
2316 //----------------------------------------------------------------------------- 
2317 // "button_press_event" from scrollbar 
2318 //----------------------------------------------------------------------------- 
2320 static gint 
gtk_scrollbar_button_press_callback( GtkRange 
*widget
, 
2321                                                  GdkEventButton 
*gdk_event
, 
2327         wxapp_install_idle_handler(); 
2330     g_blockEventsOnScroll 
= TRUE
; 
2332     // FIXME: there is no 'slider' field in GTK+ 2.0 any more 
2334     win
->m_isScrolling 
= (gdk_event
->window 
== widget
->slider
); 
2340 //----------------------------------------------------------------------------- 
2341 // "button_release_event" from scrollbar 
2342 //----------------------------------------------------------------------------- 
2344 static gint 
gtk_scrollbar_button_release_callback( GtkRange 
*widget
, 
2345                                                    GdkEventButton 
*WXUNUSED(gdk_event
), 
2350 //  don't test here as we can release the mouse while being over 
2351 //  a different window than the slider 
2353 //    if (gdk_event->window != widget->slider) return FALSE; 
2355     g_blockEventsOnScroll 
= FALSE
; 
2357     if (win
->m_isScrolling
) 
2359         wxEventType command 
= wxEVT_SCROLLWIN_THUMBRELEASE
; 
2363         GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
2364         if (widget 
== GTK_RANGE(scrolledWindow
->hscrollbar
)) 
2366             value 
= (int)(win
->m_hAdjust
->value
+0.5); 
2369         if (widget 
== GTK_RANGE(scrolledWindow
->vscrollbar
)) 
2371             value 
= (int)(win
->m_vAdjust
->value
+0.5); 
2375         wxScrollWinEvent 
event( command
, value
, dir 
); 
2376         event
.SetEventObject( win 
); 
2377         win
->GetEventHandler()->ProcessEvent( event 
); 
2380     win
->m_isScrolling 
= FALSE
; 
2385 // ---------------------------------------------------------------------------- 
2386 // this wxWindowBase function is implemented here (in platform-specific file) 
2387 // because it is static and so couldn't be made virtual 
2388 // ---------------------------------------------------------------------------- 
2390 wxWindow 
*wxWindowBase::DoFindFocus() 
2392     // the cast is necessary when we compile in wxUniversal mode 
2393     return (wxWindow 
*)g_focusWindow
; 
2397 //----------------------------------------------------------------------------- 
2398 // "realize" from m_widget 
2399 //----------------------------------------------------------------------------- 
2401 /* We cannot set colours and fonts before the widget has 
2402    been realized, so we do this directly after realization. */ 
2405 gtk_window_realized_callback( GtkWidget 
*m_widget
, wxWindow 
*win 
) 
2410         wxapp_install_idle_handler(); 
2415         GtkPizza 
*pizza 
= GTK_PIZZA( m_widget 
); 
2416         gtk_im_context_set_client_window( win
->m_imData
->context
, 
2417                                           pizza
->bin_window 
); 
2421     wxWindowCreateEvent 
event( win 
); 
2422     event
.SetEventObject( win 
); 
2423     win
->GetEventHandler()->ProcessEvent( event 
); 
2428 //----------------------------------------------------------------------------- 
2430 //----------------------------------------------------------------------------- 
2433 void gtk_window_size_callback( GtkWidget 
*WXUNUSED(widget
), 
2434                                GtkAllocation 
*WXUNUSED(alloc
), 
2438         wxapp_install_idle_handler(); 
2440     if (!win
->m_hasScrolling
) return; 
2442     int client_width 
= 0; 
2443     int client_height 
= 0; 
2444     win
->GetClientSize( &client_width
, &client_height 
); 
2445     if ((client_width 
== win
->m_oldClientWidth
) && (client_height 
== win
->m_oldClientHeight
)) 
2448     win
->m_oldClientWidth 
= client_width
; 
2449     win
->m_oldClientHeight 
= client_height
; 
2451     if (!win
->m_nativeSizeEvent
) 
2453         wxSizeEvent 
event( win
->GetSize(), win
->GetId() ); 
2454         event
.SetEventObject( win 
); 
2455         win
->GetEventHandler()->ProcessEvent( event 
); 
2461     #define WXUNUSED_UNLESS_XIM(param)  param 
2463     #define WXUNUSED_UNLESS_XIM(param)  WXUNUSED(param) 
2466 /* Resize XIM window */ 
2469 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
), 
2470                                  GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
), 
2471                                  wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) ) 
2474         wxapp_install_idle_handler(); 
2480     if  (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
) 
2484         gdk_window_get_size (widget
->window
, &width
, &height
); 
2485         win
->m_icattr
->preedit_area
.width 
= width
; 
2486         win
->m_icattr
->preedit_area
.height 
= height
; 
2487         gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
); 
2492 //----------------------------------------------------------------------------- 
2493 // "realize" from m_wxwindow 
2494 //----------------------------------------------------------------------------- 
2496 /* Initialize XIM support */ 
2499 gtk_wxwindow_realized_callback( GtkWidget 
* WXUNUSED_UNLESS_XIM(widget
), 
2500                                 wxWindowGTK 
* WXUNUSED_UNLESS_XIM(win
) ) 
2503         wxapp_install_idle_handler(); 
2506     if (win
->m_ic
) return FALSE
; 
2507     if (!widget
) return FALSE
; 
2508     if (!gdk_im_ready()) return FALSE
; 
2510     win
->m_icattr 
= gdk_ic_attr_new(); 
2511     if (!win
->m_icattr
) return FALSE
; 
2515     GdkColormap 
*colormap
; 
2516     GdkICAttr 
*attr 
= win
->m_icattr
; 
2517     unsigned attrmask 
= GDK_IC_ALL_REQ
; 
2519     GdkIMStyle supported_style 
= (GdkIMStyle
) 
2520                                   (GDK_IM_PREEDIT_NONE 
| 
2521                                    GDK_IM_PREEDIT_NOTHING 
| 
2522                                    GDK_IM_PREEDIT_POSITION 
| 
2523                                    GDK_IM_STATUS_NONE 
| 
2524                                    GDK_IM_STATUS_NOTHING
); 
2526     if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2527         supported_style 
= (GdkIMStyle
)(supported_style 
& ~GDK_IM_PREEDIT_POSITION
); 
2529     attr
->style 
= style 
= gdk_im_decide_style (supported_style
); 
2530     attr
->client_window 
= widget
->window
; 
2532     if ((colormap 
= gtk_widget_get_colormap (widget
)) != 
2533             gtk_widget_get_default_colormap ()) 
2535         attrmask 
|= GDK_IC_PREEDIT_COLORMAP
; 
2536         attr
->preedit_colormap 
= colormap
; 
2539     attrmask 
|= GDK_IC_PREEDIT_FOREGROUND
; 
2540     attrmask 
|= GDK_IC_PREEDIT_BACKGROUND
; 
2541     attr
->preedit_foreground 
= widget
->style
->fg
[GTK_STATE_NORMAL
]; 
2542     attr
->preedit_background 
= widget
->style
->base
[GTK_STATE_NORMAL
]; 
2544     switch (style 
& GDK_IM_PREEDIT_MASK
) 
2546         case GDK_IM_PREEDIT_POSITION
: 
2547             if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2549                 g_warning ("over-the-spot style requires fontset"); 
2553             gdk_window_get_size (widget
->window
, &width
, &height
); 
2555             attrmask 
|= GDK_IC_PREEDIT_POSITION_REQ
; 
2556             attr
->spot_location
.x 
= 0; 
2557             attr
->spot_location
.y 
= height
; 
2558             attr
->preedit_area
.x 
= 0; 
2559             attr
->preedit_area
.y 
= 0; 
2560             attr
->preedit_area
.width 
= width
; 
2561             attr
->preedit_area
.height 
= height
; 
2562             attr
->preedit_fontset 
= widget
->style
->font
; 
2567       win
->m_ic 
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
); 
2569       if (win
->m_ic 
== NULL
) 
2570           g_warning ("Can't create input context."); 
2573           mask 
= gdk_window_get_events (widget
->window
); 
2574           mask 
= (GdkEventMask
)(mask 
| gdk_ic_get_events (win
->m_ic
)); 
2575           gdk_window_set_events (widget
->window
, mask
); 
2577           if (GTK_WIDGET_HAS_FOCUS(widget
)) 
2578               gdk_im_begin (win
->m_ic
, widget
->window
); 
2585 //----------------------------------------------------------------------------- 
2586 // InsertChild for wxWindowGTK. 
2587 //----------------------------------------------------------------------------- 
2589 /* Callback for wxWindowGTK. This very strange beast has to be used because 
2590  * C++ has no virtual methods in a constructor. We have to emulate a 
2591  * virtual function here as wxNotebook requires a different way to insert 
2592  * a child in it. I had opted for creating a wxNotebookPage window class 
2593  * which would have made this superfluous (such in the MDI window system), 
2594  * but no-one was listening to me... */ 
2596 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child 
) 
2598     /* the window might have been scrolled already, do we 
2599        have to adapt the position */ 
2600     GtkPizza 
*pizza 
= GTK_PIZZA(parent
->m_wxwindow
); 
2601     child
->m_x 
+= pizza
->xoffset
; 
2602     child
->m_y 
+= pizza
->yoffset
; 
2604     gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
), 
2605                      GTK_WIDGET(child
->m_widget
), 
2612 //----------------------------------------------------------------------------- 
2614 //----------------------------------------------------------------------------- 
2616 wxWindow 
*wxGetActiveWindow() 
2618     return wxWindow::FindFocus(); 
2621 //----------------------------------------------------------------------------- 
2623 //----------------------------------------------------------------------------- 
2625 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
2627 #ifdef __WXUNIVERSAL__ 
2628     IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
) 
2630     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
2631 #endif // __WXUNIVERSAL__/__WXGTK__ 
2633 void wxWindowGTK::Init() 
2636     m_widget 
= (GtkWidget 
*) NULL
; 
2637     m_wxwindow 
= (GtkWidget 
*) NULL
; 
2638     m_focusWidget 
= (GtkWidget 
*) NULL
; 
2648     m_needParent 
= TRUE
; 
2649     m_isBeingDeleted 
= FALSE
; 
2652     m_nativeSizeEvent 
= FALSE
; 
2654     m_hasScrolling 
= FALSE
; 
2655     m_isScrolling 
= FALSE
; 
2657     m_hAdjust 
= (GtkAdjustment
*) NULL
; 
2658     m_vAdjust 
= (GtkAdjustment
*) NULL
; 
2659     m_oldHorizontalPos 
= 
2660     m_oldVerticalPos 
= 0.0; 
2662     m_oldClientHeight 
= 0; 
2666     m_insertCallback 
= (wxInsertChildFunction
) NULL
; 
2668     m_acceptsFocus 
= FALSE
; 
2671     m_clipPaintRegion 
= FALSE
; 
2673     m_needsStyleChange 
= false; 
2675     m_cursor 
= *wxSTANDARD_CURSOR
; 
2679     m_x11Context 
= NULL
; 
2680     m_dirtyTabOrder 
= false; 
2683     m_ic 
= (GdkIC
*) NULL
; 
2684     m_icattr 
= (GdkICAttr
*) NULL
; 
2689 wxWindowGTK::wxWindowGTK() 
2694 wxWindowGTK::wxWindowGTK( wxWindow 
*parent
, 
2699                           const wxString 
&name  
) 
2703     Create( parent
, id
, pos
, size
, style
, name 
); 
2706 bool wxWindowGTK::Create( wxWindow 
*parent
, 
2711                           const wxString 
&name  
) 
2713     if (!PreCreation( parent
, pos
, size 
) || 
2714         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
2716         wxFAIL_MSG( wxT("wxWindowGTK creation failed") ); 
2720     m_insertCallback 
= wxInsertChildInWindow
; 
2722     m_widget 
= gtk_scrolled_window_new( (GtkAdjustment 
*) NULL
, (GtkAdjustment 
*) NULL 
); 
2723     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
2725     GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
2727     GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2728     scroll_class
->scrollbar_spacing 
= 0; 
2730     gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
2732     m_hAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) ); 
2733     m_vAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) ); 
2735     m_wxwindow 
= gtk_pizza_new(); 
2737 #ifndef __WXUNIVERSAL__ 
2738     GtkPizza 
*pizza 
= GTK_PIZZA(m_wxwindow
); 
2740     if (HasFlag(wxRAISED_BORDER
)) 
2742         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT 
); 
2744     else if (HasFlag(wxSUNKEN_BORDER
)) 
2746         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN 
); 
2748     else if (HasFlag(wxSIMPLE_BORDER
)) 
2750         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN 
); 
2754         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE 
); 
2756 #endif // __WXUNIVERSAL__ 
2758     gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
2760     GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
2761     m_acceptsFocus 
= TRUE
; 
2763     // I _really_ don't want scrollbars in the beginning 
2764     m_vAdjust
->lower 
= 0.0; 
2765     m_vAdjust
->upper 
= 1.0; 
2766     m_vAdjust
->value 
= 0.0; 
2767     m_vAdjust
->step_increment 
= 1.0; 
2768     m_vAdjust
->page_increment 
= 1.0; 
2769     m_vAdjust
->page_size 
= 5.0; 
2770     gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
2771     m_hAdjust
->lower 
= 0.0; 
2772     m_hAdjust
->upper 
= 1.0; 
2773     m_hAdjust
->value 
= 0.0; 
2774     m_hAdjust
->step_increment 
= 1.0; 
2775     m_hAdjust
->page_increment 
= 1.0; 
2776     m_hAdjust
->page_size 
= 5.0; 
2777     gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
2779     // these handlers block mouse events to any window during scrolling such as 
2780     // motion events and prevent GTK and wxWidgets from fighting over where the 
2783     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event", 
2784           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
2786     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event", 
2787           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
2789     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event", 
2790           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
2792     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event", 
2793           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
2795     // these handlers get notified when screen updates are required either when 
2796     // scrolling or when the window size (and therefore scrollbar configuration) 
2799     gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
2800           (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
2801     gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
2802           (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
2804     gtk_widget_show( m_wxwindow 
); 
2807         m_parent
->DoAddChild( this ); 
2809     m_focusWidget 
= m_wxwindow
; 
2816 wxWindowGTK::~wxWindowGTK() 
2820     if (g_focusWindow 
== this) 
2821         g_focusWindow 
= NULL
; 
2823     if ( g_delayedFocus 
== this ) 
2824         g_delayedFocus 
= NULL
; 
2826     m_isBeingDeleted 
= TRUE
; 
2836         gdk_ic_destroy (m_ic
); 
2838         gdk_ic_attr_destroy (m_icattr
); 
2843         gtk_widget_destroy( m_wxwindow 
); 
2844         m_wxwindow 
= (GtkWidget
*) NULL
; 
2849         gtk_widget_destroy( m_widget 
); 
2850         m_widget 
= (GtkWidget
*) NULL
; 
2858 bool wxWindowGTK::PreCreation( wxWindowGTK 
*parent
, const wxPoint 
&pos
,  const wxSize 
&size 
) 
2860     wxCHECK_MSG( !m_needParent 
|| parent
, FALSE
, wxT("Need complete parent.") ); 
2862     // Use either the given size, or the default if -1 is given. 
2863     // See wxWindowBase for these functions. 
2864     m_width 
= WidthDefault(size
.x
) ; 
2865     m_height 
= HeightDefault(size
.y
); 
2873 void wxWindowGTK::PostCreation() 
2875     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2881             // these get reported to wxWidgets -> wxPaintEvent 
2883             gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE 
); 
2885             gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event", 
2886                 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this ); 
2889             gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw", 
2890                 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this ); 
2892             if (!HasFlag(wxFULL_REPAINT_ON_RESIZE
)) 
2894                 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event", 
2895                     GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this ); 
2898             // gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), !HasFlag( wxFULL_REPAINT_ON_RESIZE ) ); 
2903         // Create input method handler 
2904         m_imData 
= new wxGtkIMData
; 
2906         // Cannot handle drawing preedited text yet 
2907         gtk_im_context_set_use_preedit( m_imData
->context
, FALSE 
); 
2909         g_signal_connect (G_OBJECT (m_imData
->context
), "commit", 
2910                           G_CALLBACK (gtk_wxwindow_commit_cb
), this); 
2913         // these are called when the "sunken" or "raised" borders are drawn 
2914         gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event", 
2915           GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this ); 
2918         gtk_signal_connect( GTK_OBJECT(m_widget
), "draw", 
2919           GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this ); 
2925     if (!GTK_IS_WINDOW(m_widget
)) 
2927         if (m_focusWidget 
== NULL
) 
2928             m_focusWidget 
= m_widget
; 
2930         gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event", 
2931             GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this ); 
2933         gtk_signal_connect_after( GTK_OBJECT(m_focusWidget
), "focus_out_event", 
2934             GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this ); 
2937     // connect to the various key and mouse handlers 
2939     GtkWidget 
*connect_widget 
= GetConnectWidget(); 
2941     ConnectWidget( connect_widget 
); 
2943     /* We cannot set colours, fonts and cursors before the widget has 
2944        been realized, so we do this directly after realization */ 
2945     gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize", 
2946                             GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this ); 
2950         // Catch native resize events 
2951         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate", 
2952                             GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this ); 
2954         // Initialize XIM support 
2955         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize", 
2956                             GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this ); 
2958         // And resize XIM window 
2959         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate", 
2960                             GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this ); 
2963     if (GTK_IS_COMBO(m_widget
)) 
2965         GtkCombo 
*gcombo 
= GTK_COMBO(m_widget
); 
2967         gtk_signal_connect( GTK_OBJECT(gcombo
->entry
), "size_request", 
2968                             GTK_SIGNAL_FUNC(wxgtk_combo_size_request_callback
), 
2973         // This is needed if we want to add our windows into native 
2974         // GTK controls, such as the toolbar. With this callback, the 
2975         // toolbar gets to know the correct size (the one set by the 
2976         // programmer). Sadly, it misbehaves for wxComboBox. 
2977         gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request", 
2978                             GTK_SIGNAL_FUNC(wxgtk_window_size_request_callback
), 
2982     InheritAttributes(); 
2986     // unless the window was created initially hidden (i.e. Hide() had been 
2987     // called before Create()), we should show it at GTK+ level as well 
2989         gtk_widget_show( m_widget 
); 
2992 void wxWindowGTK::ConnectWidget( GtkWidget 
*widget 
) 
2994     gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event", 
2995       GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this ); 
2997     gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event", 
2998       GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this ); 
3000     gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event", 
3001       GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this ); 
3003     gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event", 
3004       GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this ); 
3006     gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event", 
3007       GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this ); 
3010     gtk_signal_connect( GTK_OBJECT(widget
), "scroll_event", 
3011       GTK_SIGNAL_FUNC(gtk_window_wheel_callback
), (gpointer
)this ); 
3012     g_signal_connect(widget
, "popup_menu", 
3013         G_CALLBACK(wxgtk_window_popup_menu_callback
), this); 
3016     gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event", 
3017       GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this ); 
3019     gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event", 
3020       GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this ); 
3023 bool wxWindowGTK::Destroy() 
3025     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3029     return wxWindowBase::Destroy(); 
3032 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
) 
3034     gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height 
); 
3037 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
3039     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3040     wxASSERT_MSG( (m_parent 
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") ); 
3043     printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height ); 
3046     if (m_resizing
) return; /* I don't like recursions */ 
3049     int currentX
, currentY
; 
3050     GetPosition(¤tX
, ¤tY
); 
3051     if (x 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
3053     if (y 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
3055     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
3057     if (m_parent
->m_wxwindow 
== NULL
) /* i.e. wxNotebook */ 
3059         /* don't set the size for children of wxNotebook, just take the values. */ 
3067         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
3068         if ((sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) == 0) 
3070             if (x 
!= -1) m_x 
= x 
+ pizza
->xoffset
; 
3071             if (y 
!= -1) m_y 
= y 
+ pizza
->yoffset
; 
3075             m_x 
= x 
+ pizza
->xoffset
; 
3076             m_y 
= y 
+ pizza
->yoffset
; 
3079         // calculate the best size if we should auto size the window 
3080         if ( ((sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1) || 
3081                 ((sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1) ) 
3083             const wxSize sizeBest 
= GetBestSize(); 
3084             if ( (sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1 ) 
3086             if ( (sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1 ) 
3087                 height 
= sizeBest
.y
; 
3095         int minWidth 
= GetMinWidth(), 
3096             minHeight 
= GetMinHeight(), 
3097             maxWidth 
= GetMaxWidth(), 
3098             maxHeight 
= GetMaxHeight(); 
3100         if ((minWidth 
!= -1) && (m_width 
< minWidth
)) m_width 
= minWidth
; 
3101         if ((minHeight 
!= -1) && (m_height 
< minHeight
)) m_height 
= minHeight
; 
3102         if ((maxWidth 
!= -1) && (m_width 
> maxWidth
)) m_width 
= maxWidth
; 
3103         if ((maxHeight 
!= -1) && (m_height 
> maxHeight
)) m_height 
= maxHeight
; 
3106         int bottom_border 
= 0; 
3109         if (GTK_WIDGET_CAN_DEFAULT(m_widget
)) 
3111             /* the default button has a border around it */ 
3117         DoMoveWindow( m_x
-border
, 
3120                       m_height
+border
+bottom_border 
); 
3125         /* Sometimes the client area changes size without the 
3126            whole windows's size changing, but if the whole 
3127            windows's size doesn't change, no wxSizeEvent will 
3128            normally be sent. Here we add an extra test if 
3129            the client test has been changed and this will 
3131         GetClientSize( &m_oldClientWidth
, &m_oldClientHeight 
); 
3135     wxPrintf( "OnSize sent from " ); 
3136     if (GetClassInfo() && GetClassInfo()->GetClassName()) 
3137         wxPrintf( GetClassInfo()->GetClassName() ); 
3138     wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height ); 
3141     if (!m_nativeSizeEvent
) 
3143         wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
3144         event
.SetEventObject( this ); 
3145         GetEventHandler()->ProcessEvent( event 
); 
3151 void wxWindowGTK::OnInternalIdle() 
3154     if ( m_dirtyTabOrder 
) 
3157     // Update style if the window was not yet realized 
3158     // and SetBackgroundStyle(wxBG_STYLE_CUSTOM) was called 
3159     if (m_needsStyleChange
) 
3161         SetBackgroundStyle(GetBackgroundStyle()); 
3162         m_needsStyleChange 
= false; 
3165     // Update invalidated regions. 
3168     wxCursor cursor 
= m_cursor
; 
3169     if (g_globalCursor
.Ok()) cursor 
= g_globalCursor
; 
3173         /* I now set the cursor anew in every OnInternalIdle call 
3174            as setting the cursor in a parent window also effects the 
3175            windows above so that checking for the current cursor is 
3180             GdkWindow 
*window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3182                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3184             if (!g_globalCursor
.Ok()) 
3185                 cursor 
= *wxSTANDARD_CURSOR
; 
3187             window 
= m_widget
->window
; 
3188             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
3189                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3195             GdkWindow 
*window 
= m_widget
->window
; 
3196             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
3197                gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3202     if (wxUpdateUIEvent::CanUpdate(this)) 
3203         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
3206 void wxWindowGTK::DoGetSize( int *width
, int *height 
) const 
3208     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3210     if (width
) (*width
) = m_width
; 
3211     if (height
) (*height
) = m_height
; 
3214 void wxWindowGTK::DoSetClientSize( int width
, int height 
) 
3216     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3220         SetSize( width
, height 
); 
3227 #ifndef __WXUNIVERSAL__ 
3228         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
3230             /* when using GTK 1.2 we set the shadow border size to 2 */ 
3234         if (HasFlag(wxSIMPLE_BORDER
)) 
3236             /* when using GTK 1.2 we set the simple border size to 1 */ 
3240 #endif // __WXUNIVERSAL__ 
3244             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
3246             GtkRequisition vscroll_req
; 
3247             vscroll_req
.width 
= 2; 
3248             vscroll_req
.height 
= 2; 
3249             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
3250                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
3252             GtkRequisition hscroll_req
; 
3253             hscroll_req
.width 
= 2; 
3254             hscroll_req
.height 
= 2; 
3255             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
3256                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
3258             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
3260             if (scroll_window
->vscrollbar_visible
) 
3262                 dw 
+= vscroll_req
.width
; 
3263                 dw 
+= scroll_class
->scrollbar_spacing
; 
3266             if (scroll_window
->hscrollbar_visible
) 
3268                 dh 
+= hscroll_req
.height
; 
3269                 dh 
+= scroll_class
->scrollbar_spacing
; 
3273        SetSize( width
+dw
, height
+dh 
); 
3277 void wxWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
3279     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3283         if (width
) (*width
) = m_width
; 
3284         if (height
) (*height
) = m_height
; 
3291 #ifndef __WXUNIVERSAL__ 
3292         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
3294             /* when using GTK 1.2 we set the shadow border size to 2 */ 
3298         if (HasFlag(wxSIMPLE_BORDER
)) 
3300             /* when using GTK 1.2 we set the simple border size to 1 */ 
3304 #endif // __WXUNIVERSAL__ 
3308             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
3310             GtkRequisition vscroll_req
; 
3311             vscroll_req
.width 
= 2; 
3312             vscroll_req
.height 
= 2; 
3313             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
3314                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
3316             GtkRequisition hscroll_req
; 
3317             hscroll_req
.width 
= 2; 
3318             hscroll_req
.height 
= 2; 
3319             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
3320                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
3322             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
3324             if (scroll_window
->vscrollbar_visible
) 
3326                 dw 
+= vscroll_req
.width
; 
3327                 dw 
+= scroll_class
->scrollbar_spacing
; 
3330             if (scroll_window
->hscrollbar_visible
) 
3332                 dh 
+= hscroll_req
.height
; 
3333                 dh 
+= scroll_class
->scrollbar_spacing
; 
3337         if (width
) (*width
) = m_width 
- dw
; 
3338         if (height
) (*height
) = m_height 
- dh
; 
3342     printf( "GetClientSize, name %s ", GetName().c_str() ); 
3343     if (width) printf( " width = %d", (*width) ); 
3344     if (height) printf( " height = %d", (*height) ); 
3349 void wxWindowGTK::DoGetPosition( int *x
, int *y 
) const 
3351     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3355     if (m_parent 
&& m_parent
->m_wxwindow
) 
3357         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
3358         dx 
= pizza
->xoffset
; 
3359         dy 
= pizza
->yoffset
; 
3362     if (x
) (*x
) = m_x 
- dx
; 
3363     if (y
) (*y
) = m_y 
- dy
; 
3366 void wxWindowGTK::DoClientToScreen( int *x
, int *y 
) const 
3368     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3370     if (!m_widget
->window
) return; 
3372     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3374         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3376         source 
= m_widget
->window
; 
3380     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3384         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3386             org_x 
+= m_widget
->allocation
.x
; 
3387             org_y 
+= m_widget
->allocation
.y
; 
3395 void wxWindowGTK::DoScreenToClient( int *x
, int *y 
) const 
3397     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3399     if (!m_widget
->window
) return; 
3401     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3403         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3405         source 
= m_widget
->window
; 
3409     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3413         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3415             org_x 
+= m_widget
->allocation
.x
; 
3416             org_y 
+= m_widget
->allocation
.y
; 
3424 bool wxWindowGTK::Show( bool show 
) 
3426     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3428     if (!wxWindowBase::Show(show
)) 
3435         gtk_widget_show( m_widget 
); 
3437         gtk_widget_hide( m_widget 
); 
3439     wxShowEvent 
eventShow(GetId(), show
); 
3440     eventShow
.SetEventObject(this); 
3442     GetEventHandler()->ProcessEvent(eventShow
); 
3447 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
) 
3449     win
->OnParentEnable(enable
); 
3451     // Recurse, so that children have the opportunity to Do The Right Thing 
3452     // and reset colours that have been messed up by a parent's (really ancestor's) 
3454     for ( wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
3456           node 
= node
->GetNext() ) 
3458         wxWindow 
*child 
= node
->GetData(); 
3459         if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
))) 
3460             wxWindowNotifyEnable(child
, enable
); 
3464 bool wxWindowGTK::Enable( bool enable 
) 
3466     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3468     if (!wxWindowBase::Enable(enable
)) 
3474     gtk_widget_set_sensitive( m_widget
, enable 
); 
3476         gtk_widget_set_sensitive( m_wxwindow
, enable 
); 
3478     wxWindowNotifyEnable(this, enable
); 
3483 int wxWindowGTK::GetCharHeight() const 
3485     wxCHECK_MSG( (m_widget 
!= NULL
), 12, wxT("invalid window") ); 
3487     wxFont font 
= GetFont(); 
3488     wxCHECK_MSG( font
.Ok(), 12, wxT("invalid font") ); 
3491     PangoContext 
*context 
= NULL
; 
3493         context 
= gtk_widget_get_pango_context( m_widget 
); 
3498     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
3499     PangoLayout 
*layout 
= pango_layout_new(context
); 
3500     pango_layout_set_font_description(layout
, desc
); 
3501     pango_layout_set_text(layout
, "H", 1); 
3502     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
3504     PangoRectangle rect
; 
3505     pango_layout_line_get_extents(line
, NULL
, &rect
); 
3507     g_object_unref( G_OBJECT( layout 
) ); 
3509     return (int) PANGO_PIXELS(rect
.height
); 
3511     GdkFont 
*gfont 
= font
.GetInternalFont( 1.0 ); 
3513     return gfont
->ascent 
+ gfont
->descent
; 
3517 int wxWindowGTK::GetCharWidth() const 
3519     wxCHECK_MSG( (m_widget 
!= NULL
), 8, wxT("invalid window") ); 
3521     wxFont font 
= GetFont(); 
3522     wxCHECK_MSG( font
.Ok(), 8, wxT("invalid font") ); 
3525     PangoContext 
*context 
= NULL
; 
3527         context 
= gtk_widget_get_pango_context( m_widget 
); 
3532     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
3533     PangoLayout 
*layout 
= pango_layout_new(context
); 
3534     pango_layout_set_font_description(layout
, desc
); 
3535     pango_layout_set_text(layout
, "g", 1); 
3536     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
3538     PangoRectangle rect
; 
3539     pango_layout_line_get_extents(line
, NULL
, &rect
); 
3541     g_object_unref( G_OBJECT( layout 
) ); 
3543     return (int) PANGO_PIXELS(rect
.width
); 
3545     GdkFont 
*gfont 
= font
.GetInternalFont( 1.0 ); 
3547     return gdk_string_width( gfont
, "g" ); 
3551 void wxWindowGTK::GetTextExtent( const wxString
& string
, 
3555                               int *externalLeading
, 
3556                               const wxFont 
*theFont 
) const 
3558     wxFont fontToUse 
= theFont 
? *theFont 
: GetFont(); 
3560     wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") ); 
3562     if (string
.IsEmpty()) 
3570     PangoContext 
*context 
= NULL
; 
3572         context 
= gtk_widget_get_pango_context( m_widget 
); 
3581     PangoFontDescription 
*desc 
= fontToUse
.GetNativeFontInfo()->description
; 
3582     PangoLayout 
*layout 
= pango_layout_new(context
); 
3583     pango_layout_set_font_description(layout
, desc
); 
3586         const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( string 
); 
3587         pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data 
)); 
3589         const wxWCharBuffer wdata 
= wxConvLocal
.cMB2WC( string 
); 
3590         const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( wdata 
); 
3591         pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data 
)); 
3595     PangoRectangle rect
; 
3596     pango_layout_get_extents(layout
, NULL
, &rect
); 
3598     if (x
) (*x
) = (wxCoord
) PANGO_PIXELS(rect
.width
); 
3599     if (y
) (*y
) = (wxCoord
) PANGO_PIXELS(rect
.height
); 
3602         PangoLayoutIter 
*iter 
= pango_layout_get_iter(layout
); 
3603         int baseline 
= pango_layout_iter_get_baseline(iter
); 
3604         pango_layout_iter_free(iter
); 
3605         *descent 
= *y 
- PANGO_PIXELS(baseline
); 
3607     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3609     g_object_unref( G_OBJECT( layout 
) ); 
3611     GdkFont 
*font 
= fontToUse
.GetInternalFont( 1.0 ); 
3612     if (x
) (*x
) = gdk_string_width( font
, wxGTK_CONV( string 
) ); 
3613     if (y
) (*y
) = font
->ascent 
+ font
->descent
; 
3614     if (descent
) (*descent
) = font
->descent
; 
3615     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3619 void wxWindowGTK::SetFocus() 
3621     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3624         // don't do anything if we already have focus 
3630         if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
)) 
3632             gtk_widget_grab_focus (m_wxwindow
); 
3638         if (GTK_IS_CONTAINER(m_widget
)) 
3640             gtk_widget_child_focus( m_widget
, GTK_DIR_TAB_FORWARD 
); 
3644         if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) ) 
3647             if (!GTK_WIDGET_REALIZED(m_widget
)) 
3649                 // we can't set the focus to the widget now so we remember that 
3650                 // it should be focused and will do it later, during the idle 
3651                 // time, as soon as we can 
3652                 wxLogTrace(TRACE_FOCUS
, 
3653                            _T("Delaying setting focus to %s(%s)"), 
3654                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3656                 g_delayedFocus 
= this; 
3660                 wxLogTrace(TRACE_FOCUS
, 
3661                            _T("Setting focus to %s(%s)"), 
3662                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3664                 gtk_widget_grab_focus (m_widget
); 
3669         if (GTK_IS_CONTAINER(m_widget
)) 
3671             gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD 
); 
3676            wxLogTrace(TRACE_FOCUS
, 
3677                       _T("Can't set focus to %s(%s)"), 
3678                       GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3683 bool wxWindowGTK::AcceptsFocus() const 
3685     return m_acceptsFocus 
&& wxWindowBase::AcceptsFocus(); 
3688 bool wxWindowGTK::Reparent( wxWindowBase 
*newParentBase 
) 
3690     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3692     wxWindowGTK 
*oldParent 
= m_parent
, 
3693              *newParent 
= (wxWindowGTK 
*)newParentBase
; 
3695     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3697     if ( !wxWindowBase::Reparent(newParent
) ) 
3700     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3702     /* prevent GTK from deleting the widget arbitrarily */ 
3703     gtk_widget_ref( m_widget 
); 
3707         gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget 
); 
3710     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3714         /* insert GTK representation */ 
3715         (*(newParent
->m_insertCallback
))(newParent
, this); 
3718     /* reverse: prevent GTK from deleting the widget arbitrarily */ 
3719     gtk_widget_unref( m_widget 
); 
3724 void wxWindowGTK::DoAddChild(wxWindowGTK 
*child
) 
3726     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3728     wxASSERT_MSG( (child 
!= NULL
), wxT("invalid child window") ); 
3730     wxASSERT_MSG( (m_insertCallback 
!= NULL
), wxT("invalid child insertion function") ); 
3735     /* insert GTK representation */ 
3736     (*m_insertCallback
)(this, child
); 
3741 void wxWindowGTK::AddChild(wxWindowBase 
*child
) 
3743     wxWindowBase::AddChild(child
); 
3744     m_dirtyTabOrder 
= true; 
3746         wxapp_install_idle_handler(); 
3749 void wxWindowGTK::RemoveChild(wxWindowBase 
*child
) 
3751     wxWindowBase::RemoveChild(child
); 
3752     m_dirtyTabOrder 
= true; 
3754         wxapp_install_idle_handler(); 
3757 void wxWindowGTK::DoMoveInTabOrder(wxWindow 
*win
, MoveKind move
) 
3759     wxWindowBase::DoMoveInTabOrder(win
, move
); 
3760     m_dirtyTabOrder 
= true; 
3762         wxapp_install_idle_handler(); 
3765 void wxWindowGTK::RealizeTabOrder() 
3769         if (m_children
.size() > 0) 
3771             GList 
*chain 
= NULL
; 
3773             for (wxWindowList::const_iterator i 
= m_children
.begin(); 
3774                     i 
!= m_children
.end(); ++i
) 
3776                 chain 
= g_list_prepend(chain
, (*i
)->m_widget
); 
3779             chain 
= g_list_reverse(chain
); 
3781             gtk_container_set_focus_chain(GTK_CONTAINER(m_wxwindow
), chain
); 
3786             gtk_container_unset_focus_chain(GTK_CONTAINER(m_wxwindow
)); 
3790     m_dirtyTabOrder 
= false; 
3793 #endif // __WXGTK20__ 
3795 void wxWindowGTK::Raise() 
3797     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3799     if (m_wxwindow 
&& m_wxwindow
->window
) 
3801         gdk_window_raise( m_wxwindow
->window 
); 
3803      else if (m_widget
->window
) 
3805         gdk_window_raise( m_widget
->window 
); 
3809 void wxWindowGTK::Lower() 
3811     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3813     if (m_wxwindow 
&& m_wxwindow
->window
) 
3815         gdk_window_lower( m_wxwindow
->window 
); 
3817      else if (m_widget
->window
) 
3819         gdk_window_lower( m_widget
->window 
); 
3823 bool wxWindowGTK::SetCursor( const wxCursor 
&cursor 
) 
3825     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3827     if (cursor 
== m_cursor
) 
3831         wxapp_install_idle_handler(); 
3833     if (cursor 
== wxNullCursor
) 
3834        return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR 
); 
3836        return wxWindowBase::SetCursor( cursor 
); 
3839 void wxWindowGTK::WarpPointer( int x
, int y 
) 
3841     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3843     // We provide this function ourselves as it is 
3844     // missing in GDK (top of this file). 
3846     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3848         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3850         window 
= GetConnectWidget()->window
; 
3853         gdk_window_warp_pointer( window
, x
, y 
); 
3857 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect 
*rect 
) 
3859     if (!m_widget
) return; 
3860     if (!m_widget
->window
) return; 
3864         wxapp_install_idle_handler(); 
3866     wxRect 
myRect(0,0,0,0); 
3867     if (m_wxwindow 
&& rect
) 
3869         myRect
.SetSize(wxSize( m_wxwindow
->allocation
.width
, 
3870                                m_wxwindow
->allocation
.height
)); 
3871         myRect
.Intersect(*rect
); 
3872         if (!myRect
.width 
|| !myRect
.height
) 
3873             // nothing to do, rectangle is empty 
3878     if (eraseBackground 
&& m_wxwindow 
&& m_wxwindow
->window
) 
3882             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3883             m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3887             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3888             m_clearRegion
.Clear(); 
3889             m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3897             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3898             m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3902             GdkRectangle gdk_rect
; 
3903             gdk_rect
.x 
= rect
->x
; 
3904             gdk_rect
.y 
= rect
->y
; 
3905             gdk_rect
.width 
= rect
->width
; 
3906             gdk_rect
.height 
= rect
->height
; 
3907             gtk_widget_draw( m_widget
, &gdk_rect 
); 
3914             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3915             m_updateRegion
.Clear(); 
3916             m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3920             gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL 
); 
3928             GdkRectangle gdk_rect
; 
3929             gdk_rect
.x 
= rect
->x
; 
3930             gdk_rect
.y 
= rect
->y
; 
3931             gdk_rect
.width 
= rect
->width
; 
3932             gdk_rect
.height 
= rect
->height
; 
3933             gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, &gdk_rect
, TRUE 
); 
3937             gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, NULL
, TRUE 
); 
3943 void wxWindowGTK::Update() 
3947     // when we call Update() we really want to update the window immediately on 
3948     // screen, even if itmeans flushing the entire queue and hence slowing down 
3949     // everything -- but it should still be done, it's just that Update() should 
3950     // be called very rarely 
3954 void wxWindowGTK::GtkUpdate() 
3957     if (m_wxwindow 
&& GTK_PIZZA(m_wxwindow
)->bin_window
) 
3958         gdk_window_process_updates( GTK_PIZZA(m_wxwindow
)->bin_window
, FALSE 
); 
3960     if (!m_updateRegion
.IsEmpty()) 
3961         GtkSendPaintEvents(); 
3965 void wxWindowGTK::GtkSendPaintEvents() 
3970         m_clearRegion
.Clear(); 
3972         m_updateRegion
.Clear(); 
3976     // Clip to paint region in wxClientDC 
3977     m_clipPaintRegion 
= TRUE
; 
3979     // widget to draw on 
3980     GtkPizza 
*pizza 
= GTK_PIZZA (m_wxwindow
); 
3982     if (GetThemeEnabled() && (GetBackgroundStyle() == wxBG_STYLE_SYSTEM
)) 
3984         // find ancestor from which to steal background 
3985         wxWindow 
*parent 
= wxGetTopLevelParent((wxWindow 
*)this); 
3987             parent 
= (wxWindow
*)this; 
3989         if (GTK_WIDGET_MAPPED(parent
->m_widget
)) 
3991             wxRegionIterator 
upd( m_updateRegion 
); 
3995                 rect
.x 
= upd
.GetX(); 
3996                 rect
.y 
= upd
.GetY(); 
3997                 rect
.width 
= upd
.GetWidth(); 
3998                 rect
.height 
= upd
.GetHeight(); 
4000                 gtk_paint_flat_box( parent
->m_widget
->style
, 
4002                             (GtkStateType
)GTK_WIDGET_STATE(m_wxwindow
), 
4017         wxWindowDC 
dc( (wxWindow
*)this ); 
4018         dc
.SetClippingRegion( m_updateRegion 
); 
4020         wxEraseEvent 
erase_event( GetId(), &dc 
); 
4021         erase_event
.SetEventObject( this ); 
4023         GetEventHandler()->ProcessEvent(erase_event
); 
4026     // if (!m_clearRegion.IsEmpty())   // Always send an erase event under GTK 1.2 
4028         wxWindowDC 
dc( (wxWindow
*)this ); 
4029         if (m_clearRegion
.IsEmpty()) 
4030             dc
.SetClippingRegion( m_updateRegion 
); 
4032             dc
.SetClippingRegion( m_clearRegion 
); 
4034         wxEraseEvent 
erase_event( GetId(), &dc 
); 
4035         erase_event
.SetEventObject( this ); 
4037         if (!GetEventHandler()->ProcessEvent(erase_event
) && GetBackgroundStyle() != wxBG_STYLE_CUSTOM
) 
4041                 g_eraseGC 
= gdk_gc_new( pizza
->bin_window 
); 
4042                 gdk_gc_set_fill( g_eraseGC
, GDK_SOLID 
); 
4044             gdk_gc_set_foreground( g_eraseGC
, GetBackgroundColour().GetColor() ); 
4046             wxRegionIterator 
upd( m_clearRegion 
); 
4049                 gdk_draw_rectangle( pizza
->bin_window
, g_eraseGC
, 1, 
4050                                     upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() ); 
4054         m_clearRegion
.Clear(); 
4058     wxNcPaintEvent 
nc_paint_event( GetId() ); 
4059     nc_paint_event
.SetEventObject( this ); 
4060     GetEventHandler()->ProcessEvent( nc_paint_event 
); 
4062     wxPaintEvent 
paint_event( GetId() ); 
4063     paint_event
.SetEventObject( this ); 
4064     GetEventHandler()->ProcessEvent( paint_event 
); 
4066     m_clipPaintRegion 
= FALSE
; 
4068 #ifndef __WXUNIVERSAL__ 
4070     // The following code will result in all window-less widgets 
4071     // being redrawn because the wxWidgets class is allowed to 
4072     // paint over the window-less widgets. 
4074     GList 
*children 
= pizza
->children
; 
4077         GtkPizzaChild 
*child 
= (GtkPizzaChild
*) children
->data
; 
4078         children 
= children
->next
; 
4080         if (GTK_WIDGET_NO_WINDOW (child
->widget
) && 
4081             GTK_WIDGET_DRAWABLE (child
->widget
)) 
4083             // Get intersection of widget area and update region 
4084             wxRegion 
region( m_updateRegion 
); 
4086             GdkEventExpose gdk_event
; 
4087             gdk_event
.type 
= GDK_EXPOSE
; 
4088             gdk_event
.window 
= pizza
->bin_window
; 
4089             gdk_event
.count 
= 0; 
4091             wxRegionIterator 
upd( m_updateRegion 
); 
4095                 rect
.x 
= upd
.GetX(); 
4096                 rect
.y 
= upd
.GetY(); 
4097                 rect
.width 
= upd
.GetWidth(); 
4098                 rect
.height 
= upd
.GetHeight(); 
4100                 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
)) 
4102                     gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
); 
4112     m_updateRegion
.Clear(); 
4115 void wxWindowGTK::ClearBackground() 
4117     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4120     if (m_wxwindow 
&& m_wxwindow
->window
) 
4122         m_clearRegion
.Clear(); 
4123         wxSize 
size( GetClientSize() ); 
4124         m_clearRegion
.Union( 0,0,size
.x
,size
.y 
); 
4126         // Better do this in idle? 
4133 void wxWindowGTK::DoSetToolTip( wxToolTip 
*tip 
) 
4135     wxWindowBase::DoSetToolTip(tip
); 
4138         m_tooltip
->Apply( (wxWindow 
*)this ); 
4141 void wxWindowGTK::ApplyToolTip( GtkTooltips 
*tips
, const wxChar 
*tip 
) 
4143     wxString 
tmp( tip 
); 
4144     gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxGTK_CONV(tmp
), (gchar
*) NULL 
); 
4146 #endif // wxUSE_TOOLTIPS 
4148 bool wxWindowGTK::SetBackgroundColour( const wxColour 
&colour 
) 
4150     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
4152     if (!wxWindowBase::SetBackgroundColour(colour
)) 
4157         // We need the pixel value e.g. for background clearing. 
4158         m_backgroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
4161     // apply style change (forceStyle=true so that new style is applied 
4162     // even if the bg colour changed from valid to wxNullColour) 
4163     if (GetBackgroundStyle() != wxBG_STYLE_CUSTOM
) 
4164         ApplyWidgetStyle(true); 
4169 bool wxWindowGTK::SetForegroundColour( const wxColour 
&colour 
) 
4171     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
4173     if (!wxWindowBase::SetForegroundColour(colour
)) 
4180         // We need the pixel value e.g. for background clearing. 
4181         m_foregroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
4184     // apply style change (forceStyle=true so that new style is applied 
4185     // even if the bg colour changed from valid to wxNullColour): 
4186     ApplyWidgetStyle(true); 
4192 PangoContext 
*wxWindowGTK::GtkGetPangoDefaultContext() 
4194     return gtk_widget_get_pango_context( m_widget 
); 
4197 PangoContext 
*wxWindowGTK::GtkGetPangoX11Context() 
4200         m_x11Context 
= pango_x_get_context( gdk_display 
); 
4202     return m_x11Context
; 
4206 GtkRcStyle 
*wxWindowGTK::CreateWidgetStyle(bool forceStyle
) 
4208     // do we need to apply any changes at all? 
4211          !m_foregroundColour
.Ok() && !m_backgroundColour
.Ok() ) 
4216     GtkRcStyle 
*style 
= gtk_rc_style_new(); 
4222             pango_font_description_copy( m_font
.GetNativeFontInfo()->description 
); 
4224         wxString xfontname 
= m_font
.GetNativeFontInfo()->GetXFontName(); 
4225         style
->fontset_name 
= g_strdup(xfontname
.c_str()); 
4229     if ( m_foregroundColour
.Ok() ) 
4231         GdkColor 
*fg 
= m_foregroundColour
.GetColor(); 
4233         style
->fg
[GTK_STATE_NORMAL
] = *fg
; 
4234         style
->color_flags
[GTK_STATE_NORMAL
] = GTK_RC_FG
; 
4236         style
->fg
[GTK_STATE_PRELIGHT
] = *fg
; 
4237         style
->color_flags
[GTK_STATE_PRELIGHT
] = GTK_RC_FG
; 
4239         style
->fg
[GTK_STATE_ACTIVE
] = *fg
; 
4240         style
->color_flags
[GTK_STATE_ACTIVE
] = GTK_RC_FG
; 
4243     if ( m_backgroundColour
.Ok() ) 
4245         GdkColor 
*bg 
= m_backgroundColour
.GetColor(); 
4247         style
->bg
[GTK_STATE_NORMAL
] = *bg
; 
4248         style
->base
[GTK_STATE_NORMAL
] = *bg
; 
4249         style
->color_flags
[GTK_STATE_NORMAL
] = (GtkRcFlags
) 
4250             (style
->color_flags
[GTK_STATE_NORMAL
] | GTK_RC_BG 
| GTK_RC_BASE
); 
4252         style
->bg
[GTK_STATE_PRELIGHT
] = *bg
; 
4253         style
->base
[GTK_STATE_PRELIGHT
] = *bg
; 
4254         style
->color_flags
[GTK_STATE_PRELIGHT
] = (GtkRcFlags
) 
4255             (style
->color_flags
[GTK_STATE_PRELIGHT
] | GTK_RC_BG 
| GTK_RC_BASE
); 
4257         style
->bg
[GTK_STATE_ACTIVE
] = *bg
; 
4258         style
->base
[GTK_STATE_ACTIVE
] = *bg
; 
4259         style
->color_flags
[GTK_STATE_ACTIVE
] = (GtkRcFlags
) 
4260             (style
->color_flags
[GTK_STATE_ACTIVE
] | GTK_RC_BG 
| GTK_RC_BASE
); 
4262         style
->bg
[GTK_STATE_INSENSITIVE
] = *bg
; 
4263         style
->base
[GTK_STATE_INSENSITIVE
] = *bg
; 
4264         style
->color_flags
[GTK_STATE_INSENSITIVE
] = (GtkRcFlags
) 
4265             (style
->color_flags
[GTK_STATE_INSENSITIVE
] | GTK_RC_BG 
| GTK_RC_BASE
); 
4271 void wxWindowGTK::ApplyWidgetStyle(bool forceStyle
) 
4273     GtkRcStyle 
*style 
= CreateWidgetStyle(forceStyle
); 
4276         DoApplyWidgetStyle(style
); 
4277         gtk_rc_style_unref(style
); 
4280     // Style change may affect GTK+'s size calculation: 
4281     InvalidateBestSize(); 
4284 void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
4287         gtk_widget_modify_style(m_wxwindow
, style
); 
4288     gtk_widget_modify_style(m_widget
, style
); 
4291 bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style
) 
4293     wxWindowBase::SetBackgroundStyle(style
); 
4295     if (style 
== wxBG_STYLE_CUSTOM
) 
4297         GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4299             window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4301             window 
= GetConnectWidget()->window
; 
4305             // Make sure GDK/X11 doesn't refresh the window 
4307             gdk_window_set_back_pixmap( window
, None
, False 
); 
4309             Display
* display 
= GDK_WINDOW_DISPLAY(window
); 
4312             m_needsStyleChange 
= false; 
4315             // Do in OnIdle, because the window is not yet available 
4316             m_needsStyleChange 
= true; 
4318         // Don't apply widget style, or we get a grey background 
4322         // apply style change (forceStyle=true so that new style is applied 
4323         // even if the bg colour changed from valid to wxNullColour): 
4324         ApplyWidgetStyle(true); 
4329 //----------------------------------------------------------------------------- 
4330 // Pop-up menu stuff 
4331 //----------------------------------------------------------------------------- 
4333 #if wxUSE_MENUS_NATIVE 
4336 void gtk_pop_hide_callback( GtkWidget 
*WXUNUSED(widget
), bool* is_waiting  
) 
4338     *is_waiting 
= FALSE
; 
4341 void SetInvokingWindow( wxMenu 
*menu
, wxWindow
* win 
) 
4343     menu
->SetInvokingWindow( win 
); 
4345     wxMenuItemList::compatibility_iterator node 
= menu
->GetMenuItems().GetFirst(); 
4348         wxMenuItem 
*menuitem 
= node
->GetData(); 
4349         if (menuitem
->IsSubMenu()) 
4351             SetInvokingWindow( menuitem
->GetSubMenu(), win 
); 
4354         node 
= node
->GetNext(); 
4358 extern "C" void wxPopupMenuPositionCallback( GtkMenu 
*menu
, 
4361                                              gboolean 
* WXUNUSED(whatever
), 
4363                                              gpointer user_data 
) 
4365     // ensure that the menu appears entirely on screen 
4367     gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
); 
4369     wxSize sizeScreen 
= wxGetDisplaySize(); 
4370     wxPoint 
*pos 
= (wxPoint
*)user_data
; 
4372     gint xmax 
= sizeScreen
.x 
- req
.width
, 
4373          ymax 
= sizeScreen
.y 
- req
.height
; 
4375     *x 
= pos
->x 
< xmax 
? pos
->x 
: xmax
; 
4376     *y 
= pos
->y 
< ymax 
? pos
->y 
: ymax
; 
4379 bool wxWindowGTK::DoPopupMenu( wxMenu 
*menu
, int x
, int y 
) 
4381     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
4383     wxCHECK_MSG( menu 
!= NULL
, false, wxT("invalid popup-menu") ); 
4385     // NOTE: if you change this code, you need to update 
4386     //       the same code in taskbar.cpp as well. This 
4387     //       is ugly code duplication, I know, 
4389     SetInvokingWindow( menu
, this ); 
4393     bool is_waiting 
= true; 
4395     gulong handler 
= gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), 
4397                                          GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), 
4398                                          (gpointer
)&is_waiting 
); 
4402     GtkMenuPositionFunc posfunc
; 
4403     if ( x 
== -1 && y 
== -1 ) 
4405         // use GTK's default positioning algorithm 
4411         pos 
= ClientToScreen(wxPoint(x
, y
)); 
4413         posfunc 
= wxPopupMenuPositionCallback
; 
4417                   GTK_MENU(menu
->m_menu
), 
4418                   (GtkWidget 
*) NULL
,           // parent menu shell 
4419                   (GtkWidget 
*) NULL
,           // parent menu item 
4420                   posfunc
,                      // function to position it 
4421                   userdata
,                     // client data 
4422                   0,                            // button used to activate it 
4424                   gtk_get_current_event_time() 
4426                   gs_timeLastClick              
// the time of activation 
4432         gtk_main_iteration(); 
4435     gtk_signal_disconnect(GTK_OBJECT(menu
->m_menu
), handler
); 
4440 #endif // wxUSE_MENUS_NATIVE 
4442 #if wxUSE_DRAG_AND_DROP 
4444 void wxWindowGTK::SetDropTarget( wxDropTarget 
*dropTarget 
) 
4446     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4448     GtkWidget 
*dnd_widget 
= GetConnectWidget(); 
4450     if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget 
); 
4452     if (m_dropTarget
) delete m_dropTarget
; 
4453     m_dropTarget 
= dropTarget
; 
4455     if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget 
); 
4458 #endif // wxUSE_DRAG_AND_DROP 
4460 GtkWidget
* wxWindowGTK::GetConnectWidget() 
4462     GtkWidget 
*connect_widget 
= m_widget
; 
4463     if (m_wxwindow
) connect_widget 
= m_wxwindow
; 
4465     return connect_widget
; 
4468 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow 
*window 
) 
4471         return (window 
== GTK_PIZZA(m_wxwindow
)->bin_window
); 
4473     return (window 
== m_widget
->window
); 
4476 bool wxWindowGTK::SetFont( const wxFont 
&font 
) 
4478     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
4480     if (!wxWindowBase::SetFont(font
)) 
4483     // apply style change (forceStyle=true so that new style is applied 
4484     // even if the font changed from valid to wxNullFont): 
4485     ApplyWidgetStyle(true);     
4490 void wxWindowGTK::DoCaptureMouse() 
4492     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4494     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4496         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4498         window 
= GetConnectWidget()->window
; 
4500     wxCHECK_RET( window
, _T("CaptureMouse() failed") ); 
4502     wxCursor
* cursor 
= & m_cursor
; 
4504         cursor 
= wxSTANDARD_CURSOR
; 
4506     gdk_pointer_grab( window
, FALSE
, 
4508                          (GDK_BUTTON_PRESS_MASK 
| 
4509                           GDK_BUTTON_RELEASE_MASK 
| 
4510                           GDK_POINTER_MOTION_HINT_MASK 
| 
4511                           GDK_POINTER_MOTION_MASK
), 
4513                       cursor
->GetCursor(), 
4514                       (guint32
)GDK_CURRENT_TIME 
); 
4515     g_captureWindow 
= this; 
4516     g_captureWindowHasMouse 
= TRUE
; 
4519 void wxWindowGTK::DoReleaseMouse() 
4521     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4523     wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") ); 
4525     g_captureWindow 
= (wxWindowGTK
*) NULL
; 
4527     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4529         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4531         window 
= GetConnectWidget()->window
; 
4536     gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME 
); 
4540 wxWindow 
*wxWindowBase::GetCapture() 
4542     return (wxWindow 
*)g_captureWindow
; 
4545 bool wxWindowGTK::IsRetained() const 
4550 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
, 
4551       int range
, bool refresh 
) 
4553     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4555     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4557     m_hasScrolling 
= TRUE
; 
4559     if (orient 
== wxHORIZONTAL
) 
4561         float fpos 
= (float)pos
; 
4562         float frange 
= (float)range
; 
4563         float fthumb 
= (float)thumbVisible
; 
4564         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4565         if (fpos 
< 0.0) fpos 
= 0.0; 
4567         if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) && 
4568             (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2)) 
4570             SetScrollPos( orient
, pos
, refresh 
); 
4574         m_oldHorizontalPos 
= fpos
; 
4576         m_hAdjust
->lower 
= 0.0; 
4577         m_hAdjust
->upper 
= frange
; 
4578         m_hAdjust
->value 
= fpos
; 
4579         m_hAdjust
->step_increment 
= 1.0; 
4580         m_hAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4581         m_hAdjust
->page_size 
= fthumb
; 
4585         float fpos 
= (float)pos
; 
4586         float frange 
= (float)range
; 
4587         float fthumb 
= (float)thumbVisible
; 
4588         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4589         if (fpos 
< 0.0) fpos 
= 0.0; 
4591         if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) && 
4592             (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2)) 
4594             SetScrollPos( orient
, pos
, refresh 
); 
4598         m_oldVerticalPos 
= fpos
; 
4600         m_vAdjust
->lower 
= 0.0; 
4601         m_vAdjust
->upper 
= frange
; 
4602         m_vAdjust
->value 
= fpos
; 
4603         m_vAdjust
->step_increment 
= 1.0; 
4604         m_vAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4605         m_vAdjust
->page_size 
= fthumb
; 
4608     if (orient 
== wxHORIZONTAL
) 
4609         gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
4611         gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
4614 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) ) 
4616     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4618     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4620     if (orient 
== wxHORIZONTAL
) 
4622         float fpos 
= (float)pos
; 
4623         if (fpos 
> m_hAdjust
->upper 
- m_hAdjust
->page_size
) fpos 
= m_hAdjust
->upper 
- m_hAdjust
->page_size
; 
4624         if (fpos 
< 0.0) fpos 
= 0.0; 
4625         m_oldHorizontalPos 
= fpos
; 
4627         if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return; 
4628         m_hAdjust
->value 
= fpos
; 
4632         float fpos 
= (float)pos
; 
4633         if (fpos 
> m_vAdjust
->upper 
- m_vAdjust
->page_size
) fpos 
= m_vAdjust
->upper 
- m_vAdjust
->page_size
; 
4634         if (fpos 
< 0.0) fpos 
= 0.0; 
4635         m_oldVerticalPos 
= fpos
; 
4637         if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return; 
4638         m_vAdjust
->value 
= fpos
; 
4641     if (m_wxwindow
->window
) 
4643         if (orient 
== wxHORIZONTAL
) 
4645             gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
), 
4646                 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
4648             gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" ); 
4650             gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
4651                 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
4655             gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
), 
4656                 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
4658             gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" ); 
4660             gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
4661                 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
4666 int wxWindowGTK::GetScrollThumb( int orient 
) const 
4668     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4670     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4672     if (orient 
== wxHORIZONTAL
) 
4673         return (int)(m_hAdjust
->page_size
+0.5); 
4675         return (int)(m_vAdjust
->page_size
+0.5); 
4678 int wxWindowGTK::GetScrollPos( int orient 
) const 
4680     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4682     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4684     if (orient 
== wxHORIZONTAL
) 
4685         return (int)(m_hAdjust
->value
+0.5); 
4687         return (int)(m_vAdjust
->value
+0.5); 
4690 int wxWindowGTK::GetScrollRange( int orient 
) const 
4692     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4694     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4696     if (orient 
== wxHORIZONTAL
) 
4697         return (int)(m_hAdjust
->upper
+0.5); 
4699         return (int)(m_vAdjust
->upper
+0.5); 
4702 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) ) 
4704     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4706     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4708     // No scrolling requested. 
4709     if ((dx 
== 0) && (dy 
== 0)) return; 
4712     if (!m_updateRegion
.IsEmpty()) 
4714         m_updateRegion
.Offset( dx
, dy 
); 
4718         GetClientSize( &cw
, &ch 
); 
4719         m_updateRegion
.Intersect( 0, 0, cw
, ch 
); 
4722     if (!m_clearRegion
.IsEmpty()) 
4724         m_clearRegion
.Offset( dx
, dy 
); 
4728         GetClientSize( &cw
, &ch 
); 
4729         m_clearRegion
.Intersect( 0, 0, cw
, ch 
); 
4733     m_clipPaintRegion 
= TRUE
; 
4735     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy 
); 
4737     m_clipPaintRegion 
= FALSE
; 
4741 // Find the wxWindow at the current mouse position, also returning the mouse 
4743 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
4745     pt 
= wxGetMousePosition(); 
4746     wxWindow
* found 
= wxFindWindowAtPoint(pt
); 
4750 // Get the current mouse position. 
4751 wxPoint 
wxGetMousePosition() 
4753   /* This crashes when used within wxHelpContext, 
4754      so we have to use the X-specific implementation below. 
4756     GdkModifierType *mask; 
4757     (void) gdk_window_get_pointer(NULL, &x, &y, mask); 
4759     return wxPoint(x, y); 
4763     GdkWindow
* windowAtPtr 
= gdk_window_at_pointer(& x
, & y
); 
4765     Display 
*display 
= windowAtPtr 
? GDK_WINDOW_XDISPLAY(windowAtPtr
) : GDK_DISPLAY(); 
4766     Window rootWindow 
= RootWindowOfScreen (DefaultScreenOfDisplay(display
)); 
4767     Window rootReturn
, childReturn
; 
4768     int rootX
, rootY
, winX
, winY
; 
4769     unsigned int maskReturn
; 
4771     XQueryPointer (display
, 
4775                    &rootX
, &rootY
, &winX
, &winY
, &maskReturn
); 
4776     return wxPoint(rootX
, rootY
); 
4780 // ---------------------------------------------------------------------------- 
4782 // ---------------------------------------------------------------------------- 
4784 class wxWinModule 
: public wxModule
 
4791     DECLARE_DYNAMIC_CLASS(wxWinModule
) 
4794 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
) 
4796 bool wxWinModule::OnInit() 
4798     // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() ); 
4799     // gdk_gc_set_fill( g_eraseGC, GDK_SOLID ); 
4804 void wxWinModule::OnExit() 
4807         gdk_gc_unref( g_eraseGC 
);