1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        gtk/window.cpp 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling, Julian Smart 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  12     #pragma implementation "window.h" 
  16 #define XWarpPointer XWARPPOINTER 
  20 #include "wx/window.h" 
  21 #include "wx/dcclient.h" 
  24 #include "wx/layout.h" 
  26 #include "wx/dialog.h" 
  27 #include "wx/msgdlg.h" 
  28 #include "wx/module.h" 
  30 #if wxUSE_DRAG_AND_DROP 
  35     #include "wx/tooltip.h" 
  43     #include "wx/textctrl.h" 
  47 #include "wx/statusbr.h" 
  49 #include "wx/settings.h" 
  51 #include "wx/fontutil.h" 
  54     #include "wx/thread.h" 
  60 #include "wx/gtk/private.h" 
  61 #include <gdk/gdkprivate.h> 
  62 #include <gdk/gdkkeysyms.h> 
  66 #include <gtk/gtkprivate.h> 
  68 #include "wx/gtk/win_gtk.h" 
  71     #define SET_CONTAINER_FOCUS(w, d) gtk_widget_child_focus((w), (d)) 
  73     #define SET_CONTAINER_FOCUS(w, d) gtk_container_focus(GTK_CONTAINER(w), (d)) 
  83 extern GtkContainerClass 
