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" 
  32 #if wxUSE_DRAG_AND_DROP 
  37     #include "wx/tooltip.h" 
  45     #include "wx/textctrl.h" 
  49 #include "wx/statusbr.h" 
  51 #include "wx/settings.h" 
  53 #include "wx/fontutil.h" 
  56     #include "wx/thread.h" 
  62 #include "wx/gtk/private.h" 
  63 #include <gdk/gdkprivate.h> 
  64 #include <gdk/gdkkeysyms.h> 
  68 #include <gtk/gtkprivate.h> 
  70 #include "wx/gtk/win_gtk.h" 
  73 #include <pango/pangox.h> 
  77     #define SET_CONTAINER_FOCUS(w, d) gtk_widget_child_focus((w), (d)) 
  79     #define SET_CONTAINER_FOCUS(w, d) gtk_container_focus(GTK_CONTAINER(w), (d)) 
  89 extern GtkContainerClass 
*pizza_parent_class
; 
  92 //----------------------------------------------------------------------------- 
  93 // documentation on internals 
  94 //----------------------------------------------------------------------------- 
  97    I have been asked several times about writing some documentation about 
  98    the GTK port of wxWidgets, especially its internal structures. Obviously, 
  99    you cannot understand wxGTK without knowing a little about the GTK, but 
 100    some more information about what the wxWindow, which is the base class 
 101    for all other window classes, does seems required as well. 
 105    What does wxWindow do? It contains the common interface for the following 
 106    jobs of its descendants: 
 108    1) Define the rudimentary behaviour common to all window classes, such as 
 109    resizing, intercepting user input (so as to make it possible to use these 
 110    events for special purposes in a derived class), window names etc. 
 112    2) Provide the possibility to contain and manage children, if the derived 
 113    class is allowed to contain children, which holds true for those window 
 114    classes which do not display a native GTK widget. To name them, these 
 115    classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame- 
 116    work classes are a special case and are handled a bit differently from 
 117    the rest. The same holds true for the wxNotebook class. 
 119    3) Provide the possibility to draw into a client area of a window. This, 
 120    too, only holds true for classes that do not display a native GTK widget 
 123    4) Provide the entire mechanism for scrolling widgets. This actual inter- 
 124    face for this is usually in wxScrolledWindow, but the GTK implementation 
 127    5) A multitude of helper or extra methods for special purposes, such as 
 128    Drag'n'Drop, managing validators etc. 
 130    6) Display a border (sunken, raised, simple or none). 
 132    Normally one might expect, that one wxWidgets window would always correspond 
 133    to one GTK widget. Under GTK, there is no such allround widget that has all 
 134    the functionality. Moreover, the GTK defines a client area as a different 
 135    widget from the actual widget you are handling. Last but not least some 
 136    special classes (e.g. wxFrame) handle different categories of widgets and 
 137    still have the possibility to draw something in the client area. 
 138    It was therefore required to write a special purpose GTK widget, that would 
 139    represent a client area in the sense of wxWidgets capable to do the jobs 
 140    2), 3) and 4). I have written this class and it resides in win_gtk.c of 
 143    All windows must have a widget, with which they interact with other under- 
 144    lying GTK widgets. It is this widget, e.g. that has to be resized etc and 
 145    thw wxWindow class has a member variable called m_widget which holds a 
 146    pointer to this widget. When the window class represents a GTK native widget, 
 147    this is (in most cases) the only GTK widget the class manages. E.g. the 
 148    wxStaticText class handles only a GtkLabel widget a pointer to which you 
 149    can find in m_widget (defined in wxWindow) 
 151    When the class has a client area for drawing into and for containing children 
 152    it has to handle the client area widget (of the type GtkPizza, defined in 
 153    win_gtk.c), but there could be any number of widgets, handled by a class 
 154    The common rule for all windows is only, that the widget that interacts with 
 155    the rest of GTK must be referenced in m_widget and all other widgets must be 
 156    children of this widget on the GTK level. The top-most widget, which also 
 157    represents the client area, must be in the m_wxwindow field and must be of 
 160    As I said, the window classes that display a GTK native widget only have 
 161    one widget, so in the case of e.g. the wxButton class m_widget holds a 
 162    pointer to a GtkButton widget. But windows with client areas (for drawing 
 163    and children) have a m_widget field that is a pointer to a GtkScrolled- 
 164    Window and a m_wxwindow field that is pointer to a GtkPizza and this 
 165    one is (in the GTK sense) a child of the GtkScrolledWindow. 
 167    If the m_wxwindow field is set, then all input to this widget is inter- 
 168    cepted and sent to the wxWidgets class. If not, all input to the widget 
 169    that gets pointed to by m_widget gets intercepted and sent to the class. 
 173    The design of scrolling in wxWidgets is markedly different from that offered 
 174    by the GTK itself and therefore we cannot simply take it as it is. In GTK, 
 175    clicking on a scrollbar belonging to scrolled window will inevitably move 
 176    the window. In wxWidgets, the scrollbar will only emit an event, send this 
 177    to (normally) a wxScrolledWindow and that class will call ScrollWindow() 
 178    which actually moves the window and its subchildren. Note that GtkPizza 
 179    memorizes how much it has been scrolled but that wxWidgets forgets this 
 180    so that the two coordinates systems have to be kept in synch. This is done 
 181    in various places using the pizza->xoffset and pizza->yoffset values. 
 185    Singularily the most broken code in GTK is the code that is supposes to 
 186    inform subwindows (child windows) about new positions. Very often, duplicate 
 187    events are sent without changes in size or position, equally often no 
 188    events are sent at all (All this is due to a bug in the GtkContainer code 
 189    which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores 
 190    GTK's own system and it simply waits for size events for toplevel windows 
 191    and then iterates down the respective size events to all window. This has 
 192    the disadvantage, that windows might get size events before the GTK widget 
 193    actually has the reported size. This doesn't normally pose any problem, but 
 194    the OpenGl drawing routines rely on correct behaviour. Therefore, I have 
 195    added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas, 
 196    i.e. the wxGLCanvas will emit a size event, when (and not before) the X11 
 197    window that is used for OpenGl output really has that size (as reported by 
 202    If someone at some point of time feels the immense desire to have a look at, 
 203    change or attempt to optimse the Refresh() logic, this person will need an 
 204    intimate understanding of what a "draw" and what an "expose" events are and 
 205    what there are used for, in particular when used in connection with GTK's 
 206    own windowless widgets. Beware. 
 210    Cursors, too, have been a constant source of pleasure. The main difficulty 
 211    is that a GdkWindow inherits a cursor if the programmer sets a new cursor 
 212    for the parent. To prevent this from doing too much harm, I use idle time 
 213    to set the cursor over and over again, starting from the toplevel windows 
 214    and ending with the youngest generation (speaking of parent and child windows). 
 215    Also don't forget that cursors (like much else) are connected to GdkWindows, 
 216    not GtkWidgets and that the "window" field of a GtkWidget might very well 
 217    point to the GdkWindow of the parent widget (-> "window less widget") and 
 218    that the two obviously have very different meanings. 
 222 //----------------------------------------------------------------------------- 
 224 //----------------------------------------------------------------------------- 
 226 extern wxList     wxPendingDelete
; 
 227 extern bool       g_blockEventsOnDrag
; 
 228 extern bool       g_blockEventsOnScroll
; 
 229 extern wxCursor   g_globalCursor
; 
 231 static GdkGC 
*g_eraseGC 
= NULL
; 
 233 // mouse capture state: the window which has it and if the mouse is currently 
 235 static wxWindowGTK  
*g_captureWindow 
= (wxWindowGTK
*) NULL
; 
 236 static bool g_captureWindowHasMouse 
= FALSE
; 
 238 /* extern */ wxWindowGTK  
*g_focusWindow 
= (wxWindowGTK
*) NULL
; 
 240 // the last window which had the focus - this is normally never NULL (except 
 241 // if we never had focus at all) as even when g_focusWindow is NULL it still 
 242 // keeps its previous value 
 243 static wxWindowGTK 
*g_focusWindowLast 
= (wxWindowGTK
*) NULL
; 
 245 // the frame that is currently active (i.e. its child has focus). It is 
 246 // used to generate wxActivateEvents 
 247 static wxWindowGTK 
*g_activeFrame 
= (wxWindowGTK
*) NULL
; 
 248 static bool g_activeFrameLostFocus 
= FALSE
; 
 250 // If a window get the focus set but has not been realized 
 251 // yet, defer setting the focus to idle time. 
 252 wxWindowGTK 
*g_delayedFocus 
= (wxWindowGTK
*) NULL
; 
 254 // if we detect that the app has got/lost the focus, we set this variable to 
 255 // either TRUE or FALSE and an activate event will be sent during the next 
 256 // OnIdle() call and it is reset to -1: this value means that we shouldn't 
 257 // send any activate events at all 
 258 static int        g_sendActivateEvent 
= -1; 
 260 // hack: we need something to pass to gtk_menu_popup, so we store the time of 
 261 // the last click here 
 262 static guint32 gs_timeLastClick 
= 0;  
 264 extern bool g_mainThreadLocked
; 
 266 //----------------------------------------------------------------------------- 
 268 //----------------------------------------------------------------------------- 
 273 #   define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance"); 
 275 #   define DEBUG_MAIN_THREAD 
 278 #define DEBUG_MAIN_THREAD 
 281 // the trace mask used for the focus debugging messages 
 282 #define TRACE_FOCUS _T("focus") 
 284 //----------------------------------------------------------------------------- 
 285 // missing gdk functions 
 286 //----------------------------------------------------------------------------- 
 289 gdk_window_warp_pointer (GdkWindow      
*window
, 
 294   GdkWindowPrivate 
*priv
; 
 298     window 
= GDK_ROOT_PARENT(); 
 301   if (!GDK_WINDOW_DESTROYED(window
)) 
 303       XWarpPointer (GDK_WINDOW_XDISPLAY(window
), 
 304                     None
,              /* not source window -> move from anywhere */ 
 305                     GDK_WINDOW_XID(window
),  /* dest window */ 
 306                     0, 0, 0, 0,        /* not source window -> move from anywhere */ 
 310   priv 
= (GdkWindowPrivate
*) window
; 
 312   if (!priv
->destroyed
) 
 314       XWarpPointer (priv
->xdisplay
, 
 315                     None
,              /* not source window -> move from anywhere */ 
 316                     priv
->xwindow
,  /* dest window */ 
 317                     0, 0, 0, 0,        /* not source window -> move from anywhere */ 
 323 //----------------------------------------------------------------------------- 
 325 //----------------------------------------------------------------------------- 
 327 extern void wxapp_install_idle_handler(); 
 328 extern bool g_isIdle
; 
 330 //----------------------------------------------------------------------------- 
 331 // local code (see below) 
 332 //----------------------------------------------------------------------------- 
 334 // returns the child of win which currently has focus or NULL if not found 
 336 // Note: can't be static, needed by textctrl.cpp. 
 337 wxWindow 
*wxFindFocusedChild(wxWindowGTK 
*win
) 
 339     wxWindow 
*winFocus 
= wxWindowGTK::FindFocus(); 
 341         return (wxWindow 
*)NULL
; 
 343     if ( winFocus 
== win 
) 
 344         return (wxWindow 
*)win
; 
 346     for ( wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
 348           node 
= node
->GetNext() ) 
 350         wxWindow 
*child 
= wxFindFocusedChild(node
->GetData()); 
 355     return (wxWindow 
*)NULL
; 
 358 static void draw_frame( GtkWidget 
*widget
, wxWindowGTK 
*win 
) 
 360     // wxUniversal widgets draw the borders and scrollbars themselves 
 361 #ifndef __WXUNIVERSAL__ 
 368     if (win
->m_hasScrolling
) 
 370         GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(widget
); 
 372         GtkRequisition vscroll_req
; 
 373         vscroll_req
.width 
= 2; 
 374         vscroll_req
.height 
= 2; 
 375         (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
 376             (scroll_window
->vscrollbar
, &vscroll_req 
); 
 378         GtkRequisition hscroll_req
; 
 379         hscroll_req
.width 
= 2; 
 380         hscroll_req
.height 
= 2; 
 381         (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
 382             (scroll_window
->hscrollbar
, &hscroll_req 
); 
 384         GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) ); 
 386         if (scroll_window
->vscrollbar_visible
) 
 388             dw 
+= vscroll_req
.width
; 
 389             dw 
+= scroll_class
->scrollbar_spacing
; 
 392         if (scroll_window
->hscrollbar_visible
) 
 394             dh 
+= hscroll_req
.height
; 
 395             dh 
+= scroll_class
->scrollbar_spacing
; 
 401     if (GTK_WIDGET_NO_WINDOW (widget
)) 
 403         dx 
+= widget
->allocation
.x
; 
 404         dy 
+= widget
->allocation
.y
; 
 407     if (win
->HasFlag(wxRAISED_BORDER
)) 
 409         gtk_draw_shadow( widget
->style
, 
 414                          widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh 
); 
 418     if (win
->HasFlag(wxSUNKEN_BORDER
)) 
 420         gtk_draw_shadow( widget
->style
, 
 425                          widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh 
); 
 429     if (win
->HasFlag(wxSIMPLE_BORDER
)) 
 432         gc 
= gdk_gc_new( widget
->window 
); 
 433         gdk_gc_set_foreground( gc
, &widget
->style
->black 
); 
 434         gdk_draw_rectangle( widget
->window
, gc
, FALSE
, 
 436                          widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 ); 
 440 #endif // __WXUNIVERSAL__ 
 443 //----------------------------------------------------------------------------- 
 444 // "expose_event" of m_widget 
 445 //----------------------------------------------------------------------------- 
 447 gint 
gtk_window_own_expose_callback( GtkWidget 
*widget
, GdkEventExpose 
*gdk_event
, wxWindowGTK 
*win 
) 
 449     if (gdk_event
->count 
> 0) return FALSE
; 
 451     draw_frame( widget
, win 
); 
 455     (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
); 
 461 //----------------------------------------------------------------------------- 
 462 // "draw" of m_widget 
 463 //----------------------------------------------------------------------------- 
 467 static void gtk_window_own_draw_callback( GtkWidget 
*widget
, GdkRectangle 
*WXUNUSED(rect
), wxWindowGTK 
*win 
) 
 469     draw_frame( widget
, win 
); 
 474 //----------------------------------------------------------------------------- 
 475 // "size_request" of m_widget 
 476 //----------------------------------------------------------------------------- 
 478 // make it extern because wxStatitText needs to disconnect this one 
 480 void wxgtk_window_size_request_callback(GtkWidget 
*widget
, 
 481                                         GtkRequisition 
*requisition
, 
 485     win
->GetSize( &w
, &h 
); 
 491     requisition
->height 
= h
; 
 492     requisition
->width 
= w
; 
 495 //----------------------------------------------------------------------------- 
 496 // "expose_event" of m_wxwindow 
 497 //----------------------------------------------------------------------------- 
 499 static int gtk_window_expose_callback( GtkWidget 
*widget
, 
 500                                        GdkEventExpose 
*gdk_event
, 
 506         wxapp_install_idle_handler(); 
 509     // This callback gets called in drawing-idle time under 
 510     // GTK 2.0, so we don't need to defer anything to idle 
 513     GtkPizza 
*pizza 
= GTK_PIZZA( widget 
); 
 514     if (gdk_event
->window 
!= pizza
->bin_window
) return FALSE
; 
 519         wxPrintf( wxT("OnExpose from ") ); 
 520         if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName()) 
 521             wxPrintf( win
->GetClassInfo()->GetClassName() ); 
 522         wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event
->area
.x
, 
 523                                          (int)gdk_event
->area
.y
, 
 524                                          (int)gdk_event
->area
.width
, 
 525                                          (int)gdk_event
->area
.height 
); 
 530         win
->m_wxwindow
->style
, 
 534         (GdkRectangle
*) NULL
, 
 536         (char *)"button", // const_cast 
 541     win
->GetUpdateRegion() = wxRegion( gdk_event
->region 
); 
 543     win
->GtkSendPaintEvents(); 
 546     // Let parent window draw window less widgets 
 547     (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
); 
 549     // This gets called immediately after an expose event 
 550     // under GTK 1.2 so we collect the calls and wait for 
 551     // the idle handler to pick things up. 
 553     win
->GetUpdateRegion().Union( gdk_event
->area
.x
, 
 555                                   gdk_event
->area
.width
, 
 556                                   gdk_event
->area
.height 
); 
 557     win
->m_clearRegion
.Union( gdk_event
->area
.x
, 
 559                                   gdk_event
->area
.width
, 
 560                                   gdk_event
->area
.height 
); 
 562     // Actual redrawing takes place in idle time. 
 569 //----------------------------------------------------------------------------- 
 570 // "event" of m_wxwindow 
 571 //----------------------------------------------------------------------------- 
 573 // GTK thinks it is clever and filters out a certain amount of "unneeded" 
 574 // expose events. We need them, of course, so we override the main event 
 575 // procedure in GtkWidget by giving our own handler for all system events. 
 576 // There, we look for expose events ourselves whereas all other events are 
 579 gint 
gtk_window_event_event_callback( GtkWidget 
*widget
, 
 580                                       GdkEventExpose 
*event
, 
 583     if (event
->type 
== GDK_EXPOSE
) 
 585         gint ret 
= gtk_window_expose_callback( widget
, event
, win 
); 
 592 //----------------------------------------------------------------------------- 
 593 // "draw" of m_wxwindow 
 594 //----------------------------------------------------------------------------- 
 598 // This callback is a complete replacement of the gtk_pizza_draw() function, 
 599 // which is disabled. 
 601 static void gtk_window_draw_callback( GtkWidget 
*widget
, 
 608         wxapp_install_idle_handler(); 
 610     // if there are any children we must refresh everything 
 613     if ( !win
->HasFlag(wxFULL_REPAINT_ON_RESIZE
) && 
 614             win
->GetChildren().IsEmpty() ) 
 622         wxPrintf( wxT("OnDraw from ") ); 
 623         if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName()) 
 624             wxPrintf( win
->GetClassInfo()->GetClassName() ); 
 625         wxPrintf( wxT(" %d %d %d %d\n"), (int)rect
->x
, 
 632 #ifndef __WXUNIVERSAL__ 
 633     GtkPizza 
*pizza 
= GTK_PIZZA (widget
); 
 635     if (win
->GetThemeEnabled() && win
->GetBackgroundStyle() == wxBG_STYLE_SYSTEM
) 
 637         wxWindow 
*parent 
= win
->GetParent(); 
 638         while (parent 
&& !parent
->IsTopLevel()) 
 639             parent 
= parent
->GetParent(); 
 643         gtk_paint_flat_box (parent
->m_widget
->style
, 
 654     win
->m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
 655     win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
 657     // Update immediately, not in idle time. 
 660 #ifndef __WXUNIVERSAL__ 
 661     // Redraw child widgets 
 662     GList 
*children 
= pizza
->children
; 
 665         GtkPizzaChild 
*child 
= (GtkPizzaChild
*) children
->data
; 
 666         children 
= children
->next
; 
 668         GdkRectangle child_area
; 
 669         if (gtk_widget_intersect (child
->widget
, rect
, &child_area
)) 
 671             gtk_widget_draw (child
->widget
, &child_area 
/* (GdkRectangle*) NULL*/ ); 
 679 //----------------------------------------------------------------------------- 
 680 // "key_press_event" from any window 
 681 //----------------------------------------------------------------------------- 
 683 // set WXTRACE to this to see the key event codes on the console 
 684 #define TRACE_KEYS  _T("keyevent") 
 686 // translates an X key symbol to WXK_XXX value 
 688 // if isChar is true it means that the value returned will be used for EVT_CHAR 
 689 // event and then we choose the logical WXK_XXX, i.e. '/' for GDK_KP_Divide, 
 690 // for example, while if it is false it means that the value is going to be 
 691 // used for KEY_DOWN/UP events and then we translate GDK_KP_Divide to 
 693 static long wxTranslateKeySymToWXKey(KeySym keysym
, bool isChar
) 
 699         // Shift, Control and Alt don't generate the CHAR events at all 
 702             key_code 
= isChar 
? 0 : WXK_SHIFT
; 
 706             key_code 
= isChar 
? 0 : WXK_CONTROL
; 
 714             key_code 
= isChar 
? 0 : WXK_ALT
; 
 717         // neither do the toggle modifies 
 718         case GDK_Scroll_Lock
: 
 719             key_code 
= isChar 
? 0 : WXK_SCROLL
; 
 723             key_code 
= isChar 
? 0 : WXK_CAPITAL
; 
 727             key_code 
= isChar 
? 0 : WXK_NUMLOCK
; 
 731         // various other special keys 
 744         case GDK_ISO_Left_Tab
: 
 751             key_code 
= WXK_RETURN
; 
 755             key_code 
= WXK_CLEAR
; 
 759             key_code 
= WXK_PAUSE
; 
 763             key_code 
= WXK_SELECT
; 
 767             key_code 
= WXK_PRINT
; 
 771             key_code 
= WXK_EXECUTE
; 
 775             key_code 
= WXK_ESCAPE
; 
 778         // cursor and other extended keyboard keys 
 780             key_code 
= WXK_DELETE
; 
 796             key_code 
= WXK_RIGHT
; 
 803         case GDK_Prior
:     // == GDK_Page_Up 
 804             key_code 
= WXK_PRIOR
; 
 807         case GDK_Next
:      // == GDK_Page_Down 
 820             key_code 
= WXK_INSERT
; 
 835             key_code 
= (isChar 
? '0' : WXK_NUMPAD0
) + keysym 
- GDK_KP_0
; 
 839             key_code 
= isChar 
? ' ' : WXK_NUMPAD_SPACE
; 
 843             key_code 
= isChar 
? WXK_TAB 
: WXK_NUMPAD_TAB
; 
 847             key_code 
= isChar 
? WXK_RETURN 
: WXK_NUMPAD_ENTER
; 
 851             key_code 
= isChar 
? WXK_F1 
: WXK_NUMPAD_F1
; 
 855             key_code 
= isChar 
? WXK_F2 
: WXK_NUMPAD_F2
; 
 859             key_code 
= isChar 
? WXK_F3 
: WXK_NUMPAD_F3
; 
 863             key_code 
= isChar 
? WXK_F4 
: WXK_NUMPAD_F4
; 
 867             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_HOME
; 
 871             key_code 
= isChar 
? WXK_LEFT 
: WXK_NUMPAD_LEFT
; 
 875             key_code 
= isChar 
? WXK_UP 
: WXK_NUMPAD_UP
; 
 879             key_code 
= isChar 
? WXK_RIGHT 
: WXK_NUMPAD_RIGHT
; 
 883             key_code 
= isChar 
? WXK_DOWN 
: WXK_NUMPAD_DOWN
; 
 886         case GDK_KP_Prior
: // == GDK_KP_Page_Up 
 887             key_code 
= isChar 
? WXK_PRIOR 
: WXK_NUMPAD_PRIOR
; 
 890         case GDK_KP_Next
: // == GDK_KP_Page_Down 
 891             key_code 
= isChar 
? WXK_NEXT 
: WXK_NUMPAD_NEXT
; 
 895             key_code 
= isChar 
? WXK_END 
: WXK_NUMPAD_END
; 
 899             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_BEGIN
; 
 903             key_code 
= isChar 
? WXK_INSERT 
: WXK_NUMPAD_INSERT
; 
 907             key_code 
= isChar 
? WXK_DELETE 
: WXK_NUMPAD_DELETE
; 
 911             key_code 
= isChar 
? '=' : WXK_NUMPAD_EQUAL
; 
 914         case GDK_KP_Multiply
: 
 915             key_code 
= isChar 
? '*' : WXK_NUMPAD_MULTIPLY
; 
 919             key_code 
= isChar 
? '+' : WXK_NUMPAD_ADD
; 
 922         case GDK_KP_Separator
: 
 923             // FIXME: what is this? 
 924             key_code 
= isChar 
? '.' : WXK_NUMPAD_SEPARATOR
; 
 927         case GDK_KP_Subtract
: 
 928             key_code 
= isChar 
? '-' : WXK_NUMPAD_SUBTRACT
; 
 932             key_code 
= isChar 
? '.' : WXK_NUMPAD_DECIMAL
; 
 936             key_code 
= isChar 
? '/' : WXK_NUMPAD_DIVIDE
; 
 953             key_code 
= WXK_F1 
+ keysym 
- GDK_F1
; 
 963 static inline bool wxIsAsciiKeysym(KeySym ks
) 
 968 static void wxFillOtherKeyEventFields(wxKeyEvent
& event
, 
 970                                       GdkEventKey 
*gdk_event
) 
 974     GdkModifierType state
; 
 975     if (gdk_event
->window
) 
 976         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
 978     event
.SetTimestamp( gdk_event
->time 
); 
 979     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
) != 0; 
 980     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
) != 0; 
 981     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
) != 0; 
 982     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
) != 0; 
 983     event
.m_scanCode 
= gdk_event
->keyval
; 
 984     event
.m_rawCode 
= (wxUint32
) gdk_event
->keyval
; 
 985     event
.m_rawFlags 
= 0; 
 988     event
.SetEventObject( win 
); 
 993 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
, 
 995                            GdkEventKey 
*gdk_event
) 
 997     // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string 
 998     //     but only event->keyval which is quite useless to us, so remember 
 999     //     the last character from GDK_KEY_PRESS and reuse it as last resort 
1001     // NB: should be MT-safe as we're always called from the main thread only 
1006     } s_lastKeyPress 
= { 0, 0 }; 
1008     KeySym keysym 
= gdk_event
->keyval
; 
1010     wxLogTrace(TRACE_KEYS
, _T("Key %s event: keysym = %ld"), 
1011                event
.GetEventType() == wxEVT_KEY_UP 
? _T("release") 
1015     long key_code 
= wxTranslateKeySymToWXKey(keysym
, FALSE 
/* !isChar */); 
1019         // do we have the translation or is it a plain ASCII character? 
1020         if ( (gdk_event
->length 
== 1) || wxIsAsciiKeysym(keysym
) ) 
1022             // we should use keysym if it is ASCII as X does some translations 
1023             // like "I pressed while Control is down" => "Ctrl-I" == "TAB" 
1024             // which we don't want here (but which we do use for OnChar()) 
1025             if ( !wxIsAsciiKeysym(keysym
) ) 
1027                 keysym 
= (KeySym
)gdk_event
->string
[0]; 
1030             // we want to always get the same key code when the same key is 
1031             // pressed regardless of the state of the modifies, i.e. on a 
1032             // standard US keyboard pressing '5' or '%' ('5' key with 
1033             // Shift) should result in the same key code in OnKeyDown(): 
1034             // '5' (although OnChar() will get either '5' or '%'). 
1036             // to do it we first translate keysym to keycode (== scan code) 
1037             // and then back but always using the lower register 
1038             Display 
*dpy 
= (Display 
*)wxGetDisplay(); 
1039             KeyCode keycode 
= XKeysymToKeycode(dpy
, keysym
); 
1041             wxLogTrace(TRACE_KEYS
, _T("\t-> keycode %d"), keycode
); 
1043             KeySym keysymNormalized 
= XKeycodeToKeysym(dpy
, keycode
, 0); 
1045             // use the normalized, i.e. lower register, keysym if we've 
1047             key_code 
= keysymNormalized 
? keysymNormalized 
: keysym
; 
1049             // as explained above, we want to have lower register key codes 
1050             // normally but for the letter keys we want to have the upper ones 
1052             // NB: don't use XConvertCase() here, we want to do it for letters 
1054             key_code 
= toupper(key_code
); 
1056         else // non ASCII key, what to do? 
1058             // by default, ignore it 
1061             // but if we have cached information from the last KEY_PRESS 
1062             if ( gdk_event
->type 
== GDK_KEY_RELEASE 
) 
1065                 if ( keysym 
== s_lastKeyPress
.keysym 
) 
1067                     key_code 
= s_lastKeyPress
.keycode
; 
1072         if ( gdk_event
->type 
== GDK_KEY_PRESS 
) 
1074             // remember it to be reused for KEY_UP event later 
1075             s_lastKeyPress
.keysym 
= keysym
; 
1076             s_lastKeyPress
.keycode 
= key_code
; 
1080     wxLogTrace(TRACE_KEYS
, _T("\t-> wxKeyCode %ld"), key_code
); 
1082     // sending unknown key events doesn't really make sense 
1086     // now fill all the other fields 
1087     wxFillOtherKeyEventFields(event
, win
, gdk_event
); 
1089     event
.m_keyCode 
= key_code
; 
1098     GtkIMContext 
*context
; 
1099     GdkEventKey  
*lastKeyEvent
; 
1103         context 
= gtk_im_multicontext_new(); 
1104         lastKeyEvent 
= NULL
; 
1108         g_object_unref(context
); 
1113 static gint 
gtk_window_key_press_callback( GtkWidget 
*widget
, 
1114                                            GdkEventKey 
*gdk_event
, 
1120         wxapp_install_idle_handler(); 
1124     if (g_blockEventsOnDrag
) 
1128     // We have to pass key press events through GTK+'s Input Method context 
1129     // object in order to get correct characters. By doing so, we loose the 
1130     // ability to let other GTK+'s handlers (namely, widgets' default signal 
1131     // handlers) handle the signal by returning false from this callback. 
1132     // Because GTK+ sends the events to parent widgets as well, we can't 
1133     // afford loosing it, otherwise native widgets inserted into wxPanel 
1134     // would break in subtle ways (e.g. spacebar would no longer toggle 
1135     // wxCheckButton's state). Therefore, we only pass the event to IM if it 
1136     // originated in this window's widget, which we detect by checking if we've 
1137     // seen the same event before (no events from children are lost this way, 
1138     // because gtk_window_key_press_callback is installed for native controls 
1139     // as well and the wxKeyEvent it creates propagates upwards). 
1140     static GdkEventKey s_lastEvent
; 
1142     bool useIM 
= (win
->m_imData 
!= NULL
) && 
1143                  memcmp(gdk_event
, &s_lastEvent
, sizeof(GdkEventKey
)) != 0; 
1145     s_lastEvent 
= *gdk_event
; 
1148     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
1149     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1151         // unknown key pressed, ignore (the event would be useless anyhow) 
1155             // it may be useful for the input method, though: 
1156             win
->m_imData
->lastKeyEvent 
= gdk_event
; 
1157             bool ret 
= gtk_im_context_filter_keypress(win
->m_imData
->context
, 
1159             win
->m_imData
->lastKeyEvent 
= NULL
; 
1166     // Emit KEY_DOWN event 
1167     bool ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1172         wxWindowGTK 
*ancestor 
= win
; 
1175             int command 
= ancestor
->GetAcceleratorTable()->GetCommand( event 
); 
1178                 wxCommandEvent 
command_event( wxEVT_COMMAND_MENU_SELECTED
, command 
); 
1179                 ret 
= ancestor
->GetEventHandler()->ProcessEvent( command_event 
); 
1182             if (ancestor
->IsTopLevel()) 
1184             ancestor 
= ancestor
->GetParent(); 
1187 #endif // wxUSE_ACCEL 
1189     // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x 
1190     // will only be sent if it is not in an accelerator table. 
1196             // In GTK 2.0, we need to hand over the key event to an input method 
1197             // and the IM will emit a "commit" event containing the actual utf8 
1198             // character.  In that case the EVT_CHAR events will be sent from 
1200             win
->m_imData
->lastKeyEvent 
= gdk_event
; 
1201             if ( gtk_im_context_filter_keypress(win
->m_imData
->context
, 
1204                 win
->m_imData
->lastKeyEvent 
= NULL
; 
1205                 wxLogTrace(TRACE_KEYS
, _T("Key event intercepted by IM")); 
1209                 win
->m_imData
->lastKeyEvent 
= NULL
; 
1214         KeySym keysym 
= gdk_event
->keyval
; 
1215         // Find key code for EVT_CHAR and EVT_CHAR_HOOK events 
1216         key_code 
= wxTranslateKeySymToWXKey(keysym
, TRUE 
/* isChar */); 
1219             if ( gdk_event
->length 
== 1 ) 
1221                 key_code 
= (unsigned char)gdk_event
->string
[0]; 
1223             else if ( wxIsAsciiKeysym(keysym
) ) 
1226                 key_code 
= (unsigned char)keysym
; 
1232             wxLogTrace(TRACE_KEYS
, _T("Char event: %ld"), key_code
); 
1234             event
.m_keyCode 
= key_code
; 
1236             // Implement OnCharHook by checking ancesteror top level windows 
1237             wxWindow 
*parent 
= win
; 
1238             while (parent 
&& !parent
->IsTopLevel()) 
1239                 parent 
= parent
->GetParent(); 
1242                 event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1243                 ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1248                 event
.SetEventType(wxEVT_CHAR
); 
1249                 ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1254     // win is a control: tab can be propagated up 
1256          ((gdk_event
->keyval 
== GDK_Tab
) || (gdk_event
->keyval 
== GDK_ISO_Left_Tab
)) && 
1257 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may 
1258 //     have this style, yet choose not to process this particular TAB in which 
1259 //     case TAB must still work as a navigational character 
1260 // JS: enabling again to make consistent with other platforms 
1261 //     (with wxTE_PROCESS_TAB you have to call Navigate to get default 
1262 //     navigation behaviour) 
1264          (! (win
->HasFlag(wxTE_PROCESS_TAB
) && win
->IsKindOf(CLASSINFO(wxTextCtrl
)) )) && 
1266          win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) ) 
1268         wxNavigationKeyEvent new_event
; 
1269         new_event
.SetEventObject( win
->GetParent() ); 
1270         // GDK reports GDK_ISO_Left_Tab for SHIFT-TAB 
1271         new_event
.SetDirection( (gdk_event
->keyval 
== GDK_Tab
) ); 
1272         // CTRL-TAB changes the (parent) window, i.e. switch notebook page 
1273         new_event
.SetWindowChange( (gdk_event
->state 
& GDK_CONTROL_MASK
) ); 
1274         new_event
.SetCurrentFocus( win 
); 
1275         ret 
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event 
); 
1278     // generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) 
1280          (gdk_event
->keyval 
== GDK_Escape
) ) 
1282         // however only do it if we have a Cancel button in the dialog, 
1283         // otherwise the user code may get confused by the events from a 
1284         // non-existing button and, worse, a wxButton might get button event 
1285         // from another button which is not really expected 
1286         wxWindow 
*winForCancel 
= win
, 
1288         while ( winForCancel 
) 
1290             btnCancel 
= winForCancel
->FindWindow(wxID_CANCEL
); 
1293                 // found a cancel button 
1297             if ( winForCancel
->IsTopLevel() ) 
1299                 // no need to look further 
1303             // maybe our parent has a cancel button? 
1304             winForCancel 
= winForCancel
->GetParent(); 
1309             wxCommandEvent 
event(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
); 
1310             event
.SetEventObject(btnCancel
); 
1311             ret 
= btnCancel
->GetEventHandler()->ProcessEvent(event
); 
1317         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" ); 
1325 static void gtk_wxwindow_commit_cb (GtkIMContext 
*context
, 
1329     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
1331     // take modifiers, cursor position, timestamp etc. from the last 
1332     // key_press_event that was fed into Input Method: 
1333     if (window
->m_imData
->lastKeyEvent
) 
1335         wxFillOtherKeyEventFields(event
, 
1336                                   window
, window
->m_imData
->lastKeyEvent
); 
1340     const wxWCharBuffer data 
= wxConvUTF8
.cMB2WC( (char*)str 
); 
1342     const wxWCharBuffer wdata 
= wxConvUTF8
.cMB2WC( (char*)str 
); 
1343     const wxCharBuffer data 
= wxConvLocal
.cWC2MB( wdata 
); 
1344 #endif // wxUSE_UNICODE 
1345     if( !(const wxChar
*)data 
) 
1350     // Implement OnCharHook by checking ancestor top level windows 
1351     wxWindow 
*parent 
= window
; 
1352     while (parent 
&& !parent
->IsTopLevel()) 
1353         parent 
= parent
->GetParent(); 
1355     for( const wxChar
* pstr 
= data
; *pstr
; pstr
++ ) 
1358         event
.m_uniChar 
= *pstr
; 
1359         // Backward compatible for ISO-8859 
1360         event
.m_keyCode 
= *pstr 
< 256 ? event
.m_uniChar 
: 0; 
1361         wxLogTrace(TRACE_KEYS
, _T("IM sent character '%c'"), event
.m_uniChar
); 
1363         event
.m_keyCode 
= *pstr
; 
1364 #endif  // wxUSE_UNICODE 
1367             event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1368             ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1373             event
.SetEventType(wxEVT_CHAR
); 
1374             ret 
= window
->GetEventHandler()->ProcessEvent( event 
); 
1381 //----------------------------------------------------------------------------- 
1382 // "key_release_event" from any window 
1383 //----------------------------------------------------------------------------- 
1385 static gint 
gtk_window_key_release_callback( GtkWidget 
*widget
, 
1386                                              GdkEventKey 
*gdk_event
, 
1392         wxapp_install_idle_handler(); 
1397     if (g_blockEventsOnDrag
) 
1400     wxKeyEvent 
event( wxEVT_KEY_UP 
); 
1401     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1403         // unknown key pressed, ignore (the event would be useless anyhow 
1407     if ( !win
->GetEventHandler()->ProcessEvent( event 
) ) 
1410     gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" ); 
1414 // ============================================================================ 
1416 // ============================================================================ 
1418 // ---------------------------------------------------------------------------- 
1419 // mouse event processing helpers 
1420 // ---------------------------------------------------------------------------- 
1422 // init wxMouseEvent with the info from GdkEventXXX struct 
1423 template<typename T
> void InitMouseEvent(wxWindowGTK 
*win
, 
1424                                          wxMouseEvent
& event
, 
1427     event
.SetTimestamp( gdk_event
->time 
); 
1428     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
); 
1429     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
); 
1430     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
); 
1431     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
); 
1432     event
.m_leftDown 
= (gdk_event
->state 
& GDK_BUTTON1_MASK
); 
1433     event
.m_middleDown 
= (gdk_event
->state 
& GDK_BUTTON2_MASK
); 
1434     event
.m_rightDown 
= (gdk_event
->state 
& GDK_BUTTON3_MASK
); 
1435     if (event
.GetEventType() == wxEVT_MOUSEWHEEL
) 
1437        event
.m_linesPerAction 
= 3; 
1438        event
.m_wheelDelta 
= 120; 
1439        if (((GdkEventButton
*)gdk_event
)->button 
== 4) 
1440            event
.m_wheelRotation 
= 120; 
1441        else if (((GdkEventButton
*)gdk_event
)->button 
== 5) 
1442            event
.m_wheelRotation 
= -120; 
1445     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1446     event
.m_x 
= (wxCoord
)gdk_event
->x 
- pt
.x
; 
1447     event
.m_y 
= (wxCoord
)gdk_event
->y 
- pt
.y
; 
1449     event
.SetEventObject( win 
); 
1450     event
.SetId( win
->GetId() ); 
1451     event
.SetTimestamp( gdk_event
->time 
); 
1454 static void AdjustEventButtonState(wxMouseEvent
& event
) 
1456     // GDK reports the old state of the button for a button press event, but 
1457     // for compatibility with MSW and common sense we want m_leftDown be TRUE 
1458     // for a LEFT_DOWN event, not FALSE, so we will invert 
1459     // left/right/middleDown for the corresponding click events 
1461     if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) || 
1462         (event
.GetEventType() == wxEVT_LEFT_DCLICK
) || 
1463         (event
.GetEventType() == wxEVT_LEFT_UP
)) 
1465         event
.m_leftDown 
= !event
.m_leftDown
; 
1469     if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) || 
1470         (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) || 
1471         (event
.GetEventType() == wxEVT_MIDDLE_UP
)) 
1473         event
.m_middleDown 
= !event
.m_middleDown
; 
1477     if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) || 
1478         (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) || 
1479         (event
.GetEventType() == wxEVT_RIGHT_UP
)) 
1481         event
.m_rightDown 
= !event
.m_rightDown
; 
1486 // find the window to send the mouse event too 
1488 wxWindowGTK 
*FindWindowForMouseEvent(wxWindowGTK 
*win
, wxCoord
& x
, wxCoord
& y
) 
1493     if (win
->m_wxwindow
) 
1495         GtkPizza 
*pizza 
= GTK_PIZZA(win
->m_wxwindow
); 
1496         xx 
+= pizza
->xoffset
; 
1497         yy 
+= pizza
->yoffset
; 
1500     wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
1503         wxWindowGTK 
*child 
= node
->GetData(); 
1505         node 
= node
->GetNext(); 
1506         if (!child
->IsShown()) 
1509         if (child
->IsTransparentForMouse()) 
1511             // wxStaticBox is transparent in the box itself 
1512             int xx1 
= child
->m_x
; 
1513             int yy1 
= child
->m_y
; 
1514             int xx2 
= child
->m_x 
+ child
->m_width
; 
1515             int yy2 
= child
->m_y 
+ child
->m_height
; 
1518             if (((xx 
>= xx1
) && (xx 
<= xx1
+10) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1520                 ((xx 
>= xx2
-10) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1522                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy1
+10)) || 
1524                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy2
-1) && (yy 
<= yy2
))) 
1535             if ((child
->m_wxwindow 
== (GtkWidget
*) NULL
) && 
1536                 (child
->m_x 
<= xx
) && 
1537                 (child
->m_y 
<= yy
) && 
1538                 (child
->m_x
+child
->m_width  
>= xx
) && 
1539                 (child
->m_y
+child
->m_height 
>= yy
)) 
1552 //----------------------------------------------------------------------------- 
1553 // "button_press_event" 
1554 //----------------------------------------------------------------------------- 
1556 static gint 
gtk_window_button_press_callback( GtkWidget 
*widget
, 
1557                                               GdkEventButton 
*gdk_event
, 
1563         wxapp_install_idle_handler(); 
1566     wxPrintf( wxT("1) OnButtonPress from ") ); 
1567     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1568         wxPrintf( win->GetClassInfo()->GetClassName() ); 
1569     wxPrintf( wxT(".\n") ); 
1571     if (!win
->m_hasVMT
) return FALSE
; 
1572     if (g_blockEventsOnDrag
) return TRUE
; 
1573     if (g_blockEventsOnScroll
) return TRUE
; 
1575     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1577     if (win
->m_wxwindow 
&& (g_focusWindow 
!= win
) && win
->AcceptsFocus()) 
1579         gtk_widget_grab_focus( win
->m_wxwindow 
); 
1581         wxPrintf( wxT("GrabFocus from ") ); 
1582         if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1583             wxPrintf( win->GetClassInfo()->GetClassName() ); 
1584         wxPrintf( wxT(".\n") ); 
1588     // GDK sends surplus button down event 
1589     // before a double click event. We 
1590     // need to filter these out. 
1591     if (gdk_event
->type 
== GDK_BUTTON_PRESS
) 
1593         GdkEvent 
*peek_event 
= gdk_event_peek(); 
1596             if ((peek_event
->type 
== GDK_2BUTTON_PRESS
) || 
1597                 (peek_event
->type 
== GDK_3BUTTON_PRESS
)) 
1599                 gdk_event_free( peek_event 
); 
1604                 gdk_event_free( peek_event 
); 
1609     wxEventType event_type 
= wxEVT_NULL
; 
1611     // GdkDisplay is a GTK+ 2.2.0 thing 
1612 #if defined(__WXGTK20__) && GTK_CHECK_VERSION(2, 2, 0) 
1613     if ( gdk_event
->type 
== GDK_2BUTTON_PRESS 
&& 
1614             gdk_event
->button 
>= 1 && gdk_event
->button 
<= 3 ) 
1616         // Reset GDK internal timestamp variables in order to disable GDK 
1617         // triple click events. GDK will then next time believe no button has 
1618         // been clicked just before, and send a normal button click event. 
1619         GdkDisplay
* display 
= gtk_widget_get_display (widget
); 
1620         display
->button_click_time
[1] = 0; 
1621         display
->button_click_time
[0] = 0; 
1625     if (gdk_event
->button 
== 1) 
1627         // note that GDK generates triple click events which are not supported 
1628         // by wxWidgets but still have to be passed to the app as otherwise 
1629         // clicks would simply go missing 
1630         switch (gdk_event
->type
) 
1632             // we shouldn't get triple clicks at all for GTK2 because we 
1633             // suppress them artificially using the code above but we still 
1634             // should map them to something for GTK1 and not just ignore them 
1635             // as this would lose clicks 
1636             case GDK_3BUTTON_PRESS
:     // we could also map this to DCLICK... 
1637             case GDK_BUTTON_PRESS
: 
1638                 event_type 
= wxEVT_LEFT_DOWN
; 
1641             case GDK_2BUTTON_PRESS
: 
1642                 event_type 
= wxEVT_LEFT_DCLICK
; 
1646                 // just to silence gcc warnings 
1650     else if (gdk_event
->button 
== 2) 
1652         switch (gdk_event
->type
) 
1654             case GDK_3BUTTON_PRESS
: 
1655             case GDK_BUTTON_PRESS
: 
1656                 event_type 
= wxEVT_MIDDLE_DOWN
; 
1659             case GDK_2BUTTON_PRESS
: 
1660                 event_type 
= wxEVT_MIDDLE_DCLICK
; 
1667     else if (gdk_event
->button 
== 3) 
1669         switch (gdk_event
->type
) 
1671             case GDK_3BUTTON_PRESS
: 
1672             case GDK_BUTTON_PRESS
: 
1673                 event_type 
= wxEVT_RIGHT_DOWN
; 
1676             case GDK_2BUTTON_PRESS
: 
1677                 event_type 
= wxEVT_RIGHT_DCLICK
; 
1684     else if (gdk_event
->button 
== 4 || gdk_event
->button 
== 5) 
1686         if (gdk_event
->type 
== GDK_BUTTON_PRESS 
) 
1688             event_type 
= wxEVT_MOUSEWHEEL
; 
1692     if ( event_type 
== wxEVT_NULL 
) 
1694         // unknown mouse button or click type 
1698     wxMouseEvent 
event( event_type 
); 
1699     InitMouseEvent( win
, event
, gdk_event 
); 
1701     AdjustEventButtonState(event
); 
1703     // wxListBox actually get mouse events from the item, so we need to give it 
1704     // a chance to correct this 
1705     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1707     if ( event_type 
== wxEVT_RIGHT_DOWN 
) 
1709         // generate a "context menu" event: this is similar to right mouse 
1710         // click under many GUIs except that it is generated differently 
1711         // (right up under MSW, ctrl-click under Mac, right down here) and 
1713         // (a) it's a command event and so is propagated to the parent 
1714         // (b) under MSW it can be generated from kbd too 
1715         // (c) it uses screen coords (because of (a)) 
1716         wxContextMenuEvent 
evtCtx(wxEVT_CONTEXT_MENU
, 
1718                                   win
->ClientToScreen(event
.GetPosition())); 
1719         (void)win
->GetEventHandler()->ProcessEvent(evtCtx
); 
1722     // find the correct window to send the event too: it may be a different one 
1723     // from the one which got it at GTK+ level because some control don't have 
1724     // their own X window and thus cannot get any events. 
1725     if ( !g_captureWindow 
) 
1726         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1728     gs_timeLastClick 
= gdk_event
->time
; 
1731     if (event_type 
== wxEVT_LEFT_DCLICK
) 
1733         // GTK 1.2 crashes when intercepting double 
1734         // click events from both wxSpinButton and 
1736         if (GTK_IS_SPIN_BUTTON(win
->m_widget
)) 
1738             // Just disable this event for now. 
1744     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1746         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" ); 
1753 //----------------------------------------------------------------------------- 
1754 // "button_release_event" 
1755 //----------------------------------------------------------------------------- 
1757 static gint 
gtk_window_button_release_callback( GtkWidget 
*widget
, 
1758                                                 GdkEventButton 
*gdk_event
, 
1764         wxapp_install_idle_handler(); 
1766     if (!win
->m_hasVMT
) return FALSE
; 
1767     if (g_blockEventsOnDrag
) return FALSE
; 
1768     if (g_blockEventsOnScroll
) return FALSE
; 
1770     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1772     wxEventType event_type 
= wxEVT_NULL
; 
1774     switch (gdk_event
->button
) 
1777             event_type 
= wxEVT_LEFT_UP
; 
1781             event_type 
= wxEVT_MIDDLE_UP
; 
1785             event_type 
= wxEVT_RIGHT_UP
; 
1789             // unknwon button, don't process 
1793     wxMouseEvent 
event( event_type 
); 
1794     InitMouseEvent( win
, event
, gdk_event 
); 
1796     AdjustEventButtonState(event
); 
1798     // same wxListBox hack as above 
1799     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1801     if ( !g_captureWindow 
) 
1802         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1804     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1806         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" ); 
1813 //----------------------------------------------------------------------------- 
1814 // "motion_notify_event" 
1815 //----------------------------------------------------------------------------- 
1817 static gint 
gtk_window_motion_notify_callback( GtkWidget 
*widget
, 
1818                                                GdkEventMotion 
*gdk_event
, 
1824         wxapp_install_idle_handler(); 
1826     if (!win
->m_hasVMT
) return FALSE
; 
1827     if (g_blockEventsOnDrag
) return FALSE
; 
1828     if (g_blockEventsOnScroll
) return FALSE
; 
1830     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1832     if (gdk_event
->is_hint
) 
1836         GdkModifierType state
; 
1837         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1843     printf( "OnMotion from " ); 
1844     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1845       printf( win->GetClassInfo()->GetClassName() ); 
1849     wxMouseEvent 
event( wxEVT_MOTION 
); 
1850     InitMouseEvent(win
, event
, gdk_event
); 
1852     if ( g_captureWindow 
) 
1854         // synthetize a mouse enter or leave event if needed 
1855         GdkWindow 
*winUnderMouse 
= gdk_window_at_pointer(NULL
, NULL
); 
1856         // This seems to be necessary and actually been added to 
1857         // GDK itself in version 2.0.X 
1860         bool hasMouse 
= winUnderMouse 
== gdk_event
->window
; 
1861         if ( hasMouse 
!= g_captureWindowHasMouse 
) 
1863             // the mouse changed window 
1864             g_captureWindowHasMouse 
= hasMouse
; 
1866             wxMouseEvent 
event(g_captureWindowHasMouse 
? wxEVT_ENTER_WINDOW
 
1867                                                        : wxEVT_LEAVE_WINDOW
); 
1868             InitMouseEvent(win
, event
, gdk_event
); 
1869             event
.SetEventObject(win
); 
1870             win
->GetEventHandler()->ProcessEvent(event
); 
1875         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1878     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1880         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" ); 
1888 //----------------------------------------------------------------------------- 
1889 // "mouse_wheel_event" 
1890 //----------------------------------------------------------------------------- 
1892 static gint 
gtk_window_wheel_callback (GtkWidget 
* widget
, 
1893                                         GdkEventScroll 
* gdk_event
, 
1899         wxapp_install_idle_handler(); 
1901     wxEventType event_type 
= wxEVT_NULL
; 
1902     if (gdk_event
->direction 
== GDK_SCROLL_UP
) 
1903         event_type 
= wxEVT_MOUSEWHEEL
; 
1904     else if (gdk_event
->direction 
== GDK_SCROLL_DOWN
) 
1905         event_type 
= wxEVT_MOUSEWHEEL
; 
1909     wxMouseEvent 
event( event_type 
); 
1910     // Can't use InitMouse macro because scroll events don't have button 
1911     event
.SetTimestamp( gdk_event
->time 
); 
1912     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
); 
1913     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
); 
1914     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
); 
1915     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
); 
1916     event
.m_leftDown 
= (gdk_event
->state 
& GDK_BUTTON1_MASK
); 
1917     event
.m_middleDown 
= (gdk_event
->state 
& GDK_BUTTON2_MASK
); 
1918     event
.m_rightDown 
= (gdk_event
->state 
& GDK_BUTTON3_MASK
); 
1919     event
.m_linesPerAction 
= 3; 
1920     event
.m_wheelDelta 
= 120; 
1921     if (gdk_event
->direction 
== GDK_SCROLL_UP
) 
1922         event
.m_wheelRotation 
= 120; 
1924         event
.m_wheelRotation 
= -120; 
1926     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1927     event
.m_x 
= (wxCoord
)gdk_event
->x 
- pt
.x
; 
1928     event
.m_y 
= (wxCoord
)gdk_event
->y 
- pt
.y
; 
1930     event
.SetEventObject( win 
); 
1931     event
.SetId( win
->GetId() ); 
1932     event
.SetTimestamp( gdk_event
->time 
); 
1934     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1936         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "scroll_event" ); 
1944 //----------------------------------------------------------------------------- 
1946 //----------------------------------------------------------------------------- 
1948 // send the wxChildFocusEvent and wxFocusEvent, common code of 
1949 // gtk_window_focus_in_callback() and SetFocus() 
1950 static bool DoSendFocusEvents(wxWindow 
*win
) 
1952     // Notify the parent keeping track of focus for the kbd navigation 
1953     // purposes that we got it. 
1954     wxChildFocusEvent 
eventChildFocus(win
); 
1955     (void)win
->GetEventHandler()->ProcessEvent(eventChildFocus
); 
1957     wxFocusEvent 
eventFocus(wxEVT_SET_FOCUS
, win
->GetId()); 
1958     eventFocus
.SetEventObject(win
); 
1960     return win
->GetEventHandler()->ProcessEvent(eventFocus
); 
1963 static gint 
gtk_window_focus_in_callback( GtkWidget 
*widget
, 
1964                                           GdkEvent 
*WXUNUSED(event
), 
1970         wxapp_install_idle_handler(); 
1974         gtk_im_context_focus_in(win
->m_imData
->context
); 
1977     if (!win
->m_hasVMT
) return FALSE
; 
1978     if (g_blockEventsOnDrag
) return FALSE
; 
1980     switch ( g_sendActivateEvent 
) 
1983             // we've got focus from outside, synthetize wxActivateEvent 
1984             g_sendActivateEvent 
= 1; 
1988             // another our window just lost focus, it was already ours before 
1989             // - don't send any wxActivateEvent 
1990             g_sendActivateEvent 
= -1; 
1995     g_focusWindow 
= win
; 
1997     wxLogTrace(TRACE_FOCUS
, 
1998                _T("%s: focus in"), win
->GetName().c_str()); 
2002         gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
); 
2006     // caret needs to be informed about focus change 
2007     wxCaret 
*caret 
= win
->GetCaret(); 
2010         caret
->OnSetFocus(); 
2012 #endif // wxUSE_CARET 
2014     g_activeFrameLostFocus 
= FALSE
; 
2016     wxWindowGTK 
*active 
= wxGetTopLevelParent(win
); 
2017     if ( active 
!= g_activeFrame 
) 
2019         if ( g_activeFrame 
) 
2021             wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
); 
2022             wxActivateEvent 
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId()); 
2023             event
.SetEventObject(g_activeFrame
); 
2024             g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
2027         wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
); 
2028         g_activeFrame 
= active
; 
2029         wxActivateEvent 
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId()); 
2030         event
.SetEventObject(g_activeFrame
); 
2031         g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
2033         // Don't send focus events in addition to activate 
2034         // if (win == g_activeFrame) 
2038     // does the window itself think that it has the focus? 
2039     if ( !win
->m_hasFocus 
) 
2041         // not yet, notify it 
2042         win
->m_hasFocus 
= TRUE
; 
2044         if ( DoSendFocusEvents(win
) ) 
2046            gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" ); 
2054 //----------------------------------------------------------------------------- 
2055 // "focus_out_event" 
2056 //----------------------------------------------------------------------------- 
2058 static gint 
gtk_window_focus_out_callback( GtkWidget 
*widget
, GdkEventFocus 
*gdk_event
, wxWindowGTK 
*win 
) 
2063         wxapp_install_idle_handler(); 
2067         gtk_im_context_focus_out(win
->m_imData
->context
); 
2070     if (!win
->m_hasVMT
) return FALSE
; 
2071     if (g_blockEventsOnDrag
) return FALSE
; 
2073     wxLogTrace( TRACE_FOCUS
, 
2074                 _T("%s: focus out"), win
->GetName().c_str() ); 
2076     if ( !g_activeFrameLostFocus 
&& g_activeFrame 
) 
2078         // VZ: commenting this out because it does happen (although not easy 
2079         //     to reproduce, I only see it when using wxMiniFrame and not 
2080         //     always) and makes using Mahogany quite annoying 
2082         wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
, 
2083                         wxT("unfocusing window that hasn't gained focus properly") ); 
2086         g_activeFrameLostFocus 
= TRUE
; 
2089     // if the focus goes out of our app alltogether, OnIdle() will send 
2090     // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset 
2091     // g_sendActivateEvent to -1 
2092     g_sendActivateEvent 
= 0; 
2094     wxWindowGTK 
*winFocus 
= wxFindFocusedChild(win
); 
2098     g_focusWindow 
= (wxWindowGTK 
*)NULL
; 
2106     // caret needs to be informed about focus change 
2107     wxCaret 
*caret 
= win
->GetCaret(); 
2110         caret
->OnKillFocus(); 
2112 #endif // wxUSE_CARET 
2114     // don't send the window a kill focus event if it thinks that it doesn't 
2115     // have focus already 
2116     if ( win
->m_hasFocus 
) 
2118         win
->m_hasFocus 
= FALSE
; 
2120         wxFocusEvent 
event( wxEVT_KILL_FOCUS
, win
->GetId() ); 
2121         event
.SetEventObject( win 
); 
2123         if (win
->GetEventHandler()->ProcessEvent( event 
)) 
2125             gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" ); 
2133 //----------------------------------------------------------------------------- 
2134 // "enter_notify_event" 
2135 //----------------------------------------------------------------------------- 
2138 gint 
gtk_window_enter_callback( GtkWidget 
*widget
, 
2139                                 GdkEventCrossing 
*gdk_event
, 
2145         wxapp_install_idle_handler(); 
2147     if (!win
->m_hasVMT
) return FALSE
; 
2148     if (g_blockEventsOnDrag
) return FALSE
; 
2150     // Event was emitted after a grab 
2151     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
2153     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
2157     GdkModifierType state 
= (GdkModifierType
)0; 
2159     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
2161     wxMouseEvent 
event( wxEVT_ENTER_WINDOW 
); 
2162     InitMouseEvent(win
, event
, gdk_event
); 
2163     wxPoint pt 
= win
->GetClientAreaOrigin(); 
2164     event
.m_x 
= x 
+ pt
.x
; 
2165     event
.m_y 
= y 
+ pt
.y
; 
2167     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
2169        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" ); 
2176 //----------------------------------------------------------------------------- 
2177 // "leave_notify_event" 
2178 //----------------------------------------------------------------------------- 
2180 static gint 
gtk_window_leave_callback( GtkWidget 
*widget
, GdkEventCrossing 
*gdk_event
, wxWindowGTK 
*win 
) 
2185         wxapp_install_idle_handler(); 
2187     if (!win
->m_hasVMT
) return FALSE
; 
2188     if (g_blockEventsOnDrag
) return FALSE
; 
2190     // Event was emitted after an ungrab 
2191     if (gdk_event
->mode 
!= GDK_CROSSING_NORMAL
) return FALSE
; 
2193     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
2195     wxMouseEvent 
event( wxEVT_LEAVE_WINDOW 
); 
2196     event
.SetTimestamp( gdk_event
->time 
); 
2197     event
.SetEventObject( win 
); 
2201     GdkModifierType state 
= (GdkModifierType
)0; 
2203     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
2205     event
.m_shiftDown 
= (state 
& GDK_SHIFT_MASK
) != 0; 
2206     event
.m_controlDown 
= (state 
& GDK_CONTROL_MASK
) != 0; 
2207     event
.m_altDown 
= (state 
& GDK_MOD1_MASK
) != 0; 
2208     event
.m_metaDown 
= (state 
& GDK_MOD2_MASK
) != 0; 
2209     event
.m_leftDown 
= (state 
& GDK_BUTTON1_MASK
) != 0; 
2210     event
.m_middleDown 
= (state 
& GDK_BUTTON2_MASK
) != 0; 
2211     event
.m_rightDown 
= (state 
& GDK_BUTTON3_MASK
) != 0; 
2213     wxPoint pt 
= win
->GetClientAreaOrigin(); 
2214     event
.m_x 
= x 
+ pt
.x
; 
2215     event
.m_y 
= y 
+ pt
.y
; 
2217     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
2219         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" ); 
2226 //----------------------------------------------------------------------------- 
2227 // "value_changed" from m_vAdjust 
2228 //----------------------------------------------------------------------------- 
2230 static void gtk_window_vscroll_callback( GtkAdjustment 
*adjust
, 
2237         wxapp_install_idle_handler(); 
2239     if (g_blockEventsOnDrag
) return; 
2241     if (!win
->m_hasVMT
) return; 
2243     float diff 
= adjust
->value 
- win
->m_oldVerticalPos
; 
2244     if (fabs(diff
) < 0.2) return; 
2246     win
->m_oldVerticalPos 
= adjust
->value
; 
2249     GtkScrolledWindow   
*sw 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
2251     wxEventType         command 
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->vscrollbar
)); 
2253     int value 
= (int)(adjust
->value
+0.5); 
2255     wxScrollWinEvent 
event( command
, value
, wxVERTICAL 
); 
2256     event
.SetEventObject( win 
); 
2257     win
->GetEventHandler()->ProcessEvent( event 
); 
2260 //----------------------------------------------------------------------------- 
2261 // "value_changed" from m_hAdjust 
2262 //----------------------------------------------------------------------------- 
2264 static void gtk_window_hscroll_callback( GtkAdjustment 
*adjust
, 
2271         wxapp_install_idle_handler(); 
2273     if (g_blockEventsOnDrag
) return; 
2274     if (!win
->m_hasVMT
) return; 
2276     float diff 
= adjust
->value 
- win
->m_oldHorizontalPos
; 
2277     if (fabs(diff
) < 0.2) return; 
2280     GtkScrolledWindow   
*sw 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
2282     wxEventType         command 
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->hscrollbar
)); 
2284     win
->m_oldHorizontalPos 
= adjust
->value
; 
2286     int value 
= (int)(adjust
->value
+0.5); 
2288     wxScrollWinEvent 
event( command
, value
, wxHORIZONTAL 
); 
2289     event
.SetEventObject( win 
); 
2290     win
->GetEventHandler()->ProcessEvent( event 
); 
2293 //----------------------------------------------------------------------------- 
2294 // "button_press_event" from scrollbar 
2295 //----------------------------------------------------------------------------- 
2297 static gint 
gtk_scrollbar_button_press_callback( GtkRange 
*widget
, 
2298                                                  GdkEventButton 
*gdk_event
, 
2304         wxapp_install_idle_handler(); 
2307     g_blockEventsOnScroll 
= TRUE
; 
2309     // FIXME: there is no 'slider' field in GTK+ 2.0 any more 
2311     win
->m_isScrolling 
= (gdk_event
->window 
== widget
->slider
); 
2317 //----------------------------------------------------------------------------- 
2318 // "button_release_event" from scrollbar 
2319 //----------------------------------------------------------------------------- 
2321 static gint 
gtk_scrollbar_button_release_callback( GtkRange 
*widget
, 
2322                                                    GdkEventButton 
*WXUNUSED(gdk_event
), 
2327 //  don't test here as we can release the mouse while being over 
2328 //  a different window than the slider 
2330 //    if (gdk_event->window != widget->slider) return FALSE; 
2332     g_blockEventsOnScroll 
= FALSE
; 
2334     if (win
->m_isScrolling
) 
2336         wxEventType command 
= wxEVT_SCROLLWIN_THUMBRELEASE
; 
2340         GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
2341         if (widget 
== GTK_RANGE(scrolledWindow
->hscrollbar
)) 
2343             value 
= (int)(win
->m_hAdjust
->value
+0.5); 
2346         if (widget 
== GTK_RANGE(scrolledWindow
->vscrollbar
)) 
2348             value 
= (int)(win
->m_vAdjust
->value
+0.5); 
2352         wxScrollWinEvent 
event( command
, value
, dir 
); 
2353         event
.SetEventObject( win 
); 
2354         win
->GetEventHandler()->ProcessEvent( event 
); 
2357     win
->m_isScrolling 
= FALSE
; 
2362 // ---------------------------------------------------------------------------- 
2363 // this wxWindowBase function is implemented here (in platform-specific file) 
2364 // because it is static and so couldn't be made virtual 
2365 // ---------------------------------------------------------------------------- 
2367 wxWindow 
*wxWindowBase::FindFocus() 
2369     // the cast is necessary when we compile in wxUniversal mode 
2370     return (wxWindow 
*)g_focusWindow
; 
2374 //----------------------------------------------------------------------------- 
2375 // "realize" from m_widget 
2376 //----------------------------------------------------------------------------- 
2378 /* We cannot set colours and fonts before the widget has 
2379    been realized, so we do this directly after realization. */ 
2382 gtk_window_realized_callback( GtkWidget 
*m_widget
, wxWindow 
*win 
) 
2387         wxapp_install_idle_handler(); 
2392         GtkPizza 
*pizza 
= GTK_PIZZA( m_widget 
); 
2393         gtk_im_context_set_client_window( win
->m_imData
->context
, 
2394                                           pizza
->bin_window 
); 
2398     wxWindowCreateEvent 
event( win 
); 
2399     event
.SetEventObject( win 
); 
2400     win
->GetEventHandler()->ProcessEvent( event 
); 
2405 //----------------------------------------------------------------------------- 
2407 //----------------------------------------------------------------------------- 
2410 void gtk_window_size_callback( GtkWidget 
*WXUNUSED(widget
), 
2411                                GtkAllocation 
*WXUNUSED(alloc
), 
2415         wxapp_install_idle_handler(); 
2417     if (!win
->m_hasScrolling
) return; 
2419     int client_width 
= 0; 
2420     int client_height 
= 0; 
2421     win
->GetClientSize( &client_width
, &client_height 
); 
2422     if ((client_width 
== win
->m_oldClientWidth
) && (client_height 
== win
->m_oldClientHeight
)) 
2425     win
->m_oldClientWidth 
= client_width
; 
2426     win
->m_oldClientHeight 
= client_height
; 
2428     if (!win
->m_nativeSizeEvent
) 
2430         wxSizeEvent 
event( win
->GetSize(), win
->GetId() ); 
2431         event
.SetEventObject( win 
); 
2432         win
->GetEventHandler()->ProcessEvent( event 
); 
2438     #define WXUNUSED_UNLESS_XIM(param)  param 
2440     #define WXUNUSED_UNLESS_XIM(param)  WXUNUSED(param) 
2443 /* Resize XIM window */ 
2446 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
), 
2447                                  GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
), 
2448                                  wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) ) 
2451         wxapp_install_idle_handler(); 
2457     if  (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
) 
2461         gdk_window_get_size (widget
->window
, &width
, &height
); 
2462         win
->m_icattr
->preedit_area
.width 
= width
; 
2463         win
->m_icattr
->preedit_area
.height 
= height
; 
2464         gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
); 
2469 //----------------------------------------------------------------------------- 
2470 // "realize" from m_wxwindow 
2471 //----------------------------------------------------------------------------- 
2473 /* Initialize XIM support */ 
2476 gtk_wxwindow_realized_callback( GtkWidget 
* WXUNUSED_UNLESS_XIM(widget
), 
2477                                 wxWindowGTK 
* WXUNUSED_UNLESS_XIM(win
) ) 
2480         wxapp_install_idle_handler(); 
2483     if (win
->m_ic
) return FALSE
; 
2484     if (!widget
) return FALSE
; 
2485     if (!gdk_im_ready()) return FALSE
; 
2487     win
->m_icattr 
= gdk_ic_attr_new(); 
2488     if (!win
->m_icattr
) return FALSE
; 
2492     GdkColormap 
*colormap
; 
2493     GdkICAttr 
*attr 
= win
->m_icattr
; 
2494     unsigned attrmask 
= GDK_IC_ALL_REQ
; 
2496     GdkIMStyle supported_style 
= (GdkIMStyle
) 
2497                                   (GDK_IM_PREEDIT_NONE 
| 
2498                                    GDK_IM_PREEDIT_NOTHING 
| 
2499                                    GDK_IM_PREEDIT_POSITION 
| 
2500                                    GDK_IM_STATUS_NONE 
| 
2501                                    GDK_IM_STATUS_NOTHING
); 
2503     if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2504         supported_style 
= (GdkIMStyle
)(supported_style 
& ~GDK_IM_PREEDIT_POSITION
); 
2506     attr
->style 
= style 
= gdk_im_decide_style (supported_style
); 
2507     attr
->client_window 
= widget
->window
; 
2509     if ((colormap 
= gtk_widget_get_colormap (widget
)) != 
2510             gtk_widget_get_default_colormap ()) 
2512         attrmask 
|= GDK_IC_PREEDIT_COLORMAP
; 
2513         attr
->preedit_colormap 
= colormap
; 
2516     attrmask 
|= GDK_IC_PREEDIT_FOREGROUND
; 
2517     attrmask 
|= GDK_IC_PREEDIT_BACKGROUND
; 
2518     attr
->preedit_foreground 
= widget
->style
->fg
[GTK_STATE_NORMAL
]; 
2519     attr
->preedit_background 
= widget
->style
->base
[GTK_STATE_NORMAL
]; 
2521     switch (style 
& GDK_IM_PREEDIT_MASK
) 
2523         case GDK_IM_PREEDIT_POSITION
: 
2524             if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2526                 g_warning ("over-the-spot style requires fontset"); 
2530             gdk_window_get_size (widget
->window
, &width
, &height
); 
2532             attrmask 
|= GDK_IC_PREEDIT_POSITION_REQ
; 
2533             attr
->spot_location
.x 
= 0; 
2534             attr
->spot_location
.y 
= height
; 
2535             attr
->preedit_area
.x 
= 0; 
2536             attr
->preedit_area
.y 
= 0; 
2537             attr
->preedit_area
.width 
= width
; 
2538             attr
->preedit_area
.height 
= height
; 
2539             attr
->preedit_fontset 
= widget
->style
->font
; 
2544       win
->m_ic 
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
); 
2546       if (win
->m_ic 
== NULL
) 
2547           g_warning ("Can't create input context."); 
2550           mask 
= gdk_window_get_events (widget
->window
); 
2551           mask 
= (GdkEventMask
)(mask 
| gdk_ic_get_events (win
->m_ic
)); 
2552           gdk_window_set_events (widget
->window
, mask
); 
2554           if (GTK_WIDGET_HAS_FOCUS(widget
)) 
2555               gdk_im_begin (win
->m_ic
, widget
->window
); 
2562 //----------------------------------------------------------------------------- 
2563 // InsertChild for wxWindowGTK. 
2564 //----------------------------------------------------------------------------- 
2566 /* Callback for wxWindowGTK. This very strange beast has to be used because 
2567  * C++ has no virtual methods in a constructor. We have to emulate a 
2568  * virtual function here as wxNotebook requires a different way to insert 
2569  * a child in it. I had opted for creating a wxNotebookPage window class 
2570  * which would have made this superfluous (such in the MDI window system), 
2571  * but no-one was listening to me... */ 
2573 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child 
) 
2575     /* the window might have been scrolled already, do we 
2576        have to adapt the position */ 
2577     GtkPizza 
*pizza 
= GTK_PIZZA(parent
->m_wxwindow
); 
2578     child
->m_x 
+= pizza
->xoffset
; 
2579     child
->m_y 
+= pizza
->yoffset
; 
2581     gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
), 
2582                      GTK_WIDGET(child
->m_widget
), 
2589 //----------------------------------------------------------------------------- 
2591 //----------------------------------------------------------------------------- 
2593 wxWindow 
*wxGetActiveWindow() 
2595     return wxWindow::FindFocus(); 
2598 //----------------------------------------------------------------------------- 
2600 //----------------------------------------------------------------------------- 
2602 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
2604 #ifdef __WXUNIVERSAL__ 
2605     IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
) 
2607     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
2608 #endif // __WXUNIVERSAL__/__WXGTK__ 
2610 void wxWindowGTK::Init() 
2613     m_widget 
= (GtkWidget 
*) NULL
; 
2614     m_wxwindow 
= (GtkWidget 
*) NULL
; 
2615     m_focusWidget 
= (GtkWidget 
*) NULL
; 
2625     m_needParent 
= TRUE
; 
2626     m_isBeingDeleted 
= FALSE
; 
2629     m_nativeSizeEvent 
= FALSE
; 
2631     m_hasScrolling 
= FALSE
; 
2632     m_isScrolling 
= FALSE
; 
2634     m_hAdjust 
= (GtkAdjustment
*) NULL
; 
2635     m_vAdjust 
= (GtkAdjustment
*) NULL
; 
2636     m_oldHorizontalPos 
= 
2637     m_oldVerticalPos 
= 0.0; 
2639     m_oldClientHeight 
= 0; 
2643     m_insertCallback 
= (wxInsertChildFunction
) NULL
; 
2645     m_acceptsFocus 
= FALSE
; 
2648     m_clipPaintRegion 
= FALSE
; 
2650     m_needsStyleChange 
= false; 
2652     m_cursor 
= *wxSTANDARD_CURSOR
; 
2656     m_x11Context 
= NULL
; 
2657     m_dirtyTabOrder 
= false; 
2660     m_ic 
= (GdkIC
*) NULL
; 
2661     m_icattr 
= (GdkICAttr
*) NULL
; 
2666 wxWindowGTK::wxWindowGTK() 
2671 wxWindowGTK::wxWindowGTK( wxWindow 
*parent
, 
2676                           const wxString 
&name  
) 
2680     Create( parent
, id
, pos
, size
, style
, name 
); 
2683 bool wxWindowGTK::Create( wxWindow 
*parent
, 
2688                           const wxString 
&name  
) 
2690     if (!PreCreation( parent
, pos
, size 
) || 
2691         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
2693         wxFAIL_MSG( wxT("wxWindowGTK creation failed") ); 
2697     m_insertCallback 
= wxInsertChildInWindow
; 
2699     m_widget 
= gtk_scrolled_window_new( (GtkAdjustment 
*) NULL
, (GtkAdjustment 
*) NULL 
); 
2700     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
2702     GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
2704     GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2705     scroll_class
->scrollbar_spacing 
= 0; 
2707     gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
2709     m_hAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) ); 
2710     m_vAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) ); 
2712     m_wxwindow 
= gtk_pizza_new(); 
2714 #ifndef __WXUNIVERSAL__ 
2715     GtkPizza 
*pizza 
= GTK_PIZZA(m_wxwindow
); 
2717     if (HasFlag(wxRAISED_BORDER
)) 
2719         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT 
); 
2721     else if (HasFlag(wxSUNKEN_BORDER
)) 
2723         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN 
); 
2725     else if (HasFlag(wxSIMPLE_BORDER
)) 
2727         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN 
); 
2731         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE 
); 
2733 #endif // __WXUNIVERSAL__ 
2735     gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
2737     GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
2738     m_acceptsFocus 
= TRUE
; 
2740     // I _really_ don't want scrollbars in the beginning 
2741     m_vAdjust
->lower 
= 0.0; 
2742     m_vAdjust
->upper 
= 1.0; 
2743     m_vAdjust
->value 
= 0.0; 
2744     m_vAdjust
->step_increment 
= 1.0; 
2745     m_vAdjust
->page_increment 
= 1.0; 
2746     m_vAdjust
->page_size 
= 5.0; 
2747     gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
2748     m_hAdjust
->lower 
= 0.0; 
2749     m_hAdjust
->upper 
= 1.0; 
2750     m_hAdjust
->value 
= 0.0; 
2751     m_hAdjust
->step_increment 
= 1.0; 
2752     m_hAdjust
->page_increment 
= 1.0; 
2753     m_hAdjust
->page_size 
= 5.0; 
2754     gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
2756     // these handlers block mouse events to any window during scrolling such as 
2757     // motion events and prevent GTK and wxWidgets from fighting over where the 
2760     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event", 
2761           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
2763     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event", 
2764           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
2766     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event", 
2767           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
2769     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event", 
2770           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
2772     // these handlers get notified when screen updates are required either when 
2773     // scrolling or when the window size (and therefore scrollbar configuration) 
2776     gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
2777           (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
2778     gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
2779           (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
2781     gtk_widget_show( m_wxwindow 
); 
2784         m_parent
->DoAddChild( this ); 
2786     m_focusWidget 
= m_wxwindow
; 
2793 wxWindowGTK::~wxWindowGTK() 
2797     if (g_focusWindow 
== this) 
2798         g_focusWindow 
= NULL
; 
2800     if (g_activeFrame 
== this) 
2801         g_activeFrame 
= NULL
; 
2803     if ( g_delayedFocus 
== this ) 
2804         g_delayedFocus 
= NULL
; 
2806     m_isBeingDeleted 
= TRUE
; 
2816         gdk_ic_destroy (m_ic
); 
2818         gdk_ic_attr_destroy (m_icattr
); 
2823         gtk_widget_destroy( m_wxwindow 
); 
2824         m_wxwindow 
= (GtkWidget
*) NULL
; 
2829         gtk_widget_destroy( m_widget 
); 
2830         m_widget 
= (GtkWidget
*) NULL
; 
2838 bool wxWindowGTK::PreCreation( wxWindowGTK 
*parent
, const wxPoint 
&pos
,  const wxSize 
&size 
) 
2840     wxCHECK_MSG( !m_needParent 
|| parent
, FALSE
, wxT("Need complete parent.") ); 
2842     // Use either the given size, or the default if -1 is given. 
2843     // See wxWindowBase for these functions. 
2844     m_width 
= WidthDefault(size
.x
) ; 
2845     m_height 
= HeightDefault(size
.y
); 
2853 void wxWindowGTK::PostCreation() 
2855     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2861             // these get reported to wxWidgets -> wxPaintEvent 
2863             gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE 
); 
2865             gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event", 
2866                 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this ); 
2869             gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw", 
2870                 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this ); 
2872             if (!HasFlag(wxFULL_REPAINT_ON_RESIZE
)) 
2874                 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event", 
2875                     GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this ); 
2878             // gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), !HasFlag( wxFULL_REPAINT_ON_RESIZE ) ); 
2883         // Create input method handler 
2884         m_imData 
= new wxGtkIMData
; 
2886         // Cannot handle drawing preedited text yet 
2887         gtk_im_context_set_use_preedit( m_imData
->context
, FALSE 
); 
2889         g_signal_connect (G_OBJECT (m_imData
->context
), "commit", 
2890                           G_CALLBACK (gtk_wxwindow_commit_cb
), this); 
2893         // these are called when the "sunken" or "raised" borders are drawn 
2894         gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event", 
2895           GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this ); 
2898         gtk_signal_connect( GTK_OBJECT(m_widget
), "draw", 
2899           GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this ); 
2905     if (m_focusWidget 
== NULL
) 
2906         m_focusWidget 
= m_widget
; 
2908     gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event", 
2909         GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this ); 
2911     gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event", 
2912          GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this ); 
2914     // connect to the various key and mouse handlers 
2916     GtkWidget 
*connect_widget 
= GetConnectWidget(); 
2918     ConnectWidget( connect_widget 
); 
2920     /* We cannot set colours, fonts and cursors before the widget has 
2921        been realized, so we do this directly after realization */ 
2922     gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize", 
2923                             GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this ); 
2927         // Catch native resize events 
2928         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate", 
2929                             GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this ); 
2931         // Initialize XIM support 
2932         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize", 
2933                             GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this ); 
2935         // And resize XIM window 
2936         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate", 
2937                             GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this ); 
2940     if ( !GTK_IS_COMBO(m_widget
)) 
2942         // This is needed if we want to add our windows into native 
2943         // GTK control, such as the toolbar. With this callback, the 
2944         // toolbar gets to know the correct size (the one set by the 
2945         // programmer). Sadly, it misbehaves for wxComboBox. FIXME 
2946         // when moving to GTK 2.0. 
2947         gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request", 
2948                             GTK_SIGNAL_FUNC(wxgtk_window_size_request_callback
), 
2952     InheritAttributes(); 
2956     // unless the window was created initially hidden (i.e. Hide() had been 
2957     // called before Create()), we should show it at GTK+ level as well 
2959         gtk_widget_show( m_widget 
); 
2962 void wxWindowGTK::ConnectWidget( GtkWidget 
*widget 
) 
2964     gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event", 
2965       GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this ); 
2967     gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event", 
2968       GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this ); 
2970     gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event", 
2971       GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this ); 
2973     gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event", 
2974       GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this ); 
2976     gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event", 
2977       GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this ); 
2980     gtk_signal_connect( GTK_OBJECT(widget
), "scroll_event", 
2981       GTK_SIGNAL_FUNC(gtk_window_wheel_callback
), (gpointer
)this ); 
2984     gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event", 
2985       GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this ); 
2987     gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event", 
2988       GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this ); 
2991 bool wxWindowGTK::Destroy() 
2993     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2997     return wxWindowBase::Destroy(); 
3000 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
) 
3002     gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height 
); 
3005 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
3007     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3008     wxASSERT_MSG( (m_parent 
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") ); 
3011     printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height ); 
3014     if (m_resizing
) return; /* I don't like recursions */ 
3017     int currentX
, currentY
; 
3018     GetPosition(¤tX
, ¤tY
); 
3019     if (x 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
3021     if (y 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
3023     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
3025     if (m_parent
->m_wxwindow 
== NULL
) /* i.e. wxNotebook */ 
3027         /* don't set the size for children of wxNotebook, just take the values. */ 
3035         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
3036         if ((sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) == 0) 
3038             if (x 
!= -1) m_x 
= x 
+ pizza
->xoffset
; 
3039             if (y 
!= -1) m_y 
= y 
+ pizza
->yoffset
; 
3043             m_x 
= x 
+ pizza
->xoffset
; 
3044             m_y 
= y 
+ pizza
->yoffset
; 
3047         // calculate the best size if we should auto size the window 
3048         if ( ((sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1) || 
3049                 ((sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1) ) 
3051             const wxSize sizeBest 
= GetBestSize(); 
3052             if ( (sizeFlags 
& wxSIZE_AUTO_WIDTH
) && width 
== -1 ) 
3054             if ( (sizeFlags 
& wxSIZE_AUTO_HEIGHT
) && height 
== -1 ) 
3055                 height 
= sizeBest
.y
; 
3063         int minWidth 
= GetMinWidth(), 
3064             minHeight 
= GetMinHeight(), 
3065             maxWidth 
= GetMaxWidth(), 
3066             maxHeight 
= GetMaxHeight(); 
3068         if ((minWidth 
!= -1) && (m_width 
< minWidth
)) m_width 
= minWidth
; 
3069         if ((minHeight 
!= -1) && (m_height 
< minHeight
)) m_height 
= minHeight
; 
3070         if ((maxWidth 
!= -1) && (m_width 
> maxWidth
)) m_width 
= maxWidth
; 
3071         if ((maxHeight 
!= -1) && (m_height 
> maxHeight
)) m_height 
= maxHeight
; 
3074         int bottom_border 
= 0; 
3077         if (GTK_WIDGET_CAN_DEFAULT(m_widget
)) 
3079             /* the default button has a border around it */ 
3085         DoMoveWindow( m_x
-border
, 
3088                       m_height
+border
+bottom_border 
); 
3093         /* Sometimes the client area changes size without the 
3094            whole windows's size changing, but if the whole 
3095            windows's size doesn't change, no wxSizeEvent will 
3096            normally be sent. Here we add an extra test if 
3097            the client test has been changed and this will 
3099         GetClientSize( &m_oldClientWidth
, &m_oldClientHeight 
); 
3103     wxPrintf( "OnSize sent from " ); 
3104     if (GetClassInfo() && GetClassInfo()->GetClassName()) 
3105         wxPrintf( GetClassInfo()->GetClassName() ); 
3106     wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height ); 
3109     if (!m_nativeSizeEvent
) 
3111         wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
3112         event
.SetEventObject( this ); 
3113         GetEventHandler()->ProcessEvent( event 
); 
3119 void wxWindowGTK::OnInternalIdle() 
3122     if ( m_dirtyTabOrder 
) 
3125     // Update style if the window was not yet realized 
3126     // and SetBackgroundStyle(wxBG_STYLE_CUSTOM) was called 
3127     if (m_needsStyleChange
) 
3129         SetBackgroundStyle(GetBackgroundStyle()); 
3130         m_needsStyleChange 
= false; 
3133     // Update invalidated regions. 
3136     // Synthetize activate events. 
3137     if ( g_sendActivateEvent 
!= -1 ) 
3139         bool activate 
= g_sendActivateEvent 
!= 0; 
3142         g_sendActivateEvent 
= -1; 
3144         wxTheApp
->SetActive(activate
, (wxWindow 
*)g_focusWindowLast
); 
3147     if ( g_activeFrameLostFocus 
) 
3149         if ( g_activeFrame 
) 
3151             wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
); 
3152             wxActivateEvent 
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId()); 
3153             event
.SetEventObject(g_activeFrame
); 
3154             g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
3155             g_activeFrame 
= NULL
; 
3157         g_activeFrameLostFocus 
= FALSE
; 
3160     wxCursor cursor 
= m_cursor
; 
3161     if (g_globalCursor
.Ok()) cursor 
= g_globalCursor
; 
3165         /* I now set the cursor anew in every OnInternalIdle call 
3166            as setting the cursor in a parent window also effects the 
3167            windows above so that checking for the current cursor is 
3172             GdkWindow 
*window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3174                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3176             if (!g_globalCursor
.Ok()) 
3177                 cursor 
= *wxSTANDARD_CURSOR
; 
3179             window 
= m_widget
->window
; 
3180             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
3181                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3187             GdkWindow 
*window 
= m_widget
->window
; 
3188             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
3189                gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
3194     if (wxUpdateUIEvent::CanUpdate(this)) 
3195         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
3198 void wxWindowGTK::DoGetSize( int *width
, int *height 
) const 
3200     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3202     if (width
) (*width
) = m_width
; 
3203     if (height
) (*height
) = m_height
; 
3206 void wxWindowGTK::DoSetClientSize( int width
, int height 
) 
3208     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3212         SetSize( width
, height 
); 
3219 #ifndef __WXUNIVERSAL__ 
3220         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
3222             /* when using GTK 1.2 we set the shadow border size to 2 */ 
3226         if (HasFlag(wxSIMPLE_BORDER
)) 
3228             /* when using GTK 1.2 we set the simple border size to 1 */ 
3232 #endif // __WXUNIVERSAL__ 
3236             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
3238             GtkRequisition vscroll_req
; 
3239             vscroll_req
.width 
= 2; 
3240             vscroll_req
.height 
= 2; 
3241             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
3242                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
3244             GtkRequisition hscroll_req
; 
3245             hscroll_req
.width 
= 2; 
3246             hscroll_req
.height 
= 2; 
3247             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
3248                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
3250             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
3252             if (scroll_window
->vscrollbar_visible
) 
3254                 dw 
+= vscroll_req
.width
; 
3255                 dw 
+= scroll_class
->scrollbar_spacing
; 
3258             if (scroll_window
->hscrollbar_visible
) 
3260                 dh 
+= hscroll_req
.height
; 
3261                 dh 
+= scroll_class
->scrollbar_spacing
; 
3265        SetSize( width
+dw
, height
+dh 
); 
3269 void wxWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
3271     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3275         if (width
) (*width
) = m_width
; 
3276         if (height
) (*height
) = m_height
; 
3283 #ifndef __WXUNIVERSAL__ 
3284         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
3286             /* when using GTK 1.2 we set the shadow border size to 2 */ 
3290         if (HasFlag(wxSIMPLE_BORDER
)) 
3292             /* when using GTK 1.2 we set the simple border size to 1 */ 
3296 #endif // __WXUNIVERSAL__ 
3300             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
3302             GtkRequisition vscroll_req
; 
3303             vscroll_req
.width 
= 2; 
3304             vscroll_req
.height 
= 2; 
3305             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
3306                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
3308             GtkRequisition hscroll_req
; 
3309             hscroll_req
.width 
= 2; 
3310             hscroll_req
.height 
= 2; 
3311             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
3312                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
3314             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
3316             if (scroll_window
->vscrollbar_visible
) 
3318                 dw 
+= vscroll_req
.width
; 
3319                 dw 
+= scroll_class
->scrollbar_spacing
; 
3322             if (scroll_window
->hscrollbar_visible
) 
3324                 dh 
+= hscroll_req
.height
; 
3325                 dh 
+= scroll_class
->scrollbar_spacing
; 
3329         if (width
) (*width
) = m_width 
- dw
; 
3330         if (height
) (*height
) = m_height 
- dh
; 
3334     printf( "GetClientSize, name %s ", GetName().c_str() ); 
3335     if (width) printf( " width = %d", (*width) ); 
3336     if (height) printf( " height = %d", (*height) ); 
3341 void wxWindowGTK::DoGetPosition( int *x
, int *y 
) const 
3343     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3347     if (m_parent 
&& m_parent
->m_wxwindow
) 
3349         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
3350         dx 
= pizza
->xoffset
; 
3351         dy 
= pizza
->yoffset
; 
3354     if (x
) (*x
) = m_x 
- dx
; 
3355     if (y
) (*y
) = m_y 
- dy
; 
3358 void wxWindowGTK::DoClientToScreen( int *x
, int *y 
) const 
3360     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3362     if (!m_widget
->window
) return; 
3364     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3366         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3368         source 
= m_widget
->window
; 
3372     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3376         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3378             org_x 
+= m_widget
->allocation
.x
; 
3379             org_y 
+= m_widget
->allocation
.y
; 
3387 void wxWindowGTK::DoScreenToClient( int *x
, int *y 
) const 
3389     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3391     if (!m_widget
->window
) return; 
3393     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3395         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3397         source 
= m_widget
->window
; 
3401     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3405         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3407             org_x 
+= m_widget
->allocation
.x
; 
3408             org_y 
+= m_widget
->allocation
.y
; 
3416 bool wxWindowGTK::Show( bool show 
) 
3418     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3420     if (!wxWindowBase::Show(show
)) 
3427         gtk_widget_show( m_widget 
); 
3429         gtk_widget_hide( m_widget 
); 
3431     wxShowEvent 
eventShow(GetId(), show
); 
3432     eventShow
.m_eventObject 
= this; 
3434     GetEventHandler()->ProcessEvent(eventShow
); 
3439 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
) 
3441     win
->OnParentEnable(enable
); 
3443     // Recurse, so that children have the opportunity to Do The Right Thing 
3444     // and reset colours that have been messed up by a parent's (really ancestor's) 
3446     for ( wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
3448           node 
= node
->GetNext() ) 
3450         wxWindow 
*child 
= node
->GetData(); 
3451         if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
))) 
3452             wxWindowNotifyEnable(child
, enable
); 
3456 bool wxWindowGTK::Enable( bool enable 
) 
3458     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3460     if (!wxWindowBase::Enable(enable
)) 
3466     gtk_widget_set_sensitive( m_widget
, enable 
); 
3468         gtk_widget_set_sensitive( m_wxwindow
, enable 
); 
3470     wxWindowNotifyEnable(this, enable
); 
3475 int wxWindowGTK::GetCharHeight() const 
3477     wxCHECK_MSG( (m_widget 
!= NULL
), 12, wxT("invalid window") ); 
3479     wxFont font 
= GetFont(); 
3480     wxCHECK_MSG( font
.Ok(), 12, wxT("invalid font") ); 
3483     PangoContext 
*context 
= NULL
; 
3485         context 
= gtk_widget_get_pango_context( m_widget 
); 
3490     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
3491     PangoLayout 
*layout 
= pango_layout_new(context
); 
3492     pango_layout_set_font_description(layout
, desc
); 
3493     pango_layout_set_text(layout
, "H", 1); 
3494     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
3496     PangoRectangle rect
; 
3497     pango_layout_line_get_extents(line
, NULL
, &rect
); 
3499     g_object_unref( G_OBJECT( layout 
) ); 
3501     return (int) PANGO_PIXELS(rect
.height
); 
3503     GdkFont 
*gfont 
= font
.GetInternalFont( 1.0 ); 
3505     return gfont
->ascent 
+ gfont
->descent
; 
3509 int wxWindowGTK::GetCharWidth() const 
3511     wxCHECK_MSG( (m_widget 
!= NULL
), 8, wxT("invalid window") ); 
3513     wxFont font 
= GetFont(); 
3514     wxCHECK_MSG( font
.Ok(), 8, wxT("invalid font") ); 
3517     PangoContext 
*context 
= NULL
; 
3519         context 
= gtk_widget_get_pango_context( m_widget 
); 
3524     PangoFontDescription 
*desc 
= font
.GetNativeFontInfo()->description
; 
3525     PangoLayout 
*layout 
= pango_layout_new(context
); 
3526     pango_layout_set_font_description(layout
, desc
); 
3527     pango_layout_set_text(layout
, "g", 1); 
3528     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
3530     PangoRectangle rect
; 
3531     pango_layout_line_get_extents(line
, NULL
, &rect
); 
3533     g_object_unref( G_OBJECT( layout 
) ); 
3535     return (int) PANGO_PIXELS(rect
.width
); 
3537     GdkFont 
*gfont 
= font
.GetInternalFont( 1.0 ); 
3539     return gdk_string_width( gfont
, "g" ); 
3543 void wxWindowGTK::GetTextExtent( const wxString
& string
, 
3547                               int *externalLeading
, 
3548                               const wxFont 
*theFont 
) const 
3550     wxFont fontToUse 
= theFont 
? *theFont 
: GetFont(); 
3552     wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") ); 
3554     if (string
.IsEmpty()) 
3562     PangoContext 
*context 
= NULL
; 
3564         context 
= gtk_widget_get_pango_context( m_widget 
); 
3573     PangoFontDescription 
*desc 
= fontToUse
.GetNativeFontInfo()->description
; 
3574     PangoLayout 
*layout 
= pango_layout_new(context
); 
3575     pango_layout_set_font_description(layout
, desc
); 
3578         const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( string 
); 
3579         pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data 
)); 
3581         const wxWCharBuffer wdata 
= wxConvLocal
.cMB2WC( string 
); 
3582         const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( wdata 
); 
3583         pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data 
)); 
3587     PangoRectangle rect
; 
3588     pango_layout_get_extents(layout
, NULL
, &rect
); 
3590     if (x
) (*x
) = (wxCoord
) PANGO_PIXELS(rect
.width
); 
3591     if (y
) (*y
) = (wxCoord
) PANGO_PIXELS(rect
.height
); 
3594         PangoLayoutIter 
*iter 
= pango_layout_get_iter(layout
); 
3595         int baseline 
= pango_layout_iter_get_baseline(iter
); 
3596         pango_layout_iter_free(iter
); 
3597         *descent 
= *y 
- PANGO_PIXELS(baseline
); 
3599     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3601     g_object_unref( G_OBJECT( layout 
) ); 
3603     GdkFont 
*font 
= fontToUse
.GetInternalFont( 1.0 ); 
3604     if (x
) (*x
) = gdk_string_width( font
, wxGTK_CONV( string 
) ); 
3605     if (y
) (*y
) = font
->ascent 
+ font
->descent
; 
3606     if (descent
) (*descent
) = font
->descent
; 
3607     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3611 void wxWindowGTK::SetFocus() 
3613     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3616         // don't do anything if we already have focus 
3622         if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
)) 
3624             gtk_widget_grab_focus (m_wxwindow
); 
3629         if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) ) 
3631             if (!GTK_WIDGET_REALIZED(m_widget
)) 
3633                 // we can't set the focus to the widget now so we remember that 
3634                 // it should be focused and will do it later, during the idle 
3635                 // time, as soon as we can 
3636                 wxLogTrace(TRACE_FOCUS
, 
3637                            _T("Delaying setting focus to %s(%s)"), 
3638                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3640                 g_delayedFocus 
= this; 
3644                 wxLogTrace(TRACE_FOCUS
, 
3645                            _T("Setting focus to %s(%s)"), 
3646                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3648                 gtk_widget_grab_focus (m_widget
); 
3651         else if (GTK_IS_CONTAINER(m_widget
)) 
3653             SET_CONTAINER_FOCUS( m_widget
, GTK_DIR_TAB_FORWARD 
); 
3657            wxLogTrace(TRACE_FOCUS
, 
3658                       _T("Can't set focus to %s(%s)"), 
3659                       GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3664 bool wxWindowGTK::AcceptsFocus() const 
3666     return m_acceptsFocus 
&& wxWindowBase::AcceptsFocus(); 
3669 bool wxWindowGTK::Reparent( wxWindowBase 
*newParentBase 
) 
3671     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3673     wxWindowGTK 
*oldParent 
= m_parent
, 
3674              *newParent 
= (wxWindowGTK 
*)newParentBase
; 
3676     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3678     if ( !wxWindowBase::Reparent(newParent
) ) 
3681     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3683     /* prevent GTK from deleting the widget arbitrarily */ 
3684     gtk_widget_ref( m_widget 
); 
3688         gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget 
); 
3691     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3695         /* insert GTK representation */ 
3696         (*(newParent
->m_insertCallback
))(newParent
, this); 
3699     /* reverse: prevent GTK from deleting the widget arbitrarily */ 
3700     gtk_widget_unref( m_widget 
); 
3705 void wxWindowGTK::DoAddChild(wxWindowGTK 
*child
) 
3707     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3709     wxASSERT_MSG( (child 
!= NULL
), wxT("invalid child window") ); 
3711     wxASSERT_MSG( (m_insertCallback 
!= NULL
), wxT("invalid child insertion function") ); 
3716     /* insert GTK representation */ 
3717     (*m_insertCallback
)(this, child
); 
3722 void wxWindowGTK::AddChild(wxWindowBase 
*child
) 
3724     wxWindowBase::AddChild(child
); 
3725     m_dirtyTabOrder 
= true; 
3727         wxapp_install_idle_handler(); 
3730 void wxWindowGTK::RemoveChild(wxWindowBase 
*child
) 
3732     wxWindowBase::RemoveChild(child
); 
3733     m_dirtyTabOrder 
= true; 
3735         wxapp_install_idle_handler(); 
3738 void wxWindowGTK::DoMoveInTabOrder(wxWindow 
*win
, MoveKind move
) 
3740     wxWindowBase::DoMoveInTabOrder(win
, move
); 
3741     m_dirtyTabOrder 
= true; 
3743         wxapp_install_idle_handler(); 
3746 void wxWindowGTK::RealizeTabOrder() 
3750         if (m_children
.size() > 0) 
3752             GList 
*chain 
= NULL
; 
3754             for (wxWindowList::const_iterator i 
= m_children
.begin(); 
3755                     i 
!= m_children
.end(); ++i
) 
3757                 chain 
= g_list_prepend(chain
, (*i
)->m_widget
); 
3760             chain 
= g_list_reverse(chain
); 
3762             gtk_container_set_focus_chain(GTK_CONTAINER(m_wxwindow
), chain
); 
3767             gtk_container_unset_focus_chain(GTK_CONTAINER(m_wxwindow
)); 
3771     m_dirtyTabOrder 
= false; 
3774 #endif // __WXGTK20__ 
3776 void wxWindowGTK::Raise() 
3778     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3780     if (!m_widget
->window
) return; 
3782     gdk_window_raise( m_widget
->window 
); 
3785 void wxWindowGTK::Lower() 
3787     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3789     if (!m_widget
->window
) return; 
3791     gdk_window_lower( m_widget
->window 
); 
3794 bool wxWindowGTK::SetCursor( const wxCursor 
&cursor 
) 
3796     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3798     if (cursor 
== m_cursor
) 
3802         wxapp_install_idle_handler(); 
3804     if (cursor 
== wxNullCursor
) 
3805        return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR 
); 
3807        return wxWindowBase::SetCursor( cursor 
); 
3810 void wxWindowGTK::WarpPointer( int x
, int y 
) 
3812     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3814     // We provide this function ourselves as it is 
3815     // missing in GDK (top of this file). 
3817     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3819         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3821         window 
= GetConnectWidget()->window
; 
3824         gdk_window_warp_pointer( window
, x
, y 
); 
3828 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect 
*rect 
) 
3830     if (!m_widget
) return; 
3831     if (!m_widget
->window
) return; 
3835         wxapp_install_idle_handler(); 
3837     wxRect 
myRect(0,0,0,0); 
3838     if (m_wxwindow 
&& rect
) 
3840         myRect
.SetSize(wxSize( m_wxwindow
->allocation
.width
, 
3841                                m_wxwindow
->allocation
.height
)); 
3842         myRect
.Intersect(*rect
); 
3843         if (!myRect
.width 
|| !myRect
.height
) 
3844             // nothing to do, rectangle is empty 
3849     if (eraseBackground 
&& m_wxwindow 
&& m_wxwindow
->window
) 
3853             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3854             m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3858             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3859             m_clearRegion
.Clear(); 
3860             m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3868             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3869             m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3873             GdkRectangle gdk_rect
; 
3874             gdk_rect
.x 
= rect
->x
; 
3875             gdk_rect
.y 
= rect
->y
; 
3876             gdk_rect
.width 
= rect
->width
; 
3877             gdk_rect
.height 
= rect
->height
; 
3878             gtk_widget_draw( m_widget
, &gdk_rect 
); 
3885             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3886             m_updateRegion
.Clear(); 
3887             m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3891             gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL 
); 
3899             GdkRectangle gdk_rect
; 
3900             gdk_rect
.x 
= rect
->x
; 
3901             gdk_rect
.y 
= rect
->y
; 
3902             gdk_rect
.width 
= rect
->width
; 
3903             gdk_rect
.height 
= rect
->height
; 
3904             gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, &gdk_rect
, TRUE 
); 
3908             gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, NULL
, TRUE 
); 
3914 void wxWindowGTK::Update() 
3919 void wxWindowGTK::GtkUpdate() 
3922     if (m_wxwindow 
&& GTK_PIZZA(m_wxwindow
)->bin_window
) 
3923         gdk_window_process_updates( GTK_PIZZA(m_wxwindow
)->bin_window
, FALSE 
); 
3925     if (!m_updateRegion
.IsEmpty()) 
3926         GtkSendPaintEvents(); 
3930 void wxWindowGTK::GtkSendPaintEvents() 
3935         m_clearRegion
.Clear(); 
3937         m_updateRegion
.Clear(); 
3941     // Clip to paint region in wxClientDC 
3942     m_clipPaintRegion 
= TRUE
; 
3944     // widget to draw on 
3945     GtkPizza 
*pizza 
= GTK_PIZZA (m_wxwindow
); 
3947     if (GetThemeEnabled() && GetBackgroundStyle() == wxBG_STYLE_SYSTEM
) 
3949         // find ancestor from which to steal background 
3950         wxWindow 
*parent 
= GetParent(); 
3951         while (parent 
&& !parent
->IsTopLevel()) 
3952             parent 
= parent
->GetParent(); 
3954             parent 
= (wxWindow
*)this; 
3956         wxRegionIterator 
upd( m_updateRegion 
); 
3960             rect
.x 
= upd
.GetX(); 
3961             rect
.y 
= upd
.GetY(); 
3962             rect
.width 
= upd
.GetWidth(); 
3963             rect
.height 
= upd
.GetHeight(); 
3965             gtk_paint_flat_box( parent
->m_widget
->style
, 
3967                         (GtkStateType
)GTK_WIDGET_STATE(m_wxwindow
), 
3981         wxWindowDC 
dc( (wxWindow
*)this ); 
3982         dc
.SetClippingRegion( m_updateRegion 
); 
3984         wxEraseEvent 
erase_event( GetId(), &dc 
); 
3985         erase_event
.SetEventObject( this ); 
3987         GetEventHandler()->ProcessEvent(erase_event
); 
3990     // if (!m_clearRegion.IsEmpty())   // Always send an erase event under GTK 1.2 
3992         wxWindowDC 
dc( (wxWindow
*)this ); 
3993         if (m_clearRegion
.IsEmpty()) 
3994             dc
.SetClippingRegion( m_updateRegion 
); 
3996             dc
.SetClippingRegion( m_clearRegion 
); 
3998         wxEraseEvent 
erase_event( GetId(), &dc 
); 
3999         erase_event
.SetEventObject( this ); 
4001         if (!GetEventHandler()->ProcessEvent(erase_event
) && GetBackgroundStyle() != wxBG_STYLE_CUSTOM
) 
4005                 g_eraseGC 
= gdk_gc_new( pizza
->bin_window 
); 
4006                 gdk_gc_set_fill( g_eraseGC
, GDK_SOLID 
); 
4008             gdk_gc_set_foreground( g_eraseGC
, GetBackgroundColour().GetColor() ); 
4010             wxRegionIterator 
upd( m_clearRegion 
); 
4013                 gdk_draw_rectangle( pizza
->bin_window
, g_eraseGC
, 1, 
4014                                     upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() ); 
4018         m_clearRegion
.Clear(); 
4022     wxNcPaintEvent 
nc_paint_event( GetId() ); 
4023     nc_paint_event
.SetEventObject( this ); 
4024     GetEventHandler()->ProcessEvent( nc_paint_event 
); 
4026     wxPaintEvent 
paint_event( GetId() ); 
4027     paint_event
.SetEventObject( this ); 
4028     GetEventHandler()->ProcessEvent( paint_event 
); 
4030     m_clipPaintRegion 
= FALSE
; 
4032 #ifndef __WXUNIVERSAL__ 
4034     // The following code will result in all window-less widgets 
4035     // being redrawn because the wxWidgets class is allowed to 
4036     // paint over the window-less widgets. 
4038     GList 
*children 
= pizza
->children
; 
4041         GtkPizzaChild 
*child 
= (GtkPizzaChild
*) children
->data
; 
4042         children 
= children
->next
; 
4044         if (GTK_WIDGET_NO_WINDOW (child
->widget
) && 
4045             GTK_WIDGET_DRAWABLE (child
->widget
)) 
4047             // Get intersection of widget area and update region 
4048             wxRegion 
region( m_updateRegion 
); 
4050             GdkEventExpose gdk_event
; 
4051             gdk_event
.type 
= GDK_EXPOSE
; 
4052             gdk_event
.window 
= pizza
->bin_window
; 
4053             gdk_event
.count 
= 0; 
4055             wxRegionIterator 
upd( m_updateRegion 
); 
4059                 rect
.x 
= upd
.GetX(); 
4060                 rect
.y 
= upd
.GetY(); 
4061                 rect
.width 
= upd
.GetWidth(); 
4062                 rect
.height 
= upd
.GetHeight(); 
4064                 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
)) 
4066                     gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
); 
4076     m_updateRegion
.Clear(); 
4079 void wxWindowGTK::ClearBackground() 
4081     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4084     if (m_wxwindow 
&& m_wxwindow
->window
) 
4086         m_clearRegion
.Clear(); 
4087         wxSize 
size( GetClientSize() ); 
4088         m_clearRegion
.Union( 0,0,size
.x
,size
.y 
); 
4090         // Better do this in idle? 
4097 void wxWindowGTK::DoSetToolTip( wxToolTip 
*tip 
) 
4099     wxWindowBase::DoSetToolTip(tip
); 
4102         m_tooltip
->Apply( (wxWindow 
*)this ); 
4105 void wxWindowGTK::ApplyToolTip( GtkTooltips 
*tips
, const wxChar 
*tip 
) 
4107     wxString 
tmp( tip 
); 
4108     gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxGTK_CONV(tmp
), (gchar
*) NULL 
); 
4110 #endif // wxUSE_TOOLTIPS 
4112 bool wxWindowGTK::SetBackgroundColour( const wxColour 
&colour 
) 
4114     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
4116     if (!wxWindowBase::SetBackgroundColour(colour
)) 
4121         // We need the pixel value e.g. for background clearing. 
4122         m_backgroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
4125     // apply style change (forceStyle=true so that new style is applied 
4126     // even if the bg colour changed from valid to wxNullColour) 
4127     if (GetBackgroundStyle() != wxBG_STYLE_CUSTOM
) 
4128         ApplyWidgetStyle(true); 
4133 bool wxWindowGTK::SetForegroundColour( const wxColour 
&colour 
) 
4135     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
4137     if (!wxWindowBase::SetForegroundColour(colour
)) 
4144         // We need the pixel value e.g. for background clearing. 
4145         m_foregroundColour
.CalcPixel(gtk_widget_get_colormap(m_widget
)); 
4148     // apply style change (forceStyle=true so that new style is applied 
4149     // even if the bg colour changed from valid to wxNullColour): 
4150     ApplyWidgetStyle(true); 
4156 PangoContext 
*wxWindowGTK::GtkGetPangoDefaultContext() 
4158     return gtk_widget_get_pango_context( m_widget 
); 
4161 PangoContext 
*wxWindowGTK::GtkGetPangoX11Context() 
4164         m_x11Context 
= pango_x_get_context( gdk_display 
); 
4166     return m_x11Context
; 
4170 GtkRcStyle 
*wxWindowGTK::CreateWidgetStyle(bool forceStyle
) 
4172     // do we need to apply any changes at all? 
4175          !m_foregroundColour
.Ok() && !m_backgroundColour
.Ok() ) 
4180     GtkRcStyle 
*style 
= gtk_rc_style_new(); 
4186             pango_font_description_copy( m_font
.GetNativeFontInfo()->description 
); 
4188         wxString xfontname 
= m_font
.GetNativeFontInfo()->GetXFontName(); 
4189         style
->fontset_name 
= g_strdup(xfontname
.c_str()); 
4193     if ( m_foregroundColour
.Ok() ) 
4195         GdkColor 
*fg 
= m_foregroundColour
.GetColor(); 
4197         style
->fg
[GTK_STATE_NORMAL
] = *fg
; 
4198         style
->color_flags
[GTK_STATE_NORMAL
] = GTK_RC_FG
; 
4200         style
->fg
[GTK_STATE_PRELIGHT
] = *fg
; 
4201         style
->color_flags
[GTK_STATE_PRELIGHT
] = GTK_RC_FG
; 
4203         style
->fg
[GTK_STATE_ACTIVE
] = *fg
; 
4204         style
->color_flags
[GTK_STATE_ACTIVE
] = GTK_RC_FG
; 
4207     if ( m_backgroundColour
.Ok() ) 
4209         GdkColor 
*bg 
= m_backgroundColour
.GetColor(); 
4211         style
->bg
[GTK_STATE_NORMAL
] = *bg
; 
4212         style
->base
[GTK_STATE_NORMAL
] = *bg
; 
4213         style
->color_flags
[GTK_STATE_NORMAL
] = (GtkRcFlags
) 
4214             (style
->color_flags
[GTK_STATE_NORMAL
] | GTK_RC_BG 
| GTK_RC_BASE
); 
4216         style
->bg
[GTK_STATE_PRELIGHT
] = *bg
; 
4217         style
->base
[GTK_STATE_PRELIGHT
] = *bg
; 
4218         style
->color_flags
[GTK_STATE_PRELIGHT
] = (GtkRcFlags
) 
4219             (style
->color_flags
[GTK_STATE_PRELIGHT
] | GTK_RC_BG 
| GTK_RC_BASE
); 
4221         style
->bg
[GTK_STATE_ACTIVE
] = *bg
; 
4222         style
->base
[GTK_STATE_ACTIVE
] = *bg
; 
4223         style
->color_flags
[GTK_STATE_ACTIVE
] = (GtkRcFlags
) 
4224             (style
->color_flags
[GTK_STATE_ACTIVE
] | GTK_RC_BG 
| GTK_RC_BASE
); 
4226         style
->bg
[GTK_STATE_INSENSITIVE
] = *bg
; 
4227         style
->base
[GTK_STATE_INSENSITIVE
] = *bg
; 
4228         style
->color_flags
[GTK_STATE_INSENSITIVE
] = (GtkRcFlags
) 
4229             (style
->color_flags
[GTK_STATE_INSENSITIVE
] | GTK_RC_BG 
| GTK_RC_BASE
); 
4235 void wxWindowGTK::ApplyWidgetStyle(bool forceStyle
) 
4237     GtkRcStyle 
*style 
= CreateWidgetStyle(forceStyle
); 
4240         DoApplyWidgetStyle(style
); 
4241         gtk_rc_style_unref(style
); 
4244     // Style change may affect GTK+'s size calculation: 
4245     InvalidateBestSize(); 
4248 void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
4251         gtk_widget_modify_style(m_wxwindow
, style
); 
4252     gtk_widget_modify_style(m_widget
, style
); 
4255 bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style
) 
4257     wxWindowBase::SetBackgroundStyle(style
); 
4259     if (style 
== wxBG_STYLE_CUSTOM
) 
4261         GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4263             window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4265             window 
= GetConnectWidget()->window
; 
4269             // Make sure GDK/X11 doesn't refresh the window 
4271             gdk_window_set_back_pixmap( window
, None
, False 
); 
4273             Display
* display 
= GDK_WINDOW_DISPLAY(window
); 
4276             m_needsStyleChange 
= false; 
4279             // Do in OnIdle, because the window is not yet available 
4280             m_needsStyleChange 
= true; 
4282         // Don't apply widget style, or we get a grey background 
4286         // apply style change (forceStyle=true so that new style is applied 
4287         // even if the bg colour changed from valid to wxNullColour): 
4288         ApplyWidgetStyle(true); 
4293 //----------------------------------------------------------------------------- 
4294 // Pop-up menu stuff 
4295 //----------------------------------------------------------------------------- 
4297 #if wxUSE_MENUS_NATIVE 
4300 void gtk_pop_hide_callback( GtkWidget 
*WXUNUSED(widget
), bool* is_waiting  
) 
4302     *is_waiting 
= FALSE
; 
4305 static void SetInvokingWindow( wxMenu 
*menu
, wxWindowGTK 
*win 
) 
4307     menu
->SetInvokingWindow( win 
); 
4308     wxMenuItemList::compatibility_iterator node 
= menu
->GetMenuItems().GetFirst(); 
4311         wxMenuItem 
*menuitem 
= node
->GetData(); 
4312         if (menuitem
->IsSubMenu()) 
4314             SetInvokingWindow( menuitem
->GetSubMenu(), win 
); 
4317         node 
= node
->GetNext(); 
4321 extern "C" void wxPopupMenuPositionCallback( GtkMenu 
*menu
, 
4324                                              gboolean 
* WXUNUSED(whatever
), 
4326                                              gpointer user_data 
) 
4328     // ensure that the menu appears entirely on screen 
4330     gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
); 
4332     wxSize sizeScreen 
= wxGetDisplaySize(); 
4333     wxPoint 
*pos 
= (wxPoint
*)user_data
; 
4335     gint xmax 
= sizeScreen
.x 
- req
.width
, 
4336          ymax 
= sizeScreen
.y 
- req
.height
; 
4338     *x 
= pos
->x 
< xmax 
? pos
->x 
: xmax
; 
4339     *y 
= pos
->y 
< ymax 
? pos
->y 
: ymax
; 
4342 bool wxWindowGTK::DoPopupMenu( wxMenu 
*menu
, int x
, int y 
) 
4344     wxCHECK_MSG( m_widget 
!= NULL
, false, wxT("invalid window") ); 
4346     wxCHECK_MSG( menu 
!= NULL
, false, wxT("invalid popup-menu") ); 
4348     SetInvokingWindow( menu
, this ); 
4352     bool is_waiting 
= true; 
4354     gulong handler 
= gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), 
4356                                          GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), 
4357                                          (gpointer
)&is_waiting 
); 
4361     GtkMenuPositionFunc posfunc
; 
4362     if ( x 
== -1 && y 
== -1 ) 
4364         // use GTK's default positioning algorithm 
4370         pos 
= ClientToScreen(wxPoint(x
, y
)); 
4372         posfunc 
= wxPopupMenuPositionCallback
; 
4376                   GTK_MENU(menu
->m_menu
), 
4377                   (GtkWidget 
*) NULL
,           // parent menu shell 
4378                   (GtkWidget 
*) NULL
,           // parent menu item 
4379                   posfunc
,                      // function to position it 
4380                   userdata
,                     // client data 
4381                   0,                            // button used to activate it 
4383                   gtk_get_current_event_time() 
4385                   gs_timeLastClick              
// the time of activation 
4391         gtk_main_iteration(); 
4394     gtk_signal_disconnect(GTK_OBJECT(menu
->m_menu
), handler
); 
4399 #endif // wxUSE_MENUS_NATIVE 
4401 #if wxUSE_DRAG_AND_DROP 
4403 void wxWindowGTK::SetDropTarget( wxDropTarget 
*dropTarget 
) 
4405     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4407     GtkWidget 
*dnd_widget 
= GetConnectWidget(); 
4409     if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget 
); 
4411     if (m_dropTarget
) delete m_dropTarget
; 
4412     m_dropTarget 
= dropTarget
; 
4414     if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget 
); 
4417 #endif // wxUSE_DRAG_AND_DROP 
4419 GtkWidget
* wxWindowGTK::GetConnectWidget() 
4421     GtkWidget 
*connect_widget 
= m_widget
; 
4422     if (m_wxwindow
) connect_widget 
= m_wxwindow
; 
4424     return connect_widget
; 
4427 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow 
*window 
) 
4430         return (window 
== GTK_PIZZA(m_wxwindow
)->bin_window
); 
4432     return (window 
== m_widget
->window
); 
4435 bool wxWindowGTK::SetFont( const wxFont 
&font 
) 
4437     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
4439     if (!wxWindowBase::SetFont(font
)) 
4442     // apply style change (forceStyle=true so that new style is applied 
4443     // even if the font changed from valid to wxNullFont): 
4444     ApplyWidgetStyle(true);     
4449 void wxWindowGTK::DoCaptureMouse() 
4451     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4453     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4455         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4457         window 
= GetConnectWidget()->window
; 
4459     wxCHECK_RET( window
, _T("CaptureMouse() failed") ); 
4461     wxCursor
* cursor 
= & m_cursor
; 
4463         cursor 
= wxSTANDARD_CURSOR
; 
4465     gdk_pointer_grab( window
, FALSE
, 
4467                          (GDK_BUTTON_PRESS_MASK 
| 
4468                           GDK_BUTTON_RELEASE_MASK 
| 
4469                           GDK_POINTER_MOTION_HINT_MASK 
| 
4470                           GDK_POINTER_MOTION_MASK
), 
4472                       cursor
->GetCursor(), 
4473                       (guint32
)GDK_CURRENT_TIME 
); 
4474     g_captureWindow 
= this; 
4475     g_captureWindowHasMouse 
= TRUE
; 
4478 void wxWindowGTK::DoReleaseMouse() 
4480     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4482     wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") ); 
4484     g_captureWindow 
= (wxWindowGTK
*) NULL
; 
4486     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4488         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4490         window 
= GetConnectWidget()->window
; 
4495     gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME 
); 
4499 wxWindow 
*wxWindowBase::GetCapture() 
4501     return (wxWindow 
*)g_captureWindow
; 
4504 bool wxWindowGTK::IsRetained() const 
4509 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
, 
4510       int range
, bool refresh 
) 
4512     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4514     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4516     m_hasScrolling 
= TRUE
; 
4518     if (orient 
== wxHORIZONTAL
) 
4520         float fpos 
= (float)pos
; 
4521         float frange 
= (float)range
; 
4522         float fthumb 
= (float)thumbVisible
; 
4523         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4524         if (fpos 
< 0.0) fpos 
= 0.0; 
4526         if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) && 
4527             (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2)) 
4529             SetScrollPos( orient
, pos
, refresh 
); 
4533         m_oldHorizontalPos 
= fpos
; 
4535         m_hAdjust
->lower 
= 0.0; 
4536         m_hAdjust
->upper 
= frange
; 
4537         m_hAdjust
->value 
= fpos
; 
4538         m_hAdjust
->step_increment 
= 1.0; 
4539         m_hAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4540         m_hAdjust
->page_size 
= fthumb
; 
4544         float fpos 
= (float)pos
; 
4545         float frange 
= (float)range
; 
4546         float fthumb 
= (float)thumbVisible
; 
4547         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4548         if (fpos 
< 0.0) fpos 
= 0.0; 
4550         if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) && 
4551             (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2)) 
4553             SetScrollPos( orient
, pos
, refresh 
); 
4557         m_oldVerticalPos 
= fpos
; 
4559         m_vAdjust
->lower 
= 0.0; 
4560         m_vAdjust
->upper 
= frange
; 
4561         m_vAdjust
->value 
= fpos
; 
4562         m_vAdjust
->step_increment 
= 1.0; 
4563         m_vAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4564         m_vAdjust
->page_size 
= fthumb
; 
4567     if (orient 
== wxHORIZONTAL
) 
4568         gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
4570         gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
4573 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) ) 
4575     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4577     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4579     if (orient 
== wxHORIZONTAL
) 
4581         float fpos 
= (float)pos
; 
4582         if (fpos 
> m_hAdjust
->upper 
- m_hAdjust
->page_size
) fpos 
= m_hAdjust
->upper 
- m_hAdjust
->page_size
; 
4583         if (fpos 
< 0.0) fpos 
= 0.0; 
4584         m_oldHorizontalPos 
= fpos
; 
4586         if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return; 
4587         m_hAdjust
->value 
= fpos
; 
4591         float fpos 
= (float)pos
; 
4592         if (fpos 
> m_vAdjust
->upper 
- m_vAdjust
->page_size
) fpos 
= m_vAdjust
->upper 
- m_vAdjust
->page_size
; 
4593         if (fpos 
< 0.0) fpos 
= 0.0; 
4594         m_oldVerticalPos 
= fpos
; 
4596         if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return; 
4597         m_vAdjust
->value 
= fpos
; 
4600     if (m_wxwindow
->window
) 
4602         if (orient 
== wxHORIZONTAL
) 
4604             gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
), 
4605                 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
4607             gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" ); 
4609             gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
4610                 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
4614             gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
), 
4615                 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
4617             gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" ); 
4619             gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
4620                 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
4625 int wxWindowGTK::GetScrollThumb( int orient 
) const 
4627     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4629     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4631     if (orient 
== wxHORIZONTAL
) 
4632         return (int)(m_hAdjust
->page_size
+0.5); 
4634         return (int)(m_vAdjust
->page_size
+0.5); 
4637 int wxWindowGTK::GetScrollPos( int orient 
) const 
4639     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4641     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4643     if (orient 
== wxHORIZONTAL
) 
4644         return (int)(m_hAdjust
->value
+0.5); 
4646         return (int)(m_vAdjust
->value
+0.5); 
4649 int wxWindowGTK::GetScrollRange( int orient 
) const 
4651     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4653     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4655     if (orient 
== wxHORIZONTAL
) 
4656         return (int)(m_hAdjust
->upper
+0.5); 
4658         return (int)(m_vAdjust
->upper
+0.5); 
4661 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) ) 
4663     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4665     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4667     // No scrolling requested. 
4668     if ((dx 
== 0) && (dy 
== 0)) return; 
4671     if (!m_updateRegion
.IsEmpty()) 
4673         m_updateRegion
.Offset( dx
, dy 
); 
4677         GetClientSize( &cw
, &ch 
); 
4678         m_updateRegion
.Intersect( 0, 0, cw
, ch 
); 
4681     if (!m_clearRegion
.IsEmpty()) 
4683         m_clearRegion
.Offset( dx
, dy 
); 
4687         GetClientSize( &cw
, &ch 
); 
4688         m_clearRegion
.Intersect( 0, 0, cw
, ch 
); 
4692     m_clipPaintRegion 
= TRUE
; 
4694     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy 
); 
4696     m_clipPaintRegion 
= FALSE
; 
4700 // Find the wxWindow at the current mouse position, also returning the mouse 
4702 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
4704     pt 
= wxGetMousePosition(); 
4705     wxWindow
* found 
= wxFindWindowAtPoint(pt
); 
4709 // Get the current mouse position. 
4710 wxPoint 
wxGetMousePosition() 
4712   /* This crashes when used within wxHelpContext, 
4713      so we have to use the X-specific implementation below. 
4715     GdkModifierType *mask; 
4716     (void) gdk_window_get_pointer(NULL, &x, &y, mask); 
4718     return wxPoint(x, y); 
4722     GdkWindow
* windowAtPtr 
= gdk_window_at_pointer(& x
, & y
); 
4724     Display 
*display 
= windowAtPtr 
? GDK_WINDOW_XDISPLAY(windowAtPtr
) : GDK_DISPLAY(); 
4725     Window rootWindow 
= RootWindowOfScreen (DefaultScreenOfDisplay(display
)); 
4726     Window rootReturn
, childReturn
; 
4727     int rootX
, rootY
, winX
, winY
; 
4728     unsigned int maskReturn
; 
4730     XQueryPointer (display
, 
4734                    &rootX
, &rootY
, &winX
, &winY
, &maskReturn
); 
4735     return wxPoint(rootX
, rootY
); 
4739 // ---------------------------------------------------------------------------- 
4741 // ---------------------------------------------------------------------------- 
4743 class wxWinModule 
: public wxModule
 
4750     DECLARE_DYNAMIC_CLASS(wxWinModule
) 
4753 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
) 
4755 bool wxWinModule::OnInit() 
4757     // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() ); 
4758     // gdk_gc_set_fill( g_eraseGC, GDK_SOLID ); 
4763 void wxWinModule::OnExit() 
4766         gdk_gc_unref( g_eraseGC 
);