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
; 
3105         int left_border 
= 0; 
3106         int right_border 
= 0; 
3108         int bottom_border 
= 0; 
3110         /* the default button has a border around it */ 
3111         if (GTK_WIDGET_CAN_DEFAULT(m_widget
)) 
3114             GtkBorder 
*default_outside_border 
= NULL
; 
3115             gtk_widget_style_get( m_widget
, "default_outside_border", &default_outside_border
, NULL 
); 
3116             if (default_outside_border
) 
3118                 left_border 
+= default_outside_border
->left
; 
3119                 right_border 
+= default_outside_border
->right
; 
3120                 top_border 
+= default_outside_border
->top
; 
3121                 bottom_border 
+= default_outside_border
->bottom
; 
3122                 g_free( default_outside_border 
); 
3132         DoMoveWindow( m_x
-top_border
, 
3134                       m_width
+left_border
+right_border
, 
3135                       m_height
+top_border
+bottom_border 
); 
3140         /* Sometimes the client area changes size without the 
3141            whole windows's size changing, but if the whole 
3142            windows's size doesn't change, no wxSizeEvent will 
3143            normally be sent. Here we add an extra test if 
3144            the client test has been changed and this will 
3146         GetClientSize( &m_oldClientWidth
, &m_oldClientHeight 
); 
3150     wxPrintf( "OnSize sent from " ); 
3151     if (GetClassInfo() && GetClassInfo()->GetClassName()) 
3152         wxPrintf( GetClassInfo()->GetClassName() ); 
3153     wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height ); 
3156     if (!m_nativeSizeEvent
) 
3158         wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
3159         event
.SetEventObject( this ); 
3160         GetEventHandler()->ProcessEvent( event 
); 
3166 void wxWindowGTK::OnInternalIdle() 
3169     if ( m_dirtyTabOrder 
) 
3172     // Update style if the window was not yet realized 
3173     // and SetBackgroundStyle(wxBG_STYLE_CUSTOM) was called 
3174     if (m_needsStyleChange
) 
3176         SetBackgroundStyle(GetBackgroundStyle()); 
3177         m_needsStyleChange 
= false; 
3180     // Update invalidated regions. 
3183     wxCursor cursor 
= m_cursor
; 
3184     if (g_globalCursor
.Ok()) cursor 
= g_globalCursor
; 
3188         /* I now set the cursor anew in every OnInternalIdle call 
3189            as setting the cursor in a parent window also effects the 
3190            windows above so that checking for the current cursor is 
3195             GdkWindow 
*window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3197                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3199             if (!g_globalCursor
.Ok()) 
3200                 cursor 
= *wxSTANDARD_CURSOR
; 
3202             window 
= m_widget
->window
; 
3203             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
3204                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3210             GdkWindow 
*window 
= m_widget
->window
; 
3211             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
3212                gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3217     if (wxUpdateUIEvent::CanUpdate(this)) 
3218         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
3221 void wxWindowGTK::DoGetSize( int *width
, int *height 
) const 
3223     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3225     if (width
) (*width
) = m_width
; 
3226     if (height
) (*height
) = m_height
; 
3229 void wxWindowGTK::DoSetClientSize( int width
, int height 
) 
3231     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3235         SetSize( width
, height 
); 
3242 #ifndef __WXUNIVERSAL__ 
3243         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
3245             /* when using GTK 1.2 we set the shadow border size to 2 */ 
3249         if (HasFlag(wxSIMPLE_BORDER
)) 
3251             /* when using GTK 1.2 we set the simple border size to 1 */ 
3255 #endif // __WXUNIVERSAL__ 
3259             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
3261             GtkRequisition vscroll_req
; 
3262             vscroll_req
.width 
= 2; 
3263             vscroll_req
.height 
= 2; 
3264             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
3265                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
3267             GtkRequisition hscroll_req
; 
3268             hscroll_req
.width 
= 2; 
3269             hscroll_req
.height 
= 2; 
3270             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
3271                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
3273             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
3275             if (scroll_window
->vscrollbar_visible
) 
3277                 dw 
+= vscroll_req
.width
; 
3278                 dw 
+= scroll_class
->scrollbar_spacing
; 
3281             if (scroll_window
->hscrollbar_visible
) 
3283                 dh 
+= hscroll_req
.height
; 
3284                 dh 
+= scroll_class
->scrollbar_spacing
; 
3288        SetSize( width
+dw
, height
+dh 
); 
3292 void wxWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
3294     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3298         if (width
) (*width
) = m_width
; 
3299         if (height
) (*height
) = m_height
; 
3306 #ifndef __WXUNIVERSAL__ 
3307         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
3309             /* when using GTK 1.2 we set the shadow border size to 2 */ 
3313         if (HasFlag(wxSIMPLE_BORDER
)) 
3315             /* when using GTK 1.2 we set the simple border size to 1 */ 
3319 #endif // __WXUNIVERSAL__ 
3323             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
3325             GtkRequisition vscroll_req
; 
3326             vscroll_req
.width 
= 2; 
3327             vscroll_req
.height 
= 2; 
3328             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
3329                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
3331             GtkRequisition hscroll_req
; 
3332             hscroll_req
.width 
= 2; 
3333             hscroll_req
.height 
= 2; 
3334             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
3335                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
3337             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
3339             if (scroll_window
->vscrollbar_visible
) 
3341                 dw 
+= vscroll_req
.width
; 
3342                 dw 
+= scroll_class
->scrollbar_spacing
; 
3345             if (scroll_window
->hscrollbar_visible
) 
3347                 dh 
+= hscroll_req
.height
; 
3348                 dh 
+= scroll_class
->scrollbar_spacing
; 
3352         if (width
) (*width
) = m_width 
- dw
; 
3353         if (height
) (*height
) = m_height 
- dh
; 
3357     printf( "GetClientSize, name %s ", GetName().c_str() ); 
3358     if (width) printf( " width = %d", (*width) ); 
3359     if (height) printf( " height = %d", (*height) ); 
3364 void wxWindowGTK::DoGetPosition( int *x
, int *y 
) const 
3366     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3370     if (m_parent 
&& m_parent
->m_wxwindow
) 
3372         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
3373         dx 
= pizza
->xoffset
; 
3374         dy 
= pizza
->yoffset
; 
3377     if (x
) (*x
) = m_x 
- dx
; 
3378     if (y
) (*y
) = m_y 
- dy
; 
3381 void wxWindowGTK::DoClientToScreen( int *x
, int *y 
) const 
3383     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3385     if (!m_widget
->window
) return; 
3387     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3389         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3391         source 
= m_widget
->window
; 
3395     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3399         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3401             org_x 
+= m_widget
->allocation
.x
; 
3402             org_y 
+= m_widget
->allocation
.y
; 
3410 void wxWindowGTK::DoScreenToClient( int *x
, int *y 
) const 
3412     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3414     if (!m_widget
->window
) return; 
3416     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3418         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3420         source 
= m_widget
->window
; 
3424     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3428         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3430             org_x 
+= m_widget
->allocation
.x
; 
3431             org_y 
+= m_widget
->allocation
.y
; 
3439 bool wxWindowGTK::Show( bool show 
) 
3441     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3443     if (!wxWindowBase::Show(show
)) 
3450         gtk_widget_show( m_widget 
); 
3452         gtk_widget_hide( m_widget 
); 
3454     wxShowEvent 
eventShow(GetId(), show
); 
3455     eventShow
.SetEventObject(this); 
3457     GetEventHandler()->ProcessEvent(eventShow
); 
3462 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
) 
3464     win
->OnParentEnable(enable
); 
3466     // Recurse, so that children have the opportunity to Do The Right Thing 
3467     // and reset colours that have been messed up by a parent's (really ancestor's) 
3469     for ( wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
3471           node 
= node
->GetNext() ) 
3473         wxWindow 
*child 
= node
->GetData(); 
3474         if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
))) 
3475             wxWindowNotifyEnable(child
, enable
); 
3479 bool wxWindowGTK::Enable( bool enable 
) 
3481     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3483     if (!wxWindowBase::Enable(enable
)) 
3489     gtk_widget_set_sensitive( m_widget
, enable 
); 
3491         gtk_widget_set_sensitive( m_wxwindow
, enable 
); 
3493     wxWindowNotifyEnable(this, enable
); 
3498 int wxWindowGTK::GetCharHeight() const 
3500     wxCHECK_MSG( (m_widget 
!= NULL
), 12, wxT("invalid window") ); 
3502     wxFont font 
= GetFont(); 
3503     wxCHECK_MSG( font
.Ok(), 12, wxT("invalid font") ); 
3506     PangoContext 
*context 
= NULL
; 
3508         context 
= gtk_widget_get_pango_context( m_widget 
); 
3513     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
3514     PangoLayout 
*layout 
= pango_layout_new(context
); 
3515     pango_layout_set_font_description(layout
, desc
); 
3516     pango_layout_set_text(layout
, "H", 1); 
3517     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
3519     PangoRectangle rect
; 
3520     pango_layout_line_get_extents(line
, NULL
, &rect
); 
3522     g_object_unref( G_OBJECT( layout 
) ); 
3524     return (int) PANGO_PIXELS(rect
.height
); 
3526     GdkFont 
*gfont 
= font
.GetInternalFont( 1.0 ); 
3528     return gfont
->ascent 
+ gfont
->descent
; 
3532 int wxWindowGTK::GetCharWidth() const 
3534     wxCHECK_MSG( (m_widget 
!= NULL
), 8, wxT("invalid window") ); 
3536     wxFont font 
= GetFont(); 
3537     wxCHECK_MSG( font
.Ok(), 8, wxT("invalid font") ); 
3540     PangoContext 
*context 
= NULL
; 
3542         context 
= gtk_widget_get_pango_context( m_widget 
); 
3547     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
3548     PangoLayout 
*layout 
= pango_layout_new(context
); 
3549     pango_layout_set_font_description(layout
, desc
); 
3550     pango_layout_set_text(layout
, "g", 1); 
3551     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
3553     PangoRectangle rect
; 
3554     pango_layout_line_get_extents(line
, NULL
, &rect
); 
3556     g_object_unref( G_OBJECT( layout 
) ); 
3558     return (int) PANGO_PIXELS(rect
.width
); 
3560     GdkFont 
*gfont 
= font
.GetInternalFont( 1.0 ); 
3562     return gdk_string_width( gfont
, "g" ); 
3566 void wxWindowGTK::GetTextExtent( const wxString
& string
, 
3570                               int *externalLeading
, 
3571                               const wxFont 
*theFont 
) const 
3573     wxFont fontToUse 
= theFont 
? *theFont 
: GetFont(); 
3575     wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") ); 
3577     if (string
.IsEmpty()) 
3585     PangoContext 
*context 
= NULL
; 
3587         context 
= gtk_widget_get_pango_context( m_widget 
); 
3596     PangoFontDescription 
*desc 
= fontToUse
.GetNativeFontInfo()->description
; 
3597     PangoLayout 
*layout 
= pango_layout_new(context
); 
3598     pango_layout_set_font_description(layout
, desc
); 
3601         const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( string 
); 
3602         pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data 
)); 
3604         const wxWCharBuffer wdata 
= wxConvLocal
.cMB2WC( string 
); 
3605         const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( wdata 
); 
3606         pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data 
)); 
3610     PangoRectangle rect
; 
3611     pango_layout_get_extents(layout
, NULL
, &rect
); 
3613     if (x
) (*x
) = (wxCoord
) PANGO_PIXELS(rect
.width
); 
3614     if (y
) (*y
) = (wxCoord
) PANGO_PIXELS(rect
.height
); 
3617         PangoLayoutIter 
*iter 
= pango_layout_get_iter(layout
); 
3618         int baseline 
= pango_layout_iter_get_baseline(iter
); 
3619         pango_layout_iter_free(iter
); 
3620         *descent 
= *y 
- PANGO_PIXELS(baseline
); 
3622     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3624     g_object_unref( G_OBJECT( layout 
) ); 
3626     GdkFont 
*font 
= fontToUse
.GetInternalFont( 1.0 ); 
3627     if (x
) (*x
) = gdk_string_width( font
, wxGTK_CONV( string 
) ); 
3628     if (y
) (*y
) = font
->ascent 
+ font
->descent
; 
3629     if (descent
) (*descent
) = font
->descent
; 
3630     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3634 void wxWindowGTK::SetFocus() 
3636     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3639         // don't do anything if we already have focus 
3645         if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
)) 
3647             gtk_widget_grab_focus (m_wxwindow
); 
3653         if (GTK_IS_CONTAINER(m_widget
)) 
3655             gtk_widget_child_focus( m_widget
, GTK_DIR_TAB_FORWARD 
); 
3659         if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) ) 
3662             if (!GTK_WIDGET_REALIZED(m_widget
)) 
3664                 // we can't set the focus to the widget now so we remember that 
3665                 // it should be focused and will do it later, during the idle 
3666                 // time, as soon as we can 
3667                 wxLogTrace(TRACE_FOCUS
, 
3668                            _T("Delaying setting focus to %s(%s)"), 
3669                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3671                 g_delayedFocus 
= this; 
3675                 wxLogTrace(TRACE_FOCUS
, 
3676                            _T("Setting focus to %s(%s)"), 
3677                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3679                 gtk_widget_grab_focus (m_widget
); 
3684         if (GTK_IS_CONTAINER(m_widget
)) 
3686             gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD 
); 
3691            wxLogTrace(TRACE_FOCUS
, 
3692                       _T("Can't set focus to %s(%s)"), 
3693                       GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3698 bool wxWindowGTK::AcceptsFocus() const 
3700     return m_acceptsFocus 
&& wxWindowBase::AcceptsFocus(); 
3703 bool wxWindowGTK::Reparent( wxWindowBase 
*newParentBase 
) 
3705     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3707     wxWindowGTK 
*oldParent 
= m_parent
, 
3708              *newParent 
= (wxWindowGTK 
*)newParentBase
; 
3710     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3712     if ( !wxWindowBase::Reparent(newParent
) ) 
3715     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3717     /* prevent GTK from deleting the widget arbitrarily */ 
3718     gtk_widget_ref( m_widget 
); 
3722         gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget 
); 
3725     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3729         /* insert GTK representation */ 
3730         (*(newParent
->m_insertCallback
))(newParent
, this); 
3733     /* reverse: prevent GTK from deleting the widget arbitrarily */ 
3734     gtk_widget_unref( m_widget 
); 
3739 void wxWindowGTK::DoAddChild(wxWindowGTK 
*child
) 
3741     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3743     wxASSERT_MSG( (child 
!= NULL
), wxT("invalid child window") ); 
3745     wxASSERT_MSG( (m_insertCallback 
!= NULL
), wxT("invalid child insertion function") ); 
3750     /* insert GTK representation */ 
3751     (*m_insertCallback
)(this, child
); 
3756 void wxWindowGTK::AddChild(wxWindowBase 
*child
) 
3758     wxWindowBase::AddChild(child
); 
3759     m_dirtyTabOrder 
= true; 
3761         wxapp_install_idle_handler(); 
3764 void wxWindowGTK::RemoveChild(wxWindowBase 
*child
) 
3766     wxWindowBase::RemoveChild(child
); 
3767     m_dirtyTabOrder 
= true; 
3769         wxapp_install_idle_handler(); 
3772 void wxWindowGTK::DoMoveInTabOrder(wxWindow 
*win
, MoveKind move
) 
3774     wxWindowBase::DoMoveInTabOrder(win
, move
); 
3775     m_dirtyTabOrder 
= true; 
3777         wxapp_install_idle_handler(); 
3780 void wxWindowGTK::RealizeTabOrder() 
3784         if (m_children
.size() > 0) 
3786             GList 
*chain 
= NULL
; 
3788             for (wxWindowList::const_iterator i 
= m_children
.begin(); 
3789                     i 
!= m_children
.end(); ++i
) 
3791                 chain 
= g_list_prepend(chain
, (*i
)->m_widget
); 
3794             chain 
= g_list_reverse(chain
); 
3796             gtk_container_set_focus_chain(GTK_CONTAINER(m_wxwindow
), chain
); 
3801             gtk_container_unset_focus_chain(GTK_CONTAINER(m_wxwindow
)); 
3805     m_dirtyTabOrder 
= false; 
3808 #endif // __WXGTK20__ 
3810 void wxWindowGTK::Raise() 
3812     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3814     if (m_wxwindow 
&& m_wxwindow
->window
) 
3816         gdk_window_raise( m_wxwindow
->window 
); 
3818      else if (m_widget
->window
) 
3820         gdk_window_raise( m_widget
->window 
); 
3824 void wxWindowGTK::Lower() 
3826     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3828     if (m_wxwindow 
&& m_wxwindow
->window
) 
3830         gdk_window_lower( m_wxwindow
->window 
); 
3832      else if (m_widget
->window
) 
3834         gdk_window_lower( m_widget
->window 
); 
3838 bool wxWindowGTK::SetCursor( const wxCursor 
&cursor 
) 
3840     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3842     if (cursor 
== m_cursor
) 
3846         wxapp_install_idle_handler(); 
3848     if (cursor 
== wxNullCursor
) 
3849        return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR 
); 
3851        return wxWindowBase::SetCursor( cursor 
); 
3854 void wxWindowGTK::WarpPointer( int x
, int y 
) 
3856     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3858     // We provide this function ourselves as it is 
3859     // missing in GDK (top of this file). 
3861     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3863         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3865         window 
= GetConnectWidget()->window
; 
3868         gdk_window_warp_pointer( window
, x
, y 
); 
3872 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect 
*rect 
) 
3874     if (!m_widget
) return; 
3875     if (!m_widget
->window
) return; 
3879         wxapp_install_idle_handler(); 
3881     wxRect 
myRect(0,0,0,0); 
3882     if (m_wxwindow 
&& rect
) 
3884         myRect
.SetSize(wxSize( m_wxwindow
->allocation
.width
, 
3885                                m_wxwindow
->allocation
.height
)); 
3886         myRect
.Intersect(*rect
); 
3887         if (!myRect
.width 
|| !myRect
.height
) 
3888             // nothing to do, rectangle is empty 
3893     if (eraseBackground 
&& m_wxwindow 
&& m_wxwindow
->window
) 
3897             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3898             m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3902             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3903             m_clearRegion
.Clear(); 
3904             m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3912             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3913             m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3917             GdkRectangle gdk_rect
; 
3918             gdk_rect
.x 
= rect
->x
; 
3919             gdk_rect
.y 
= rect
->y
; 
3920             gdk_rect
.width 
= rect
->width
; 
3921             gdk_rect
.height 
= rect
->height
; 
3922             gtk_widget_draw( m_widget
, &gdk_rect 
); 
3929             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3930             m_updateRegion
.Clear(); 
3931             m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3935             gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL 
); 
3943             GdkRectangle gdk_rect
; 
3944             gdk_rect
.x 
= rect
->x
; 
3945             gdk_rect
.y 
= rect
->y
; 
3946             gdk_rect
.width 
= rect
->width
; 
3947             gdk_rect
.height 
= rect
->height
; 
3948             gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, &gdk_rect
, TRUE 
); 
3952             gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, NULL
, TRUE 
); 
3958 void wxWindowGTK::Update() 
3962     // when we call Update() we really want to update the window immediately on 
3963     // screen, even if itmeans flushing the entire queue and hence slowing down 
3964     // everything -- but it should still be done, it's just that Update() should 
3965     // be called very rarely 
3969 void wxWindowGTK::GtkUpdate() 
3972     if (m_wxwindow 
&& GTK_PIZZA(m_wxwindow
)->bin_window
) 
3973         gdk_window_process_updates( GTK_PIZZA(m_wxwindow
)->bin_window
, FALSE 
); 
3975     if (!m_updateRegion
.IsEmpty()) 
3976         GtkSendPaintEvents(); 
3980 void wxWindowGTK::GtkSendPaintEvents() 
3985         m_clearRegion
.Clear(); 
3987         m_updateRegion
.Clear(); 
3991     // Clip to paint region in wxClientDC 
3992     m_clipPaintRegion 
= TRUE
; 
3994     // widget to draw on 
3995     GtkPizza 
*pizza 
= GTK_PIZZA (m_wxwindow
); 
3997     if (GetThemeEnabled() && (GetBackgroundStyle() == wxBG_STYLE_SYSTEM
)) 
3999         // find ancestor from which to steal background 
4000         wxWindow 
*parent 
= wxGetTopLevelParent((wxWindow 
*)this); 
4002             parent 
= (wxWindow
*)this; 
4004         if (GTK_WIDGET_MAPPED(parent
->m_widget
)) 
4006             wxRegionIterator 
upd( m_updateRegion 
); 
4010                 rect
.x 
= upd
.GetX(); 
4011                 rect
.y 
= upd
.GetY(); 
4012                 rect
.width 
= upd
.GetWidth(); 
4013                 rect
.height 
= upd
.GetHeight(); 
4015                 gtk_paint_flat_box( parent
->m_widget
->style
, 
4017                             (GtkStateType
)GTK_WIDGET_STATE(m_wxwindow
), 
4032         wxWindowDC 
dc( (wxWindow
*)this ); 
4033         dc
.SetClippingRegion( m_updateRegion 
); 
4035         wxEraseEvent 
erase_event( GetId(), &dc 
); 
4036         erase_event
.SetEventObject( this ); 
4038         GetEventHandler()->ProcessEvent(erase_event
); 
4041     // if (!m_clearRegion.IsEmpty())   // Always send an erase event under GTK 1.2 
4043         wxWindowDC 
dc( (wxWindow
*)this ); 
4044         if (m_clearRegion
.IsEmpty()) 
4045             dc
.SetClippingRegion( m_updateRegion 
); 
4047             dc
.SetClippingRegion( m_clearRegion 
); 
4049         wxEraseEvent 
erase_event( GetId(), &dc 
); 
4050         erase_event
.SetEventObject( this ); 
4052         if (!GetEventHandler()->ProcessEvent(erase_event
) && GetBackgroundStyle() != wxBG_STYLE_CUSTOM
) 
4056                 g_eraseGC 
= gdk_gc_new( pizza
->bin_window 
); 
4057                 gdk_gc_set_fill( g_eraseGC
, GDK_SOLID 
); 
4059             gdk_gc_set_foreground( g_eraseGC
, GetBackgroundColour().GetColor() ); 
4061             wxRegionIterator 
upd( m_clearRegion 
); 
4064                 gdk_draw_rectangle( pizza
->bin_window
, g_eraseGC
, 1, 
4065                                     upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() ); 
4069         m_clearRegion
.Clear(); 
4073     wxNcPaintEvent 
nc_paint_event( GetId() ); 
4074     nc_paint_event
.SetEventObject( this ); 
4075     GetEventHandler()->ProcessEvent( nc_paint_event 
); 
4077     wxPaintEvent 
paint_event( GetId() ); 
4078     paint_event
.SetEventObject( this ); 
4079     GetEventHandler()->ProcessEvent( paint_event 
); 
4081     m_clipPaintRegion 
= FALSE
; 
4083 #ifndef __WXUNIVERSAL__ 
4085     // The following code will result in all window-less widgets 
4086     // being redrawn because the wxWidgets class is allowed to 
4087     // paint over the window-less widgets. 
4089     GList 
*children 
= pizza
->children
; 
4092         GtkPizzaChild 
*child 
= (GtkPizzaChild
*) children
->data
; 
4093         children 
= children
->next
; 
4095         if (GTK_WIDGET_NO_WINDOW (child
->widget
) && 
4096             GTK_WIDGET_DRAWABLE (child
->widget
)) 
4098             // Get intersection of widget area and update region 
4099             wxRegion 
region( m_updateRegion 
); 
4101             GdkEventExpose gdk_event
; 
4102             gdk_event
.type 
= GDK_EXPOSE
; 
4103             gdk_event
.window 
= pizza
->bin_window
; 
4104             gdk_event
.count 
= 0; 
4106             wxRegionIterator 
upd( m_updateRegion 
); 
4110                 rect
.x 
= upd
.GetX(); 
4111                 rect
.y 
= upd
.GetY(); 
4112                 rect
.width 
= upd
.GetWidth(); 
4113                 rect
.height 
= upd
.GetHeight(); 
4115                 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
)) 
4117                     gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
); 
4127     m_updateRegion
.Clear(); 
4130 void wxWindowGTK::ClearBackground() 
4132     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4135     if (m_wxwindow 
&& m_wxwindow
->window
) 
4137         m_clearRegion
.Clear(); 
4138         wxSize 
size( GetClientSize() ); 
4139         m_clearRegion
.Union( 0,0,size
.x
,size
.y 
); 
4141         // Better do this in idle? 
4148 void wxWindowGTK::DoSetToolTip( wxToolTip 
*tip 
) 
4150     wxWindowBase::DoSetToolTip(tip
); 
4153         m_tooltip
->Apply( (wxWindow 
*)this ); 
4156 void wxWindowGTK::ApplyToolTip( GtkTooltips 
*tips
, const wxChar 
*tip 
) 
4158     wxString 
tmp( tip 
); 
4159     gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxGTK_CONV(tmp
), (gchar
*) NULL 
); 
4161 #endif // wxUSE_TOOLTIPS 
4163 bool wxWindowGTK::SetBackgroundColour( const wxColour 
&colour 
) 
4165     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
4167     if (!wxWindowBase::SetBackgroundColour(colour
)) 
4172         // We need the pixel value e.g. for background clearing. 
4173         m_backgroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
4176     // apply style change (forceStyle=true so that new style is applied 
4177     // even if the bg colour changed from valid to wxNullColour) 
4178     if (GetBackgroundStyle() != wxBG_STYLE_CUSTOM
) 
4179         ApplyWidgetStyle(true); 
4184 bool wxWindowGTK::SetForegroundColour( const wxColour 
&colour 
) 
4186     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
4188     if (!wxWindowBase::SetForegroundColour(colour
)) 
4195         // We need the pixel value e.g. for background clearing. 
4196         m_foregroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
4199     // apply style change (forceStyle=true so that new style is applied 
4200     // even if the bg colour changed from valid to wxNullColour): 
4201     ApplyWidgetStyle(true); 
4207 PangoContext 
*wxWindowGTK::GtkGetPangoDefaultContext() 
4209     return gtk_widget_get_pango_context( m_widget 
); 
4212 PangoContext 
*wxWindowGTK::GtkGetPangoX11Context() 
4215         m_x11Context 
= pango_x_get_context( gdk_display 
); 
4217     return m_x11Context
; 
4221 GtkRcStyle 
*wxWindowGTK::CreateWidgetStyle(bool forceStyle
) 
4223     // do we need to apply any changes at all? 
4226          !m_foregroundColour
.Ok() && !m_backgroundColour
.Ok() ) 
4231     GtkRcStyle 
*style 
= gtk_rc_style_new(); 
4237             pango_font_description_copy( m_font
.GetNativeFontInfo()->description 
); 
4239         wxString xfontname 
= m_font
.GetNativeFontInfo()->GetXFontName(); 
4240         style
->fontset_name 
= g_strdup(xfontname
.c_str()); 
4244     if ( m_foregroundColour
.Ok() ) 
4246         GdkColor 
*fg 
= m_foregroundColour
.GetColor(); 
4248         style
->fg
[GTK_STATE_NORMAL
] = *fg
; 
4249         style
->color_flags
[GTK_STATE_NORMAL
] = GTK_RC_FG
; 
4251         style
->fg
[GTK_STATE_PRELIGHT
] = *fg
; 
4252         style
->color_flags
[GTK_STATE_PRELIGHT
] = GTK_RC_FG
; 
4254         style
->fg
[GTK_STATE_ACTIVE
] = *fg
; 
4255         style
->color_flags
[GTK_STATE_ACTIVE
] = GTK_RC_FG
; 
4258     if ( m_backgroundColour
.Ok() ) 
4260         GdkColor 
*bg 
= m_backgroundColour
.GetColor(); 
4262         style
->bg
[GTK_STATE_NORMAL
] = *bg
; 
4263         style
->base
[GTK_STATE_NORMAL
] = *bg
; 
4264         style
->color_flags
[GTK_STATE_NORMAL
] = (GtkRcFlags
) 
4265             (style
->color_flags
[GTK_STATE_NORMAL
] | GTK_RC_BG 
| GTK_RC_BASE
); 
4267         style
->bg
[GTK_STATE_PRELIGHT
] = *bg
; 
4268         style
->base
[GTK_STATE_PRELIGHT
] = *bg
; 
4269         style
->color_flags
[GTK_STATE_PRELIGHT
] = (GtkRcFlags
) 
4270             (style
->color_flags
[GTK_STATE_PRELIGHT
] | GTK_RC_BG 
| GTK_RC_BASE
); 
4272         style
->bg
[GTK_STATE_ACTIVE
] = *bg
; 
4273         style
->base
[GTK_STATE_ACTIVE
] = *bg
; 
4274         style
->color_flags
[GTK_STATE_ACTIVE
] = (GtkRcFlags
) 
4275             (style
->color_flags
[GTK_STATE_ACTIVE
] | GTK_RC_BG 
| GTK_RC_BASE
); 
4277         style
->bg
[GTK_STATE_INSENSITIVE
] = *bg
; 
4278         style
->base
[GTK_STATE_INSENSITIVE
] = *bg
; 
4279         style
->color_flags
[GTK_STATE_INSENSITIVE
] = (GtkRcFlags
) 
4280             (style
->color_flags
[GTK_STATE_INSENSITIVE
] | GTK_RC_BG 
| GTK_RC_BASE
); 
4286 void wxWindowGTK::ApplyWidgetStyle(bool forceStyle
) 
4288     GtkRcStyle 
*style 
= CreateWidgetStyle(forceStyle
); 
4291         DoApplyWidgetStyle(style
); 
4292         gtk_rc_style_unref(style
); 
4295     // Style change may affect GTK+'s size calculation: 
4296     InvalidateBestSize(); 
4299 void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
4302         gtk_widget_modify_style(m_wxwindow
, style
); 
4303     gtk_widget_modify_style(m_widget
, style
); 
4306 bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style
) 
4308     wxWindowBase::SetBackgroundStyle(style
); 
4310     if (style 
== wxBG_STYLE_CUSTOM
) 
4312         GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4314             window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4316             window 
= GetConnectWidget()->window
; 
4320             // Make sure GDK/X11 doesn't refresh the window 
4322             gdk_window_set_back_pixmap( window
, None
, False 
); 
4324             Display
* display 
= GDK_WINDOW_DISPLAY(window
); 
4327             m_needsStyleChange 
= false; 
4330             // Do in OnIdle, because the window is not yet available 
4331             m_needsStyleChange 
= true; 
4333         // Don't apply widget style, or we get a grey background 
4337         // apply style change (forceStyle=true so that new style is applied 
4338         // even if the bg colour changed from valid to wxNullColour): 
4339         ApplyWidgetStyle(true); 
4344 //----------------------------------------------------------------------------- 
4345 // Pop-up menu stuff 
4346 //----------------------------------------------------------------------------- 
4348 #if wxUSE_MENUS_NATIVE 
4351 void gtk_pop_hide_callback( GtkWidget 
*WXUNUSED(widget
), bool* is_waiting  
) 
4353     *is_waiting 
= FALSE
; 
4356 void SetInvokingWindow( wxMenu 
*menu
, wxWindow
* win 
) 
4358     menu
->SetInvokingWindow( win 
); 
4360     wxMenuItemList::compatibility_iterator node 
= menu
->GetMenuItems().GetFirst(); 
4363         wxMenuItem 
*menuitem 
= node
->GetData(); 
4364         if (menuitem
->IsSubMenu()) 
4366             SetInvokingWindow( menuitem
->GetSubMenu(), win 
); 
4369         node 
= node
->GetNext(); 
4373 extern "C" void wxPopupMenuPositionCallback( GtkMenu 
*menu
, 
4376                                              gboolean 
* WXUNUSED(whatever
), 
4378                                              gpointer user_data 
) 
4380     // ensure that the menu appears entirely on screen 
4382     gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
); 
4384     wxSize sizeScreen 
= wxGetDisplaySize(); 
4385     wxPoint 
*pos 
= (wxPoint
*)user_data
; 
4387     gint xmax 
= sizeScreen
.x 
- req
.width
, 
4388          ymax 
= sizeScreen
.y 
- req
.height
; 
4390     *x 
= pos
->x 
< xmax 
? pos
->x 
: xmax
; 
4391     *y 
= pos
->y 
< ymax 
? pos
->y 
: ymax
; 
4394 bool wxWindowGTK::DoPopupMenu( wxMenu 
*menu
, int x
, int y 
) 
4396     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
4398     wxCHECK_MSG( menu 
!= NULL
, false, wxT("invalid popup-menu") ); 
4400     // NOTE: if you change this code, you need to update 
4401     //       the same code in taskbar.cpp as well. This 
4402     //       is ugly code duplication, I know, 
4404     SetInvokingWindow( menu
, this ); 
4408     bool is_waiting 
= true; 
4410     gulong handler 
= gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), 
4412                                          GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), 
4413                                          (gpointer
)&is_waiting 
); 
4417     GtkMenuPositionFunc posfunc
; 
4418     if ( x 
== -1 && y 
== -1 ) 
4420         // use GTK's default positioning algorithm 
4426         pos 
= ClientToScreen(wxPoint(x
, y
)); 
4428         posfunc 
= wxPopupMenuPositionCallback
; 
4432                   GTK_MENU(menu
->m_menu
), 
4433                   (GtkWidget 
*) NULL
,           // parent menu shell 
4434                   (GtkWidget 
*) NULL
,           // parent menu item 
4435                   posfunc
,                      // function to position it 
4436                   userdata
,                     // client data 
4437                   0,                            // button used to activate it 
4439                   gtk_get_current_event_time() 
4441                   gs_timeLastClick              
// the time of activation 
4447         gtk_main_iteration(); 
4450     gtk_signal_disconnect(GTK_OBJECT(menu
->m_menu
), handler
); 
4455 #endif // wxUSE_MENUS_NATIVE 
4457 #if wxUSE_DRAG_AND_DROP 
4459 void wxWindowGTK::SetDropTarget( wxDropTarget 
*dropTarget 
) 
4461     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4463     GtkWidget 
*dnd_widget 
= GetConnectWidget(); 
4465     if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget 
); 
4467     if (m_dropTarget
) delete m_dropTarget
; 
4468     m_dropTarget 
= dropTarget
; 
4470     if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget 
); 
4473 #endif // wxUSE_DRAG_AND_DROP 
4475 GtkWidget
* wxWindowGTK::GetConnectWidget() 
4477     GtkWidget 
*connect_widget 
= m_widget
; 
4478     if (m_wxwindow
) connect_widget 
= m_wxwindow
; 
4480     return connect_widget
; 
4483 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow 
*window 
) 
4486         return (window 
== GTK_PIZZA(m_wxwindow
)->bin_window
); 
4488     return (window 
== m_widget
->window
); 
4491 bool wxWindowGTK::SetFont( const wxFont 
&font 
) 
4493     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
4495     if (!wxWindowBase::SetFont(font
)) 
4498     // apply style change (forceStyle=true so that new style is applied 
4499     // even if the font changed from valid to wxNullFont): 
4500     ApplyWidgetStyle(true);     
4505 void wxWindowGTK::DoCaptureMouse() 
4507     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4509     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4511         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4513         window 
= GetConnectWidget()->window
; 
4515     wxCHECK_RET( window
, _T("CaptureMouse() failed") ); 
4517     wxCursor
* cursor 
= & m_cursor
; 
4519         cursor 
= wxSTANDARD_CURSOR
; 
4521     gdk_pointer_grab( window
, FALSE
, 
4523                          (GDK_BUTTON_PRESS_MASK 
| 
4524                           GDK_BUTTON_RELEASE_MASK 
| 
4525                           GDK_POINTER_MOTION_HINT_MASK 
| 
4526                           GDK_POINTER_MOTION_MASK
), 
4528                       cursor
->GetCursor(), 
4529                       (guint32
)GDK_CURRENT_TIME 
); 
4530     g_captureWindow 
= this; 
4531     g_captureWindowHasMouse 
= TRUE
; 
4534 void wxWindowGTK::DoReleaseMouse() 
4536     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4538     wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") ); 
4540     g_captureWindow 
= (wxWindowGTK
*) NULL
; 
4542     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4544         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4546         window 
= GetConnectWidget()->window
; 
4551     gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME 
); 
4555 wxWindow 
*wxWindowBase::GetCapture() 
4557     return (wxWindow 
*)g_captureWindow
; 
4560 bool wxWindowGTK::IsRetained() const 
4565 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
, 
4566       int range
, bool refresh 
) 
4568     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4570     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4572     m_hasScrolling 
= TRUE
; 
4574     if (orient 
== wxHORIZONTAL
) 
4576         float fpos 
= (float)pos
; 
4577         float frange 
= (float)range
; 
4578         float fthumb 
= (float)thumbVisible
; 
4579         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4580         if (fpos 
< 0.0) fpos 
= 0.0; 
4582         if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) && 
4583             (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2)) 
4585             SetScrollPos( orient
, pos
, refresh 
); 
4589         m_oldHorizontalPos 
= fpos
; 
4591         m_hAdjust
->lower 
= 0.0; 
4592         m_hAdjust
->upper 
= frange
; 
4593         m_hAdjust
->value 
= fpos
; 
4594         m_hAdjust
->step_increment 
= 1.0; 
4595         m_hAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4596         m_hAdjust
->page_size 
= fthumb
; 
4600         float fpos 
= (float)pos
; 
4601         float frange 
= (float)range
; 
4602         float fthumb 
= (float)thumbVisible
; 
4603         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4604         if (fpos 
< 0.0) fpos 
= 0.0; 
4606         if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) && 
4607             (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2)) 
4609             SetScrollPos( orient
, pos
, refresh 
); 
4613         m_oldVerticalPos 
= fpos
; 
4615         m_vAdjust
->lower 
= 0.0; 
4616         m_vAdjust
->upper 
= frange
; 
4617         m_vAdjust
->value 
= fpos
; 
4618         m_vAdjust
->step_increment 
= 1.0; 
4619         m_vAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4620         m_vAdjust
->page_size 
= fthumb
; 
4623     if (orient 
== wxHORIZONTAL
) 
4624         gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
4626         gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
4629 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) ) 
4631     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4633     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4635     if (orient 
== wxHORIZONTAL
) 
4637         float fpos 
= (float)pos
; 
4638         if (fpos 
> m_hAdjust
->upper 
- m_hAdjust
->page_size
) fpos 
= m_hAdjust
->upper 
- m_hAdjust
->page_size
; 
4639         if (fpos 
< 0.0) fpos 
= 0.0; 
4640         m_oldHorizontalPos 
= fpos
; 
4642         if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return; 
4643         m_hAdjust
->value 
= fpos
; 
4647         float fpos 
= (float)pos
; 
4648         if (fpos 
> m_vAdjust
->upper 
- m_vAdjust
->page_size
) fpos 
= m_vAdjust
->upper 
- m_vAdjust
->page_size
; 
4649         if (fpos 
< 0.0) fpos 
= 0.0; 
4650         m_oldVerticalPos 
= fpos
; 
4652         if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return; 
4653         m_vAdjust
->value 
= fpos
; 
4656     if (m_wxwindow
->window
) 
4658         if (orient 
== wxHORIZONTAL
) 
4660             gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
), 
4661                 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
4663             gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" ); 
4665             gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
4666                 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
4670             gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
), 
4671                 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
4673             gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" ); 
4675             gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
4676                 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
4681 int wxWindowGTK::GetScrollThumb( int orient 
) const 
4683     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4685     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4687     if (orient 
== wxHORIZONTAL
) 
4688         return (int)(m_hAdjust
->page_size
+0.5); 
4690         return (int)(m_vAdjust
->page_size
+0.5); 
4693 int wxWindowGTK::GetScrollPos( int orient 
) const 
4695     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4697     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4699     if (orient 
== wxHORIZONTAL
) 
4700         return (int)(m_hAdjust
->value
+0.5); 
4702         return (int)(m_vAdjust
->value
+0.5); 
4705 int wxWindowGTK::GetScrollRange( int orient 
) const 
4707     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4709     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4711     if (orient 
== wxHORIZONTAL
) 
4712         return (int)(m_hAdjust
->upper
+0.5); 
4714         return (int)(m_vAdjust
->upper
+0.5); 
4717 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) ) 
4719     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4721     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4723     // No scrolling requested. 
4724     if ((dx 
== 0) && (dy 
== 0)) return; 
4727     if (!m_updateRegion
.IsEmpty()) 
4729         m_updateRegion
.Offset( dx
, dy 
); 
4733         GetClientSize( &cw
, &ch 
); 
4734         m_updateRegion
.Intersect( 0, 0, cw
, ch 
); 
4737     if (!m_clearRegion
.IsEmpty()) 
4739         m_clearRegion
.Offset( dx
, dy 
); 
4743         GetClientSize( &cw
, &ch 
); 
4744         m_clearRegion
.Intersect( 0, 0, cw
, ch 
); 
4748     m_clipPaintRegion 
= TRUE
; 
4750     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy 
); 
4752     m_clipPaintRegion 
= FALSE
; 
4756 // Find the wxWindow at the current mouse position, also returning the mouse 
4758 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
4760     pt 
= wxGetMousePosition(); 
4761     wxWindow
* found 
= wxFindWindowAtPoint(pt
); 
4765 // Get the current mouse position. 
4766 wxPoint 
wxGetMousePosition() 
4768   /* This crashes when used within wxHelpContext, 
4769      so we have to use the X-specific implementation below. 
4771     GdkModifierType *mask; 
4772     (void) gdk_window_get_pointer(NULL, &x, &y, mask); 
4774     return wxPoint(x, y); 
4778     GdkWindow
* windowAtPtr 
= gdk_window_at_pointer(& x
, & y
); 
4780     Display 
*display 
= windowAtPtr 
? GDK_WINDOW_XDISPLAY(windowAtPtr
) : GDK_DISPLAY(); 
4781     Window rootWindow 
= RootWindowOfScreen (DefaultScreenOfDisplay(display
)); 
4782     Window rootReturn
, childReturn
; 
4783     int rootX
, rootY
, winX
, winY
; 
4784     unsigned int maskReturn
; 
4786     XQueryPointer (display
, 
4790                    &rootX
, &rootY
, &winX
, &winY
, &maskReturn
); 
4791     return wxPoint(rootX
, rootY
); 
4795 // ---------------------------------------------------------------------------- 
4797 // ---------------------------------------------------------------------------- 
4799 class wxWinModule 
: public wxModule
 
4806     DECLARE_DYNAMIC_CLASS(wxWinModule
) 
4809 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
) 
4811 bool wxWinModule::OnInit() 
4813     // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() ); 
4814     // gdk_gc_set_fill( g_eraseGC, GDK_SOLID ); 
4819 void wxWinModule::OnExit() 
4822         gdk_gc_unref( g_eraseGC 
);