*pizza_parent_class
; 
  86 //----------------------------------------------------------------------------- 
  87 // documentation on internals 
  88 //----------------------------------------------------------------------------- 
  91    I have been asked several times about writing some documentation about 
  92    the GTK port of wxWindows, especially its internal structures. Obviously, 
  93    you cannot understand wxGTK without knowing a little about the GTK, but 
  94    some more information about what the wxWindow, which is the base class 
  95    for all other window classes, does seems required as well. 
  99    What does wxWindow do? It contains the common interface for the following 
 100    jobs of its descendants: 
 102    1) Define the rudimentary behaviour common to all window classes, such as 
 103    resizing, intercepting user input (so as to make it possible to use these 
 104    events for special purposes in a derived class), window names etc. 
 106    2) Provide the possibility to contain and manage children, if the derived 
 107    class is allowed to contain children, which holds true for those window 
 108    classes which do not display a native GTK widget. To name them, these 
 109    classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame- 
 110    work classes are a special case and are handled a bit differently from 
 111    the rest. The same holds true for the wxNotebook class. 
 113    3) Provide the possibility to draw into a client area of a window. This, 
 114    too, only holds true for classes that do not display a native GTK widget 
 117    4) Provide the entire mechanism for scrolling widgets. This actual inter- 
 118    face for this is usually in wxScrolledWindow, but the GTK implementation 
 121    5) A multitude of helper or extra methods for special purposes, such as 
 122    Drag'n'Drop, managing validators etc. 
 124    6) Display a border (sunken, raised, simple or none). 
 126    Normally one might expect, that one wxWindows window would always correspond 
 127    to one GTK widget. Under GTK, there is no such allround widget that has all 
 128    the functionality. Moreover, the GTK defines a client area as a different 
 129    widget from the actual widget you are handling. Last but not least some 
 130    special classes (e.g. wxFrame) handle different categories of widgets and 
 131    still have the possibility to draw something in the client area. 
 132    It was therefore required to write a special purpose GTK widget, that would 
 133    represent a client area in the sense of wxWindows capable to do the jobs 
 134    2), 3) and 4). I have written this class and it resides in win_gtk.c of 
 137    All windows must have a widget, with which they interact with other under- 
 138    lying GTK widgets. It is this widget, e.g. that has to be resized etc and 
 139    thw wxWindow class has a member variable called m_widget which holds a 
 140    pointer to this widget. When the window class represents a GTK native widget, 
 141    this is (in most cases) the only GTK widget the class manages. E.g. the 
 142    wxStatitText class handles only a GtkLabel widget a pointer to which you 
 143    can find in m_widget (defined in wxWindow) 
 145    When the class has a client area for drawing into and for containing children 
 146    it has to handle the client area widget (of the type GtkPizza, defined in 
 147    win_gtk.c), but there could be any number of widgets, handled by a class 
 148    The common rule for all windows is only, that the widget that interacts with 
 149    the rest of GTK must be referenced in m_widget and all other widgets must be 
 150    children of this widget on the GTK level. The top-most widget, which also 
 151    represents the client area, must be in the m_wxwindow field and must be of 
 154    As I said, the window classes that display a GTK native widget only have 
 155    one widget, so in the case of e.g. the wxButton class m_widget holds a 
 156    pointer to a GtkButton widget. But windows with client areas (for drawing 
 157    and children) have a m_widget field that is a pointer to a GtkScrolled- 
 158    Window and a m_wxwindow field that is pointer to a GtkPizza and this 
 159    one is (in the GTK sense) a child of the GtkScrolledWindow. 
 161    If the m_wxwindow field is set, then all input to this widget is inter- 
 162    cepted and sent to the wxWindows class. If not, all input to the widget 
 163    that gets pointed to by m_widget gets intercepted and sent to the class. 
 167    The design of scrolling in wxWindows is markedly different from that offered 
 168    by the GTK itself and therefore we cannot simply take it as it is. In GTK, 
 169    clicking on a scrollbar belonging to scrolled window will inevitably move 
 170    the window. In wxWindows, the scrollbar will only emit an event, send this 
 171    to (normally) a wxScrolledWindow and that class will call ScrollWindow() 
 172    which actually moves the window and its subchildren. Note that GtkPizza 
 173    memorizes how much it has been scrolled but that wxWindows forgets this 
 174    so that the two coordinates systems have to be kept in synch. This is done 
 175    in various places using the pizza->xoffset and pizza->yoffset values. 
 179    Singularily the most broken code in GTK is the code that is supposes to 
 180    inform subwindows (child windows) about new positions. Very often, duplicate 
 181    events are sent without changes in size or position, equally often no 
 182    events are sent at all (All this is due to a bug in the GtkContainer code 
 183    which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores 
 184    GTK's own system and it simply waits for size events for toplevel windows 
 185    and then iterates down the respective size events to all window. This has 
 186    the disadvantage, that windows might get size events before the GTK widget 
 187    actually has the reported size. This doesn't normally pose any problem, but 
 188    the OpenGl drawing routines rely on correct behaviour. Therefore, I have 
 189    added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas, 
 190    i.e. the wxGLCanvas will emit a size event, when (and not before) the X11 
 191    window that is used for OpenGl output really has that size (as reported by 
 196    If someone at some point of time feels the immense desire to have a look at, 
 197    change or attempt to optimse the Refresh() logic, this person will need an 
 198    intimate understanding of what a "draw" and what an "expose" events are and 
 199    what there are used for, in particular when used in connection with GTK's 
 200    own windowless widgets. Beware. 
 204    Cursors, too, have been a constant source of pleasure. The main difficulty 
 205    is that a GdkWindow inherits a cursor if the programmer sets a new cursor 
 206    for the parent. To prevent this from doing too much harm, I use idle time 
 207    to set the cursor over and over again, starting from the toplevel windows 
 208    and ending with the youngest generation (speaking of parent and child windows). 
 209    Also don't forget that cursors (like much else) are connected to GdkWindows, 
 210    not GtkWidgets and that the "window" field of a GtkWidget might very well 
 211    point to the GdkWindow of the parent widget (-> "window less widget") and 
 212    that the two obviously have very different meanings. 
 216 //----------------------------------------------------------------------------- 
 218 //----------------------------------------------------------------------------- 
 220 extern wxList     wxPendingDelete
; 
 221 extern bool       g_blockEventsOnDrag
; 
 222 extern bool       g_blockEventsOnScroll
; 
 223 extern wxCursor   g_globalCursor
; 
 225 static GdkGC 
*g_eraseGC 
= NULL
; 
 227 // mouse capture state: the window which has it and if the mouse is currently 
 229 static wxWindowGTK  
*g_captureWindow 
= (wxWindowGTK
*) NULL
; 
 230 static bool g_captureWindowHasMouse 
= FALSE
; 
 232 /* extern */ wxWindowGTK  
*g_focusWindow 
= (wxWindowGTK
*) NULL
; 
 234 // the last window which had the focus - this is normally never NULL (except 
 235 // if we never had focus at all) as even when g_focusWindow is NULL it still 
 236 // keeps its previous value 
 237 static wxWindowGTK 
*g_focusWindowLast 
= (wxWindowGTK
*) NULL
; 
 239 // the frame that is currently active (i.e. its child has focus). It is 
 240 // used to generate wxActivateEvents 
 241 static wxWindowGTK 
*g_activeFrame 
= (wxWindowGTK
*) NULL
; 
 242 static bool g_activeFrameLostFocus 
= FALSE
; 
 244 // If a window get the focus set but has not been realized 
 245 // yet, defer setting the focus to idle time. 
 246 wxWindowGTK 
*g_delayedFocus 
= (wxWindowGTK
*) NULL
; 
 248 // if we detect that the app has got/lost the focus, we set this variable to 
 249 // either TRUE or FALSE and an activate event will be sent during the next 
 250 // OnIdle() call and it is reset to -1: this value means that we shouldn't 
 251 // send any activate events at all 
 252 static int        g_sendActivateEvent 
= -1; 
 254 /* hack: we need something to pass to gtk_menu_popup, so we store the time of 
 255    the last click here */ 
 256 static guint32 gs_timeLastClick 
= 0; 
 258 extern bool g_mainThreadLocked
; 
 260 //----------------------------------------------------------------------------- 
 262 //----------------------------------------------------------------------------- 
 265 #define DISABLE_STYLE_IF_BROKEN_THEME 1 
 271 #   define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance"); 
 273 #   define DEBUG_MAIN_THREAD 
 276 #define DEBUG_MAIN_THREAD 
 279 // the trace mask used for the focus debugging messages 
 280 #define TRACE_FOCUS _T("focus") 
 282 //----------------------------------------------------------------------------- 
 283 // missing gdk functions 
 284 //----------------------------------------------------------------------------- 
 287 gdk_window_warp_pointer (GdkWindow      
*window
, 
 292   GdkWindowPrivate 
*priv
; 
 296     window 
= GDK_ROOT_PARENT(); 
 299   if (!GDK_WINDOW_DESTROYED(window
)) 
 301       XWarpPointer (GDK_WINDOW_XDISPLAY(window
), 
 302                     None
,              /* not source window -> move from anywhere */ 
 303                     GDK_WINDOW_XID(window
),  /* dest window */ 
 304                     0, 0, 0, 0,        /* not source window -> move from anywhere */ 
 308   priv 
= (GdkWindowPrivate
*) window
; 
 310   if (!priv
->destroyed
) 
 312       XWarpPointer (priv
->xdisplay
, 
 313                     None
,              /* not source window -> move from anywhere */ 
 314                     priv
->xwindow
,  /* dest window */ 
 315                     0, 0, 0, 0,        /* not source window -> move from anywhere */ 
 321 //----------------------------------------------------------------------------- 
 323 //----------------------------------------------------------------------------- 
 325 extern void wxapp_install_idle_handler(); 
 326 extern bool g_isIdle
; 
 328 //----------------------------------------------------------------------------- 
 329 // local code (see below) 
 330 //----------------------------------------------------------------------------- 
 332 // returns the child of win which currently has focus or NULL if not found 
 334 // Note: can't be static, needed by textctrl.cpp. 
 335 wxWindow 
*wxFindFocusedChild(wxWindowGTK 
*win
) 
 337     wxWindow 
*winFocus 
= wxWindowGTK::FindFocus(); 
 339         return (wxWindow 
*)NULL
; 
 341     if ( winFocus 
== win 
) 
 342         return (wxWindow 
*)win
; 
 344     for ( wxWindowList::Node 
*node 
= win
->GetChildren().GetFirst(); 
 346           node 
= node
->GetNext() ) 
 348         wxWindow 
*child 
= wxFindFocusedChild(node
->GetData()); 
 353     return (wxWindow 
*)NULL
; 
 356 static void draw_frame( GtkWidget 
*widget
, wxWindowGTK 
*win 
) 
 358     // wxUniversal widgets draw the borders and scrollbars themselves 
 359 #ifndef __WXUNIVERSAL__ 
 366     if (win
->m_hasScrolling
) 
 368         GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(widget
); 
 370         GtkRequisition vscroll_req
; 
 371         vscroll_req
.width 
= 2; 
 372         vscroll_req
.height 
= 2; 
 373         (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
 374             (scroll_window
->vscrollbar
, &vscroll_req 
); 
 376         GtkRequisition hscroll_req
; 
 377         hscroll_req
.width 
= 2; 
 378         hscroll_req
.height 
= 2; 
 379         (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
 380             (scroll_window
->hscrollbar
, &hscroll_req 
); 
 382         GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) ); 
 384         if (scroll_window
->vscrollbar_visible
) 
 386             dw 
+= vscroll_req
.width
; 
 387             dw 
+= scroll_class
->scrollbar_spacing
; 
 390         if (scroll_window
->hscrollbar_visible
) 
 392             dh 
+= hscroll_req
.height
; 
 393             dh 
+= scroll_class
->scrollbar_spacing
; 
 399     if (GTK_WIDGET_NO_WINDOW (widget
)) 
 401         dx 
+= widget
->allocation
.x
; 
 402         dy 
+= widget
->allocation
.y
; 
 405     if (win
->HasFlag(wxRAISED_BORDER
)) 
 407         gtk_draw_shadow( widget
->style
, 
 412                          widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh 
); 
 416     if (win
->HasFlag(wxSUNKEN_BORDER
)) 
 418         gtk_draw_shadow( widget
->style
, 
 423                          widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh 
); 
 427     if (win
->HasFlag(wxSIMPLE_BORDER
)) 
 430         gc 
= gdk_gc_new( widget
->window 
); 
 431         gdk_gc_set_foreground( gc
, &widget
->style
->black 
); 
 432         gdk_draw_rectangle( widget
->window
, gc
, FALSE
, 
 434                          widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 ); 
 438 #endif // __WXUNIVERSAL__ 
 441 //----------------------------------------------------------------------------- 
 442 // "expose_event" of m_widget 
 443 //----------------------------------------------------------------------------- 
 445 gint 
gtk_window_own_expose_callback( GtkWidget 
*widget
, GdkEventExpose 
*gdk_event
, wxWindowGTK 
*win 
) 
 447     if (gdk_event
->count 
> 0) return FALSE
; 
 449     draw_frame( widget
, win 
); 
 453     (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
); 
 459 //----------------------------------------------------------------------------- 
 460 // "draw" of m_widget 
 461 //----------------------------------------------------------------------------- 
 465 static void gtk_window_own_draw_callback( GtkWidget 
*widget
, GdkRectangle 
*WXUNUSED(rect
), wxWindowGTK 
*win 
) 
 467     draw_frame( widget
, win 
); 
 472 //----------------------------------------------------------------------------- 
 473 // "size_request" of m_widget 
 474 //----------------------------------------------------------------------------- 
 476 static void gtk_window_size_request_callback( GtkWidget 
*widget
, GtkRequisition 
*requisition
, wxWindow 
*win 
) 
 479     win
->GetSize( &w
, &h 
); 
 483     requisition
->height 
= h
; 
 484     requisition
->width 
= w
; 
 487 //----------------------------------------------------------------------------- 
 488 // "expose_event" of m_wxwindow 
 489 //----------------------------------------------------------------------------- 
 491 static int gtk_window_expose_callback( GtkWidget 
*widget
, 
 492                                        GdkEventExpose 
*gdk_event
, 
 498         wxapp_install_idle_handler(); 
 501     // This callback gets called in drawing-idle time under 
 502     // GTK 2.0, so we don't need to defer anything to idle 
 505     GtkPizza 
*pizza 
= GTK_PIZZA( widget 
); 
 506     if (gdk_event
->window 
!= pizza
->bin_window
) return FALSE
; 
 511         wxPrintf( wxT("OnExpose from ") ); 
 512         if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName()) 
 513             wxPrintf( win
->GetClassInfo()->GetClassName() ); 
 514         wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event
->area
.x
, 
 515                                          (int)gdk_event
->area
.y
, 
 516                                          (int)gdk_event
->area
.width
, 
 517                                          (int)gdk_event
->area
.height 
); 
 521     win
->GetUpdateRegion() = wxRegion( gdk_event
->region 
); 
 523     win
->GtkSendPaintEvents(); 
 525     // Let parent window draw window less widgets 
 526     (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
); 
 528     // This gets called immediately after an expose event 
 529     // under GTK 1.2 so we collect the calls and wait for 
 530     // the idle handler to pick things up. 
 532     win
->GetUpdateRegion().Union( gdk_event
->area
.x
, 
 534                                   gdk_event
->area
.width
, 
 535                                   gdk_event
->area
.height 
); 
 536     win
->m_clearRegion
.Union( gdk_event
->area
.x
, 
 538                                   gdk_event
->area
.width
, 
 539                                   gdk_event
->area
.height 
); 
 541     // Actual redrawing takes place in idle time. 
 548 //----------------------------------------------------------------------------- 
 549 // "event" of m_wxwindow 
 550 //----------------------------------------------------------------------------- 
 552 // GTK thinks it is clever and filters out a certain amount of "unneeded" 
 553 // expose events. We need them, of course, so we override the main event 
 554 // procedure in GtkWidget by giving our own handler for all system events. 
 555 // There, we look for expose events ourselves whereas all other events are 
 558 gint 
gtk_window_event_event_callback( GtkWidget 
*widget
, 
 559                                       GdkEventExpose 
*event
, 
 562     if (event
->type 
== GDK_EXPOSE
) 
 564         gint ret 
= gtk_window_expose_callback( widget
, event
, win 
); 
 571 //----------------------------------------------------------------------------- 
 572 // "draw" of m_wxwindow 
 573 //----------------------------------------------------------------------------- 
 577 // This callback is a complete replacement of the gtk_pizza_draw() function, 
 578 // which is disabled. 
 580 static void gtk_window_draw_callback( GtkWidget 
*widget
, 
 587         wxapp_install_idle_handler(); 
 589     // The wxNO_FULL_REPAINT_ON_RESIZE flag only works if 
 590     // there are no child windows. 
 591     if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) && 
 592         (win
->GetChildren().GetCount() == 0)) 
 600         wxPrintf( wxT("OnDraw from ") ); 
 601         if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName()) 
 602             wxPrintf( win
->GetClassInfo()->GetClassName() ); 
 603         wxPrintf( wxT(" %d %d %d %d\n"), (int)rect
->x
, 
 610 #ifndef __WXUNIVERSAL__ 
 611     GtkPizza 
*pizza 
= GTK_PIZZA (widget
); 
 613     if (win
->GetThemeEnabled()) 
 615         wxWindow 
*parent 
= win
->GetParent(); 
 616         while (parent 
&& !parent
->IsTopLevel()) 
 617             parent 
= parent
->GetParent(); 
 621         gtk_paint_flat_box (parent
->m_widget
->style
, 
 632     win
->m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
 633     win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
 635     // Update immediately, not in idle time. 
 638 #ifndef __WXUNIVERSAL__ 
 639     // Redraw child widgets 
 640     GList 
*children 
= pizza
->children
; 
 643         GtkPizzaChild 
*child 
= (GtkPizzaChild
*) children
->data
; 
 644         children 
= children
->next
; 
 646         GdkRectangle child_area
; 
 647         if (gtk_widget_intersect (child
->widget
, rect
, &child_area
)) 
 649             gtk_widget_draw (child
->widget
, &child_area 
/* (GdkRectangle*) NULL*/ ); 
 657 //----------------------------------------------------------------------------- 
 658 // "key_press_event" from any window 
 659 //----------------------------------------------------------------------------- 
 661 // set WXTRACE to this to see the key event codes on the console 
 662 #define TRACE_KEYS  _T("keyevent") 
 664 // translates an X key symbol to WXK_XXX value 
 666 // if isChar is true it means that the value returned will be used for EVT_CHAR 
 667 // event and then we choose the logical WXK_XXX, i.e. '/' for GDK_KP_Divide, 
 668 // for example, while if it is false it means that the value is going to be 
 669 // used for KEY_DOWN/UP events and then we translate GDK_KP_Divide to 
 671 static long wxTranslateKeySymToWXKey(KeySym keysym
, bool isChar
) 
 677         // Shift, Control and Alt don't generate the CHAR events at all 
 680             key_code 
= isChar 
? 0 : WXK_SHIFT
; 
 684             key_code 
= isChar 
? 0 : WXK_CONTROL
; 
 692             key_code 
= isChar 
? 0 : WXK_ALT
; 
 695         // neither do the toggle modifies 
 696         case GDK_Scroll_Lock
: 
 697             key_code 
= isChar 
? 0 : WXK_SCROLL
; 
 701             key_code 
= isChar 
? 0 : WXK_CAPITAL
; 
 705             key_code 
= isChar 
? 0 : WXK_NUMLOCK
; 
 709         // various other special keys 
 722         case GDK_ISO_Left_Tab
: 
 729             key_code 
= WXK_RETURN
; 
 733             key_code 
= WXK_CLEAR
; 
 737             key_code 
= WXK_PAUSE
; 
 741             key_code 
= WXK_SELECT
; 
 745             key_code 
= WXK_PRINT
; 
 749             key_code 
= WXK_EXECUTE
; 
 753             key_code 
= WXK_ESCAPE
; 
 756         // cursor and other extended keyboard keys 
 758             key_code 
= WXK_DELETE
; 
 774             key_code 
= WXK_RIGHT
; 
 781         case GDK_Prior
:     // == GDK_Page_Up 
 782             key_code 
= WXK_PRIOR
; 
 785         case GDK_Next
:      // == GDK_Page_Down 
 798             key_code 
= WXK_INSERT
; 
 813             key_code 
= (isChar 
? '0' : WXK_NUMPAD0
) + keysym 
- GDK_KP_0
; 
 817             key_code 
= isChar 
? ' ' : WXK_NUMPAD_SPACE
; 
 821             key_code 
= isChar 
? WXK_TAB 
: WXK_NUMPAD_TAB
; 
 825             key_code 
= isChar 
? WXK_RETURN 
: WXK_NUMPAD_ENTER
; 
 829             key_code 
= isChar 
? WXK_F1 
: WXK_NUMPAD_F1
; 
 833             key_code 
= isChar 
? WXK_F2 
: WXK_NUMPAD_F2
; 
 837             key_code 
= isChar 
? WXK_F3 
: WXK_NUMPAD_F3
; 
 841             key_code 
= isChar 
? WXK_F4 
: WXK_NUMPAD_F4
; 
 845             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_HOME
; 
 849             key_code 
= isChar 
? WXK_LEFT 
: WXK_NUMPAD_LEFT
; 
 853             key_code 
= isChar 
? WXK_UP 
: WXK_NUMPAD_UP
; 
 857             key_code 
= isChar 
? WXK_RIGHT 
: WXK_NUMPAD_RIGHT
; 
 861             key_code 
= isChar 
? WXK_DOWN 
: WXK_NUMPAD_DOWN
; 
 864         case GDK_KP_Prior
: // == GDK_KP_Page_Up 
 865             key_code 
= isChar 
? WXK_PRIOR 
: WXK_NUMPAD_PRIOR
; 
 868         case GDK_KP_Next
: // == GDK_KP_Page_Down 
 869             key_code 
= isChar 
? WXK_NEXT 
: WXK_NUMPAD_NEXT
; 
 873             key_code 
= isChar 
? WXK_END 
: WXK_NUMPAD_END
; 
 877             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_BEGIN
; 
 881             key_code 
= isChar 
? WXK_INSERT 
: WXK_NUMPAD_INSERT
; 
 885             key_code 
= isChar 
? WXK_DELETE 
: WXK_NUMPAD_DELETE
; 
 889             key_code 
= isChar 
? '=' : WXK_NUMPAD_EQUAL
; 
 892         case GDK_KP_Multiply
: 
 893             key_code 
= isChar 
? '*' : WXK_NUMPAD_MULTIPLY
; 
 897             key_code 
= isChar 
? '+' : WXK_NUMPAD_ADD
; 
 900         case GDK_KP_Separator
: 
 901             // FIXME: what is this? 
 902             key_code 
= isChar 
? '.' : WXK_NUMPAD_SEPARATOR
; 
 905         case GDK_KP_Subtract
: 
 906             key_code 
= isChar 
? '-' : WXK_NUMPAD_SUBTRACT
; 
 910             key_code 
= isChar 
? '.' : WXK_NUMPAD_DECIMAL
; 
 914             key_code 
= isChar 
? '/' : WXK_NUMPAD_DIVIDE
; 
 931             key_code 
= WXK_F1 
+ keysym 
- GDK_F1
; 
 941 static inline bool wxIsAsciiKeysym(KeySym ks
) 
 947 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
, 
 949                            GdkEventKey 
*gdk_event
) 
 951     // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string 
 952     //     but only event->keyval which is quite useless to us, so remember 
 953     //     the last character from GDK_KEY_PRESS and reuse it as last resort 
 955     // NB: should be MT-safe as we're always called from the main thread only 
 960     } s_lastKeyPress 
= { 0, 0 }; 
 962     KeySym keysym 
= gdk_event
->keyval
; 
 964     wxLogTrace(TRACE_KEYS
, _T("Key %s event: keysym = %ld"), 
 965                event
.GetEventType() == wxEVT_KEY_UP 
? _T("release") 
 969     long key_code 
= wxTranslateKeySymToWXKey(keysym
, FALSE 
/* !isChar */); 
 973         // do we have the translation or is it a plain ASCII character? 
 974         if ( (gdk_event
->length 
== 1) || wxIsAsciiKeysym(keysym
) ) 
 976             // we should use keysym if it is ASCII as X does some translations 
 977             // like "I pressed while Control is down" => "Ctrl-I" == "TAB" 
 978             // which we don't want here (but which we do use for OnChar()) 
 979             if ( !wxIsAsciiKeysym(keysym
) ) 
 981                 keysym 
= (KeySym
)gdk_event
->string
[0]; 
 984             // we want to always get the same key code when the same key is 
 985             // pressed regardless of the state of the modifies, i.e. on a 
 986             // standard US keyboard pressing '5' or '%' ('5' key with 
 987             // Shift) should result in the same key code in OnKeyDown(): 
 988             // '5' (although OnChar() will get either '5' or '%'). 
 990             // to do it we first translate keysym to keycode (== scan code) 
 991             // and then back but always using the lower register 
 992             Display 
*dpy 
= (Display 
*)wxGetDisplay(); 
 993             KeyCode keycode 
= XKeysymToKeycode(dpy
, keysym
); 
 995             wxLogTrace(TRACE_KEYS
, _T("\t-> keycode %d"), keycode
); 
 997             KeySym keysymNormalized 
= XKeycodeToKeysym(dpy
, keycode
, 0); 
 999             // use the normalized, i.e. lower register, keysym if we've 
1001             key_code 
= keysymNormalized 
? keysymNormalized 
: keysym
; 
1003             // as explained above, we want to have lower register key codes 
1004             // normally but for the letter keys we want to have the upper ones 
1006             // NB: don't use XConvertCase() here, we want to do it for letters 
1008             key_code 
= toupper(key_code
); 
1010         else // non ASCII key, what to do? 
1012             // by default, ignore it 
1015             // but if we have cached information from the last KEY_PRESS 
1016             if ( gdk_event
->type 
== GDK_KEY_RELEASE 
) 
1019                 if ( keysym 
== s_lastKeyPress
.keysym 
) 
1021                     key_code 
= s_lastKeyPress
.keycode
; 
1026         if ( gdk_event
->type 
== GDK_KEY_PRESS 
) 
1028             // remember it to be reused for KEY_UP event later 
1029             s_lastKeyPress
.keysym 
= keysym
; 
1030             s_lastKeyPress
.keycode 
= key_code
; 
1034     wxLogTrace(TRACE_KEYS
, _T("\t-> wxKeyCode %ld"), key_code
); 
1036     // sending unknown key events doesn't really make sense 
1040     // now fill all the other fields 
1043     GdkModifierType state
; 
1044     if (gdk_event
->window
) 
1045         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1047     event
.SetTimestamp( gdk_event
->time 
); 
1048     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
) != 0; 
1049     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
) != 0; 
1050     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
) != 0; 
1051     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
) != 0; 
1052     event
.m_keyCode 
= key_code
; 
1053     event
.m_scanCode 
= gdk_event
->keyval
; 
1054     event
.m_rawCode 
= (wxUint32
) gdk_event
->keyval
; 
1055     event
.m_rawFlags 
= 0; 
1058     event
.SetEventObject( win 
); 
1063 static gint 
gtk_window_key_press_callback( GtkWidget 
*widget
, 
1064                                            GdkEventKey 
*gdk_event
, 
1070         wxapp_install_idle_handler(); 
1074     if (g_blockEventsOnDrag
) 
1078     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
1079     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1081         // unknown key pressed, ignore (the event would be useless anyhow) 
1085     // Emit KEY_DOWN event 
1086     bool ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1091         wxWindowGTK 
*ancestor 
= win
; 
1094             int command 
= ancestor
->GetAcceleratorTable()->GetCommand( event 
); 
1097                 wxCommandEvent 
command_event( wxEVT_COMMAND_MENU_SELECTED
, command 
); 
1098                 ret 
= ancestor
->GetEventHandler()->ProcessEvent( command_event 
); 
1101             if (ancestor
->IsTopLevel()) 
1103             ancestor 
= ancestor
->GetParent(); 
1106 #endif // wxUSE_ACCEL 
1108     // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x 
1109     // will only be sent if it is not in an accelerator table. 
1112         // Find key code for EVT_CHAR and EVT_CHAR_HOOK events 
1113         KeySym keysym 
= gdk_event
->keyval
; 
1114         long key_code 
= wxTranslateKeySymToWXKey(keysym
, TRUE 
/* isChar */); 
1117             if ( gdk_event
->length 
== 1 ) 
1119                 key_code 
= (unsigned char)gdk_event
->string
[0]; 
1121             else if ( wxIsAsciiKeysym(keysym
) ) 
1124                 key_code 
= (unsigned char)keysym
; 
1130             wxLogTrace(TRACE_KEYS
, _T("Char event: %ld"), key_code
); 
1132             event
.m_keyCode 
= key_code
; 
1134             // Implement OnCharHook by checking ancesteror top level windows 
1135             wxWindow 
*parent 
= win
; 
1136             while (parent 
&& !parent
->IsTopLevel()) 
1137             parent 
= parent
->GetParent(); 
1140                 event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1141                 ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1146                 event
.SetEventType(wxEVT_CHAR
); 
1147                 ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1152     // win is a control: tab can be propagated up 
1154          ((gdk_event
->keyval 
== GDK_Tab
) || (gdk_event
->keyval 
== GDK_ISO_Left_Tab
)) && 
1155 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may 
1156 //     have this style, yet choose not to process this particular TAB in which 
1157 //     case TAB must still work as a navigational character 
1159          !win
->HasFlag(wxTE_PROCESS_TAB
) && 
1161          win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) ) 
1163         wxNavigationKeyEvent new_event
; 
1164         new_event
.SetEventObject( win
->GetParent() ); 
1165         // GDK reports GDK_ISO_Left_Tab for SHIFT-TAB 
1166         new_event
.SetDirection( (gdk_event
->keyval 
== GDK_Tab
) ); 
1167         // CTRL-TAB changes the (parent) window, i.e. switch notebook page 
1168         new_event
.SetWindowChange( (gdk_event
->state 
& GDK_CONTROL_MASK
) ); 
1169         new_event
.SetCurrentFocus( win 
); 
1170         ret 
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event 
); 
1173     // generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) 
1175          (gdk_event
->keyval 
== GDK_Escape
) ) 
1177         // however only do it if we have a Cancel button in the dialog, 
1178         // otherwise the user code may get confused by the events from a 
1179         // non-existing button and, worse, a wxButton might get button event 
1180         // from another button which is not really expected 
1181         wxWindow 
*winForCancel 
= win
, 
1183         while ( winForCancel 
) 
1185             btnCancel 
= winForCancel
->FindWindow(wxID_CANCEL
); 
1188                 // found a cancel button 
1192             if ( winForCancel
->IsTopLevel() ) 
1194                 // no need to look further 
1198             // maybe our parent has a cancel button? 
1199             winForCancel 
= winForCancel
->GetParent(); 
1204             wxCommandEvent 
event(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
); 
1205             event
.SetEventObject(btnCancel
); 
1206             ret 
= btnCancel
->GetEventHandler()->ProcessEvent(event
); 
1212     // Pressing F10 will activate the menu bar of the top frame 
1214          (gdk_event
->keyval 
== GDK_F10
) ) 
1216         wxWindowGTK 
*ancestor 
= win
; 
1219             if (wxIsKindOf(ancestor
,wxFrame
)) 
1221                 wxFrame 
*frame 
= (wxFrame
*) ancestor
; 
1222                 wxMenuBar 
*menubar 
= frame
->GetMenuBar(); 
1225                     wxNode 
*node 
= menubar
->GetMenus().First(); 
1228                         wxMenu 
*firstMenu 
= (wxMenu
*) node
->Data(); 
1229                         gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) ); 
1235             ancestor 
= ancestor
->GetParent(); 
1242         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" ); 
1249 //----------------------------------------------------------------------------- 
1250 // "key_release_event" from any window 
1251 //----------------------------------------------------------------------------- 
1253 static gint 
gtk_window_key_release_callback( GtkWidget 
*widget
, 
1254                                              GdkEventKey 
*gdk_event
, 
1260         wxapp_install_idle_handler(); 
1265     if (g_blockEventsOnDrag
) 
1268     wxKeyEvent 
event( wxEVT_KEY_UP 
); 
1269     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1271         // unknown key pressed, ignore (the event would be useless anyhow 
1275     if ( !win
->GetEventHandler()->ProcessEvent( event 
) ) 
1278     gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" ); 
1282 // ============================================================================ 
1284 // ============================================================================ 
1286 // ---------------------------------------------------------------------------- 
1287 // mouse event processing helpers 
1288 // ---------------------------------------------------------------------------- 
1290 // init wxMouseEvent with the info from gdk_event 
1292 // NB: this has to be a macro as gdk_event type is different for different 
1293 //     events we're used with 
1294 #define InitMouseEvent(/* wxWindowGTK * */ win,                               \ 
1295                        /* wxMouseEvent& */ event,                             \ 
1296                        /* GdkEventXXX * */ gdk_event)                         \ 
1298     event.SetTimestamp( gdk_event->time );                                    \ 
1299     event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);                  \ 
1300     event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);              \ 
1301     event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);                     \ 
1302     event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);                    \ 
1303     event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);                 \ 
1304     event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);               \ 
1305     event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);                \ 
1307     wxPoint pt = win->GetClientAreaOrigin();                                  \ 
1308     event.m_x = (wxCoord)gdk_event->x - pt.x;                                 \ 
1309     event.m_y = (wxCoord)gdk_event->y - pt.y;                                 \ 
1311     event.SetEventObject( win );                                              \ 
1312     event.SetId( win->GetId() );                                              \ 
1313     event.SetTimestamp( gdk_event->time );                                    \ 
1316 static void AdjustEventButtonState(wxMouseEvent& event) 
1318     // GDK reports the old state of the button for a button press event, but 
1319     // for compatibility with MSW and common sense we want m_leftDown be TRUE 
1320     // for a LEFT_DOWN event, not FALSE, so we will invert 
1321     // left/right/middleDown for the corresponding click events 
1323     if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) || 
1324         (event
.GetEventType() == wxEVT_LEFT_DCLICK
) || 
1325         (event
.GetEventType() == wxEVT_LEFT_UP
)) 
1327         event
.m_leftDown 
= !event
.m_leftDown
; 
1331     if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) || 
1332         (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) || 
1333         (event
.GetEventType() == wxEVT_MIDDLE_UP
)) 
1335         event
.m_middleDown 
= !event
.m_middleDown
; 
1339     if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) || 
1340         (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) || 
1341         (event
.GetEventType() == wxEVT_RIGHT_UP
)) 
1343         event
.m_rightDown 
= !event
.m_rightDown
; 
1348 // find the window to send the mouse event too 
1350 wxWindowGTK 
*FindWindowForMouseEvent(wxWindowGTK 
*win
, wxCoord
& x
, wxCoord
& y
) 
1355     if (win
->m_wxwindow
) 
1357         GtkPizza 
*pizza 
= GTK_PIZZA(win
->m_wxwindow
); 
1358         xx 
+= pizza
->xoffset
; 
1359         yy 
+= pizza
->yoffset
; 
1362     wxNode 
*node 
= win
->GetChildren().First(); 
1365         wxWindowGTK 
*child 
= (wxWindowGTK
*)node
->Data(); 
1367         node 
= node
->Next(); 
1368         if (!child
->IsShown()) 
1371         if (child
->IsTransparentForMouse()) 
1373             // wxStaticBox is transparent in the box itself 
1374             int xx1 
= child
->m_x
; 
1375             int yy1 
= child
->m_y
; 
1376             int xx2 
= child
->m_x 
+ child
->m_width
; 
1377             int yy2 
= child
->m_x 
+ child
->m_height
; 
1380             if (((xx 
>= xx1
) && (xx 
<= xx1
+10) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1382                 ((xx 
>= xx2
-10) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1384                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy1
+10)) || 
1386                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy2
-1) && (yy 
<= yy2
))) 
1397             if ((child
->m_wxwindow 
== (GtkWidget
*) NULL
) && 
1398                 (child
->m_x 
<= xx
) && 
1399                 (child
->m_y 
<= yy
) && 
1400                 (child
->m_x
+child
->m_width  
>= xx
) && 
1401                 (child
->m_y
+child
->m_height 
>= yy
)) 
1414 //----------------------------------------------------------------------------- 
1415 // "button_press_event" 
1416 //----------------------------------------------------------------------------- 
1418 static gint 
gtk_window_button_press_callback( GtkWidget 
*widget
, 
1419                                               GdkEventButton 
*gdk_event
, 
1425         wxapp_install_idle_handler(); 
1428     wxPrintf( wxT("1) OnButtonPress from ") ); 
1429     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1430         wxPrintf( win->GetClassInfo()->GetClassName() ); 
1431     wxPrintf( wxT(".\n") ); 
1433     if (!win
->m_hasVMT
) return FALSE
; 
1434     if (g_blockEventsOnDrag
) return TRUE
; 
1435     if (g_blockEventsOnScroll
) return TRUE
; 
1437     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1439     if (win
->m_wxwindow 
&& (g_focusWindow 
!= win
) && win
->AcceptsFocus()) 
1441         gtk_widget_grab_focus( win
->m_wxwindow 
); 
1443         wxPrintf( wxT("GrabFocus from ") ); 
1444         if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1445             wxPrintf( win->GetClassInfo()->GetClassName() ); 
1446         wxPrintf( wxT(".\n") ); 
1450     wxEventType event_type 
= wxEVT_NULL
; 
1452     if (gdk_event
->button 
== 1) 
1454         switch (gdk_event
->type
) 
1456             case GDK_BUTTON_PRESS
: event_type 
= wxEVT_LEFT_DOWN
; break; 
1457             case GDK_2BUTTON_PRESS
: event_type 
= wxEVT_LEFT_DCLICK
; break; 
1461     else if (gdk_event
->button 
== 2) 
1463         switch (gdk_event
->type
) 
1465             case GDK_BUTTON_PRESS
: event_type 
= wxEVT_MIDDLE_DOWN
; break; 
1466             case GDK_2BUTTON_PRESS
: event_type 
= wxEVT_MIDDLE_DCLICK
; break; 
1470     else if (gdk_event
->button 
== 3) 
1472         switch (gdk_event
->type
) 
1474             case GDK_BUTTON_PRESS
: event_type 
= wxEVT_RIGHT_DOWN
; break; 
1475             case GDK_2BUTTON_PRESS
: event_type 
= wxEVT_RIGHT_DCLICK
; break; 
1480     if ( event_type 
== wxEVT_NULL 
) 
1482         // unknown mouse button or click type 
1486     wxMouseEvent 
event( event_type 
); 
1487     InitMouseEvent( win
, event
, gdk_event 
); 
1489     AdjustEventButtonState(event
); 
1491     // wxListBox actually get mouse events from the item, so we need to give it 
1492     // a chance to correct this 
1493     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1495     // find the correct window to send the event too: it may be a different one 
1496     // from the one which got it at GTK+ level because some control don't have 
1497     // their own X window and thus cannot get any events. 
1498     if ( !g_captureWindow 
) 
1499         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1501     gs_timeLastClick 
= gdk_event
->time
; 
1504     wxPrintf( wxT("2) OnButtonPress from ") ); 
1505     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1506         wxPrintf( win->GetClassInfo()->GetClassName() ); 
1507     wxPrintf( wxT(".\n") ); 
1510     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1512         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" ); 
1519 //----------------------------------------------------------------------------- 
1520 // "button_release_event" 
1521 //----------------------------------------------------------------------------- 
1523 static gint 
gtk_window_button_release_callback( GtkWidget 
*widget
, GdkEventButton 
*gdk_event
, wxWindowGTK 
*win 
) 
1528         wxapp_install_idle_handler(); 
1530     if (!win
->m_hasVMT
) return FALSE
; 
1531     if (g_blockEventsOnDrag
) return FALSE
; 
1532     if (g_blockEventsOnScroll
) return FALSE
; 
1534     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1537     printf( "OnButtonRelease from " ); 
1538     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1539         printf( win->GetClassInfo()->GetClassName() ); 
1543     wxEventType event_type 
= wxEVT_NULL
; 
1545     switch (gdk_event
->button
) 
1547         case 1: event_type 
= wxEVT_LEFT_UP
; break; 
1548         case 2: event_type 
= wxEVT_MIDDLE_UP
; break; 
1549         case 3: event_type 
= wxEVT_RIGHT_UP
; break; 
1550         default: return FALSE
; 
1553     wxMouseEvent 
event( event_type 
); 
1554     InitMouseEvent( win
, event
, gdk_event 
); 
1556     AdjustEventButtonState(event
); 
1558     // same wxListBox hack as above 
1559     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1561     if ( !g_captureWindow 
) 
1562         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1564     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1566         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" ); 
1573 //----------------------------------------------------------------------------- 
1574 // "motion_notify_event" 
1575 //----------------------------------------------------------------------------- 
1577 static gint 
gtk_window_motion_notify_callback( GtkWidget 
*widget
, 
1578                                                GdkEventMotion 
*gdk_event
, 
1584         wxapp_install_idle_handler(); 
1586     if (!win
->m_hasVMT
) return FALSE
; 
1587     if (g_blockEventsOnDrag
) return FALSE
; 
1588     if (g_blockEventsOnScroll
) return FALSE
; 
1590     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1592     if (gdk_event
->is_hint
) 
1596         GdkModifierType state
; 
1597         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1603     printf( "OnMotion from " ); 
1604     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1605       printf( win->GetClassInfo()->GetClassName() ); 
1609     wxMouseEvent 
event( wxEVT_MOTION 
); 
1610     InitMouseEvent(win
, event
, gdk_event
); 
1612     if ( g_captureWindow 
) 
1614         // synthetize a mouse enter or leave event if needed 
1615         GdkWindow 
*winUnderMouse 
= gdk_window_at_pointer(NULL
, NULL
); 
1616         bool hasMouse 
= winUnderMouse 
== gdk_event
->window
; 
1617         if ( hasMouse 
!= g_captureWindowHasMouse 
) 
1619             // the mouse changed window 
1620             g_captureWindowHasMouse 
= hasMouse
; 
1622             wxMouseEvent 
event(g_captureWindowHasMouse 
? wxEVT_ENTER_WINDOW
 
1623                                                        : wxEVT_LEAVE_WINDOW
); 
1624             InitMouseEvent(win
, event
, gdk_event
); 
1625             event
.SetEventObject(win
); 
1626             win
->GetEventHandler()->ProcessEvent(event
); 
1631         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1634     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1636         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" ); 
1643 //----------------------------------------------------------------------------- 
1645 //----------------------------------------------------------------------------- 
1647 // send the wxChildFocusEvent and wxFocusEvent, common code of 
1648 // gtk_window_focus_in_callback() and SetFocus() 
1649 static bool DoSendFocusEvents(wxWindow 
*win
) 
1651     // Notify the parent keeping track of focus for the kbd navigation 
1652     // purposes that we got it. 
1653     wxChildFocusEvent 
eventChildFocus(win
); 
1654     (void)win
->GetEventHandler()->ProcessEvent(eventChildFocus
); 
1656     wxFocusEvent 
eventFocus(wxEVT_SET_FOCUS
, win
->GetId()); 
1657     eventFocus
.SetEventObject(win
); 
1659     return win
->GetEventHandler()->ProcessEvent(eventFocus
); 
1662 static gint 
gtk_window_focus_in_callback( GtkWidget 
*widget
, 
1663                                           GdkEvent 
*WXUNUSED(event
), 
1669         wxapp_install_idle_handler(); 
1671     if (!win
->m_hasVMT
) return FALSE
; 
1672     if (g_blockEventsOnDrag
) return FALSE
; 
1674     switch ( g_sendActivateEvent 
) 
1677             // we've got focus from outside, synthetize wxActivateEvent 
1678             g_sendActivateEvent 
= 1; 
1682             // another our window just lost focus, it was already ours before 
1683             // - don't send any wxActivateEvent 
1684             g_sendActivateEvent 
= -1; 
1689     g_focusWindow 
= win
; 
1691     wxLogTrace(TRACE_FOCUS
, 
1692                _T("%s: focus in"), win
->GetName().c_str()); 
1696         gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
); 
1700     // caret needs to be informed about focus change 
1701     wxCaret 
*caret 
= win
->GetCaret(); 
1704         caret
->OnSetFocus(); 
1706 #endif // wxUSE_CARET 
1708     g_activeFrameLostFocus 
= FALSE
; 
1710     wxWindowGTK 
*active 
= wxGetTopLevelParent(win
); 
1711     if ( active 
!= g_activeFrame 
) 
1713         if ( g_activeFrame 
) 
1715             wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
); 
1716             wxActivateEvent 
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId()); 
1717             event
.SetEventObject(g_activeFrame
); 
1718             g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
1721         wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
); 
1722         g_activeFrame 
= active
; 
1723         wxActivateEvent 
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId()); 
1724         event
.SetEventObject(g_activeFrame
); 
1725         g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
1727         // Don't send focus events in addition to activate 
1728         // if (win == g_activeFrame) 
1732     // does the window itself think that it has the focus? 
1733     if ( !win
->m_hasFocus 
) 
1735         // not yet, notify it 
1736         win
->m_hasFocus 
= TRUE
; 
1738         if ( DoSendFocusEvents(win
) ) 
1740            gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" ); 
1748 //----------------------------------------------------------------------------- 
1749 // "focus_out_event" 
1750 //----------------------------------------------------------------------------- 
1752 static gint 
gtk_window_focus_out_callback( GtkWidget 
*widget
, GdkEventFocus 
*gdk_event
, wxWindowGTK 
*win 
) 
1757         wxapp_install_idle_handler(); 
1759     if (!win
->m_hasVMT
) return FALSE
; 
1760     if (g_blockEventsOnDrag
) return FALSE
; 
1762     wxLogTrace( TRACE_FOCUS
, 
1763                 _T("%s: focus out"), win
->GetName().c_str() ); 
1765     if ( !g_activeFrameLostFocus 
&& g_activeFrame 
) 
1767         // VZ: commenting this out because it does happen (although not easy 
1768         //     to reproduce, I only see it when using wxMiniFrame and not 
1769         //     always) and makes using Mahogany quite annoying 
1771         wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
, 
1772                         wxT("unfocusing window that hasn't gained focus properly") ); 
1775         g_activeFrameLostFocus 
= TRUE
; 
1778     // if the focus goes out of our app alltogether, OnIdle() will send 
1779     // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset 
1780     // g_sendActivateEvent to -1 
1781     g_sendActivateEvent 
= 0; 
1783     wxWindowGTK 
*winFocus 
= wxFindFocusedChild(win
); 
1787     g_focusWindow 
= (wxWindowGTK 
*)NULL
; 
1795     // caret needs to be informed about focus change 
1796     wxCaret 
*caret 
= win
->GetCaret(); 
1799         caret
->OnKillFocus(); 
1801 #endif // wxUSE_CARET 
1803     // don't send the window a kill focus event if it thinks that it doesn't 
1804     // have focus already 
1805     if ( win
->m_hasFocus 
) 
1807         win
->m_hasFocus 
= FALSE
; 
1809         wxFocusEvent 
event( wxEVT_KILL_FOCUS
, win
->GetId() ); 
1810         event
.SetEventObject( win 
); 
1812         if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1814             gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" ); 
1822 //----------------------------------------------------------------------------- 
1823 // "enter_notify_event" 
1824 //----------------------------------------------------------------------------- 
1827 gint 
gtk_window_enter_callback( GtkWidget 
*widget
, 
1828                                 GdkEventCrossing 
*gdk_event
, 
1834         wxapp_install_idle_handler(); 
1836     if (!win
->m_hasVMT
) return FALSE
; 
1837     if (g_blockEventsOnDrag
) return FALSE
; 
1839     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1843     GdkModifierType state 
= (GdkModifierType
)0; 
1845     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
1847     wxMouseEvent 
event( wxEVT_ENTER_WINDOW 
); 
1848     InitMouseEvent(win
, event
, gdk_event
); 
1849     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1850     event
.m_x 
= x 
+ pt
.x
; 
1851     event
.m_y 
= y 
+ pt
.y
; 
1853     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1855        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" ); 
1862 //----------------------------------------------------------------------------- 
1863 // "leave_notify_event" 
1864 //----------------------------------------------------------------------------- 
1866 static gint 
gtk_window_leave_callback( GtkWidget 
*widget
, GdkEventCrossing 
*gdk_event
, wxWindowGTK 
*win 
) 
1871         wxapp_install_idle_handler(); 
1873     if (!win
->m_hasVMT
) return FALSE
; 
1874     if (g_blockEventsOnDrag
) return FALSE
; 
1876     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1878     wxMouseEvent 
event( wxEVT_LEAVE_WINDOW 
); 
1879     event
.SetTimestamp( gdk_event
->time 
); 
1880     event
.SetEventObject( win 
); 
1884     GdkModifierType state 
= (GdkModifierType
)0; 
1886     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
1888     event
.m_shiftDown 
= (state 
& GDK_SHIFT_MASK
) != 0; 
1889     event
.m_controlDown 
= (state 
& GDK_CONTROL_MASK
) != 0; 
1890     event
.m_altDown 
= (state 
& GDK_MOD1_MASK
) != 0; 
1891     event
.m_metaDown 
= (state 
& GDK_MOD2_MASK
) != 0; 
1892     event
.m_leftDown 
= (state 
& GDK_BUTTON1_MASK
) != 0; 
1893     event
.m_middleDown 
= (state 
& GDK_BUTTON2_MASK
) != 0; 
1894     event
.m_rightDown 
= (state 
& GDK_BUTTON3_MASK
) != 0; 
1896     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1897     event
.m_x 
= x 
+ pt
.x
; 
1898     event
.m_y 
= y 
+ pt
.y
; 
1900     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1902         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" ); 
1909 //----------------------------------------------------------------------------- 
1910 // "value_changed" from m_vAdjust 
1911 //----------------------------------------------------------------------------- 
1913 static void gtk_window_vscroll_callback( GtkAdjustment 
*adjust
, 
1920         wxapp_install_idle_handler(); 
1922     if (g_blockEventsOnDrag
) return; 
1924     if (!win
->m_hasVMT
) return; 
1926     float diff 
= adjust
->value 
- win
->m_oldVerticalPos
; 
1927     if (fabs(diff
) < 0.2) return; 
1929     win
->m_oldVerticalPos 
= adjust
->value
; 
1932     GtkScrolledWindow   
*sw 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
1934     wxEventType         command 
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->vscrollbar
)); 
1936     int value 
= (int)(adjust
->value
+0.5); 
1938     wxScrollWinEvent 
event( command
, value
, wxVERTICAL 
); 
1939     event
.SetEventObject( win 
); 
1940     win
->GetEventHandler()->ProcessEvent( event 
); 
1943 //----------------------------------------------------------------------------- 
1944 // "value_changed" from m_hAdjust 
1945 //----------------------------------------------------------------------------- 
1947 static void gtk_window_hscroll_callback( GtkAdjustment 
*adjust
, 
1954         wxapp_install_idle_handler(); 
1956     if (g_blockEventsOnDrag
) return; 
1957     if (!win
->m_hasVMT
) return; 
1959     float diff 
= adjust
->value 
- win
->m_oldHorizontalPos
; 
1960     if (fabs(diff
) < 0.2) return; 
1963     GtkScrolledWindow   
*sw 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
1965     wxEventType         command 
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->hscrollbar
)); 
1967     win
->m_oldHorizontalPos 
= adjust
->value
; 
1969     int value 
= (int)(adjust
->value
+0.5); 
1971     wxScrollWinEvent 
event( command
, value
, wxHORIZONTAL 
); 
1972     event
.SetEventObject( win 
); 
1973     win
->GetEventHandler()->ProcessEvent( event 
); 
1976 //----------------------------------------------------------------------------- 
1977 // "button_press_event" from scrollbar 
1978 //----------------------------------------------------------------------------- 
1980 static gint 
gtk_scrollbar_button_press_callback( GtkRange 
*widget
, 
1981                                                  GdkEventButton 
*gdk_event
, 
1987         wxapp_install_idle_handler(); 
1990     g_blockEventsOnScroll 
= TRUE
; 
1992     // FIXME: there is no 'slider' field in GTK+ 2.0 any more 
1994     win
->m_isScrolling 
= (gdk_event
->window 
== widget
->slider
); 
2000 //----------------------------------------------------------------------------- 
2001 // "button_release_event" from scrollbar 
2002 //----------------------------------------------------------------------------- 
2004 static gint 
gtk_scrollbar_button_release_callback( GtkRange 
*widget
, 
2005                                                    GdkEventButton 
*WXUNUSED(gdk_event
), 
2010 //  don't test here as we can release the mouse while being over 
2011 //  a different window than the slider 
2013 //    if (gdk_event->window != widget->slider) return FALSE; 
2015     g_blockEventsOnScroll 
= FALSE
; 
2017     if (win
->m_isScrolling
) 
2019         wxEventType command 
= wxEVT_SCROLLWIN_THUMBRELEASE
; 
2023         GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
2024         if (widget 
== GTK_RANGE(scrolledWindow
->hscrollbar
)) 
2026             value 
= (int)(win
->m_hAdjust
->value
+0.5); 
2029         if (widget 
== GTK_RANGE(scrolledWindow
->vscrollbar
)) 
2031             value 
= (int)(win
->m_vAdjust
->value
+0.5); 
2035         wxScrollWinEvent 
event( command
, value
, dir 
); 
2036         event
.SetEventObject( win 
); 
2037         win
->GetEventHandler()->ProcessEvent( event 
); 
2040     win
->m_isScrolling 
= FALSE
; 
2045 // ---------------------------------------------------------------------------- 
2046 // this wxWindowBase function is implemented here (in platform-specific file) 
2047 // because it is static and so couldn't be made virtual 
2048 // ---------------------------------------------------------------------------- 
2050 wxWindow 
*wxWindowBase::FindFocus() 
2052     // the cast is necessary when we compile in wxUniversal mode 
2053     return (wxWindow 
*)g_focusWindow
; 
2056 //----------------------------------------------------------------------------- 
2058 //----------------------------------------------------------------------------- 
2060 // VZ: Robert commented the code using out so it generates warnings: should 
2061 //     be either fixed or removed completely 
2064 static void gtk_window_destroy_callback( GtkWidget
* widget
, wxWindow 
*win 
) 
2066     wxWindowDestroyEvent 
event(win
); 
2067     win
->GetEventHandler()->ProcessEvent(event
); 
2072 //----------------------------------------------------------------------------- 
2073 // "realize" from m_widget 
2074 //----------------------------------------------------------------------------- 
2076 /* We cannot set colours and fonts before the widget has 
2077    been realized, so we do this directly after realization. */ 
2080 gtk_window_realized_callback( GtkWidget 
*WXUNUSED(m_widget
), wxWindow 
*win 
) 
2085         wxapp_install_idle_handler(); 
2087     if (win
->m_delayedBackgroundColour
) 
2088         win
->GtkSetBackgroundColour( win
->GetBackgroundColour() ); 
2090     if (win
->m_delayedForegroundColour
) 
2091         win
->GtkSetForegroundColour( win
->GetForegroundColour() ); 
2093     wxWindowCreateEvent 
event( win 
); 
2094     event
.SetEventObject( win 
); 
2095     win
->GetEventHandler()->ProcessEvent( event 
); 
2100 //----------------------------------------------------------------------------- 
2102 //----------------------------------------------------------------------------- 
2105 void gtk_window_size_callback( GtkWidget 
*WXUNUSED(widget
), 
2106                                GtkAllocation 
*WXUNUSED(alloc
), 
2110         wxapp_install_idle_handler(); 
2112     if (!win
->m_hasScrolling
) return; 
2114     int client_width 
= 0; 
2115     int client_height 
= 0; 
2116     win
->GetClientSize( &client_width
, &client_height 
); 
2117     if ((client_width 
== win
->m_oldClientWidth
) && (client_height 
== win
->m_oldClientHeight
)) 
2120     win
->m_oldClientWidth 
= client_width
; 
2121     win
->m_oldClientHeight 
= client_height
; 
2123     if (!win
->m_nativeSizeEvent
) 
2125         wxSizeEvent 
event( win
->GetSize(), win
->GetId() ); 
2126         event
.SetEventObject( win 
); 
2127         win
->GetEventHandler()->ProcessEvent( event 
); 
2133     #define WXUNUSED_UNLESS_XIM(param)  param 
2135     #define WXUNUSED_UNLESS_XIM(param)  WXUNUSED(param) 
2138 /* Resize XIM window */ 
2141 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
), 
2142                                  GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
), 
2143                                  wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) ) 
2146         wxapp_install_idle_handler(); 
2152     if  (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
) 
2156         gdk_window_get_size (widget
->window
, &width
, &height
); 
2157         win
->m_icattr
->preedit_area
.width 
= width
; 
2158         win
->m_icattr
->preedit_area
.height 
= height
; 
2159         gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
); 
2164 //----------------------------------------------------------------------------- 
2165 // "realize" from m_wxwindow 
2166 //----------------------------------------------------------------------------- 
2168 /* Initialize XIM support */ 
2171 gtk_wxwindow_realized_callback( GtkWidget 
* WXUNUSED_UNLESS_XIM(widget
), 
2172                                 wxWindowGTK 
* WXUNUSED_UNLESS_XIM(win
) ) 
2175         wxapp_install_idle_handler(); 
2178     if (win
->m_ic
) return FALSE
; 
2179     if (!widget
) return FALSE
; 
2180     if (!gdk_im_ready()) return FALSE
; 
2182     win
->m_icattr 
= gdk_ic_attr_new(); 
2183     if (!win
->m_icattr
) return FALSE
; 
2187     GdkColormap 
*colormap
; 
2188     GdkICAttr 
*attr 
= win
->m_icattr
; 
2189     unsigned attrmask 
= GDK_IC_ALL_REQ
; 
2191     GdkIMStyle supported_style 
= (GdkIMStyle
) 
2192                                   (GDK_IM_PREEDIT_NONE 
| 
2193                                    GDK_IM_PREEDIT_NOTHING 
| 
2194                                    GDK_IM_PREEDIT_POSITION 
| 
2195                                    GDK_IM_STATUS_NONE 
| 
2196                                    GDK_IM_STATUS_NOTHING
); 
2198     if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2199         supported_style 
= (GdkIMStyle
)(supported_style 
& ~GDK_IM_PREEDIT_POSITION
); 
2201     attr
->style 
= style 
= gdk_im_decide_style (supported_style
); 
2202     attr
->client_window 
= widget
->window
; 
2204     if ((colormap 
= gtk_widget_get_colormap (widget
)) != 
2205             gtk_widget_get_default_colormap ()) 
2207         attrmask 
|= GDK_IC_PREEDIT_COLORMAP
; 
2208         attr
->preedit_colormap 
= colormap
; 
2211     attrmask 
|= GDK_IC_PREEDIT_FOREGROUND
; 
2212     attrmask 
|= GDK_IC_PREEDIT_BACKGROUND
; 
2213     attr
->preedit_foreground 
= widget
->style
->fg
[GTK_STATE_NORMAL
]; 
2214     attr
->preedit_background 
= widget
->style
->base
[GTK_STATE_NORMAL
]; 
2216     switch (style 
& GDK_IM_PREEDIT_MASK
) 
2218         case GDK_IM_PREEDIT_POSITION
: 
2219             if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2221                 g_warning ("over-the-spot style requires fontset"); 
2225             gdk_window_get_size (widget
->window
, &width
, &height
); 
2227             attrmask 
|= GDK_IC_PREEDIT_POSITION_REQ
; 
2228             attr
->spot_location
.x 
= 0; 
2229             attr
->spot_location
.y 
= height
; 
2230             attr
->preedit_area
.x 
= 0; 
2231             attr
->preedit_area
.y 
= 0; 
2232             attr
->preedit_area
.width 
= width
; 
2233             attr
->preedit_area
.height 
= height
; 
2234             attr
->preedit_fontset 
= widget
->style
->font
; 
2239       win
->m_ic 
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
); 
2241       if (win
->m_ic 
== NULL
) 
2242           g_warning ("Can't create input context."); 
2245           mask 
= gdk_window_get_events (widget
->window
); 
2246           mask 
= (GdkEventMask
)(mask 
| gdk_ic_get_events (win
->m_ic
)); 
2247           gdk_window_set_events (widget
->window
, mask
); 
2249           if (GTK_WIDGET_HAS_FOCUS(widget
)) 
2250               gdk_im_begin (win
->m_ic
, widget
->window
); 
2257 //----------------------------------------------------------------------------- 
2258 // InsertChild for wxWindowGTK. 
2259 //----------------------------------------------------------------------------- 
2261 /* Callback for wxWindowGTK. This very strange beast has to be used because 
2262  * C++ has no virtual methods in a constructor. We have to emulate a 
2263  * virtual function here as wxNotebook requires a different way to insert 
2264  * a child in it. I had opted for creating a wxNotebookPage window class 
2265  * which would have made this superfluous (such in the MDI window system), 
2266  * but no-one was listening to me... */ 
2268 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child 
) 
2270     /* the window might have been scrolled already, do we 
2271        have to adapt the position */ 
2272     GtkPizza 
*pizza 
= GTK_PIZZA(parent
->m_wxwindow
); 
2273     child
->m_x 
+= pizza
->xoffset
; 
2274     child
->m_y 
+= pizza
->yoffset
; 
2276     gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
), 
2277                      GTK_WIDGET(child
->m_widget
), 
2284 //----------------------------------------------------------------------------- 
2286 //----------------------------------------------------------------------------- 
2288 wxWindow 
*wxGetActiveWindow() 
2290     return wxWindow::FindFocus(); 
2293 //----------------------------------------------------------------------------- 
2295 //----------------------------------------------------------------------------- 
2297 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
2299 #ifdef __WXUNIVERSAL__ 
2300     IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
) 
2302     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
2303 #endif // __WXUNIVERSAL__/__WXGTK__ 
2305 void wxWindowGTK::Init() 
2311     m_widget 
= (GtkWidget 
*) NULL
; 
2312     m_wxwindow 
= (GtkWidget 
*) NULL
; 
2313     m_focusWidget 
= (GtkWidget 
*) NULL
; 
2323     m_needParent 
= TRUE
; 
2324     m_isBeingDeleted 
= FALSE
; 
2327     m_nativeSizeEvent 
= FALSE
; 
2329     m_hasScrolling 
= FALSE
; 
2330     m_isScrolling 
= FALSE
; 
2332     m_hAdjust 
= (GtkAdjustment
*) NULL
; 
2333     m_vAdjust 
= (GtkAdjustment
*) NULL
; 
2334     m_oldHorizontalPos 
= 0.0; 
2335     m_oldVerticalPos 
= 0.0; 
2338     m_widgetStyle 
= (GtkStyle
*) NULL
; 
2340     m_insertCallback 
= (wxInsertChildFunction
) NULL
; 
2342     m_acceptsFocus 
= FALSE
; 
2345     m_clipPaintRegion 
= FALSE
; 
2347     m_cursor 
= *wxSTANDARD_CURSOR
; 
2349     m_delayedForegroundColour 
= FALSE
; 
2350     m_delayedBackgroundColour 
= FALSE
; 
2353     m_ic 
= (GdkIC
*) NULL
; 
2354     m_icattr 
= (GdkICAttr
*) NULL
; 
2358 wxWindowGTK::wxWindowGTK() 
2363 wxWindowGTK::wxWindowGTK( wxWindow 
*parent
, 
2368                           const wxString 
&name  
) 
2372     Create( parent
, id
, pos
, size
, style
, name 
); 
2375 bool wxWindowGTK::Create( wxWindow 
*parent
, 
2380                           const wxString 
&name  
) 
2382     if (!PreCreation( parent
, pos
, size 
) || 
2383         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
2385         wxFAIL_MSG( wxT("wxWindowGTK creation failed") ); 
2389     m_insertCallback 
= wxInsertChildInWindow
; 
2391     // always needed for background clearing 
2392     m_delayedBackgroundColour 
= TRUE
;  
2394     m_widget 
= gtk_scrolled_window_new( (GtkAdjustment 
*) NULL
, (GtkAdjustment 
*) NULL 
); 
2395     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
2397     GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
2399     GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2400     scroll_class
->scrollbar_spacing 
= 0; 
2402     gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
2404     m_hAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) ); 
2405     m_vAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) ); 
2407     m_wxwindow 
= gtk_pizza_new(); 
2409 #ifndef __WXUNIVERSAL__ 
2410     GtkPizza 
*pizza 
= GTK_PIZZA(m_wxwindow
); 
2412     if (HasFlag(wxRAISED_BORDER
)) 
2414         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT 
); 
2416     else if (HasFlag(wxSUNKEN_BORDER
)) 
2418         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN 
); 
2420     else if (HasFlag(wxSIMPLE_BORDER
)) 
2422         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN 
); 
2426         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE 
); 
2428 #endif // __WXUNIVERSAL__ 
2430     gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
2432     GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
2433     m_acceptsFocus 
= TRUE
; 
2435     // I _really_ don't want scrollbars in the beginning 
2436     m_vAdjust
->lower 
= 0.0; 
2437     m_vAdjust
->upper 
= 1.0; 
2438     m_vAdjust
->value 
= 0.0; 
2439     m_vAdjust
->step_increment 
= 1.0; 
2440     m_vAdjust
->page_increment 
= 1.0; 
2441     m_vAdjust
->page_size 
= 5.0; 
2442     gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
2443     m_hAdjust
->lower 
= 0.0; 
2444     m_hAdjust
->upper 
= 1.0; 
2445     m_hAdjust
->value 
= 0.0; 
2446     m_hAdjust
->step_increment 
= 1.0; 
2447     m_hAdjust
->page_increment 
= 1.0; 
2448     m_hAdjust
->page_size 
= 5.0; 
2449     gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
2451     // these handlers block mouse events to any window during scrolling such as 
2452     // motion events and prevent GTK and wxWindows from fighting over where the 
2455     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event", 
2456           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
2458     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event", 
2459           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
2461     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event", 
2462           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
2464     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event", 
2465           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
2467     // these handlers get notified when screen updates are required either when 
2468     // scrolling or when the window size (and therefore scrollbar configuration) 
2471     gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
2472           (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
2473     gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
2474           (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
2476     gtk_widget_show( m_wxwindow 
); 
2479         m_parent
->DoAddChild( this ); 
2481     m_focusWidget 
= m_wxwindow
; 
2490 wxWindowGTK::~wxWindowGTK() 
2492     if (g_focusWindow 
== this) 
2493         g_focusWindow 
= NULL
; 
2495     if (g_activeFrame 
== this) 
2496         g_activeFrame 
= NULL
; 
2498     if ( g_delayedFocus 
== this ) 
2499         g_delayedFocus 
= NULL
; 
2501     m_isBeingDeleted 
= TRUE
; 
2510         m_parent
->RemoveChild( this ); 
2514         gdk_ic_destroy (m_ic
); 
2516         gdk_ic_attr_destroy (m_icattr
); 
2521 #if DISABLE_STYLE_IF_BROKEN_THEME 
2522         // don't delete if it's a pixmap theme style 
2523         if (!m_widgetStyle
->engine_data
) 
2524             gtk_style_unref( m_widgetStyle 
); 
2526         m_widgetStyle 
= (GtkStyle
*) NULL
; 
2531         gtk_widget_destroy( m_wxwindow 
); 
2532         m_wxwindow 
= (GtkWidget
*) NULL
; 
2537         gtk_widget_destroy( m_widget 
); 
2538         m_widget 
= (GtkWidget
*) NULL
; 
2542 bool wxWindowGTK::PreCreation( wxWindowGTK 
*parent
, const wxPoint 
&pos
,  const wxSize 
&size 
) 
2544     wxCHECK_MSG( !m_needParent 
|| parent
, FALSE
, wxT("Need complete parent.") ); 
2546     // This turns -1 into 30 so that a minimal window is 
2547     // visible even although -1,-1 has been given as the 
2548     // size of the window. the same trick is used in other 
2549     // ports and should make debugging easier. 
2550     m_width 
= WidthDefault(size
.x
) ; 
2551     m_height 
= HeightDefault(size
.y
); 
2556     // some reasonable defaults 
2561             m_x 
= (gdk_screen_width () - m_width
) / 2; 
2562             if (m_x 
< 10) m_x 
= 10; 
2566             m_y 
= (gdk_screen_height () - m_height
) / 2; 
2567             if (m_y 
< 10) m_y 
= 10; 
2574 void wxWindowGTK::PostCreation() 
2576     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2582             // these get reported to wxWindows -> wxPaintEvent 
2584             gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE 
); 
2586             gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event", 
2587                 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this ); 
2590             gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw", 
2591                 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this ); 
2593             if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) 
2595                 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event", 
2596                     GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this ); 
2599             gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow
), HasFlag( wxNO_FULL_REPAINT_ON_RESIZE 
) ); 
2603         // these are called when the "sunken" or "raised" borders are drawn 
2604         gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event", 
2605           GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this ); 
2608         gtk_signal_connect( GTK_OBJECT(m_widget
), "draw", 
2609           GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this ); 
2615     if (m_focusWidget 
== NULL
) 
2616         m_focusWidget 
= m_widget
; 
2618     gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event", 
2619         GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this ); 
2621     gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event", 
2622          GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this ); 
2624     // connect to the various key and mouse handlers 
2626     GtkWidget 
*connect_widget 
= GetConnectWidget(); 
2628     ConnectWidget( connect_widget 
); 
2630     /* We cannot set colours, fonts and cursors before the widget has 
2631        been realized, so we do this directly after realization */ 
2632     gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize", 
2633                             GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this ); 
2637         // Catch native resize events 
2638         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate", 
2639                             GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this ); 
2641         // Initialize XIM support 
2642         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize", 
2643                             GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this ); 
2645         // And resize XIM window 
2646         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate", 
2647                             GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this ); 
2650     if (!GTK_IS_COMBO(m_widget
)) 
2652         // This is needed if we want to add our windows into native 
2653         // GTK control, such as the toolbar. With this callback, the 
2654         // toolbar gets to know the correct size (the one set by the 
2655         // programmer). Sadly, it misbehaves for wxComboBox. FIXME 
2656         // when moving to GTK 2.0. 
2657         gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request", 
2658                             GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this ); 
2664 void wxWindowGTK::ConnectWidget( GtkWidget 
*widget 
) 
2666     gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event", 
2667       GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this ); 
2669     gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event", 
2670       GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this ); 
2672     gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event", 
2673       GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this ); 
2675     gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event", 
2676       GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this ); 
2678     gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event", 
2679       GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this ); 
2681     gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event", 
2682       GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this ); 
2684     gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event", 
2685       GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this ); 
2687     // This keeps crashing on me. RR. 
2689     // gtk_signal_connect( GTK_OBJECT(widget), "destroy", 
2690     //  GTK_SIGNAL_FUNC(gtk_window_destroy_callback), (gpointer)this ); 
2693 bool wxWindowGTK::Destroy() 
2695     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2699     return wxWindowBase::Destroy(); 
2702 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
) 
2704     gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height 
); 
2707 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
2709     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2710     wxASSERT_MSG( (m_parent 
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") ); 
2713     printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height ); 
2716     if (m_resizing
) return; /* I don't like recursions */ 
2719     int currentX
, currentY
; 
2720     GetPosition(¤tX
, ¤tY
); 
2725     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
2727     if (m_parent
->m_wxwindow 
== NULL
) /* i.e. wxNotebook */ 
2729         /* don't set the size for children of wxNotebook, just take the values. */ 
2737         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
2738         if ((sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) == 0) 
2740             if (x 
!= -1) m_x 
= x 
+ pizza
->xoffset
; 
2741             if (y 
!= -1) m_y 
= y 
+ pizza
->yoffset
; 
2745             m_x 
= x 
+ pizza
->xoffset
; 
2746             m_y 
= y 
+ pizza
->yoffset
; 
2748         if (width 
!= -1) m_width 
= width
; 
2749         if (height 
!= -1) m_height 
= height
; 
2751         if ((sizeFlags 
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
) 
2753              if (width 
== -1) m_width 
= 80; 
2756         if ((sizeFlags 
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
) 
2758              if (height 
== -1) m_height 
= 26; 
2761         int minWidth 
= GetMinWidth(), 
2762             minHeight 
= GetMinHeight(), 
2763             maxWidth 
= GetMaxWidth(), 
2764             maxHeight 
= GetMaxHeight(); 
2766         if ((minWidth 
!= -1) && (m_width 
< minWidth
)) m_width 
= minWidth
; 
2767         if ((minHeight 
!= -1) && (m_height 
< minHeight
)) m_height 
= minHeight
; 
2768         if ((maxWidth 
!= -1) && (m_width 
> maxWidth
)) m_width 
= maxWidth
; 
2769         if ((maxHeight 
!= -1) && (m_height 
> maxHeight
)) m_height 
= maxHeight
; 
2772         int bottom_border 
= 0; 
2775         if (GTK_WIDGET_CAN_DEFAULT(m_widget
)) 
2777             /* the default button has a border around it */ 
2783         DoMoveWindow( m_x
-border
, 
2786                       m_height
+border
+bottom_border 
); 
2791         /* Sometimes the client area changes size without the 
2792            whole windows's size changing, but if the whole 
2793            windows's size doesn't change, no wxSizeEvent will 
2794            normally be sent. Here we add an extra test if 
2795            the client test has been changed and this will 
2797         GetClientSize( &m_oldClientWidth
, &m_oldClientHeight 
); 
2801     wxPrintf( "OnSize sent from " ); 
2802     if (GetClassInfo() && GetClassInfo()->GetClassName()) 
2803         wxPrintf( GetClassInfo()->GetClassName() ); 
2804     wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height ); 
2807     if (!m_nativeSizeEvent
) 
2809         wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
2810         event
.SetEventObject( this ); 
2811         GetEventHandler()->ProcessEvent( event 
); 
2817 void wxWindowGTK::OnInternalIdle() 
2819     // Update invalidated regions. 
2822     // Synthetize activate events. 
2823     if ( g_sendActivateEvent 
!= -1 ) 
2825         bool activate 
= g_sendActivateEvent 
!= 0; 
2828         g_sendActivateEvent 
= -1; 
2830         wxTheApp
->SetActive(activate
, (wxWindow 
*)g_focusWindowLast
); 
2833     if ( g_activeFrameLostFocus 
) 
2835         if ( g_activeFrame 
) 
2837             wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
); 
2838             wxActivateEvent 
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId()); 
2839             event
.SetEventObject(g_activeFrame
); 
2840             g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
2841             g_activeFrame 
= NULL
; 
2843         g_activeFrameLostFocus 
= FALSE
; 
2846     wxCursor cursor 
= m_cursor
; 
2847     if (g_globalCursor
.Ok()) cursor 
= g_globalCursor
; 
2851         /* I now set the cursor anew in every OnInternalIdle call 
2852            as setting the cursor in a parent window also effects the 
2853            windows above so that checking for the current cursor is 
2858             GdkWindow 
*window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
2860                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2862             if (!g_globalCursor
.Ok()) 
2863                 cursor 
= *wxSTANDARD_CURSOR
; 
2865             window 
= m_widget
->window
; 
2866             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
2867                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2873             GdkWindow 
*window 
= m_widget
->window
; 
2874             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
2875                gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2883 void wxWindowGTK::DoGetSize( int *width
, int *height 
) const 
2885     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2887     if (width
) (*width
) = m_width
; 
2888     if (height
) (*height
) = m_height
; 
2891 void wxWindowGTK::DoSetClientSize( int width
, int height 
) 
2893     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2897         SetSize( width
, height 
); 
2904 #ifndef __WXUNIVERSAL__ 
2905         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
2907             /* when using GTK 1.2 we set the shadow border size to 2 */ 
2911         if (HasFlag(wxSIMPLE_BORDER
)) 
2913             /* when using GTK 1.2 we set the simple border size to 1 */ 
2917 #endif // __WXUNIVERSAL__ 
2921             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
2923             GtkRequisition vscroll_req
; 
2924             vscroll_req
.width 
= 2; 
2925             vscroll_req
.height 
= 2; 
2926             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
2927                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
2929             GtkRequisition hscroll_req
; 
2930             hscroll_req
.width 
= 2; 
2931             hscroll_req
.height 
= 2; 
2932             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
2933                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
2935             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2937             if (scroll_window
->vscrollbar_visible
) 
2939                 dw 
+= vscroll_req
.width
; 
2940                 dw 
+= scroll_class
->scrollbar_spacing
; 
2943             if (scroll_window
->hscrollbar_visible
) 
2945                 dh 
+= hscroll_req
.height
; 
2946                 dh 
+= scroll_class
->scrollbar_spacing
; 
2950        SetSize( width
+dw
, height
+dh 
); 
2954 void wxWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
2956     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2960         if (width
) (*width
) = m_width
; 
2961         if (height
) (*height
) = m_height
; 
2968 #ifndef __WXUNIVERSAL__ 
2969         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
2971             /* when using GTK 1.2 we set the shadow border size to 2 */ 
2975         if (HasFlag(wxSIMPLE_BORDER
)) 
2977             /* when using GTK 1.2 we set the simple border size to 1 */ 
2981 #endif // __WXUNIVERSAL__ 
2985             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
2987             GtkRequisition vscroll_req
; 
2988             vscroll_req
.width 
= 2; 
2989             vscroll_req
.height 
= 2; 
2990             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
2991                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
2993             GtkRequisition hscroll_req
; 
2994             hscroll_req
.width 
= 2; 
2995             hscroll_req
.height 
= 2; 
2996             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
2997                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
2999             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
3001             if (scroll_window
->vscrollbar_visible
) 
3003                 dw 
+= vscroll_req
.width
; 
3004                 dw 
+= scroll_class
->scrollbar_spacing
; 
3007             if (scroll_window
->hscrollbar_visible
) 
3009                 dh 
+= hscroll_req
.height
; 
3010                 dh 
+= scroll_class
->scrollbar_spacing
; 
3014         if (width
) (*width
) = m_width 
- dw
; 
3015         if (height
) (*height
) = m_height 
- dh
; 
3019     printf( "GetClientSize, name %s ", GetName().c_str() ); 
3020     if (width) printf( " width = %d", (*width) ); 
3021     if (height) printf( " height = %d", (*height) ); 
3026 void wxWindowGTK::DoGetPosition( int *x
, int *y 
) const 
3028     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3032     if (m_parent 
&& m_parent
->m_wxwindow
) 
3034         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
3035         dx 
= pizza
->xoffset
; 
3036         dy 
= pizza
->yoffset
; 
3039     if (x
) (*x
) = m_x 
- dx
; 
3040     if (y
) (*y
) = m_y 
- dy
; 
3043 void wxWindowGTK::DoClientToScreen( int *x
, int *y 
) const 
3045     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3047     if (!m_widget
->window
) return; 
3049     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3051         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3053         source 
= m_widget
->window
; 
3057     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3061         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3063             org_x 
+= m_widget
->allocation
.x
; 
3064             org_y 
+= m_widget
->allocation
.y
; 
3072 void wxWindowGTK::DoScreenToClient( int *x
, int *y 
) const 
3074     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3076     if (!m_widget
->window
) return; 
3078     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3080         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3082         source 
= m_widget
->window
; 
3086     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3090         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3092             org_x 
+= m_widget
->allocation
.x
; 
3093             org_y 
+= m_widget
->allocation
.y
; 
3101 bool wxWindowGTK::Show( bool show 
) 
3103     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3105     if (!wxWindowBase::Show(show
)) 
3112         gtk_widget_show( m_widget 
); 
3114         gtk_widget_hide( m_widget 
); 
3119 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
) 
3121     win
->OnParentEnable(enable
); 
3123     // Recurse, so that children have the opportunity to Do The Right Thing 
3124     // and reset colours that have been messed up by a parent's (really ancestor's) 
3126     for ( wxWindowList::Node 
*node 
= win
->GetChildren().GetFirst(); 
3128           node 
= node
->GetNext() ) 
3130         wxWindow 
*child 
= node
->GetData(); 
3131         if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
))) 
3132             wxWindowNotifyEnable(child
, enable
); 
3136 bool wxWindowGTK::Enable( bool enable 
) 
3138     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3140     if (!wxWindowBase::Enable(enable
)) 
3146     gtk_widget_set_sensitive( m_widget
, enable 
); 
3148         gtk_widget_set_sensitive( m_wxwindow
, enable 
); 
3150     wxWindowNotifyEnable(this, enable
); 
3155 int wxWindowGTK::GetCharHeight() const 
3157     wxCHECK_MSG( (m_widget 
!= NULL
), 12, wxT("invalid window") ); 
3159     wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") ); 
3161     GdkFont 
*font 
= m_font
.GetInternalFont( 1.0 ); 
3163     return font
->ascent 
+ font
->descent
; 
3166 int wxWindowGTK::GetCharWidth() const 
3168     wxCHECK_MSG( (m_widget 
!= NULL
), 8, wxT("invalid window") ); 
3170     wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") ); 
3172     GdkFont 
*font 
= m_font
.GetInternalFont( 1.0 ); 
3174     return gdk_string_width( font
, "H" ); 
3177 void wxWindowGTK::GetTextExtent( const wxString
& string
, 
3181                               int *externalLeading
, 
3182                               const wxFont 
*theFont 
) const 
3184     wxFont fontToUse 
= m_font
; 
3185     if (theFont
) fontToUse 
= *theFont
; 
3187     wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") ); 
3189     if (string
.IsEmpty()) 
3197     PangoContext 
*context 
= NULL
; 
3199         gtk_widget_get_pango_context( m_widget 
); 
3208     PangoFontDescription 
*desc 
= fontToUse
.GetNativeFontInfo()->description
; 
3209     PangoLayout 
*layout 
= pango_layout_new(context
); 
3210     pango_layout_set_font_description(layout
, desc
); 
3213         const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( string 
); 
3214         pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data 
)); 
3216         const wxWCharBuffer wdata 
= wxConvLocal
.cMB2WC( string 
); 
3217         const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( wdata 
); 
3218         pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data 
)); 
3221     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
3223     PangoRectangle rect
; 
3224     pango_layout_line_get_extents(line
, NULL
, &rect
); 
3226     if (x
) (*x
) = (wxCoord
) (rect
.width 
/ PANGO_SCALE
); 
3227     if (y
) (*y
) = (wxCoord
) (rect
.height 
/ PANGO_SCALE
); 
3230         // Do something about metrics here 
3233     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3235     g_object_unref( G_OBJECT( layout 
) ); 
3237     GdkFont 
*font 
= fontToUse
.GetInternalFont( 1.0 ); 
3238     if (x
) (*x
) = gdk_string_width( font
, wxGTK_CONV( string 
) ); 
3239     if (y
) (*y
) = font
->ascent 
+ font
->descent
; 
3240     if (descent
) (*descent
) = font
->descent
; 
3241     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3245 void wxWindowGTK::SetFocus() 
3247     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3251         // don't do anything if we already have focus 
3257         if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
)) 
3259             gtk_widget_grab_focus (m_wxwindow
); 
3264         if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) ) 
3266             if (!GTK_WIDGET_REALIZED(m_widget
)) 
3268                 // we can't set the focus to the widget now so we remember that 
3269                 // it should be focused and will do it later, during the idle 
3270                 // time, as soon as we can 
3271                 wxLogTrace(TRACE_FOCUS
, 
3272                            _T("Delaying setting focus to %s(%s)"), 
3273                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3275                 g_delayedFocus 
= this; 
3279                 wxLogTrace(TRACE_FOCUS
, 
3280                            _T("Setting focus to %s(%s)"), 
3281                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3283                 gtk_widget_grab_focus (m_widget
); 
3286         else if (GTK_IS_CONTAINER(m_widget
)) 
3288             SET_CONTAINER_FOCUS( m_widget
, GTK_DIR_TAB_FORWARD 
); 
3292            wxLogTrace(TRACE_FOCUS
, 
3293                       _T("Can't set focus to %s(%s)"), 
3294                       GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3299 bool wxWindowGTK::AcceptsFocus() const 
3301     return m_acceptsFocus 
&& wxWindowBase::AcceptsFocus(); 
3304 bool wxWindowGTK::Reparent( wxWindowBase 
*newParentBase 
) 
3306     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3308     wxWindowGTK 
*oldParent 
= m_parent
, 
3309              *newParent 
= (wxWindowGTK 
*)newParentBase
; 
3311     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3313     if ( !wxWindowBase::Reparent(newParent
) ) 
3316     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3318     /* prevent GTK from deleting the widget arbitrarily */ 
3319     gtk_widget_ref( m_widget 
); 
3323         gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget 
); 
3326     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3330         /* insert GTK representation */ 
3331         (*(newParent
->m_insertCallback
))(newParent
, this); 
3334     /* reverse: prevent GTK from deleting the widget arbitrarily */ 
3335     gtk_widget_unref( m_widget 
); 
3340 void wxWindowGTK::DoAddChild(wxWindowGTK 
*child
) 
3342     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3344     wxASSERT_MSG( (child 
!= NULL
), wxT("invalid child window") ); 
3346     wxASSERT_MSG( (m_insertCallback 
!= NULL
), wxT("invalid child insertion function") ); 
3351     /* insert GTK representation */ 
3352     (*m_insertCallback
)(this, child
); 
3355 void wxWindowGTK::Raise() 
3357     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3359     if (!m_widget
->window
) return; 
3361     gdk_window_raise( m_widget
->window 
); 
3364 void wxWindowGTK::Lower() 
3366     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3368     if (!m_widget
->window
) return; 
3370     gdk_window_lower( m_widget
->window 
); 
3373 bool wxWindowGTK::SetCursor( const wxCursor 
&cursor 
) 
3375     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3377     if (cursor 
== m_cursor
) 
3381         wxapp_install_idle_handler(); 
3383     if (cursor 
== wxNullCursor
) 
3384        return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR 
); 
3386        return wxWindowBase::SetCursor( cursor 
); 
3389 void wxWindowGTK::WarpPointer( int x
, int y 
) 
3391     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3393     // We provide this function ourselves as it is 
3394     // missing in GDK (top of this file). 
3396     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3398         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3400         window 
= GetConnectWidget()->window
; 
3403         gdk_window_warp_pointer( window
, x
, y 
); 
3407 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect 
*rect 
) 
3409     if (!m_widget
) return; 
3410     if (!m_widget
->window
) return; 
3414         wxapp_install_idle_handler(); 
3416     if (eraseBackground 
&& m_wxwindow 
&& m_wxwindow
->window
) 
3420             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3421             m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3425             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3426             m_clearRegion
.Clear(); 
3427             m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3435             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3436             m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3440             GdkRectangle gdk_rect
; 
3441             gdk_rect
.x 
= rect
->x
; 
3442             gdk_rect
.y 
= rect
->y
; 
3443             gdk_rect
.width 
= rect
->width
; 
3444             gdk_rect
.height 
= rect
->height
; 
3445             gtk_widget_draw( m_widget
, &gdk_rect 
); 
3452             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3453             m_updateRegion
.Clear(); 
3454             m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3458             gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL 
); 
3466             GdkRectangle gdk_rect
; 
3467             gdk_rect
.x 
= rect
->x
; 
3468             gdk_rect
.y 
= rect
->y
; 
3469             gdk_rect
.width 
= rect
->width
; 
3470             gdk_rect
.height 
= rect
->height
; 
3471             gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, &gdk_rect
, TRUE 
); 
3475             gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, NULL
, TRUE 
); 
3481 void wxWindowGTK::Update() 
3486 void wxWindowGTK::GtkUpdate() 
3489     if (m_wxwindow 
&& GTK_PIZZA(m_wxwindow
)->bin_window
) 
3490         gdk_window_process_updates( GTK_PIZZA(m_wxwindow
)->bin_window
, FALSE 
); 
3492     if (!m_updateRegion
.IsEmpty()) 
3493         GtkSendPaintEvents(); 
3497 void wxWindowGTK::GtkSendPaintEvents() 
3502         m_clearRegion
.Clear(); 
3504         m_updateRegion
.Clear(); 
3508     // Clip to paint region in wxClientDC 
3509     m_clipPaintRegion 
= TRUE
; 
3512     // widget to draw on 
3513     GtkPizza 
*pizza 
= GTK_PIZZA (m_wxwindow
); 
3515     // later for GTK 2.0, too. 
3516     if (GetThemeEnabled()) 
3518         // find ancestor from which to steal background 
3519         wxWindow 
*parent 
= GetParent(); 
3520         while (parent 
&& !parent
->IsTopLevel()) 
3521             parent 
= parent
->GetParent(); 
3523             parent 
= (wxWindow
*)this; 
3525         wxRegionIterator 
upd( m_updateRegion 
); 
3529             rect
.x 
= upd
.GetX(); 
3530             rect
.y 
= upd
.GetY(); 
3531             rect
.width 
= upd
.GetWidth(); 
3532             rect
.height 
= upd
.GetHeight(); 
3534             gtk_paint_flat_box( parent
->m_widget
->style
, 
3551         wxWindowDC 
dc( (wxWindow
*)this ); 
3552         dc
.SetClippingRegion( m_updateRegion 
); 
3554         wxEraseEvent 
erase_event( GetId(), &dc 
); 
3555         erase_event
.SetEventObject( this ); 
3557         GetEventHandler()->ProcessEvent(erase_event
); 
3560     // if (!m_clearRegion.IsEmpty())   // Always send an erase event under GTK 1.2 
3562         wxWindowDC 
dc( (wxWindow
*)this ); 
3563         if (m_clearRegion
.IsEmpty()) 
3564             dc
.SetClippingRegion( m_updateRegion 
); 
3566             dc
.SetClippingRegion( m_clearRegion 
); 
3568         wxEraseEvent 
erase_event( GetId(), &dc 
); 
3569         erase_event
.SetEventObject( this ); 
3571         if (!GetEventHandler()->ProcessEvent(erase_event
)) 
3575                 g_eraseGC 
= gdk_gc_new( pizza
->bin_window 
); 
3576                 gdk_gc_set_fill( g_eraseGC
, GDK_SOLID 
); 
3578             gdk_gc_set_foreground( g_eraseGC
, m_backgroundColour
.GetColor() ); 
3580             wxRegionIterator 
upd( m_clearRegion 
); 
3583                 gdk_draw_rectangle( pizza
->bin_window
, g_eraseGC
, 1, 
3584                                     upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() ); 
3588         m_clearRegion
.Clear(); 
3592     wxNcPaintEvent 
nc_paint_event( GetId() ); 
3593     nc_paint_event
.SetEventObject( this ); 
3594     GetEventHandler()->ProcessEvent( nc_paint_event 
); 
3596     wxPaintEvent 
paint_event( GetId() ); 
3597     paint_event
.SetEventObject( this ); 
3598     GetEventHandler()->ProcessEvent( paint_event 
); 
3600     m_clipPaintRegion 
= FALSE
; 
3602 #ifndef __WXUNIVERSAL__ 
3604     // The following code will result in all window-less widgets 
3605     // being redrawn because the wxWindows class is allowed to 
3606     // paint over the window-less widgets. 
3608     GList 
*children 
= pizza
->children
; 
3611         GtkPizzaChild 
*child 
= (GtkPizzaChild
*) children
->data
; 
3612         children 
= children
->next
; 
3614         if (GTK_WIDGET_NO_WINDOW (child
->widget
) && 
3615             GTK_WIDGET_DRAWABLE (child
->widget
)) 
3617             // Get intersection of widget area and update region 
3618             wxRegion 
region( m_updateRegion 
); 
3620             GdkEventExpose gdk_event
; 
3621             gdk_event
.type 
= GDK_EXPOSE
; 
3622             gdk_event
.window 
= pizza
->bin_window
; 
3623             gdk_event
.count 
= 0; 
3625             wxRegionIterator 
upd( m_updateRegion 
); 
3629                 rect
.x 
= upd
.GetX(); 
3630                 rect
.y 
= upd
.GetY(); 
3631                 rect
.width 
= upd
.GetWidth(); 
3632                 rect
.height 
= upd
.GetHeight(); 
3634                 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
)) 
3636                     gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
); 
3646     m_updateRegion
.Clear(); 
3649 void wxWindowGTK::Clear() 
3651     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3654     if (m_wxwindow 
&& m_wxwindow
->window
) 
3656         m_clearRegion
.Clear(); 
3657         wxSize 
size( GetClientSize() ); 
3658         m_clearRegion
.Union( 0,0,size
.x
,size
.y 
); 
3660         // Better do this in idle? 
3667 void wxWindowGTK::DoSetToolTip( wxToolTip 
*tip 
) 
3669     wxWindowBase::DoSetToolTip(tip
); 
3672         m_tooltip
->Apply( (wxWindow 
*)this ); 
3675 void wxWindowGTK::ApplyToolTip( GtkTooltips 
*tips
, const wxChar 
*tip 
) 
3677     gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL 
); 
3679 #endif // wxUSE_TOOLTIPS 
3681 void wxWindowGTK::GtkSetBackgroundColour( const wxColour 
&colour 
) 
3683     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3685         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3687         window 
= GetConnectWidget()->window
; 
3691     // We need the pixel value e.g. for background clearing. 
3692     m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window 
) ); 
3696         // wxMSW doesn't clear the window here, either. 
3697         gdk_window_set_background( window
, m_backgroundColour
.GetColor() ); 
3703 bool wxWindowGTK::SetBackgroundColour( const wxColour 
&colour 
) 
3705     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
3707     if (!wxWindowBase::SetBackgroundColour(colour
)) 
3710     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3712         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3714         window 
= GetConnectWidget()->window
; 
3718         // indicate that a new style has been set 
3719         // but it couldn't get applied as the 
3720         // widget hasn't been realized yet. 
3721         m_delayedBackgroundColour 
= TRUE
; 
3726         GtkSetBackgroundColour( colour 
); 
3732 void wxWindowGTK::GtkSetForegroundColour( const wxColour 
&colour 
) 
3734     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3736         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3738         window 
= GetConnectWidget()->window
; 
3745 bool wxWindowGTK::SetForegroundColour( const wxColour 
&colour 
) 
3747     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
3749     if (!wxWindowBase::SetForegroundColour(colour
)) 
3751         // don't leave if the GTK widget has just 
3753         if (!m_delayedForegroundColour
) return FALSE
; 
3756     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3758         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3760         window 
= GetConnectWidget()->window
; 
3764         // indicate that a new style has been set 
3765         // but it couldn't get applied as the 
3766         // widget hasn't been realized yet. 
3767         m_delayedForegroundColour 
= TRUE
; 
3771        GtkSetForegroundColour( colour 
); 
3777 GtkStyle 
*wxWindowGTK::GetWidgetStyle() 
3781         GtkStyle 
*remake 
= gtk_style_copy( m_widgetStyle 
); 
3783         // FIXME: no more klass in 2.0 
3785         remake
->klass 
= m_widgetStyle
->klass
; 
3788         gtk_style_unref( m_widgetStyle 
); 
3789         m_widgetStyle 
= remake
; 
3793         GtkStyle 
*def 
= gtk_rc_get_style( m_widget 
); 
3796             def 
= gtk_widget_get_default_style(); 
3798         m_widgetStyle 
= gtk_style_copy( def 
); 
3800         // FIXME: no more klass in 2.0 
3802         m_widgetStyle
->klass 
= def
->klass
; 
3806     return m_widgetStyle
; 
3809 void wxWindowGTK::SetWidgetStyle() 
3811 #if DISABLE_STYLE_IF_BROKEN_THEME 
3812     if (m_widget
->style
->engine_data
) 
3814         static bool s_warningPrinted 
= FALSE
; 
3815         if (!s_warningPrinted
) 
3817             printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" ); 
3818             s_warningPrinted 
= TRUE
; 
3820         m_widgetStyle 
= m_widget
->style
; 
3825     GtkStyle 
*style 
= GetWidgetStyle(); 
3827     if (m_font 
!= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT 
)) 
3829         SET_STYLE_FONT(style
, m_font
.GetInternalFont( 1.0 )); 
3832     if (m_foregroundColour
.Ok()) 
3834         m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget 
) ); 
3835         if (m_foregroundColour 
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT
)) 
3837             style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor(); 
3838             style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor(); 
3839             style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor(); 
3843             // Try to restore the gtk default style.  This is still a little 
3844             // oversimplified for what is probably really needed here for controls 
3845             // other than buttons, but is better than not being able to (re)set a 
3846             // control's foreground colour to *wxBLACK -- RL 
3847             GtkStyle 
*def 
= gtk_rc_get_style( m_widget 
); 
3850                 def 
= gtk_widget_get_default_style(); 
3852             style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
]; 
3853             style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
]; 
3854             style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
]; 
3858     if (m_backgroundColour
.Ok()) 
3860         m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget 
) ); 
3861         if (m_backgroundColour 
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
)) 
3863             style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor(); 
3864             style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor(); 
3865             style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor(); 
3866             style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor(); 
3867             style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor(); 
3868             style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor(); 
3869             style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor(); 
3870             style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor(); 
3874             // Try to restore the gtk default style.  This is still a little 
3875             // oversimplified for what is probably really needed here for controls 
3876             // other than buttons, but is better than not being able to (re)set a 
3877             // control's background colour to default grey and means resetting a 
3878             // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting 
3880             GtkStyle 
*def 
= gtk_rc_get_style( m_widget 
); 
3883                 def 
= gtk_widget_get_default_style(); 
3885             style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
]; 
3886             style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
]; 
3887             style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
]; 
3888             style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
]; 
3889             style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
]; 
3890             style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
]; 
3891             style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
]; 
3892             style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
]; 
3897 void wxWindowGTK::ApplyWidgetStyle() 
3901 //----------------------------------------------------------------------------- 
3902 // Pop-up menu stuff 
3903 //----------------------------------------------------------------------------- 
3905 #if wxUSE_MENUS_NATIVE 
3908 void gtk_pop_hide_callback( GtkWidget 
*WXUNUSED(widget
), bool* is_waiting  
) 
3910     *is_waiting 
= FALSE
; 
3913 static void SetInvokingWindow( wxMenu 
*menu
, wxWindowGTK 
*win 
) 
3915     menu
->SetInvokingWindow( win 
); 
3916     wxMenuItemList::Node 
*node 
= menu
->GetMenuItems().GetFirst(); 
3919         wxMenuItem 
*menuitem 
= node
->GetData(); 
3920         if (menuitem
->IsSubMenu()) 
3922             SetInvokingWindow( menuitem
->GetSubMenu(), win 
); 
3925         node 
= node
->GetNext(); 
3929 // used to pass the coordinates from wxWindowGTK::DoPopupMenu() to 
3930 // wxPopupMenuPositionCallback() 
3932 // should be safe even in the MT case as the user can hardly popup 2 menus 
3933 // simultaneously, can he? 
3934 static gint gs_pop_x 
= 0; 
3935 static gint gs_pop_y 
= 0; 
3937 extern "C" void wxPopupMenuPositionCallback( GtkMenu 
*menu
, 
3940                                              gboolean 
* WXUNUSED(whatever
), 
3942                                              gpointer 
WXUNUSED(user_data
) ) 
3944     // ensure that the menu appears entirely on screen 
3946     gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
); 
3948     wxSize sizeScreen 
= wxGetDisplaySize(); 
3950     gint xmax 
= sizeScreen
.x 
- req
.width
, 
3951          ymax 
= sizeScreen
.y 
- req
.height
; 
3953     *x 
= gs_pop_x 
< xmax 
? gs_pop_x 
: xmax
; 
3954     *y 
= gs_pop_y 
< ymax 
? gs_pop_y 
: ymax
; 
3957 bool wxWindowGTK::DoPopupMenu( wxMenu 
*menu
, int x
, int y 
) 
3959     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
3961     wxCHECK_MSG( menu 
!= NULL
, FALSE
, wxT("invalid popup-menu") ); 
3963     SetInvokingWindow( menu
, this ); 
3969     ClientToScreen( &gs_pop_x
, &gs_pop_y 
); 
3971     bool is_waiting 
= TRUE
; 
3973     gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), 
3975                         GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), 
3976                         (gpointer
)&is_waiting 
); 
3979                   GTK_MENU(menu
->m_menu
), 
3980                   (GtkWidget 
*) NULL
,           // parent menu shell 
3981                   (GtkWidget 
*) NULL
,           // parent menu item 
3982                   wxPopupMenuPositionCallback
,  // function to position it 
3983                   NULL
,                         // client data 
3984                   0,                            // button used to activate it 
3985                   gs_timeLastClick              
// the time of activation 
3990         while (gtk_events_pending()) 
3991             gtk_main_iteration(); 
3997 #endif // wxUSE_MENUS_NATIVE 
3999 #if wxUSE_DRAG_AND_DROP 
4001 void wxWindowGTK::SetDropTarget( wxDropTarget 
*dropTarget 
) 
4003     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4005     GtkWidget 
*dnd_widget 
= GetConnectWidget(); 
4007     if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget 
); 
4009     if (m_dropTarget
) delete m_dropTarget
; 
4010     m_dropTarget 
= dropTarget
; 
4012     if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget 
); 
4015 #endif // wxUSE_DRAG_AND_DROP 
4017 GtkWidget
* wxWindowGTK::GetConnectWidget() 
4019     GtkWidget 
*connect_widget 
= m_widget
; 
4020     if (m_wxwindow
) connect_widget 
= m_wxwindow
; 
4022     return connect_widget
; 
4025 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow 
*window 
) 
4028         return (window 
== GTK_PIZZA(m_wxwindow
)->bin_window
); 
4030     return (window 
== m_widget
->window
); 
4033 bool wxWindowGTK::SetFont( const wxFont 
&font 
) 
4035     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
4037     if (!wxWindowBase::SetFont(font
)) 
4042     wxColour sysbg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE 
); 
4043     if ( sysbg 
== m_backgroundColour 
) 
4045         m_backgroundColour 
= wxNullColour
; 
4047         m_backgroundColour 
= sysbg
; 
4057 void wxWindowGTK::DoCaptureMouse() 
4059     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4061     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4063         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4065         window 
= GetConnectWidget()->window
; 
4067     wxCHECK_RET( window
, _T("CaptureMouse() failed") ); 
4069     wxCursor
* cursor 
= & m_cursor
; 
4071         cursor 
= wxSTANDARD_CURSOR
; 
4073     gdk_pointer_grab( window
, FALSE
, 
4075                          (GDK_BUTTON_PRESS_MASK 
| 
4076                           GDK_BUTTON_RELEASE_MASK 
| 
4077                           GDK_POINTER_MOTION_HINT_MASK 
| 
4078                           GDK_POINTER_MOTION_MASK
), 
4080                       cursor
->GetCursor(), 
4081                       (guint32
)GDK_CURRENT_TIME 
); 
4082     g_captureWindow 
= this; 
4083     g_captureWindowHasMouse 
= TRUE
; 
4086 void wxWindowGTK::DoReleaseMouse() 
4088     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4090     wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") ); 
4092     g_captureWindow 
= (wxWindowGTK
*) NULL
; 
4094     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4096         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4098         window 
= GetConnectWidget()->window
; 
4103     gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME 
); 
4107 wxWindow 
*wxWindowBase::GetCapture() 
4109     return (wxWindow 
*)g_captureWindow
; 
4112 bool wxWindowGTK::IsRetained() const 
4117 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
, 
4118       int range
, bool refresh 
) 
4120     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4122     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4124     m_hasScrolling 
= TRUE
; 
4126     if (orient 
== wxHORIZONTAL
) 
4128         float fpos 
= (float)pos
; 
4129         float frange 
= (float)range
; 
4130         float fthumb 
= (float)thumbVisible
; 
4131         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4132         if (fpos 
< 0.0) fpos 
= 0.0; 
4134         if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) && 
4135             (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2)) 
4137             SetScrollPos( orient
, pos
, refresh 
); 
4141         m_oldHorizontalPos 
= fpos
; 
4143         m_hAdjust
->lower 
= 0.0; 
4144         m_hAdjust
->upper 
= frange
; 
4145         m_hAdjust
->value 
= fpos
; 
4146         m_hAdjust
->step_increment 
= 1.0; 
4147         m_hAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4148         m_hAdjust
->page_size 
= fthumb
; 
4152         float fpos 
= (float)pos
; 
4153         float frange 
= (float)range
; 
4154         float fthumb 
= (float)thumbVisible
; 
4155         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4156         if (fpos 
< 0.0) fpos 
= 0.0; 
4158         if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) && 
4159             (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2)) 
4161             SetScrollPos( orient
, pos
, refresh 
); 
4165         m_oldVerticalPos 
= fpos
; 
4167         m_vAdjust
->lower 
= 0.0; 
4168         m_vAdjust
->upper 
= frange
; 
4169         m_vAdjust
->value 
= fpos
; 
4170         m_vAdjust
->step_increment 
= 1.0; 
4171         m_vAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4172         m_vAdjust
->page_size 
= fthumb
; 
4175     if (orient 
== wxHORIZONTAL
) 
4176         gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
4178         gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
4181 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) ) 
4183     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4185     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4187     if (orient 
== wxHORIZONTAL
) 
4189         float fpos 
= (float)pos
; 
4190         if (fpos 
> m_hAdjust
->upper 
- m_hAdjust
->page_size
) fpos 
= m_hAdjust
->upper 
- m_hAdjust
->page_size
; 
4191         if (fpos 
< 0.0) fpos 
= 0.0; 
4192         m_oldHorizontalPos 
= fpos
; 
4194         if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return; 
4195         m_hAdjust
->value 
= fpos
; 
4199         float fpos 
= (float)pos
; 
4200         if (fpos 
> m_vAdjust
->upper 
- m_vAdjust
->page_size
) fpos 
= m_vAdjust
->upper 
- m_vAdjust
->page_size
; 
4201         if (fpos 
< 0.0) fpos 
= 0.0; 
4202         m_oldVerticalPos 
= fpos
; 
4204         if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return; 
4205         m_vAdjust
->value 
= fpos
; 
4208     if (m_wxwindow
->window
) 
4210         if (orient 
== wxHORIZONTAL
) 
4212             gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
), 
4213                 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
4215             gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" ); 
4217             gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
4218                 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
4222             gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
), 
4223                 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
4225             gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" ); 
4227             gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
4228                 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
4233 int wxWindowGTK::GetScrollThumb( int orient 
) const 
4235     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4237     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4239     if (orient 
== wxHORIZONTAL
) 
4240         return (int)(m_hAdjust
->page_size
+0.5); 
4242         return (int)(m_vAdjust
->page_size
+0.5); 
4245 int wxWindowGTK::GetScrollPos( int orient 
) const 
4247     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4249     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4251     if (orient 
== wxHORIZONTAL
) 
4252         return (int)(m_hAdjust
->value
+0.5); 
4254         return (int)(m_vAdjust
->value
+0.5); 
4257 int wxWindowGTK::GetScrollRange( int orient 
) const 
4259     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4261     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4263     if (orient 
== wxHORIZONTAL
) 
4264         return (int)(m_hAdjust
->upper
+0.5); 
4266         return (int)(m_vAdjust
->upper
+0.5); 
4269 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) ) 
4271     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4273     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4275     // No scrolling requested. 
4276     if ((dx 
== 0) && (dy 
== 0)) return; 
4279     if (!m_updateRegion
.IsEmpty()) 
4281         m_updateRegion
.Offset( dx
, dy 
); 
4285         GetClientSize( &cw
, &ch 
); 
4286         m_updateRegion
.Intersect( 0, 0, cw
, ch 
); 
4289     if (!m_clearRegion
.IsEmpty()) 
4291         m_clearRegion
.Offset( dx
, dy 
); 
4295         GetClientSize( &cw
, &ch 
); 
4296         m_clearRegion
.Intersect( 0, 0, cw
, ch 
); 
4300     m_clipPaintRegion 
= TRUE
; 
4302     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy 
); 
4304     m_clipPaintRegion 
= FALSE
; 
4308 // Find the wxWindow at the current mouse position, also returning the mouse 
4310 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
4312     pt 
= wxGetMousePosition(); 
4313     wxWindow
* found 
= wxFindWindowAtPoint(pt
); 
4317 // Get the current mouse position. 
4318 wxPoint 
wxGetMousePosition() 
4320   /* This crashes when used within wxHelpContext, 
4321      so we have to use the X-specific implementation below. 
4323     GdkModifierType *mask; 
4324     (void) gdk_window_get_pointer(NULL, &x, &y, mask); 
4326     return wxPoint(x, y); 
4330     GdkWindow
* windowAtPtr 
= gdk_window_at_pointer(& x
, & y
); 
4332       return wxPoint(-999, -999); 
4334     Display 
*display 
= GDK_WINDOW_XDISPLAY(windowAtPtr
); 
4335     Window rootWindow 
= RootWindowOfScreen (DefaultScreenOfDisplay(display
)); 
4336     Window rootReturn
, childReturn
; 
4337     int rootX
, rootY
, winX
, winY
; 
4338     unsigned int maskReturn
; 
4340     XQueryPointer (display
, 
4344                    &rootX
, &rootY
, &winX
, &winY
, &maskReturn
); 
4345     return wxPoint(rootX
, rootY
); 
4349 // ---------------------------------------------------------------------------- 
4351 // ---------------------------------------------------------------------------- 
4353 class wxWinModule 
: public wxModule
 
4360     DECLARE_DYNAMIC_CLASS(wxWinModule
) 
4363 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
) 
4365 bool wxWinModule::OnInit() 
4367     // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() ); 
4368     // gdk_gc_set_fill( g_eraseGC, GDK_SOLID ); 
4373 void wxWinModule::OnExit() 
4376         gdk_gc_unref( g_eraseGC 
);