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(); 
 503         wxPrintf( wxT("OnExpose from ") ); 
 504         if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName()) 
 505             wxPrintf( win
->GetClassInfo()->GetClassName() ); 
 506         wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event
->area
.x
, 
 507                                          (int)gdk_event
->area
.y
, 
 508                                          (int)gdk_event
->area
.width
, 
 509                                          (int)gdk_event
->area
.height 
); 
 513     win
->GetUpdateRegion().Union( gdk_event
->area
.x
, 
 515                                   gdk_event
->area
.width
, 
 516                                   gdk_event
->area
.height 
); 
 517     win
->m_clearRegion
.Union( gdk_event
->area
.x
, 
 519                                   gdk_event
->area
.width
, 
 520                                   gdk_event
->area
.height 
); 
 522     // Actual redrawing takes place in idle time. 
 527     (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
); 
 534 //----------------------------------------------------------------------------- 
 535 // "event" of m_wxwindow 
 536 //----------------------------------------------------------------------------- 
 538 // GTK thinks it is clever and filters out a certain amount of "unneeded" 
 539 // expose events. We need them, of course, so we override the main event 
 540 // procedure in GtkWidget by giving our own handler for all system events. 
 541 // There, we look for expose events ourselves whereas all other events are 
 544 gint 
gtk_window_event_event_callback( GtkWidget 
*widget
, 
 545                                       GdkEventExpose 
*event
, 
 548     if (event
->type 
== GDK_EXPOSE
) 
 550         gint ret 
= gtk_window_expose_callback( widget
, event
, win 
); 
 557 //----------------------------------------------------------------------------- 
 558 // "draw" of m_wxwindow 
 559 //----------------------------------------------------------------------------- 
 563 // This callback is a complete replacement of the gtk_pizza_draw() function, 
 564 // which is disabled. 
 566 static void gtk_window_draw_callback( GtkWidget 
*widget
, 
 573         wxapp_install_idle_handler(); 
 575     // The wxNO_FULL_REPAINT_ON_RESIZE flag only works if 
 576     // there are no child windows. 
 577     if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) && 
 578         (win
->GetChildren().GetCount() == 0)) 
 586         wxPrintf( wxT("OnDraw from ") ); 
 587         if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName()) 
 588             wxPrintf( win
->GetClassInfo()->GetClassName() ); 
 589         wxPrintf( wxT(" %d %d %d %d\n"), (int)rect
->x
, 
 596 #ifndef __WXUNIVERSAL__ 
 597     GtkPizza 
*pizza 
= GTK_PIZZA (widget
); 
 599     if (win
->GetThemeEnabled()) 
 601         wxWindow 
*parent 
= win
->GetParent(); 
 602         while (parent 
&& !parent
->IsTopLevel()) 
 603             parent 
= parent
->GetParent(); 
 607         gtk_paint_flat_box (parent
->m_widget
->style
, 
 618     win
->m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
 619     win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
 621     // Update immediately, not in idle time. 
 624 #ifndef __WXUNIVERSAL__ 
 625     // Redraw child widgets 
 626     GList 
*children 
= pizza
->children
; 
 629         GtkPizzaChild 
*child 
= (GtkPizzaChild
*) children
->data
; 
 630         children 
= children
->next
; 
 632         GdkRectangle child_area
; 
 633         if (gtk_widget_intersect (child
->widget
, rect
, &child_area
)) 
 635             gtk_widget_draw (child
->widget
, &child_area 
/* (GdkRectangle*) NULL*/ ); 
 643 //----------------------------------------------------------------------------- 
 644 // "key_press_event" from any window 
 645 //----------------------------------------------------------------------------- 
 647 // set WXTRACE to this to see the key event codes on the console 
 648 #define TRACE_KEYS  _T("keyevent") 
 650 // translates an X key symbol to WXK_XXX value 
 652 // if isChar is true it means that the value returned will be used for EVT_CHAR 
 653 // event and then we choose the logical WXK_XXX, i.e. '/' for GDK_KP_Divide, 
 654 // for example, while if it is false it means that the value is going to be 
 655 // used for KEY_DOWN/UP events and then we translate GDK_KP_Divide to 
 657 static long wxTranslateKeySymToWXKey(KeySym keysym
, bool isChar
) 
 663         // Shift, Control and Alt don't generate the CHAR events at all 
 666             key_code 
= isChar 
? 0 : WXK_SHIFT
; 
 670             key_code 
= isChar 
? 0 : WXK_CONTROL
; 
 678             key_code 
= isChar 
? 0 : WXK_ALT
; 
 681         // neither do the toggle modifies 
 682         case GDK_Scroll_Lock
: 
 683             key_code 
= isChar 
? 0 : WXK_SCROLL
; 
 687             key_code 
= isChar 
? 0 : WXK_CAPITAL
; 
 691             key_code 
= isChar 
? 0 : WXK_NUMLOCK
; 
 695         // various other special keys 
 708         case GDK_ISO_Left_Tab
: 
 715             key_code 
= WXK_RETURN
; 
 719             key_code 
= WXK_CLEAR
; 
 723             key_code 
= WXK_PAUSE
; 
 727             key_code 
= WXK_SELECT
; 
 731             key_code 
= WXK_PRINT
; 
 735             key_code 
= WXK_EXECUTE
; 
 739             key_code 
= WXK_ESCAPE
; 
 742         // cursor and other extended keyboard keys 
 744             key_code 
= WXK_DELETE
; 
 760             key_code 
= WXK_RIGHT
; 
 767         case GDK_Prior
:     // == GDK_Page_Up 
 768             key_code 
= WXK_PRIOR
; 
 771         case GDK_Next
:      // == GDK_Page_Down 
 784             key_code 
= WXK_INSERT
; 
 799             key_code 
= (isChar 
? '0' : WXK_NUMPAD0
) + keysym 
- GDK_KP_0
; 
 803             key_code 
= isChar 
? ' ' : WXK_NUMPAD_SPACE
; 
 807             key_code 
= isChar 
? WXK_TAB 
: WXK_NUMPAD_TAB
; 
 811             key_code 
= isChar 
? WXK_RETURN 
: WXK_NUMPAD_ENTER
; 
 815             key_code 
= isChar 
? WXK_F1 
: WXK_NUMPAD_F1
; 
 819             key_code 
= isChar 
? WXK_F2 
: WXK_NUMPAD_F2
; 
 823             key_code 
= isChar 
? WXK_F3 
: WXK_NUMPAD_F3
; 
 827             key_code 
= isChar 
? WXK_F4 
: WXK_NUMPAD_F4
; 
 831             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_HOME
; 
 835             key_code 
= isChar 
? WXK_LEFT 
: WXK_NUMPAD_LEFT
; 
 839             key_code 
= isChar 
? WXK_UP 
: WXK_NUMPAD_UP
; 
 843             key_code 
= isChar 
? WXK_RIGHT 
: WXK_NUMPAD_RIGHT
; 
 847             key_code 
= isChar 
? WXK_DOWN 
: WXK_NUMPAD_DOWN
; 
 850         case GDK_KP_Prior
: // == GDK_KP_Page_Up 
 851             key_code 
= isChar 
? WXK_PRIOR 
: WXK_NUMPAD_PRIOR
; 
 854         case GDK_KP_Next
: // == GDK_KP_Page_Down 
 855             key_code 
= isChar 
? WXK_NEXT 
: WXK_NUMPAD_NEXT
; 
 859             key_code 
= isChar 
? WXK_END 
: WXK_NUMPAD_END
; 
 863             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_BEGIN
; 
 867             key_code 
= isChar 
? WXK_INSERT 
: WXK_NUMPAD_INSERT
; 
 871             key_code 
= isChar 
? WXK_DELETE 
: WXK_NUMPAD_DELETE
; 
 875             key_code 
= isChar 
? '=' : WXK_NUMPAD_EQUAL
; 
 878         case GDK_KP_Multiply
: 
 879             key_code 
= isChar 
? '*' : WXK_NUMPAD_MULTIPLY
; 
 883             key_code 
= isChar 
? '+' : WXK_NUMPAD_ADD
; 
 886         case GDK_KP_Separator
: 
 887             // FIXME: what is this? 
 888             key_code 
= isChar 
? '.' : WXK_NUMPAD_SEPARATOR
; 
 891         case GDK_KP_Subtract
: 
 892             key_code 
= isChar 
? '-' : WXK_NUMPAD_SUBTRACT
; 
 896             key_code 
= isChar 
? '.' : WXK_NUMPAD_DECIMAL
; 
 900             key_code 
= isChar 
? '/' : WXK_NUMPAD_DIVIDE
; 
 917             key_code 
= WXK_F1 
+ keysym 
- GDK_F1
; 
 927 static inline bool wxIsAsciiKeysym(KeySym ks
) 
 933 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
, 
 935                            GdkEventKey 
*gdk_event
) 
 937     // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string 
 938     //     but only event->keyval which is quite useless to us, so remember 
 939     //     the last character from GDK_KEY_PRESS and reuse it as last resort 
 941     // NB: should be MT-safe as we're always called from the main thread only 
 946     } s_lastKeyPress 
= { 0, 0 }; 
 948     KeySym keysym 
= gdk_event
->keyval
; 
 950     wxLogTrace(TRACE_KEYS
, _T("Key %s event: keysym = %ld"), 
 951                event
.GetEventType() == wxEVT_KEY_UP 
? _T("release") 
 955     long key_code 
= wxTranslateKeySymToWXKey(keysym
, FALSE 
/* !isChar */); 
 959         // do we have the translation or is it a plain ASCII character? 
 960         if ( (gdk_event
->length 
== 1) || wxIsAsciiKeysym(keysym
) ) 
 962             // we should use keysym if it is ASCII as X does some translations 
 963             // like "I pressed while Control is down" => "Ctrl-I" == "TAB" 
 964             // which we don't want here (but which we do use for OnChar()) 
 965             if ( !wxIsAsciiKeysym(keysym
) ) 
 967                 keysym 
= (KeySym
)gdk_event
->string
[0]; 
 970             // we want to always get the same key code when the same key is 
 971             // pressed regardless of the state of the modifies, i.e. on a 
 972             // standard US keyboard pressing '5' or '%' ('5' key with 
 973             // Shift) should result in the same key code in OnKeyDown(): 
 974             // '5' (although OnChar() will get either '5' or '%'). 
 976             // to do it we first translate keysym to keycode (== scan code) 
 977             // and then back but always using the lower register 
 978             Display 
*dpy 
= (Display 
*)wxGetDisplay(); 
 979             KeyCode keycode 
= XKeysymToKeycode(dpy
, keysym
); 
 981             wxLogTrace(TRACE_KEYS
, _T("\t-> keycode %d"), keycode
); 
 983             KeySym keysymNormalized 
= XKeycodeToKeysym(dpy
, keycode
, 0); 
 985             // use the normalized, i.e. lower register, keysym if we've 
 987             key_code 
= keysymNormalized 
? keysymNormalized 
: keysym
; 
 989             // as explained above, we want to have lower register key codes 
 990             // normally but for the letter keys we want to have the upper ones 
 992             // NB: don't use XConvertCase() here, we want to do it for letters 
 994             key_code 
= toupper(key_code
); 
 996         else // non ASCII key, what to do? 
 998             // by default, ignore it 
1001             // but if we have cached information from the last KEY_PRESS 
1002             if ( gdk_event
->type 
== GDK_KEY_RELEASE 
) 
1005                 if ( keysym 
== s_lastKeyPress
.keysym 
) 
1007                     key_code 
= s_lastKeyPress
.keycode
; 
1012         if ( gdk_event
->type 
== GDK_KEY_PRESS 
) 
1014             // remember it to be reused for KEY_UP event later 
1015             s_lastKeyPress
.keysym 
= keysym
; 
1016             s_lastKeyPress
.keycode 
= key_code
; 
1020     wxLogTrace(TRACE_KEYS
, _T("\t-> wxKeyCode %ld"), key_code
); 
1022     // sending unknown key events doesn't really make sense 
1026     // now fill all the other fields 
1029     GdkModifierType state
; 
1030     if (gdk_event
->window
) 
1031         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1033     event
.SetTimestamp( gdk_event
->time 
); 
1034     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
) != 0; 
1035     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
) != 0; 
1036     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
) != 0; 
1037     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
) != 0; 
1038     event
.m_keyCode 
= key_code
; 
1039     event
.m_scanCode 
= gdk_event
->keyval
; 
1040     event
.m_rawCode 
= (wxUint32
) gdk_event
->keyval
; 
1041     event
.m_rawFlags 
= 0; 
1044     event
.SetEventObject( win 
); 
1049 static gint 
gtk_window_key_press_callback( GtkWidget 
*widget
, 
1050                                            GdkEventKey 
*gdk_event
, 
1056         wxapp_install_idle_handler(); 
1060     if (g_blockEventsOnDrag
) 
1064     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
1065     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1067         // unknown key pressed, ignore (the event would be useless anyhow) 
1071     // Emit KEY_DOWN event 
1072     bool ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1077         wxWindowGTK 
*ancestor 
= win
; 
1080             int command 
= ancestor
->GetAcceleratorTable()->GetCommand( event 
); 
1083                 wxCommandEvent 
command_event( wxEVT_COMMAND_MENU_SELECTED
, command 
); 
1084                 ret 
= ancestor
->GetEventHandler()->ProcessEvent( command_event 
); 
1087             if (ancestor
->IsTopLevel()) 
1089             ancestor 
= ancestor
->GetParent(); 
1092 #endif // wxUSE_ACCEL 
1094     // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x 
1095     // will only be sent if it is not in an accelerator table. 
1098         // Find key code for EVT_CHAR and EVT_CHAR_HOOK events 
1099         KeySym keysym 
= gdk_event
->keyval
; 
1100         long key_code 
= wxTranslateKeySymToWXKey(keysym
, TRUE 
/* isChar */); 
1103             if ( gdk_event
->length 
== 1 ) 
1105                 key_code 
= (unsigned char)gdk_event
->string
[0]; 
1107             else if ( wxIsAsciiKeysym(keysym
) ) 
1110                 key_code 
= (unsigned char)keysym
; 
1116             wxLogTrace(TRACE_KEYS
, _T("Char event: %ld"), key_code
); 
1118             event
.m_keyCode 
= key_code
; 
1120             // Implement OnCharHook by checking ancesteror top level windows 
1121             wxWindow 
*parent 
= win
; 
1122             while (parent 
&& !parent
->IsTopLevel()) 
1123             parent 
= parent
->GetParent(); 
1126                 event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1127                 ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1132                 event
.SetEventType(wxEVT_CHAR
); 
1133                 ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1138     // win is a control: tab can be propagated up 
1140          ((gdk_event
->keyval 
== GDK_Tab
) || (gdk_event
->keyval 
== GDK_ISO_Left_Tab
)) && 
1141 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may 
1142 //     have this style, yet choose not to process this particular TAB in which 
1143 //     case TAB must still work as a navigational character 
1145          !win
->HasFlag(wxTE_PROCESS_TAB
) && 
1147          win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) ) 
1149         wxNavigationKeyEvent new_event
; 
1150         new_event
.SetEventObject( win
->GetParent() ); 
1151         // GDK reports GDK_ISO_Left_Tab for SHIFT-TAB 
1152         new_event
.SetDirection( (gdk_event
->keyval 
== GDK_Tab
) ); 
1153         // CTRL-TAB changes the (parent) window, i.e. switch notebook page 
1154         new_event
.SetWindowChange( (gdk_event
->state 
& GDK_CONTROL_MASK
) ); 
1155         new_event
.SetCurrentFocus( win 
); 
1156         ret 
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event 
); 
1159     // generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) 
1161          (gdk_event
->keyval 
== GDK_Escape
) ) 
1163         wxCommandEvent 
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
); 
1164         new_event
.SetEventObject( win 
); 
1165         ret 
= win
->GetEventHandler()->ProcessEvent( new_event 
); 
1170     // Pressing F10 will activate the menu bar of the top frame 
1172          (gdk_event
->keyval 
== GDK_F10
) ) 
1174         wxWindowGTK 
*ancestor 
= win
; 
1177             if (wxIsKindOf(ancestor
,wxFrame
)) 
1179                 wxFrame 
*frame 
= (wxFrame
*) ancestor
; 
1180                 wxMenuBar 
*menubar 
= frame
->GetMenuBar(); 
1183                     wxNode 
*node 
= menubar
->GetMenus().First(); 
1186                         wxMenu 
*firstMenu 
= (wxMenu
*) node
->Data(); 
1187                         gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) ); 
1193             ancestor 
= ancestor
->GetParent(); 
1200         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" ); 
1207 //----------------------------------------------------------------------------- 
1208 // "key_release_event" from any window 
1209 //----------------------------------------------------------------------------- 
1211 static gint 
gtk_window_key_release_callback( GtkWidget 
*widget
, 
1212                                              GdkEventKey 
*gdk_event
, 
1218         wxapp_install_idle_handler(); 
1223     if (g_blockEventsOnDrag
) 
1226     wxKeyEvent 
event( wxEVT_KEY_UP 
); 
1227     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1229         // unknown key pressed, ignore (the event would be useless anyhow 
1233     if ( !win
->GetEventHandler()->ProcessEvent( event 
) ) 
1236     gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" ); 
1240 // ============================================================================ 
1242 // ============================================================================ 
1244 // ---------------------------------------------------------------------------- 
1245 // mouse event processing helpers 
1246 // ---------------------------------------------------------------------------- 
1248 // init wxMouseEvent with the info from gdk_event 
1250 // NB: this has to be a macro as gdk_event type is different for different 
1251 //     events we're used with 
1252 #define InitMouseEvent(/* wxWindowGTK * */ win,                               \ 
1253                        /* wxMouseEvent& */ event,                             \ 
1254                        /* GdkEventXXX * */ gdk_event)                         \ 
1256     event.SetTimestamp( gdk_event->time );                                    \ 
1257     event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);                  \ 
1258     event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);              \ 
1259     event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);                     \ 
1260     event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);                    \ 
1261     event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);                 \ 
1262     event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);               \ 
1263     event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);                \ 
1265     wxPoint pt = win->GetClientAreaOrigin();                                  \ 
1266     event.m_x = (wxCoord)gdk_event->x - pt.x;                                 \ 
1267     event.m_y = (wxCoord)gdk_event->y - pt.y;                                 \ 
1269     event.SetEventObject( win );                                              \ 
1270     event.SetId( win->GetId() );                                              \ 
1271     event.SetTimestamp( gdk_event->time );                                    \ 
1274 static void AdjustEventButtonState(wxMouseEvent& event) 
1276     // GDK reports the old state of the button for a button press event, but 
1277     // for compatibility with MSW and common sense we want m_leftDown be TRUE 
1278     // for a LEFT_DOWN event, not FALSE, so we will invert 
1279     // left/right/middleDown for the corresponding click events 
1281     if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) || 
1282         (event
.GetEventType() == wxEVT_LEFT_DCLICK
) || 
1283         (event
.GetEventType() == wxEVT_LEFT_UP
)) 
1285         event
.m_leftDown 
= !event
.m_leftDown
; 
1289     if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) || 
1290         (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) || 
1291         (event
.GetEventType() == wxEVT_MIDDLE_UP
)) 
1293         event
.m_middleDown 
= !event
.m_middleDown
; 
1297     if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) || 
1298         (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) || 
1299         (event
.GetEventType() == wxEVT_RIGHT_UP
)) 
1301         event
.m_rightDown 
= !event
.m_rightDown
; 
1306 // find the window to send the mouse event too 
1308 wxWindowGTK 
*FindWindowForMouseEvent(wxWindowGTK 
*win
, wxCoord
& x
, wxCoord
& y
) 
1313     if (win
->m_wxwindow
) 
1315         GtkPizza 
*pizza 
= GTK_PIZZA(win
->m_wxwindow
); 
1316         xx 
+= pizza
->xoffset
; 
1317         yy 
+= pizza
->yoffset
; 
1320     wxNode 
*node 
= win
->GetChildren().First(); 
1323         wxWindowGTK 
*child 
= (wxWindowGTK
*)node
->Data(); 
1325         node 
= node
->Next(); 
1326         if (!child
->IsShown()) 
1329         if (child
->IsTransparentForMouse()) 
1331             // wxStaticBox is transparent in the box itself 
1332             int xx1 
= child
->m_x
; 
1333             int yy1 
= child
->m_y
; 
1334             int xx2 
= child
->m_x 
+ child
->m_width
; 
1335             int yy2 
= child
->m_x 
+ child
->m_height
; 
1338             if (((xx 
>= xx1
) && (xx 
<= xx1
+10) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1340                 ((xx 
>= xx2
-10) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1342                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy1
+10)) || 
1344                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy2
-1) && (yy 
<= yy2
))) 
1355             if ((child
->m_wxwindow 
== (GtkWidget
*) NULL
) && 
1356                 (child
->m_x 
<= xx
) && 
1357                 (child
->m_y 
<= yy
) && 
1358                 (child
->m_x
+child
->m_width  
>= xx
) && 
1359                 (child
->m_y
+child
->m_height 
>= yy
)) 
1372 //----------------------------------------------------------------------------- 
1373 // "button_press_event" 
1374 //----------------------------------------------------------------------------- 
1376 static gint 
gtk_window_button_press_callback( GtkWidget 
*widget
, 
1377                                               GdkEventButton 
*gdk_event
, 
1383         wxapp_install_idle_handler(); 
1386     wxPrintf( wxT("1) OnButtonPress from ") ); 
1387     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1388         wxPrintf( win->GetClassInfo()->GetClassName() ); 
1389     wxPrintf( wxT(".\n") ); 
1391     if (!win
->m_hasVMT
) return FALSE
; 
1392     if (g_blockEventsOnDrag
) return TRUE
; 
1393     if (g_blockEventsOnScroll
) return TRUE
; 
1395     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1397     if (win
->m_wxwindow 
&& (g_focusWindow 
!= win
) && win
->AcceptsFocus()) 
1399         gtk_widget_grab_focus( win
->m_wxwindow 
); 
1401         wxPrintf( wxT("GrabFocus from ") ); 
1402         if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1403             wxPrintf( win->GetClassInfo()->GetClassName() ); 
1404         wxPrintf( wxT(".\n") ); 
1408     wxEventType event_type 
= wxEVT_NULL
; 
1410     if (gdk_event
->button 
== 1) 
1412         switch (gdk_event
->type
) 
1414             case GDK_BUTTON_PRESS
: event_type 
= wxEVT_LEFT_DOWN
; break; 
1415             case GDK_2BUTTON_PRESS
: event_type 
= wxEVT_LEFT_DCLICK
; break; 
1419     else if (gdk_event
->button 
== 2) 
1421         switch (gdk_event
->type
) 
1423             case GDK_BUTTON_PRESS
: event_type 
= wxEVT_MIDDLE_DOWN
; break; 
1424             case GDK_2BUTTON_PRESS
: event_type 
= wxEVT_MIDDLE_DCLICK
; break; 
1428     else if (gdk_event
->button 
== 3) 
1430         switch (gdk_event
->type
) 
1432             case GDK_BUTTON_PRESS
: event_type 
= wxEVT_RIGHT_DOWN
; break; 
1433             case GDK_2BUTTON_PRESS
: event_type 
= wxEVT_RIGHT_DCLICK
; break; 
1438     if ( event_type 
== wxEVT_NULL 
) 
1440         // unknown mouse button or click type 
1444     wxMouseEvent 
event( event_type 
); 
1445     InitMouseEvent( win
, event
, gdk_event 
); 
1447     AdjustEventButtonState(event
); 
1449     // wxListBox actually get mouse events from the item, so we need to give it 
1450     // a chance to correct this 
1451     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1453     // find the correct window to send the event too: it may be a different one 
1454     // from the one which got it at GTK+ level because some control don't have 
1455     // their own X window and thus cannot get any events. 
1456     if ( !g_captureWindow 
) 
1457         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1459     gs_timeLastClick 
= gdk_event
->time
; 
1462     wxPrintf( wxT("2) OnButtonPress from ") ); 
1463     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1464         wxPrintf( win->GetClassInfo()->GetClassName() ); 
1465     wxPrintf( wxT(".\n") ); 
1468     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1470         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" ); 
1477 //----------------------------------------------------------------------------- 
1478 // "button_release_event" 
1479 //----------------------------------------------------------------------------- 
1481 static gint 
gtk_window_button_release_callback( GtkWidget 
*widget
, GdkEventButton 
*gdk_event
, wxWindowGTK 
*win 
) 
1486         wxapp_install_idle_handler(); 
1488     if (!win
->m_hasVMT
) return FALSE
; 
1489     if (g_blockEventsOnDrag
) return FALSE
; 
1490     if (g_blockEventsOnScroll
) return FALSE
; 
1492     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1495     printf( "OnButtonRelease from " ); 
1496     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1497         printf( win->GetClassInfo()->GetClassName() ); 
1501     wxEventType event_type 
= wxEVT_NULL
; 
1503     switch (gdk_event
->button
) 
1505         case 1: event_type 
= wxEVT_LEFT_UP
; break; 
1506         case 2: event_type 
= wxEVT_MIDDLE_UP
; break; 
1507         case 3: event_type 
= wxEVT_RIGHT_UP
; break; 
1508         default: return FALSE
; 
1511     wxMouseEvent 
event( event_type 
); 
1512     InitMouseEvent( win
, event
, gdk_event 
); 
1514     AdjustEventButtonState(event
); 
1516     // same wxListBox hack as above 
1517     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1519     if ( !g_captureWindow 
) 
1520         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1522     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1524         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" ); 
1531 //----------------------------------------------------------------------------- 
1532 // "motion_notify_event" 
1533 //----------------------------------------------------------------------------- 
1535 static gint 
gtk_window_motion_notify_callback( GtkWidget 
*widget
, 
1536                                                GdkEventMotion 
*gdk_event
, 
1542         wxapp_install_idle_handler(); 
1544     if (!win
->m_hasVMT
) return FALSE
; 
1545     if (g_blockEventsOnDrag
) return FALSE
; 
1546     if (g_blockEventsOnScroll
) return FALSE
; 
1548     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1550     if (gdk_event
->is_hint
) 
1554         GdkModifierType state
; 
1555         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1561     printf( "OnMotion from " ); 
1562     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1563       printf( win->GetClassInfo()->GetClassName() ); 
1567     wxMouseEvent 
event( wxEVT_MOTION 
); 
1568     InitMouseEvent(win
, event
, gdk_event
); 
1570     if ( g_captureWindow 
) 
1572         // synthetize a mouse enter or leave event if needed 
1573         GdkWindow 
*winUnderMouse 
= gdk_window_at_pointer(NULL
, NULL
); 
1574         bool hasMouse 
= winUnderMouse 
== gdk_event
->window
; 
1575         if ( hasMouse 
!= g_captureWindowHasMouse 
) 
1577             // the mouse changed window 
1578             g_captureWindowHasMouse 
= hasMouse
; 
1580             wxMouseEvent 
event(g_captureWindowHasMouse 
? wxEVT_ENTER_WINDOW
 
1581                                                        : wxEVT_LEAVE_WINDOW
); 
1582             InitMouseEvent(win
, event
, gdk_event
); 
1583             event
.SetEventObject(win
); 
1584             win
->GetEventHandler()->ProcessEvent(event
); 
1589         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1592     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1594         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" ); 
1601 //----------------------------------------------------------------------------- 
1603 //----------------------------------------------------------------------------- 
1605 // send the wxChildFocusEvent and wxFocusEvent, common code of 
1606 // gtk_window_focus_in_callback() and SetFocus() 
1607 static bool DoSendFocusEvents(wxWindow 
*win
) 
1609     // Notify the parent keeping track of focus for the kbd navigation 
1610     // purposes that we got it. 
1611     wxChildFocusEvent 
eventChildFocus(win
); 
1612     (void)win
->GetEventHandler()->ProcessEvent(eventChildFocus
); 
1614     wxFocusEvent 
eventFocus(wxEVT_SET_FOCUS
, win
->GetId()); 
1615     eventFocus
.SetEventObject(win
); 
1617     return win
->GetEventHandler()->ProcessEvent(eventFocus
); 
1620 static gint 
gtk_window_focus_in_callback( GtkWidget 
*widget
, 
1621                                           GdkEvent 
*WXUNUSED(event
), 
1627         wxapp_install_idle_handler(); 
1629     if (!win
->m_hasVMT
) return FALSE
; 
1630     if (g_blockEventsOnDrag
) return FALSE
; 
1632     switch ( g_sendActivateEvent 
) 
1635             // we've got focus from outside, synthetize wxActivateEvent 
1636             g_sendActivateEvent 
= 1; 
1640             // another our window just lost focus, it was already ours before 
1641             // - don't send any wxActivateEvent 
1642             g_sendActivateEvent 
= -1; 
1647     g_focusWindow 
= win
; 
1649     wxLogTrace(TRACE_FOCUS
, 
1650                _T("%s: focus in"), win
->GetName().c_str()); 
1654         gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
); 
1658     // caret needs to be informed about focus change 
1659     wxCaret 
*caret 
= win
->GetCaret(); 
1662         caret
->OnSetFocus(); 
1664 #endif // wxUSE_CARET 
1666     g_activeFrameLostFocus 
= FALSE
; 
1668     wxWindowGTK 
*active 
= wxGetTopLevelParent(win
); 
1669     if ( active 
!= g_activeFrame 
) 
1671         if ( g_activeFrame 
) 
1673             wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
); 
1674             wxActivateEvent 
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId()); 
1675             event
.SetEventObject(g_activeFrame
); 
1676             g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
1679         wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
); 
1680         g_activeFrame 
= active
; 
1681         wxActivateEvent 
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId()); 
1682         event
.SetEventObject(g_activeFrame
); 
1683         g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
1685         // Don't send focus events in addition to activate 
1686         // if (win == g_activeFrame) 
1690     // does the window itself think that it has the focus? 
1691     if ( !win
->m_hasFocus 
) 
1693         // not yet, notify it 
1694         win
->m_hasFocus 
= TRUE
; 
1696         if ( DoSendFocusEvents(win
) ) 
1698            gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" ); 
1706 //----------------------------------------------------------------------------- 
1707 // "focus_out_event" 
1708 //----------------------------------------------------------------------------- 
1710 static gint 
gtk_window_focus_out_callback( GtkWidget 
*widget
, GdkEventFocus 
*gdk_event
, wxWindowGTK 
*win 
) 
1715         wxapp_install_idle_handler(); 
1717     if (!win
->m_hasVMT
) return FALSE
; 
1718     if (g_blockEventsOnDrag
) return FALSE
; 
1720     wxLogTrace( TRACE_FOCUS
, 
1721                 _T("%s: focus out"), win
->GetName().c_str() ); 
1723     if ( !g_activeFrameLostFocus 
&& g_activeFrame 
) 
1725         // VZ: commenting this out because it does happen (although not easy 
1726         //     to reproduce, I only see it when using wxMiniFrame and not 
1727         //     always) and makes using Mahogany quite annoying 
1729         wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
, 
1730                         wxT("unfocusing window that hasn't gained focus properly") ); 
1733         g_activeFrameLostFocus 
= TRUE
; 
1736     // if the focus goes out of our app alltogether, OnIdle() will send 
1737     // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset 
1738     // g_sendActivateEvent to -1 
1739     g_sendActivateEvent 
= 0; 
1741     wxWindowGTK 
*winFocus 
= wxFindFocusedChild(win
); 
1745     g_focusWindow 
= (wxWindowGTK 
*)NULL
; 
1753     // caret needs to be informed about focus change 
1754     wxCaret 
*caret 
= win
->GetCaret(); 
1757         caret
->OnKillFocus(); 
1759 #endif // wxUSE_CARET 
1761     // don't send the window a kill focus event if it thinks that it doesn't 
1762     // have focus already 
1763     if ( win
->m_hasFocus 
) 
1765         win
->m_hasFocus 
= FALSE
; 
1767         wxFocusEvent 
event( wxEVT_KILL_FOCUS
, win
->GetId() ); 
1768         event
.SetEventObject( win 
); 
1770         if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1772             gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" ); 
1780 //----------------------------------------------------------------------------- 
1781 // "enter_notify_event" 
1782 //----------------------------------------------------------------------------- 
1785 gint 
gtk_window_enter_callback( GtkWidget 
*widget
, 
1786                                 GdkEventCrossing 
*gdk_event
, 
1792         wxapp_install_idle_handler(); 
1794     if (!win
->m_hasVMT
) return FALSE
; 
1795     if (g_blockEventsOnDrag
) return FALSE
; 
1797     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1801     GdkModifierType state 
= (GdkModifierType
)0; 
1803     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
1805     wxMouseEvent 
event( wxEVT_ENTER_WINDOW 
); 
1806     InitMouseEvent(win
, event
, gdk_event
); 
1807     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1808     event
.m_x 
= x 
+ pt
.x
; 
1809     event
.m_y 
= y 
+ pt
.y
; 
1811     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1813        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" ); 
1820 //----------------------------------------------------------------------------- 
1821 // "leave_notify_event" 
1822 //----------------------------------------------------------------------------- 
1824 static gint 
gtk_window_leave_callback( GtkWidget 
*widget
, GdkEventCrossing 
*gdk_event
, wxWindowGTK 
*win 
) 
1829         wxapp_install_idle_handler(); 
1831     if (!win
->m_hasVMT
) return FALSE
; 
1832     if (g_blockEventsOnDrag
) return FALSE
; 
1834     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1836     wxMouseEvent 
event( wxEVT_LEAVE_WINDOW 
); 
1837     event
.SetTimestamp( gdk_event
->time 
); 
1838     event
.SetEventObject( win 
); 
1842     GdkModifierType state 
= (GdkModifierType
)0; 
1844     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
1846     event
.m_shiftDown 
= (state 
& GDK_SHIFT_MASK
) != 0; 
1847     event
.m_controlDown 
= (state 
& GDK_CONTROL_MASK
) != 0; 
1848     event
.m_altDown 
= (state 
& GDK_MOD1_MASK
) != 0; 
1849     event
.m_metaDown 
= (state 
& GDK_MOD2_MASK
) != 0; 
1850     event
.m_leftDown 
= (state 
& GDK_BUTTON1_MASK
) != 0; 
1851     event
.m_middleDown 
= (state 
& GDK_BUTTON2_MASK
) != 0; 
1852     event
.m_rightDown 
= (state 
& GDK_BUTTON3_MASK
) != 0; 
1854     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1855     event
.m_x 
= x 
+ pt
.x
; 
1856     event
.m_y 
= y 
+ pt
.y
; 
1858     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1860         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" ); 
1867 //----------------------------------------------------------------------------- 
1868 // "value_changed" from m_vAdjust 
1869 //----------------------------------------------------------------------------- 
1871 static void gtk_window_vscroll_callback( GtkAdjustment 
*adjust
, 
1878         wxapp_install_idle_handler(); 
1880     if (g_blockEventsOnDrag
) return; 
1882     if (!win
->m_hasVMT
) return; 
1884     float diff 
= adjust
->value 
- win
->m_oldVerticalPos
; 
1885     if (fabs(diff
) < 0.2) return; 
1887     win
->m_oldVerticalPos 
= adjust
->value
; 
1889     GtkScrolledWindow   
*sw 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
1890     wxEventType         command 
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->vscrollbar
)); 
1892     int value 
= (int)(adjust
->value
+0.5); 
1894     wxScrollWinEvent 
event( command
, value
, wxVERTICAL 
); 
1895     event
.SetEventObject( win 
); 
1896     win
->GetEventHandler()->ProcessEvent( event 
); 
1899 //----------------------------------------------------------------------------- 
1900 // "value_changed" from m_hAdjust 
1901 //----------------------------------------------------------------------------- 
1903 static void gtk_window_hscroll_callback( GtkAdjustment 
*adjust
, 
1910         wxapp_install_idle_handler(); 
1912     if (g_blockEventsOnDrag
) return; 
1913     if (!win
->m_hasVMT
) return; 
1915     float diff 
= adjust
->value 
- win
->m_oldHorizontalPos
; 
1916     if (fabs(diff
) < 0.2) return; 
1918     GtkScrolledWindow   
*sw 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
1919     wxEventType         command 
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->hscrollbar
)); 
1921     win
->m_oldHorizontalPos 
= adjust
->value
; 
1923     int value 
= (int)(adjust
->value
+0.5); 
1925     wxScrollWinEvent 
event( command
, value
, wxHORIZONTAL 
); 
1926     event
.SetEventObject( win 
); 
1927     win
->GetEventHandler()->ProcessEvent( event 
); 
1930 //----------------------------------------------------------------------------- 
1931 // "button_press_event" from scrollbar 
1932 //----------------------------------------------------------------------------- 
1934 static gint 
gtk_scrollbar_button_press_callback( GtkRange 
*widget
, 
1935                                                  GdkEventButton 
*gdk_event
, 
1941         wxapp_install_idle_handler(); 
1944     g_blockEventsOnScroll 
= TRUE
; 
1946     // FIXME: there is no 'slider' field in GTK+ 2.0 any more 
1948     win
->m_isScrolling 
= (gdk_event
->window 
== widget
->slider
); 
1954 //----------------------------------------------------------------------------- 
1955 // "button_release_event" from scrollbar 
1956 //----------------------------------------------------------------------------- 
1958 static gint 
gtk_scrollbar_button_release_callback( GtkRange 
*widget
, 
1959                                                    GdkEventButton 
*WXUNUSED(gdk_event
), 
1964 //  don't test here as we can release the mouse while being over 
1965 //  a different window than the slider 
1967 //    if (gdk_event->window != widget->slider) return FALSE; 
1969     g_blockEventsOnScroll 
= FALSE
; 
1971     if (win
->m_isScrolling
) 
1973         wxEventType command 
= wxEVT_SCROLLWIN_THUMBRELEASE
; 
1977         GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
1978         if (widget 
== GTK_RANGE(scrolledWindow
->hscrollbar
)) 
1980             value 
= (int)(win
->m_hAdjust
->value
+0.5); 
1983         if (widget 
== GTK_RANGE(scrolledWindow
->vscrollbar
)) 
1985             value 
= (int)(win
->m_vAdjust
->value
+0.5); 
1989         wxScrollWinEvent 
event( command
, value
, dir 
); 
1990         event
.SetEventObject( win 
); 
1991         win
->GetEventHandler()->ProcessEvent( event 
); 
1994     win
->m_isScrolling 
= FALSE
; 
1999 // ---------------------------------------------------------------------------- 
2000 // this wxWindowBase function is implemented here (in platform-specific file) 
2001 // because it is static and so couldn't be made virtual 
2002 // ---------------------------------------------------------------------------- 
2004 wxWindow 
*wxWindowBase::FindFocus() 
2006     // the cast is necessary when we compile in wxUniversal mode 
2007     return (wxWindow 
*)g_focusWindow
; 
2010 //----------------------------------------------------------------------------- 
2012 //----------------------------------------------------------------------------- 
2014 // VZ: Robert commented the code using out so it generates warnings: should 
2015 //     be either fixed or removed completely 
2018 static void gtk_window_destroy_callback( GtkWidget
* widget
, wxWindow 
*win 
) 
2020     wxWindowDestroyEvent 
event(win
); 
2021     win
->GetEventHandler()->ProcessEvent(event
); 
2026 //----------------------------------------------------------------------------- 
2027 // "realize" from m_widget 
2028 //----------------------------------------------------------------------------- 
2030 /* We cannot set colours and fonts before the widget has 
2031    been realized, so we do this directly after realization. */ 
2034 gtk_window_realized_callback( GtkWidget 
*WXUNUSED(m_widget
), wxWindow 
*win 
) 
2039         wxapp_install_idle_handler(); 
2041     if (win
->m_delayedBackgroundColour
) 
2042         win
->GtkSetBackgroundColour( win
->GetBackgroundColour() ); 
2044     if (win
->m_delayedForegroundColour
) 
2045         win
->GtkSetForegroundColour( win
->GetForegroundColour() ); 
2047     wxWindowCreateEvent 
event( win 
); 
2048     event
.SetEventObject( win 
); 
2049     win
->GetEventHandler()->ProcessEvent( event 
); 
2054 //----------------------------------------------------------------------------- 
2056 //----------------------------------------------------------------------------- 
2059 void gtk_window_size_callback( GtkWidget 
*WXUNUSED(widget
), 
2060                                GtkAllocation 
*WXUNUSED(alloc
), 
2064         wxapp_install_idle_handler(); 
2066     if (!win
->m_hasScrolling
) return; 
2068     int client_width 
= 0; 
2069     int client_height 
= 0; 
2070     win
->GetClientSize( &client_width
, &client_height 
); 
2071     if ((client_width 
== win
->m_oldClientWidth
) && (client_height 
== win
->m_oldClientHeight
)) 
2074     win
->m_oldClientWidth 
= client_width
; 
2075     win
->m_oldClientHeight 
= client_height
; 
2077     if (!win
->m_nativeSizeEvent
) 
2079         wxSizeEvent 
event( win
->GetSize(), win
->GetId() ); 
2080         event
.SetEventObject( win 
); 
2081         win
->GetEventHandler()->ProcessEvent( event 
); 
2087     #define WXUNUSED_UNLESS_XIM(param)  param 
2089     #define WXUNUSED_UNLESS_XIM(param)  WXUNUSED(param) 
2092 /* Resize XIM window */ 
2095 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
), 
2096                                  GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
), 
2097                                  wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) ) 
2100         wxapp_install_idle_handler(); 
2106     if  (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
) 
2110         gdk_window_get_size (widget
->window
, &width
, &height
); 
2111         win
->m_icattr
->preedit_area
.width 
= width
; 
2112         win
->m_icattr
->preedit_area
.height 
= height
; 
2113         gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
); 
2118 //----------------------------------------------------------------------------- 
2119 // "realize" from m_wxwindow 
2120 //----------------------------------------------------------------------------- 
2122 /* Initialize XIM support */ 
2125 gtk_wxwindow_realized_callback( GtkWidget 
* WXUNUSED_UNLESS_XIM(widget
), 
2126                                 wxWindowGTK 
* WXUNUSED_UNLESS_XIM(win
) ) 
2129         wxapp_install_idle_handler(); 
2132     if (win
->m_ic
) return FALSE
; 
2133     if (!widget
) return FALSE
; 
2134     if (!gdk_im_ready()) return FALSE
; 
2136     win
->m_icattr 
= gdk_ic_attr_new(); 
2137     if (!win
->m_icattr
) return FALSE
; 
2141     GdkColormap 
*colormap
; 
2142     GdkICAttr 
*attr 
= win
->m_icattr
; 
2143     unsigned attrmask 
= GDK_IC_ALL_REQ
; 
2145     GdkIMStyle supported_style 
= (GdkIMStyle
) 
2146                                   (GDK_IM_PREEDIT_NONE 
| 
2147                                    GDK_IM_PREEDIT_NOTHING 
| 
2148                                    GDK_IM_PREEDIT_POSITION 
| 
2149                                    GDK_IM_STATUS_NONE 
| 
2150                                    GDK_IM_STATUS_NOTHING
); 
2152     if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2153         supported_style 
= (GdkIMStyle
)(supported_style 
& ~GDK_IM_PREEDIT_POSITION
); 
2155     attr
->style 
= style 
= gdk_im_decide_style (supported_style
); 
2156     attr
->client_window 
= widget
->window
; 
2158     if ((colormap 
= gtk_widget_get_colormap (widget
)) != 
2159             gtk_widget_get_default_colormap ()) 
2161         attrmask 
|= GDK_IC_PREEDIT_COLORMAP
; 
2162         attr
->preedit_colormap 
= colormap
; 
2165     attrmask 
|= GDK_IC_PREEDIT_FOREGROUND
; 
2166     attrmask 
|= GDK_IC_PREEDIT_BACKGROUND
; 
2167     attr
->preedit_foreground 
= widget
->style
->fg
[GTK_STATE_NORMAL
]; 
2168     attr
->preedit_background 
= widget
->style
->base
[GTK_STATE_NORMAL
]; 
2170     switch (style 
& GDK_IM_PREEDIT_MASK
) 
2172         case GDK_IM_PREEDIT_POSITION
: 
2173             if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2175                 g_warning ("over-the-spot style requires fontset"); 
2179             gdk_window_get_size (widget
->window
, &width
, &height
); 
2181             attrmask 
|= GDK_IC_PREEDIT_POSITION_REQ
; 
2182             attr
->spot_location
.x 
= 0; 
2183             attr
->spot_location
.y 
= height
; 
2184             attr
->preedit_area
.x 
= 0; 
2185             attr
->preedit_area
.y 
= 0; 
2186             attr
->preedit_area
.width 
= width
; 
2187             attr
->preedit_area
.height 
= height
; 
2188             attr
->preedit_fontset 
= widget
->style
->font
; 
2193       win
->m_ic 
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
); 
2195       if (win
->m_ic 
== NULL
) 
2196           g_warning ("Can't create input context."); 
2199           mask 
= gdk_window_get_events (widget
->window
); 
2200           mask 
= (GdkEventMask
)(mask 
| gdk_ic_get_events (win
->m_ic
)); 
2201           gdk_window_set_events (widget
->window
, mask
); 
2203           if (GTK_WIDGET_HAS_FOCUS(widget
)) 
2204               gdk_im_begin (win
->m_ic
, widget
->window
); 
2211 //----------------------------------------------------------------------------- 
2212 // InsertChild for wxWindowGTK. 
2213 //----------------------------------------------------------------------------- 
2215 /* Callback for wxWindowGTK. This very strange beast has to be used because 
2216  * C++ has no virtual methods in a constructor. We have to emulate a 
2217  * virtual function here as wxNotebook requires a different way to insert 
2218  * a child in it. I had opted for creating a wxNotebookPage window class 
2219  * which would have made this superfluous (such in the MDI window system), 
2220  * but no-one was listening to me... */ 
2222 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child 
) 
2224     /* the window might have been scrolled already, do we 
2225        have to adapt the position */ 
2226     GtkPizza 
*pizza 
= GTK_PIZZA(parent
->m_wxwindow
); 
2227     child
->m_x 
+= pizza
->xoffset
; 
2228     child
->m_y 
+= pizza
->yoffset
; 
2230     gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
), 
2231                      GTK_WIDGET(child
->m_widget
), 
2238 //----------------------------------------------------------------------------- 
2240 //----------------------------------------------------------------------------- 
2242 wxWindow 
*wxGetActiveWindow() 
2244     return wxWindow::FindFocus(); 
2247 //----------------------------------------------------------------------------- 
2249 //----------------------------------------------------------------------------- 
2251 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
2253 #ifdef __WXUNIVERSAL__ 
2254     IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
) 
2256     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
2257 #endif // __WXUNIVERSAL__/__WXGTK__ 
2259 void wxWindowGTK::Init() 
2265     m_widget 
= (GtkWidget 
*) NULL
; 
2266     m_wxwindow 
= (GtkWidget 
*) NULL
; 
2267     m_focusWidget 
= (GtkWidget 
*) NULL
; 
2277     m_needParent 
= TRUE
; 
2278     m_isBeingDeleted 
= FALSE
; 
2281     m_nativeSizeEvent 
= FALSE
; 
2283     m_hasScrolling 
= FALSE
; 
2284     m_isScrolling 
= FALSE
; 
2286     m_hAdjust 
= (GtkAdjustment
*) NULL
; 
2287     m_vAdjust 
= (GtkAdjustment
*) NULL
; 
2288     m_oldHorizontalPos 
= 0.0; 
2289     m_oldVerticalPos 
= 0.0; 
2292     m_widgetStyle 
= (GtkStyle
*) NULL
; 
2294     m_insertCallback 
= (wxInsertChildFunction
) NULL
; 
2296     m_acceptsFocus 
= FALSE
; 
2299     m_clipPaintRegion 
= FALSE
; 
2301     m_cursor 
= *wxSTANDARD_CURSOR
; 
2303     m_delayedForegroundColour 
= FALSE
; 
2304     m_delayedBackgroundColour 
= FALSE
; 
2307     m_ic 
= (GdkIC
*) NULL
; 
2308     m_icattr 
= (GdkICAttr
*) NULL
; 
2312 wxWindowGTK::wxWindowGTK() 
2317 wxWindowGTK::wxWindowGTK( wxWindow 
*parent
, 
2322                           const wxString 
&name  
) 
2326     Create( parent
, id
, pos
, size
, style
, name 
); 
2329 bool wxWindowGTK::Create( wxWindow 
*parent
, 
2334                           const wxString 
&name  
) 
2336     if (!PreCreation( parent
, pos
, size 
) || 
2337         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
2339         wxFAIL_MSG( wxT("wxWindowGTK creation failed") ); 
2343     m_insertCallback 
= wxInsertChildInWindow
; 
2345     // always needed for background clearing 
2346     m_delayedBackgroundColour 
= TRUE
;  
2348     m_widget 
= gtk_scrolled_window_new( (GtkAdjustment 
*) NULL
, (GtkAdjustment 
*) NULL 
); 
2349     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
2351     GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
2353     GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2354     scroll_class
->scrollbar_spacing 
= 0; 
2356     gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
2358     m_hAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) ); 
2359     m_vAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) ); 
2361     m_wxwindow 
= gtk_pizza_new(); 
2363 #ifndef __WXUNIVERSAL__ 
2364     GtkPizza 
*pizza 
= GTK_PIZZA(m_wxwindow
); 
2366     if (HasFlag(wxRAISED_BORDER
)) 
2368         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT 
); 
2370     else if (HasFlag(wxSUNKEN_BORDER
)) 
2372         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN 
); 
2374     else if (HasFlag(wxSIMPLE_BORDER
)) 
2376         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN 
); 
2380         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE 
); 
2382 #endif // __WXUNIVERSAL__ 
2384     gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
2386     GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
2387     m_acceptsFocus 
= TRUE
; 
2389     // I _really_ don't want scrollbars in the beginning 
2390     m_vAdjust
->lower 
= 0.0; 
2391     m_vAdjust
->upper 
= 1.0; 
2392     m_vAdjust
->value 
= 0.0; 
2393     m_vAdjust
->step_increment 
= 1.0; 
2394     m_vAdjust
->page_increment 
= 1.0; 
2395     m_vAdjust
->page_size 
= 5.0; 
2396     gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
2397     m_hAdjust
->lower 
= 0.0; 
2398     m_hAdjust
->upper 
= 1.0; 
2399     m_hAdjust
->value 
= 0.0; 
2400     m_hAdjust
->step_increment 
= 1.0; 
2401     m_hAdjust
->page_increment 
= 1.0; 
2402     m_hAdjust
->page_size 
= 5.0; 
2403     gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
2405     // these handlers block mouse events to any window during scrolling such as 
2406     // motion events and prevent GTK and wxWindows from fighting over where the 
2409     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event", 
2410           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
2412     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event", 
2413           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
2415     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event", 
2416           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
2418     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event", 
2419           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
2421     // these handlers get notified when screen updates are required either when 
2422     // scrolling or when the window size (and therefore scrollbar configuration) 
2425     gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
2426           (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
2427     gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
2428           (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
2430     gtk_widget_show( m_wxwindow 
); 
2433         m_parent
->DoAddChild( this ); 
2435     m_focusWidget 
= m_wxwindow
; 
2444 wxWindowGTK::~wxWindowGTK() 
2446     if (g_focusWindow 
== this) 
2447         g_focusWindow 
= NULL
; 
2449     if (g_activeFrame 
== this) 
2450         g_activeFrame 
= NULL
; 
2452     if ( g_delayedFocus 
== this ) 
2453         g_delayedFocus 
= NULL
; 
2455     m_isBeingDeleted 
= TRUE
; 
2464         m_parent
->RemoveChild( this ); 
2468         gdk_ic_destroy (m_ic
); 
2470         gdk_ic_attr_destroy (m_icattr
); 
2475 #if DISABLE_STYLE_IF_BROKEN_THEME 
2476         // don't delete if it's a pixmap theme style 
2477         if (!m_widgetStyle
->engine_data
) 
2478             gtk_style_unref( m_widgetStyle 
); 
2480         m_widgetStyle 
= (GtkStyle
*) NULL
; 
2485         gtk_widget_destroy( m_wxwindow 
); 
2486         m_wxwindow 
= (GtkWidget
*) NULL
; 
2491         gtk_widget_destroy( m_widget 
); 
2492         m_widget 
= (GtkWidget
*) NULL
; 
2496 bool wxWindowGTK::PreCreation( wxWindowGTK 
*parent
, const wxPoint 
&pos
,  const wxSize 
&size 
) 
2498     wxCHECK_MSG( !m_needParent 
|| parent
, FALSE
, wxT("Need complete parent.") ); 
2500     // This turns -1 into 30 so that a minimal window is 
2501     // visible even although -1,-1 has been given as the 
2502     // size of the window. the same trick is used in other 
2503     // ports and should make debugging easier. 
2504     m_width 
= WidthDefault(size
.x
) ; 
2505     m_height 
= HeightDefault(size
.y
); 
2510     // some reasonable defaults 
2515             m_x 
= (gdk_screen_width () - m_width
) / 2; 
2516             if (m_x 
< 10) m_x 
= 10; 
2520             m_y 
= (gdk_screen_height () - m_height
) / 2; 
2521             if (m_y 
< 10) m_y 
= 10; 
2528 void wxWindowGTK::PostCreation() 
2530     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2536             // these get reported to wxWindows -> wxPaintEvent 
2538             gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE 
); 
2540             gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event", 
2541                 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this ); 
2544             gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw", 
2545                 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this ); 
2547             if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) 
2549                 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event", 
2550                     GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this ); 
2553             gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow
), HasFlag( wxNO_FULL_REPAINT_ON_RESIZE 
) ); 
2557         // these are called when the "sunken" or "raised" borders are drawn 
2558         gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event", 
2559           GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this ); 
2562         gtk_signal_connect( GTK_OBJECT(m_widget
), "draw", 
2563           GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this ); 
2569     if (m_focusWidget 
== NULL
) 
2570         m_focusWidget 
= m_widget
; 
2572     gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event", 
2573         GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this ); 
2575     gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event", 
2576          GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this ); 
2578     // connect to the various key and mouse handlers 
2580     GtkWidget 
*connect_widget 
= GetConnectWidget(); 
2582     ConnectWidget( connect_widget 
); 
2584     /* We cannot set colours, fonts and cursors before the widget has 
2585        been realized, so we do this directly after realization */ 
2586     gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize", 
2587                             GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this ); 
2591         // Catch native resize events 
2592         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate", 
2593                             GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this ); 
2595         // Initialize XIM support 
2596         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize", 
2597                             GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this ); 
2599         // And resize XIM window 
2600         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate", 
2601                             GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this ); 
2604     if (!GTK_IS_COMBO(m_widget
)) 
2606         // This is needed if we want to add our windows into native 
2607         // GTK control, such as the toolbar. With this callback, the 
2608         // toolbar gets to know the correct size (the one set by the 
2609         // programmer). Sadly, it misbehaves for wxComboBox. FIXME 
2610         // when moving to GTK 2.0. 
2611         gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request", 
2612                             GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this ); 
2618 void wxWindowGTK::ConnectWidget( GtkWidget 
*widget 
) 
2620     gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event", 
2621       GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this ); 
2623     gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event", 
2624       GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this ); 
2626     gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event", 
2627       GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this ); 
2629     gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event", 
2630       GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this ); 
2632     gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event", 
2633       GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this ); 
2635     gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event", 
2636       GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this ); 
2638     gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event", 
2639       GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this ); 
2641     // This keeps crashing on me. RR. 
2643     // gtk_signal_connect( GTK_OBJECT(widget), "destroy", 
2644     //  GTK_SIGNAL_FUNC(gtk_window_destroy_callback), (gpointer)this ); 
2647 bool wxWindowGTK::Destroy() 
2649     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2653     return wxWindowBase::Destroy(); 
2656 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
) 
2658     gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height 
); 
2661 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
2663     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2664     wxASSERT_MSG( (m_parent 
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") ); 
2667     printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height ); 
2670     if (m_resizing
) return; /* I don't like recursions */ 
2673     int currentX
, currentY
; 
2674     GetPosition(¤tX
, ¤tY
); 
2679     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
2681     if (m_parent
->m_wxwindow 
== NULL
) /* i.e. wxNotebook */ 
2683         /* don't set the size for children of wxNotebook, just take the values. */ 
2691         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
2692         if ((sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) == 0) 
2694             if (x 
!= -1) m_x 
= x 
+ pizza
->xoffset
; 
2695             if (y 
!= -1) m_y 
= y 
+ pizza
->yoffset
; 
2699             m_x 
= x 
+ pizza
->xoffset
; 
2700             m_y 
= y 
+ pizza
->yoffset
; 
2702         if (width 
!= -1) m_width 
= width
; 
2703         if (height 
!= -1) m_height 
= height
; 
2705         if ((sizeFlags 
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
) 
2707              if (width 
== -1) m_width 
= 80; 
2710         if ((sizeFlags 
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
) 
2712              if (height 
== -1) m_height 
= 26; 
2715         int minWidth 
= GetMinWidth(), 
2716             minHeight 
= GetMinHeight(), 
2717             maxWidth 
= GetMaxWidth(), 
2718             maxHeight 
= GetMaxHeight(); 
2720         if ((minWidth 
!= -1) && (m_width 
< minWidth
)) m_width 
= minWidth
; 
2721         if ((minHeight 
!= -1) && (m_height 
< minHeight
)) m_height 
= minHeight
; 
2722         if ((maxWidth 
!= -1) && (m_width 
> maxWidth
)) m_width 
= maxWidth
; 
2723         if ((maxHeight 
!= -1) && (m_height 
> maxHeight
)) m_height 
= maxHeight
; 
2726         int bottom_border 
= 0; 
2729         if (GTK_WIDGET_CAN_DEFAULT(m_widget
)) 
2731             /* the default button has a border around it */ 
2737         DoMoveWindow( m_x
-border
, 
2740                       m_height
+border
+bottom_border 
); 
2745         /* Sometimes the client area changes size without the 
2746            whole windows's size changing, but if the whole 
2747            windows's size doesn't change, no wxSizeEvent will 
2748            normally be sent. Here we add an extra test if 
2749            the client test has been changed and this will 
2751         GetClientSize( &m_oldClientWidth
, &m_oldClientHeight 
); 
2755     wxPrintf( "OnSize sent from " ); 
2756     if (GetClassInfo() && GetClassInfo()->GetClassName()) 
2757         wxPrintf( GetClassInfo()->GetClassName() ); 
2758     wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height ); 
2761     if (!m_nativeSizeEvent
) 
2763         wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
2764         event
.SetEventObject( this ); 
2765         GetEventHandler()->ProcessEvent( event 
); 
2771 void wxWindowGTK::OnInternalIdle() 
2773     // Update invalidated regions. 
2776     // Synthetize activate events. 
2777     if ( g_sendActivateEvent 
!= -1 ) 
2779         bool activate 
= g_sendActivateEvent 
!= 0; 
2782         g_sendActivateEvent 
= -1; 
2784         wxTheApp
->SetActive(activate
, (wxWindow 
*)g_focusWindowLast
); 
2787     if ( g_activeFrameLostFocus 
) 
2789         if ( g_activeFrame 
) 
2791             wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
); 
2792             wxActivateEvent 
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId()); 
2793             event
.SetEventObject(g_activeFrame
); 
2794             g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
2795             g_activeFrame 
= NULL
; 
2797         g_activeFrameLostFocus 
= FALSE
; 
2800     wxCursor cursor 
= m_cursor
; 
2801     if (g_globalCursor
.Ok()) cursor 
= g_globalCursor
; 
2805         /* I now set the cursor anew in every OnInternalIdle call 
2806            as setting the cursor in a parent window also effects the 
2807            windows above so that checking for the current cursor is 
2812             GdkWindow 
*window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
2814                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2816             if (!g_globalCursor
.Ok()) 
2817                 cursor 
= *wxSTANDARD_CURSOR
; 
2819             window 
= m_widget
->window
; 
2820             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
2821                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2827             GdkWindow 
*window 
= m_widget
->window
; 
2828             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
2829                gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2837 void wxWindowGTK::DoGetSize( int *width
, int *height 
) const 
2839     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2841     if (width
) (*width
) = m_width
; 
2842     if (height
) (*height
) = m_height
; 
2845 void wxWindowGTK::DoSetClientSize( int width
, int height 
) 
2847     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2851         SetSize( width
, height 
); 
2858 #ifndef __WXUNIVERSAL__ 
2859         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
2861             /* when using GTK 1.2 we set the shadow border size to 2 */ 
2865         if (HasFlag(wxSIMPLE_BORDER
)) 
2867             /* when using GTK 1.2 we set the simple border size to 1 */ 
2871 #endif // __WXUNIVERSAL__ 
2875             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
2877             GtkRequisition vscroll_req
; 
2878             vscroll_req
.width 
= 2; 
2879             vscroll_req
.height 
= 2; 
2880             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
2881                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
2883             GtkRequisition hscroll_req
; 
2884             hscroll_req
.width 
= 2; 
2885             hscroll_req
.height 
= 2; 
2886             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
2887                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
2889             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2891             if (scroll_window
->vscrollbar_visible
) 
2893                 dw 
+= vscroll_req
.width
; 
2894                 dw 
+= scroll_class
->scrollbar_spacing
; 
2897             if (scroll_window
->hscrollbar_visible
) 
2899                 dh 
+= hscroll_req
.height
; 
2900                 dh 
+= scroll_class
->scrollbar_spacing
; 
2904        SetSize( width
+dw
, height
+dh 
); 
2908 void wxWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
2910     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2914         if (width
) (*width
) = m_width
; 
2915         if (height
) (*height
) = m_height
; 
2922 #ifndef __WXUNIVERSAL__ 
2923         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
2925             /* when using GTK 1.2 we set the shadow border size to 2 */ 
2929         if (HasFlag(wxSIMPLE_BORDER
)) 
2931             /* when using GTK 1.2 we set the simple border size to 1 */ 
2935 #endif // __WXUNIVERSAL__ 
2939             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
2941             GtkRequisition vscroll_req
; 
2942             vscroll_req
.width 
= 2; 
2943             vscroll_req
.height 
= 2; 
2944             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
2945                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
2947             GtkRequisition hscroll_req
; 
2948             hscroll_req
.width 
= 2; 
2949             hscroll_req
.height 
= 2; 
2950             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
2951                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
2953             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2955             if (scroll_window
->vscrollbar_visible
) 
2957                 dw 
+= vscroll_req
.width
; 
2958                 dw 
+= scroll_class
->scrollbar_spacing
; 
2961             if (scroll_window
->hscrollbar_visible
) 
2963                 dh 
+= hscroll_req
.height
; 
2964                 dh 
+= scroll_class
->scrollbar_spacing
; 
2968         if (width
) (*width
) = m_width 
- dw
; 
2969         if (height
) (*height
) = m_height 
- dh
; 
2973     printf( "GetClientSize, name %s ", GetName().c_str() ); 
2974     if (width) printf( " width = %d", (*width) ); 
2975     if (height) printf( " height = %d", (*height) ); 
2980 void wxWindowGTK::DoGetPosition( int *x
, int *y 
) const 
2982     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2986     if (m_parent 
&& m_parent
->m_wxwindow
) 
2988         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
2989         dx 
= pizza
->xoffset
; 
2990         dy 
= pizza
->yoffset
; 
2993     if (x
) (*x
) = m_x 
- dx
; 
2994     if (y
) (*y
) = m_y 
- dy
; 
2997 void wxWindowGTK::DoClientToScreen( int *x
, int *y 
) const 
2999     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3001     if (!m_widget
->window
) return; 
3003     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3005         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3007         source 
= m_widget
->window
; 
3011     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3015         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3017             org_x 
+= m_widget
->allocation
.x
; 
3018             org_y 
+= m_widget
->allocation
.y
; 
3026 void wxWindowGTK::DoScreenToClient( int *x
, int *y 
) const 
3028     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3030     if (!m_widget
->window
) return; 
3032     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3034         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3036         source 
= m_widget
->window
; 
3040     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3044         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3046             org_x 
+= m_widget
->allocation
.x
; 
3047             org_y 
+= m_widget
->allocation
.y
; 
3055 bool wxWindowGTK::Show( bool show 
) 
3057     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3059     if (!wxWindowBase::Show(show
)) 
3066         gtk_widget_show( m_widget 
); 
3068         gtk_widget_hide( m_widget 
); 
3073 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
) 
3075     win
->OnParentEnable(enable
); 
3077     // Recurse, so that children have the opportunity to Do The Right Thing 
3078     // and reset colours that have been messed up by a parent's (really ancestor's) 
3080     for ( wxWindowList::Node 
*node 
= win
->GetChildren().GetFirst(); 
3082           node 
= node
->GetNext() ) 
3084         wxWindow 
*child 
= node
->GetData(); 
3085         if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
))) 
3086             wxWindowNotifyEnable(child
, enable
); 
3090 bool wxWindowGTK::Enable( bool enable 
) 
3092     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3094     if (!wxWindowBase::Enable(enable
)) 
3100     gtk_widget_set_sensitive( m_widget
, enable 
); 
3102         gtk_widget_set_sensitive( m_wxwindow
, enable 
); 
3104     wxWindowNotifyEnable(this, enable
); 
3109 int wxWindowGTK::GetCharHeight() const 
3111     wxCHECK_MSG( (m_widget 
!= NULL
), 12, wxT("invalid window") ); 
3113     wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") ); 
3115     GdkFont 
*font 
= m_font
.GetInternalFont( 1.0 ); 
3117     return font
->ascent 
+ font
->descent
; 
3120 int wxWindowGTK::GetCharWidth() const 
3122     wxCHECK_MSG( (m_widget 
!= NULL
), 8, wxT("invalid window") ); 
3124     wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") ); 
3126     GdkFont 
*font 
= m_font
.GetInternalFont( 1.0 ); 
3128     return gdk_string_width( font
, "H" ); 
3131 void wxWindowGTK::GetTextExtent( const wxString
& string
, 
3135                               int *externalLeading
, 
3136                               const wxFont 
*theFont 
) const 
3138     wxFont fontToUse 
= m_font
; 
3139     if (theFont
) fontToUse 
= *theFont
; 
3141     wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") ); 
3143     if (string
.IsEmpty()) 
3151     PangoContext 
*context 
= NULL
; 
3153         gtk_widget_get_pango_context( m_widget 
); 
3162     PangoFontDescription 
*desc 
= fontToUse
.GetNativeFontInfo()->description
; 
3163     PangoLayout 
*layout 
= pango_layout_new(context
); 
3164     pango_layout_set_font_description(layout
, desc
); 
3166         const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( string 
); 
3167         pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data 
)); 
3169     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
3171     PangoRectangle rect
; 
3172     pango_layout_line_get_extents(line
, NULL
, &rect
); 
3174     if (x
) (*x
) = (wxCoord
) rect
.width
; 
3175     if (y
) (*y
) = (wxCoord
) rect
.height
; 
3178         // Do something about metrics here 
3181     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3183     g_object_unref( G_OBJECT( layout 
) ); 
3185     GdkFont 
*font 
= fontToUse
.GetInternalFont( 1.0 ); 
3186     if (x
) (*x
) = gdk_string_width( font
, wxGTK_CONV( string 
) ); 
3187     if (y
) (*y
) = font
->ascent 
+ font
->descent
; 
3188     if (descent
) (*descent
) = font
->descent
; 
3189     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3193 void wxWindowGTK::SetFocus() 
3195     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3199         // don't do anything if we already have focus 
3205         if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
)) 
3207             gtk_widget_grab_focus (m_wxwindow
); 
3212         if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) ) 
3214             if (!GTK_WIDGET_REALIZED(m_widget
)) 
3216                 // we can't set the focus to the widget now so we remember that 
3217                 // it should be focused and will do it later, during the idle 
3218                 // time, as soon as we can 
3219                 wxLogTrace(TRACE_FOCUS
, 
3220                            _T("Delaying setting focus to %s(%s)"), 
3221                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3223                 g_delayedFocus 
= this; 
3227                 wxLogTrace(TRACE_FOCUS
, 
3228                            _T("Setting focus to %s(%s)"), 
3229                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3231                 gtk_widget_grab_focus (m_widget
); 
3234         else if (GTK_IS_CONTAINER(m_widget
)) 
3236             SET_CONTAINER_FOCUS( m_widget
, GTK_DIR_TAB_FORWARD 
); 
3240            wxLogTrace(TRACE_FOCUS
, 
3241                       _T("Can't set focus to %s(%s)"), 
3242                       GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3247 bool wxWindowGTK::AcceptsFocus() const 
3249     return m_acceptsFocus 
&& wxWindowBase::AcceptsFocus(); 
3252 bool wxWindowGTK::Reparent( wxWindowBase 
*newParentBase 
) 
3254     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3256     wxWindowGTK 
*oldParent 
= m_parent
, 
3257              *newParent 
= (wxWindowGTK 
*)newParentBase
; 
3259     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3261     if ( !wxWindowBase::Reparent(newParent
) ) 
3264     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3266     /* prevent GTK from deleting the widget arbitrarily */ 
3267     gtk_widget_ref( m_widget 
); 
3271         gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget 
); 
3274     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3278         /* insert GTK representation */ 
3279         (*(newParent
->m_insertCallback
))(newParent
, this); 
3282     /* reverse: prevent GTK from deleting the widget arbitrarily */ 
3283     gtk_widget_unref( m_widget 
); 
3288 void wxWindowGTK::DoAddChild(wxWindowGTK 
*child
) 
3290     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3292     wxASSERT_MSG( (child 
!= NULL
), wxT("invalid child window") ); 
3294     wxASSERT_MSG( (m_insertCallback 
!= NULL
), wxT("invalid child insertion function") ); 
3299     /* insert GTK representation */ 
3300     (*m_insertCallback
)(this, child
); 
3303 void wxWindowGTK::Raise() 
3305     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3307     if (!m_widget
->window
) return; 
3309     gdk_window_raise( m_widget
->window 
); 
3312 void wxWindowGTK::Lower() 
3314     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3316     if (!m_widget
->window
) return; 
3318     gdk_window_lower( m_widget
->window 
); 
3321 bool wxWindowGTK::SetCursor( const wxCursor 
&cursor 
) 
3323     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3325     if (cursor 
== m_cursor
) 
3329         wxapp_install_idle_handler(); 
3331     if (cursor 
== wxNullCursor
) 
3332        return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR 
); 
3334        return wxWindowBase::SetCursor( cursor 
); 
3337 void wxWindowGTK::WarpPointer( int x
, int y 
) 
3339     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3341     // We provide this function ourselves as it is 
3342     // missing in GDK (top of this file). 
3344     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3346         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3348         window 
= GetConnectWidget()->window
; 
3351         gdk_window_warp_pointer( window
, x
, y 
); 
3355 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect 
*rect 
) 
3357     if (!m_widget
) return; 
3358     if (!m_widget
->window
) return; 
3362         wxapp_install_idle_handler(); 
3364     if (eraseBackground 
&& m_wxwindow 
&& m_wxwindow
->window
) 
3368             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3369             m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3373             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3374             m_clearRegion
.Clear(); 
3375             m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3383             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3384             m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3388             GdkRectangle gdk_rect
; 
3389             gdk_rect
.x 
= rect
->x
; 
3390             gdk_rect
.y 
= rect
->y
; 
3391             gdk_rect
.width 
= rect
->width
; 
3392             gdk_rect
.height 
= rect
->height
; 
3393             gtk_widget_draw( m_widget
, &gdk_rect 
); 
3400             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3401             m_updateRegion
.Clear(); 
3402             m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3406             gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL 
); 
3414             GdkRectangle gdk_rect
; 
3415             gdk_rect
.x 
= rect
->x
; 
3416             gdk_rect
.y 
= rect
->y
; 
3417             gdk_rect
.width 
= rect
->width
; 
3418             gdk_rect
.height 
= rect
->height
; 
3419             gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, &gdk_rect
, TRUE 
); 
3423             gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, NULL
, TRUE 
); 
3429 void wxWindowGTK::Update() 
3434 void wxWindowGTK::GtkUpdate() 
3437     if (m_wxwindow 
&& GTK_PIZZA(m_wxwindow
)->bin_window
) 
3438         gdk_window_process_updates( GTK_PIZZA(m_wxwindow
)->bin_window
, FALSE 
); 
3441     if (!m_updateRegion
.IsEmpty()) 
3442         GtkSendPaintEvents(); 
3445 void wxWindowGTK::GtkSendPaintEvents() 
3449         m_clearRegion
.Clear(); 
3450         m_updateRegion
.Clear(); 
3454     // widget to draw on 
3455     GtkPizza 
*pizza 
= GTK_PIZZA (m_wxwindow
); 
3457     // Clip to paint region in wxClientDC 
3458     m_clipPaintRegion 
= TRUE
; 
3461     if (GetThemeEnabled()) 
3463         // find ancestor from which to steal background 
3464         wxWindow 
*parent 
= GetParent(); 
3465         while (parent 
&& !parent
->IsTopLevel()) 
3466             parent 
= parent
->GetParent(); 
3468             parent 
= (wxWindow
*)this; 
3470         wxRegionIterator 
upd( m_updateRegion 
); 
3474             rect
.x 
= upd
.GetX(); 
3475             rect
.y 
= upd
.GetY(); 
3476             rect
.width 
= upd
.GetWidth(); 
3477             rect
.height 
= upd
.GetHeight(); 
3479             gtk_paint_flat_box( parent
->m_widget
->style
, 
3494     if (!m_clearRegion
.IsEmpty())   // Always send an erase event under GTK 1.2 
3497         wxWindowDC 
dc( (wxWindow
*)this ); 
3498         if (m_clearRegion
.IsEmpty()) 
3499             dc
.SetClippingRegion( m_updateRegion 
); 
3501             dc
.SetClippingRegion( m_clearRegion 
); 
3503         wxEraseEvent 
erase_event( GetId(), &dc 
); 
3504         erase_event
.SetEventObject( this ); 
3506         if (!GetEventHandler()->ProcessEvent(erase_event
)) 
3511                 g_eraseGC 
= gdk_gc_new( pizza
->bin_window 
); 
3512                 gdk_gc_set_fill( g_eraseGC
, GDK_SOLID 
); 
3514             gdk_gc_set_foreground( g_eraseGC
, m_backgroundColour
.GetColor() ); 
3516             wxRegionIterator 
upd( m_clearRegion 
); 
3519                 gdk_draw_rectangle( pizza
->bin_window
, g_eraseGC
, 1, 
3520                                     upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() ); 
3525         m_clearRegion
.Clear(); 
3528     wxNcPaintEvent 
nc_paint_event( GetId() ); 
3529     nc_paint_event
.SetEventObject( this ); 
3530     GetEventHandler()->ProcessEvent( nc_paint_event 
); 
3532     wxPaintEvent 
paint_event( GetId() ); 
3533     paint_event
.SetEventObject( this ); 
3534     GetEventHandler()->ProcessEvent( paint_event 
); 
3536     m_clipPaintRegion 
= FALSE
; 
3538 #ifndef __WXUNIVERSAL__ 
3540     // The following code will result in all window-less widgets 
3541     // being redrawn because the wxWindows class is allowed to 
3542     // paint over the window-less widgets. 
3544     GList 
*children 
= pizza
->children
; 
3547         GtkPizzaChild 
*child 
= (GtkPizzaChild
*) children
->data
; 
3548         children 
= children
->next
; 
3550         if (GTK_WIDGET_NO_WINDOW (child
->widget
) && 
3551             GTK_WIDGET_DRAWABLE (child
->widget
)) 
3553             // Get intersection of widget area and update region 
3554             wxRegion 
region( m_updateRegion 
); 
3556             GdkEventExpose gdk_event
; 
3557             gdk_event
.type 
= GDK_EXPOSE
; 
3558             gdk_event
.window 
= pizza
->bin_window
; 
3559             gdk_event
.count 
= 0; 
3561             wxRegionIterator 
upd( m_updateRegion 
); 
3565                 rect
.x 
= upd
.GetX(); 
3566                 rect
.y 
= upd
.GetY(); 
3567                 rect
.width 
= upd
.GetWidth(); 
3568                 rect
.height 
= upd
.GetHeight(); 
3570                 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
)) 
3572                     gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
); 
3582     m_updateRegion
.Clear(); 
3585 void wxWindowGTK::Clear() 
3587     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3589     if (m_wxwindow 
&& m_wxwindow
->window
) 
3591         m_clearRegion
.Clear(); 
3592         wxSize 
size( GetClientSize() ); 
3593         m_clearRegion
.Union( 0,0,size
.x
,size
.y 
); 
3595         // Better do this in idle? 
3601 void wxWindowGTK::DoSetToolTip( wxToolTip 
*tip 
) 
3603     wxWindowBase::DoSetToolTip(tip
); 
3606         m_tooltip
->Apply( (wxWindow 
*)this ); 
3609 void wxWindowGTK::ApplyToolTip( GtkTooltips 
*tips
, const wxChar 
*tip 
) 
3611     gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL 
); 
3613 #endif // wxUSE_TOOLTIPS 
3615 void wxWindowGTK::GtkSetBackgroundColour( const wxColour 
&colour 
) 
3617     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3619         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3621         window 
= GetConnectWidget()->window
; 
3625     // We need the pixel value e.g. for background clearing. 
3626     m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window 
) ); 
3630         // wxMSW doesn't clear the window here, either. 
3631         gdk_window_set_background( window
, m_backgroundColour
.GetColor() ); 
3637 bool wxWindowGTK::SetBackgroundColour( const wxColour 
&colour 
) 
3639     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
3641     if (!wxWindowBase::SetBackgroundColour(colour
)) 
3644     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3646         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3648         window 
= GetConnectWidget()->window
; 
3652         // indicate that a new style has been set 
3653         // but it couldn't get applied as the 
3654         // widget hasn't been realized yet. 
3655         m_delayedBackgroundColour 
= TRUE
; 
3660         GtkSetBackgroundColour( colour 
); 
3666 void wxWindowGTK::GtkSetForegroundColour( const wxColour 
&colour 
) 
3668     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3670         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3672         window 
= GetConnectWidget()->window
; 
3679 bool wxWindowGTK::SetForegroundColour( const wxColour 
&colour 
) 
3681     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
3683     if (!wxWindowBase::SetForegroundColour(colour
)) 
3685         // don't leave if the GTK widget has just 
3687         if (!m_delayedForegroundColour
) return FALSE
; 
3690     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3692         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3694         window 
= GetConnectWidget()->window
; 
3698         // indicate that a new style has been set 
3699         // but it couldn't get applied as the 
3700         // widget hasn't been realized yet. 
3701         m_delayedForegroundColour 
= TRUE
; 
3705        GtkSetForegroundColour( colour 
); 
3711 GtkStyle 
*wxWindowGTK::GetWidgetStyle() 
3715         GtkStyle 
*remake 
= gtk_style_copy( m_widgetStyle 
); 
3717         // FIXME: no more klass in 2.0 
3719         remake
->klass 
= m_widgetStyle
->klass
; 
3722         gtk_style_unref( m_widgetStyle 
); 
3723         m_widgetStyle 
= remake
; 
3727         GtkStyle 
*def 
= gtk_rc_get_style( m_widget 
); 
3730             def 
= gtk_widget_get_default_style(); 
3732         m_widgetStyle 
= gtk_style_copy( def 
); 
3734         // FIXME: no more klass in 2.0 
3736         m_widgetStyle
->klass 
= def
->klass
; 
3740     return m_widgetStyle
; 
3743 void wxWindowGTK::SetWidgetStyle() 
3745 #if DISABLE_STYLE_IF_BROKEN_THEME 
3746     if (m_widget
->style
->engine_data
) 
3748         static bool s_warningPrinted 
= FALSE
; 
3749         if (!s_warningPrinted
) 
3751             printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" ); 
3752             s_warningPrinted 
= TRUE
; 
3754         m_widgetStyle 
= m_widget
->style
; 
3759     GtkStyle 
*style 
= GetWidgetStyle(); 
3761     if (m_font 
!= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT 
)) 
3763         SET_STYLE_FONT(style
, m_font
.GetInternalFont( 1.0 )); 
3766     if (m_foregroundColour
.Ok()) 
3768         m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget 
) ); 
3769         if (m_foregroundColour 
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT
)) 
3771             style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor(); 
3772             style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor(); 
3773             style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor(); 
3777             // Try to restore the gtk default style.  This is still a little 
3778             // oversimplified for what is probably really needed here for controls 
3779             // other than buttons, but is better than not being able to (re)set a 
3780             // control's foreground colour to *wxBLACK -- RL 
3781             GtkStyle 
*def 
= gtk_rc_get_style( m_widget 
); 
3784                 def 
= gtk_widget_get_default_style(); 
3786             style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
]; 
3787             style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
]; 
3788             style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
]; 
3792     if (m_backgroundColour
.Ok()) 
3794         m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget 
) ); 
3795         if (m_backgroundColour 
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
)) 
3797             style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor(); 
3798             style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor(); 
3799             style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor(); 
3800             style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor(); 
3801             style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor(); 
3802             style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor(); 
3803             style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor(); 
3804             style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor(); 
3808             // Try to restore the gtk default style.  This is still a little 
3809             // oversimplified for what is probably really needed here for controls 
3810             // other than buttons, but is better than not being able to (re)set a 
3811             // control's background colour to default grey and means resetting a 
3812             // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting 
3814             GtkStyle 
*def 
= gtk_rc_get_style( m_widget 
); 
3817                 def 
= gtk_widget_get_default_style(); 
3819             style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
]; 
3820             style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
]; 
3821             style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
]; 
3822             style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
]; 
3823             style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
]; 
3824             style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
]; 
3825             style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
]; 
3826             style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
]; 
3831 void wxWindowGTK::ApplyWidgetStyle() 
3835 //----------------------------------------------------------------------------- 
3836 // Pop-up menu stuff 
3837 //----------------------------------------------------------------------------- 
3839 #if wxUSE_MENUS_NATIVE 
3842 void gtk_pop_hide_callback( GtkWidget 
*WXUNUSED(widget
), bool* is_waiting  
) 
3844     *is_waiting 
= FALSE
; 
3847 static void SetInvokingWindow( wxMenu 
*menu
, wxWindowGTK 
*win 
) 
3849     menu
->SetInvokingWindow( win 
); 
3850     wxMenuItemList::Node 
*node 
= menu
->GetMenuItems().GetFirst(); 
3853         wxMenuItem 
*menuitem 
= node
->GetData(); 
3854         if (menuitem
->IsSubMenu()) 
3856             SetInvokingWindow( menuitem
->GetSubMenu(), win 
); 
3859         node 
= node
->GetNext(); 
3863 // used to pass the coordinates from wxWindowGTK::DoPopupMenu() to 
3864 // wxPopupMenuPositionCallback() 
3866 // should be safe even in the MT case as the user can hardly popup 2 menus 
3867 // simultaneously, can he? 
3868 static gint gs_pop_x 
= 0; 
3869 static gint gs_pop_y 
= 0; 
3871 extern "C" void wxPopupMenuPositionCallback( GtkMenu 
*menu
, 
3874                                              gboolean 
* WXUNUSED(whatever
), 
3876                                              gpointer 
WXUNUSED(user_data
) ) 
3878     // ensure that the menu appears entirely on screen 
3880     gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
); 
3882     wxSize sizeScreen 
= wxGetDisplaySize(); 
3884     gint xmax 
= sizeScreen
.x 
- req
.width
, 
3885          ymax 
= sizeScreen
.y 
- req
.height
; 
3887     *x 
= gs_pop_x 
< xmax 
? gs_pop_x 
: xmax
; 
3888     *y 
= gs_pop_y 
< ymax 
? gs_pop_y 
: ymax
; 
3891 bool wxWindowGTK::DoPopupMenu( wxMenu 
*menu
, int x
, int y 
) 
3893     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
3895     wxCHECK_MSG( menu 
!= NULL
, FALSE
, wxT("invalid popup-menu") ); 
3897     SetInvokingWindow( menu
, this ); 
3903     ClientToScreen( &gs_pop_x
, &gs_pop_y 
); 
3905     bool is_waiting 
= TRUE
; 
3907     gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), 
3909                         GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), 
3910                         (gpointer
)&is_waiting 
); 
3913                   GTK_MENU(menu
->m_menu
), 
3914                   (GtkWidget 
*) NULL
,           // parent menu shell 
3915                   (GtkWidget 
*) NULL
,           // parent menu item 
3916                   wxPopupMenuPositionCallback
,  // function to position it 
3917                   NULL
,                         // client data 
3918                   0,                            // button used to activate it 
3919                   gs_timeLastClick              
// the time of activation 
3924         while (gtk_events_pending()) 
3925             gtk_main_iteration(); 
3931 #endif // wxUSE_MENUS_NATIVE 
3933 #if wxUSE_DRAG_AND_DROP 
3935 void wxWindowGTK::SetDropTarget( wxDropTarget 
*dropTarget 
) 
3937     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3939     GtkWidget 
*dnd_widget 
= GetConnectWidget(); 
3941     if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget 
); 
3943     if (m_dropTarget
) delete m_dropTarget
; 
3944     m_dropTarget 
= dropTarget
; 
3946     if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget 
); 
3949 #endif // wxUSE_DRAG_AND_DROP 
3951 GtkWidget
* wxWindowGTK::GetConnectWidget() 
3953     GtkWidget 
*connect_widget 
= m_widget
; 
3954     if (m_wxwindow
) connect_widget 
= m_wxwindow
; 
3956     return connect_widget
; 
3959 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow 
*window 
) 
3962         return (window 
== GTK_PIZZA(m_wxwindow
)->bin_window
); 
3964     return (window 
== m_widget
->window
); 
3967 bool wxWindowGTK::SetFont( const wxFont 
&font 
) 
3969     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
3971     if (!wxWindowBase::SetFont(font
)) 
3976     wxColour sysbg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE 
); 
3977     if ( sysbg 
== m_backgroundColour 
) 
3979         m_backgroundColour 
= wxNullColour
; 
3981         m_backgroundColour 
= sysbg
; 
3991 void wxWindowGTK::DoCaptureMouse() 
3993     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3995     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3997         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3999         window 
= GetConnectWidget()->window
; 
4001     wxCHECK_RET( window
, _T("CaptureMouse() failed") ); 
4003     wxCursor
* cursor 
= & m_cursor
; 
4005         cursor 
= wxSTANDARD_CURSOR
; 
4007     gdk_pointer_grab( window
, FALSE
, 
4009                          (GDK_BUTTON_PRESS_MASK 
| 
4010                           GDK_BUTTON_RELEASE_MASK 
| 
4011                           GDK_POINTER_MOTION_HINT_MASK 
| 
4012                           GDK_POINTER_MOTION_MASK
), 
4014                       cursor
->GetCursor(), 
4015                       (guint32
)GDK_CURRENT_TIME 
); 
4016     g_captureWindow 
= this; 
4017     g_captureWindowHasMouse 
= TRUE
; 
4020 void wxWindowGTK::DoReleaseMouse() 
4022     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4024     wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") ); 
4026     g_captureWindow 
= (wxWindowGTK
*) NULL
; 
4028     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4030         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4032         window 
= GetConnectWidget()->window
; 
4037     gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME 
); 
4041 wxWindow 
*wxWindowBase::GetCapture() 
4043     return (wxWindow 
*)g_captureWindow
; 
4046 bool wxWindowGTK::IsRetained() const 
4051 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
, 
4052       int range
, bool refresh 
) 
4054     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4056     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4058     m_hasScrolling 
= TRUE
; 
4060     if (orient 
== wxHORIZONTAL
) 
4062         float fpos 
= (float)pos
; 
4063         float frange 
= (float)range
; 
4064         float fthumb 
= (float)thumbVisible
; 
4065         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4066         if (fpos 
< 0.0) fpos 
= 0.0; 
4068         if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) && 
4069             (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2)) 
4071             SetScrollPos( orient
, pos
, refresh 
); 
4075         m_oldHorizontalPos 
= fpos
; 
4077         m_hAdjust
->lower 
= 0.0; 
4078         m_hAdjust
->upper 
= frange
; 
4079         m_hAdjust
->value 
= fpos
; 
4080         m_hAdjust
->step_increment 
= 1.0; 
4081         m_hAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4082         m_hAdjust
->page_size 
= fthumb
; 
4086         float fpos 
= (float)pos
; 
4087         float frange 
= (float)range
; 
4088         float fthumb 
= (float)thumbVisible
; 
4089         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4090         if (fpos 
< 0.0) fpos 
= 0.0; 
4092         if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) && 
4093             (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2)) 
4095             SetScrollPos( orient
, pos
, refresh 
); 
4099         m_oldVerticalPos 
= fpos
; 
4101         m_vAdjust
->lower 
= 0.0; 
4102         m_vAdjust
->upper 
= frange
; 
4103         m_vAdjust
->value 
= fpos
; 
4104         m_vAdjust
->step_increment 
= 1.0; 
4105         m_vAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4106         m_vAdjust
->page_size 
= fthumb
; 
4109     if (orient 
== wxHORIZONTAL
) 
4110         gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
4112         gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
4115 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) ) 
4117     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4119     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4121     if (orient 
== wxHORIZONTAL
) 
4123         float fpos 
= (float)pos
; 
4124         if (fpos 
> m_hAdjust
->upper 
- m_hAdjust
->page_size
) fpos 
= m_hAdjust
->upper 
- m_hAdjust
->page_size
; 
4125         if (fpos 
< 0.0) fpos 
= 0.0; 
4126         m_oldHorizontalPos 
= fpos
; 
4128         if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return; 
4129         m_hAdjust
->value 
= fpos
; 
4133         float fpos 
= (float)pos
; 
4134         if (fpos 
> m_vAdjust
->upper 
- m_vAdjust
->page_size
) fpos 
= m_vAdjust
->upper 
- m_vAdjust
->page_size
; 
4135         if (fpos 
< 0.0) fpos 
= 0.0; 
4136         m_oldVerticalPos 
= fpos
; 
4138         if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return; 
4139         m_vAdjust
->value 
= fpos
; 
4142     if (m_wxwindow
->window
) 
4144         if (orient 
== wxHORIZONTAL
) 
4146             gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
), 
4147                 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
4149             gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" ); 
4151             gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
4152                 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
4156             gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
), 
4157                 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
4159             gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" ); 
4161             gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
4162                 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
4167 int wxWindowGTK::GetScrollThumb( int orient 
) const 
4169     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4171     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4173     if (orient 
== wxHORIZONTAL
) 
4174         return (int)(m_hAdjust
->page_size
+0.5); 
4176         return (int)(m_vAdjust
->page_size
+0.5); 
4179 int wxWindowGTK::GetScrollPos( int orient 
) const 
4181     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4183     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4185     if (orient 
== wxHORIZONTAL
) 
4186         return (int)(m_hAdjust
->value
+0.5); 
4188         return (int)(m_vAdjust
->value
+0.5); 
4191 int wxWindowGTK::GetScrollRange( int orient 
) const 
4193     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4195     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4197     if (orient 
== wxHORIZONTAL
) 
4198         return (int)(m_hAdjust
->upper
+0.5); 
4200         return (int)(m_vAdjust
->upper
+0.5); 
4203 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) ) 
4205     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4207     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4209     // No scrolling requested. 
4210     if ((dx 
== 0) && (dy 
== 0)) return; 
4213     if (!m_updateRegion
.IsEmpty()) 
4215         m_updateRegion
.Offset( dx
, dy 
); 
4219         GetClientSize( &cw
, &ch 
); 
4220         m_updateRegion
.Intersect( 0, 0, cw
, ch 
); 
4223     if (!m_clearRegion
.IsEmpty()) 
4225         m_clearRegion
.Offset( dx
, dy 
); 
4229         GetClientSize( &cw
, &ch 
); 
4230         m_clearRegion
.Intersect( 0, 0, cw
, ch 
); 
4232     m_clipPaintRegion 
= TRUE
; 
4234     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy 
); 
4236     m_clipPaintRegion 
= FALSE
; 
4239     gdk_window_scroll( GTK_PIZZA(m_wxwindow
)->bin_window
, dx
, dy 
); 
4241     GTK_PIZZA(m_wxwindow
)->xoffset 
+= dx
; 
4242     GTK_PIZZA(m_wxwindow
)->yoffset 
+= dy
; 
4249 // Find the wxWindow at the current mouse position, also returning the mouse 
4251 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
4253     pt 
= wxGetMousePosition(); 
4254     wxWindow
* found 
= wxFindWindowAtPoint(pt
); 
4258 // Get the current mouse position. 
4259 wxPoint 
wxGetMousePosition() 
4261   /* This crashes when used within wxHelpContext, 
4262      so we have to use the X-specific implementation below. 
4264     GdkModifierType *mask; 
4265     (void) gdk_window_get_pointer(NULL, &x, &y, mask); 
4267     return wxPoint(x, y); 
4271     GdkWindow
* windowAtPtr 
= gdk_window_at_pointer(& x
, & y
); 
4273       return wxPoint(-999, -999); 
4275     Display 
*display 
= GDK_WINDOW_XDISPLAY(windowAtPtr
); 
4276     Window rootWindow 
= RootWindowOfScreen (DefaultScreenOfDisplay(display
)); 
4277     Window rootReturn
, childReturn
; 
4278     int rootX
, rootY
, winX
, winY
; 
4279     unsigned int maskReturn
; 
4281     XQueryPointer (display
, 
4285                    &rootX
, &rootY
, &winX
, &winY
, &maskReturn
); 
4286     return wxPoint(rootX
, rootY
); 
4290 // ---------------------------------------------------------------------------- 
4292 // ---------------------------------------------------------------------------- 
4294 class wxWinModule 
: public wxModule
 
4301     DECLARE_DYNAMIC_CLASS(wxWinModule
) 
4304 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
) 
4306 bool wxWinModule::OnInit() 
4308     // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() ); 
4309     // gdk_gc_set_fill( g_eraseGC, GDK_SOLID ); 
4314 void wxWinModule::OnExit() 
4317         gdk_gc_unref( g_eraseGC 
);