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" 
  53     #include "wx/thread.h" 
  58 #include "wx/gtk/private.h" 
  59 #include <gdk/gdkprivate.h> 
  60 #include <gdk/gdkkeysyms.h> 
  64 #include <gtk/gtkprivate.h> 
  66 #include "wx/gtk/win_gtk.h" 
  69     #define SET_CONTAINER_FOCUS(w, d) gtk_widget_child_focus((w), (d)) 
  71     #define SET_CONTAINER_FOCUS(w, d) gtk_container_focus(GTK_CONTAINER(w), (d)) 
  81 extern GtkContainerClass 
*pizza_parent_class
; 
  84 //----------------------------------------------------------------------------- 
  85 // documentation on internals 
  86 //----------------------------------------------------------------------------- 
  89    I have been asked several times about writing some documentation about 
  90    the GTK port of wxWindows, especially its internal structures. Obviously, 
  91    you cannot understand wxGTK without knowing a little about the GTK, but 
  92    some more information about what the wxWindow, which is the base class 
  93    for all other window classes, does seems required as well. 
  97    What does wxWindow do? It contains the common interface for the following 
  98    jobs of its descendants: 
 100    1) Define the rudimentary behaviour common to all window classes, such as 
 101    resizing, intercepting user input (so as to make it possible to use these 
 102    events for special purposes in a derived class), window names etc. 
 104    2) Provide the possibility to contain and manage children, if the derived 
 105    class is allowed to contain children, which holds true for those window 
 106    classes which do not display a native GTK widget. To name them, these 
 107    classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame- 
 108    work classes are a special case and are handled a bit differently from 
 109    the rest. The same holds true for the wxNotebook class. 
 111    3) Provide the possibility to draw into a client area of a window. This, 
 112    too, only holds true for classes that do not display a native GTK widget 
 115    4) Provide the entire mechanism for scrolling widgets. This actual inter- 
 116    face for this is usually in wxScrolledWindow, but the GTK implementation 
 119    5) A multitude of helper or extra methods for special purposes, such as 
 120    Drag'n'Drop, managing validators etc. 
 122    6) Display a border (sunken, raised, simple or none). 
 124    Normally one might expect, that one wxWindows window would always correspond 
 125    to one GTK widget. Under GTK, there is no such allround widget that has all 
 126    the functionality. Moreover, the GTK defines a client area as a different 
 127    widget from the actual widget you are handling. Last but not least some 
 128    special classes (e.g. wxFrame) handle different categories of widgets and 
 129    still have the possibility to draw something in the client area. 
 130    It was therefore required to write a special purpose GTK widget, that would 
 131    represent a client area in the sense of wxWindows capable to do the jobs 
 132    2), 3) and 4). I have written this class and it resides in win_gtk.c of 
 135    All windows must have a widget, with which they interact with other under- 
 136    lying GTK widgets. It is this widget, e.g. that has to be resized etc and 
 137    thw wxWindow class has a member variable called m_widget which holds a 
 138    pointer to this widget. When the window class represents a GTK native widget, 
 139    this is (in most cases) the only GTK widget the class manages. E.g. the 
 140    wxStatitText class handles only a GtkLabel widget a pointer to which you 
 141    can find in m_widget (defined in wxWindow) 
 143    When the class has a client area for drawing into and for containing children 
 144    it has to handle the client area widget (of the type GtkPizza, defined in 
 145    win_gtk.c), but there could be any number of widgets, handled by a class 
 146    The common rule for all windows is only, that the widget that interacts with 
 147    the rest of GTK must be referenced in m_widget and all other widgets must be 
 148    children of this widget on the GTK level. The top-most widget, which also 
 149    represents the client area, must be in the m_wxwindow field and must be of 
 152    As I said, the window classes that display a GTK native widget only have 
 153    one widget, so in the case of e.g. the wxButton class m_widget holds a 
 154    pointer to a GtkButton widget. But windows with client areas (for drawing 
 155    and children) have a m_widget field that is a pointer to a GtkScrolled- 
 156    Window and a m_wxwindow field that is pointer to a GtkPizza and this 
 157    one is (in the GTK sense) a child of the GtkScrolledWindow. 
 159    If the m_wxwindow field is set, then all input to this widget is inter- 
 160    cepted and sent to the wxWindows class. If not, all input to the widget 
 161    that gets pointed to by m_widget gets intercepted and sent to the class. 
 165    The design of scrolling in wxWindows is markedly different from that offered 
 166    by the GTK itself and therefore we cannot simply take it as it is. In GTK, 
 167    clicking on a scrollbar belonging to scrolled window will inevitably move 
 168    the window. In wxWindows, the scrollbar will only emit an event, send this 
 169    to (normally) a wxScrolledWindow and that class will call ScrollWindow() 
 170    which actually moves the window and its subchildren. Note that GtkPizza 
 171    memorizes how much it has been scrolled but that wxWindows forgets this 
 172    so that the two coordinates systems have to be kept in synch. This is done 
 173    in various places using the pizza->xoffset and pizza->yoffset values. 
 177    Singularily the most broken code in GTK is the code that is supposes to 
 178    inform subwindows (child windows) about new positions. Very often, duplicate 
 179    events are sent without changes in size or position, equally often no 
 180    events are sent at all (All this is due to a bug in the GtkContainer code 
 181    which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores 
 182    GTK's own system and it simply waits for size events for toplevel windows 
 183    and then iterates down the respective size events to all window. This has 
 184    the disadvantage, that windows might get size events before the GTK widget 
 185    actually has the reported size. This doesn't normally pose any problem, but 
 186    the OpenGl drawing routines rely on correct behaviour. Therefore, I have 
 187    added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas, 
 188    i.e. the wxGLCanvas will emit a size event, when (and not before) the X11 
 189    window that is used for OpenGl output really has that size (as reported by 
 194    If someone at some point of time feels the immense desire to have a look at, 
 195    change or attempt to optimse the Refresh() logic, this person will need an 
 196    intimate understanding of what a "draw" and what an "expose" events are and 
 197    what there are used for, in particular when used in connection with GTK's 
 198    own windowless widgets. Beware. 
 202    Cursors, too, have been a constant source of pleasure. The main difficulty 
 203    is that a GdkWindow inherits a cursor if the programmer sets a new cursor 
 204    for the parent. To prevent this from doing too much harm, I use idle time 
 205    to set the cursor over and over again, starting from the toplevel windows 
 206    and ending with the youngest generation (speaking of parent and child windows). 
 207    Also don't forget that cursors (like much else) are connected to GdkWindows, 
 208    not GtkWidgets and that the "window" field of a GtkWidget might very well 
 209    point to the GdkWindow of the parent widget (-> "window less widget") and 
 210    that the two obviously have very different meanings. 
 214 //----------------------------------------------------------------------------- 
 216 //----------------------------------------------------------------------------- 
 218 extern wxList     wxPendingDelete
; 
 219 extern bool       g_blockEventsOnDrag
; 
 220 extern bool       g_blockEventsOnScroll
; 
 221 extern wxCursor   g_globalCursor
; 
 223 static GdkGC 
*g_eraseGC 
= NULL
; 
 225 // mouse capture state: the window which has it and if the mouse is currently 
 227 static wxWindowGTK  
*g_captureWindow 
= (wxWindowGTK
*) NULL
; 
 228 static bool g_captureWindowHasMouse 
= FALSE
; 
 230 /* extern */ wxWindowGTK  
*g_focusWindow 
= (wxWindowGTK
*) NULL
; 
 232 // the last window which had the focus - this is normally never NULL (except 
 233 // if we never had focus at all) as even when g_focusWindow is NULL it still 
 234 // keeps its previous value 
 235 static wxWindowGTK 
*g_focusWindowLast 
= (wxWindowGTK
*) NULL
; 
 237 // the frame that is currently active (i.e. its child has focus). It is 
 238 // used to generate wxActivateEvents 
 239 static wxWindowGTK 
*g_activeFrame 
= (wxWindowGTK
*) NULL
; 
 240 static bool g_activeFrameLostFocus 
= FALSE
; 
 242 // If a window get the focus set but has not been realized 
 243 // yet, defer setting the focus to idle time. 
 244 wxWindowGTK 
*g_delayedFocus 
= (wxWindowGTK
*) NULL
; 
 246 // if we detect that the app has got/lost the focus, we set this variable to 
 247 // either TRUE or FALSE and an activate event will be sent during the next 
 248 // OnIdle() call and it is reset to -1: this value means that we shouldn't 
 249 // send any activate events at all 
 250 static int        g_sendActivateEvent 
= -1; 
 252 /* hack: we need something to pass to gtk_menu_popup, so we store the time of 
 253    the last click here */ 
 254 static guint32 gs_timeLastClick 
= 0; 
 256 extern bool g_mainThreadLocked
; 
 258 //----------------------------------------------------------------------------- 
 260 //----------------------------------------------------------------------------- 
 263 #define DISABLE_STYLE_IF_BROKEN_THEME 1 
 269 #   define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance"); 
 271 #   define DEBUG_MAIN_THREAD 
 274 #define DEBUG_MAIN_THREAD 
 277 // the trace mask used for the focus debugging messages 
 278 #define TRACE_FOCUS _T("focus") 
 280 //----------------------------------------------------------------------------- 
 281 // missing gdk functions 
 282 //----------------------------------------------------------------------------- 
 285 gdk_window_warp_pointer (GdkWindow      
*window
, 
 290   GdkWindowPrivate 
*priv
; 
 294     window 
= GDK_ROOT_PARENT(); 
 297   if (!GDK_WINDOW_DESTROYED(window
)) 
 299       XWarpPointer (GDK_WINDOW_XDISPLAY(window
), 
 300                     None
,              /* not source window -> move from anywhere */ 
 301                     GDK_WINDOW_XID(window
),  /* dest window */ 
 302                     0, 0, 0, 0,        /* not source window -> move from anywhere */ 
 306   priv 
= (GdkWindowPrivate
*) window
; 
 308   if (!priv
->destroyed
) 
 310       XWarpPointer (priv
->xdisplay
, 
 311                     None
,              /* not source window -> move from anywhere */ 
 312                     priv
->xwindow
,  /* dest window */ 
 313                     0, 0, 0, 0,        /* not source window -> move from anywhere */ 
 319 //----------------------------------------------------------------------------- 
 321 //----------------------------------------------------------------------------- 
 323 extern void wxapp_install_idle_handler(); 
 324 extern bool g_isIdle
; 
 326 //----------------------------------------------------------------------------- 
 327 // local code (see below) 
 328 //----------------------------------------------------------------------------- 
 330 // returns the child of win which currently has focus or NULL if not found 
 332 // Note: can't be static, needed by textctrl.cpp. 
 333 wxWindow 
*wxFindFocusedChild(wxWindowGTK 
*win
) 
 335     wxWindow 
*winFocus 
= wxWindowGTK::FindFocus(); 
 337         return (wxWindow 
*)NULL
; 
 339     if ( winFocus 
== win 
) 
 340         return (wxWindow 
*)win
; 
 342     for ( wxWindowList::Node 
*node 
= win
->GetChildren().GetFirst(); 
 344           node 
= node
->GetNext() ) 
 346         wxWindow 
*child 
= wxFindFocusedChild(node
->GetData()); 
 351     return (wxWindow 
*)NULL
; 
 354 static void draw_frame( GtkWidget 
*widget
, wxWindowGTK 
*win 
) 
 356     // wxUniversal widgets draw the borders and scrollbars themselves 
 357 #ifndef __WXUNIVERSAL__ 
 364     if (win
->m_hasScrolling
) 
 366         GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(widget
); 
 368         GtkRequisition vscroll_req
; 
 369         vscroll_req
.width 
= 2; 
 370         vscroll_req
.height 
= 2; 
 371         (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
 372             (scroll_window
->vscrollbar
, &vscroll_req 
); 
 374         GtkRequisition hscroll_req
; 
 375         hscroll_req
.width 
= 2; 
 376         hscroll_req
.height 
= 2; 
 377         (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
 378             (scroll_window
->hscrollbar
, &hscroll_req 
); 
 380         GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) ); 
 382         if (scroll_window
->vscrollbar_visible
) 
 384             dw 
+= vscroll_req
.width
; 
 385             dw 
+= scroll_class
->scrollbar_spacing
; 
 388         if (scroll_window
->hscrollbar_visible
) 
 390             dh 
+= hscroll_req
.height
; 
 391             dh 
+= scroll_class
->scrollbar_spacing
; 
 397     if (GTK_WIDGET_NO_WINDOW (widget
)) 
 399         dx 
+= widget
->allocation
.x
; 
 400         dy 
+= widget
->allocation
.y
; 
 403     if (win
->HasFlag(wxRAISED_BORDER
)) 
 405         gtk_draw_shadow( widget
->style
, 
 410                          widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh 
); 
 414     if (win
->HasFlag(wxSUNKEN_BORDER
)) 
 416         gtk_draw_shadow( widget
->style
, 
 421                          widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh 
); 
 425     if (win
->HasFlag(wxSIMPLE_BORDER
)) 
 428         gc 
= gdk_gc_new( widget
->window 
); 
 429         gdk_gc_set_foreground( gc
, &widget
->style
->black 
); 
 430         gdk_draw_rectangle( widget
->window
, gc
, FALSE
, 
 432                          widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 ); 
 436 #endif // __WXUNIVERSAL__ 
 439 //----------------------------------------------------------------------------- 
 440 // "expose_event" of m_widget 
 441 //----------------------------------------------------------------------------- 
 443 gint 
gtk_window_own_expose_callback( GtkWidget 
*widget
, GdkEventExpose 
*gdk_event
, wxWindowGTK 
*win 
) 
 445     if (gdk_event
->count 
> 0) return FALSE
; 
 447     draw_frame( widget
, win 
); 
 451     (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
); 
 457 //----------------------------------------------------------------------------- 
 458 // "draw" of m_widget 
 459 //----------------------------------------------------------------------------- 
 463 static void gtk_window_own_draw_callback( GtkWidget 
*widget
, GdkRectangle 
*WXUNUSED(rect
), wxWindowGTK 
*win 
) 
 465     draw_frame( widget
, win 
); 
 470 //----------------------------------------------------------------------------- 
 471 // "size_request" of m_widget 
 472 //----------------------------------------------------------------------------- 
 474 static void gtk_window_size_request_callback( GtkWidget 
*widget
, GtkRequisition 
*requisition
, wxWindow 
*win 
) 
 477     win
->GetSize( &w
, &h 
); 
 481     requisition
->height 
= h
; 
 482     requisition
->width 
= w
; 
 485 //----------------------------------------------------------------------------- 
 486 // "expose_event" of m_wxwindow 
 487 //----------------------------------------------------------------------------- 
 489 static int gtk_window_expose_callback( GtkWidget 
*widget
, 
 490                                        GdkEventExpose 
*gdk_event
, 
 496         wxapp_install_idle_handler(); 
 501         wxPrintf( wxT("OnExpose from ") ); 
 502         if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName()) 
 503             wxPrintf( win
->GetClassInfo()->GetClassName() ); 
 504         wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event
->area
.x
, 
 505                                          (int)gdk_event
->area
.y
, 
 506                                          (int)gdk_event
->area
.width
, 
 507                                          (int)gdk_event
->area
.height 
); 
 511     win
->GetUpdateRegion().Union( gdk_event
->area
.x
, 
 513                                   gdk_event
->area
.width
, 
 514                                   gdk_event
->area
.height 
); 
 515     win
->m_clearRegion
.Union( gdk_event
->area
.x
, 
 517                                   gdk_event
->area
.width
, 
 518                                   gdk_event
->area
.height 
); 
 520     // Actual redrawing takes place in idle time. 
 525     (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
); 
 532 //----------------------------------------------------------------------------- 
 533 // "event" of m_wxwindow 
 534 //----------------------------------------------------------------------------- 
 536 // GTK thinks it is clever and filters out a certain amount of "unneeded" 
 537 // expose events. We need them, of course, so we override the main event 
 538 // procedure in GtkWidget by giving our own handler for all system events. 
 539 // There, we look for expose events ourselves whereas all other events are 
 542 gint 
gtk_window_event_event_callback( GtkWidget 
*widget
, 
 543                                       GdkEventExpose 
*event
, 
 546     if (event
->type 
== GDK_EXPOSE
) 
 548         gint ret 
= gtk_window_expose_callback( widget
, event
, win 
); 
 555 //----------------------------------------------------------------------------- 
 556 // "draw" of m_wxwindow 
 557 //----------------------------------------------------------------------------- 
 561 // This callback is a complete replacement of the gtk_pizza_draw() function, 
 562 // which is disabled. 
 564 static void gtk_window_draw_callback( GtkWidget 
*widget
, 
 571         wxapp_install_idle_handler(); 
 573     // The wxNO_FULL_REPAINT_ON_RESIZE flag only works if 
 574     // there are no child windows. 
 575     if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) && 
 576         (win
->GetChildren().GetCount() == 0)) 
 584         wxPrintf( wxT("OnDraw from ") ); 
 585         if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName()) 
 586             wxPrintf( win
->GetClassInfo()->GetClassName() ); 
 587         wxPrintf( wxT(" %d %d %d %d\n"), (int)rect
->x
, 
 594 #ifndef __WXUNIVERSAL__ 
 595     GtkPizza 
*pizza 
= GTK_PIZZA (widget
); 
 597     if (win
->GetThemeEnabled()) 
 599         wxWindow 
*parent 
= win
->GetParent(); 
 600         while (parent 
&& !parent
->IsTopLevel()) 
 601             parent 
= parent
->GetParent(); 
 605         gtk_paint_flat_box (parent
->m_widget
->style
, 
 616     if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) && 
 617          (pizza
->clear_on_draw
)) 
 619         gdk_window_clear_area( pizza
->bin_window
, 
 620                                rect
->x
, rect
->y
, rect
->width
, rect
->height
); 
 624     win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
 626     // Actual redrawing takes place in idle time. 
 630 #ifndef __WXUNIVERSAL__ 
 631     // Redraw child widgets 
 632     GList 
*children 
= pizza
->children
; 
 635         GtkPizzaChild 
*child 
= (GtkPizzaChild
*) children
->data
; 
 636         children 
= children
->next
; 
 638         GdkRectangle child_area
; 
 639         if (gtk_widget_intersect (child
->widget
, rect
, &child_area
)) 
 641             gtk_widget_draw (child
->widget
, &child_area 
/* (GdkRectangle*) NULL*/ ); 
 649 //----------------------------------------------------------------------------- 
 650 // "key_press_event" from any window 
 651 //----------------------------------------------------------------------------- 
 653 // set WXTRACE to this to see the key event codes on the console 
 654 #define TRACE_KEYS  _T("keyevent") 
 656 // translates an X key symbol to WXK_XXX value 
 658 // if isChar is true it means that the value returned will be used for EVT_CHAR 
 659 // event and then we choose the logical WXK_XXX, i.e. '/' for GDK_KP_Divide, 
 660 // for example, while if it is false it means that the value is going to be 
 661 // used for KEY_DOWN/UP events and then we translate GDK_KP_Divide to 
 663 static long wxTranslateKeySymToWXKey(KeySym keysym
, bool isChar
) 
 669         // Shift, Control and Alt don't generate the CHAR events at all 
 672             key_code 
= isChar 
? 0 : WXK_SHIFT
; 
 676             key_code 
= isChar 
? 0 : WXK_CONTROL
; 
 684             key_code 
= isChar 
? 0 : WXK_ALT
; 
 687         // neither do the toggle modifies 
 688         case GDK_Scroll_Lock
: 
 689             key_code 
= isChar 
? 0 : WXK_SCROLL
; 
 693             key_code 
= isChar 
? 0 : WXK_CAPITAL
; 
 697             key_code 
= isChar 
? 0 : WXK_NUMLOCK
; 
 701         // various other special keys 
 714         case GDK_ISO_Left_Tab
: 
 721             key_code 
= WXK_RETURN
; 
 725             key_code 
= WXK_CLEAR
; 
 729             key_code 
= WXK_PAUSE
; 
 733             key_code 
= WXK_SELECT
; 
 737             key_code 
= WXK_PRINT
; 
 741             key_code 
= WXK_EXECUTE
; 
 745             key_code 
= WXK_ESCAPE
; 
 748         // cursor and other extended keyboard keys 
 750             key_code 
= WXK_DELETE
; 
 766             key_code 
= WXK_RIGHT
; 
 773         case GDK_Prior
:     // == GDK_Page_Up 
 774             key_code 
= WXK_PRIOR
; 
 777         case GDK_Next
:      // == GDK_Page_Down 
 790             key_code 
= WXK_INSERT
; 
 805             key_code 
= (isChar 
? '0' : WXK_NUMPAD0
) + keysym 
- GDK_KP_0
; 
 809             key_code 
= isChar 
? ' ' : WXK_NUMPAD_SPACE
; 
 813             key_code 
= isChar 
? WXK_TAB 
: WXK_NUMPAD_TAB
; 
 817             key_code 
= isChar 
? WXK_RETURN 
: WXK_NUMPAD_ENTER
; 
 821             key_code 
= isChar 
? WXK_F1 
: WXK_NUMPAD_F1
; 
 825             key_code 
= isChar 
? WXK_F2 
: WXK_NUMPAD_F2
; 
 829             key_code 
= isChar 
? WXK_F3 
: WXK_NUMPAD_F3
; 
 833             key_code 
= isChar 
? WXK_F4 
: WXK_NUMPAD_F4
; 
 837             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_HOME
; 
 841             key_code 
= isChar 
? WXK_LEFT 
: WXK_NUMPAD_LEFT
; 
 845             key_code 
= isChar 
? WXK_UP 
: WXK_NUMPAD_UP
; 
 849             key_code 
= isChar 
? WXK_RIGHT 
: WXK_NUMPAD_RIGHT
; 
 853             key_code 
= isChar 
? WXK_DOWN 
: WXK_NUMPAD_DOWN
; 
 856         case GDK_KP_Prior
: // == GDK_KP_Page_Up 
 857             key_code 
= isChar 
? WXK_PRIOR 
: WXK_NUMPAD_PRIOR
; 
 860         case GDK_KP_Next
: // == GDK_KP_Page_Down 
 861             key_code 
= isChar 
? WXK_NEXT 
: WXK_NUMPAD_NEXT
; 
 865             key_code 
= isChar 
? WXK_END 
: WXK_NUMPAD_END
; 
 869             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_BEGIN
; 
 873             key_code 
= isChar 
? WXK_INSERT 
: WXK_NUMPAD_INSERT
; 
 877             key_code 
= isChar 
? WXK_DELETE 
: WXK_NUMPAD_DELETE
; 
 881             key_code 
= isChar 
? '=' : WXK_NUMPAD_EQUAL
; 
 884         case GDK_KP_Multiply
: 
 885             key_code 
= isChar 
? '*' : WXK_NUMPAD_MULTIPLY
; 
 889             key_code 
= isChar 
? '+' : WXK_NUMPAD_ADD
; 
 892         case GDK_KP_Separator
: 
 893             // FIXME: what is this? 
 894             key_code 
= isChar 
? '.' : WXK_NUMPAD_SEPARATOR
; 
 897         case GDK_KP_Subtract
: 
 898             key_code 
= isChar 
? '-' : WXK_NUMPAD_SUBTRACT
; 
 902             key_code 
= isChar 
? '.' : WXK_NUMPAD_DECIMAL
; 
 906             key_code 
= isChar 
? '/' : WXK_NUMPAD_DIVIDE
; 
 923             key_code 
= WXK_F1 
+ keysym 
- GDK_F1
; 
 933 static inline bool wxIsAsciiKeysym(KeySym ks
) 
 939 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
, 
 941                            GdkEventKey 
*gdk_event
) 
 943     // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string 
 944     //     but only event->keyval which is quite useless to us, so remember 
 945     //     the last character from GDK_KEY_PRESS and reuse it as last resort 
 947     // NB: should be MT-safe as we're always called from the main thread only 
 952     } s_lastKeyPress 
= { 0, 0 }; 
 954     KeySym keysym 
= gdk_event
->keyval
; 
 956     wxLogTrace(TRACE_KEYS
, _T("Key %s event: keysym = %d"), 
 957                event
.GetEventType() == wxEVT_KEY_UP 
? _T("release") 
 961     long key_code 
= wxTranslateKeySymToWXKey(keysym
, FALSE 
/* !isChar */); 
 965         // do we have the translation or is it a plain ASCII character? 
 966         if ( (gdk_event
->length 
== 1) || wxIsAsciiKeysym(keysym
) ) 
 968             // we should use keysym if it is ASCII as X does some translations 
 969             // like "I pressed while Control is down" => "Ctrl-I" == "TAB" 
 970             // which we don't want here (but which we do use for OnChar()) 
 971             if ( !wxIsAsciiKeysym(keysym
) ) 
 973                 keysym 
= (KeySym
)gdk_event
->string
[0]; 
 976             // we want to always get the same key code when the same key is 
 977             // pressed regardless of the state of the modifies, i.e. on a 
 978             // standard US keyboard pressing '5' or '%' ('5' key with 
 979             // Shift) should result in the same key code in OnKeyDown(): 
 980             // '5' (although OnChar() will get either '5' or '%'). 
 982             // to do it we first translate keysym to keycode (== scan code) 
 983             // and then back but always using the lower register 
 984             Display 
*dpy 
= (Display 
*)wxGetDisplay(); 
 985             KeyCode keycode 
= XKeysymToKeycode(dpy
, keysym
); 
 987             wxLogTrace(TRACE_KEYS
, _T("\t-> keycode %d"), keycode
); 
 989             KeySym keysymNormalized 
= XKeycodeToKeysym(dpy
, keycode
, 0); 
 991             // use the normalized, i.e. lower register, keysym if we've 
 993             key_code 
= keysymNormalized 
? keysymNormalized 
: keysym
; 
 995             // as explained above, we want to have lower register key codes 
 996             // normally but for the letter keys we want to have the upper ones 
 998             // NB: don't use XConvertCase() here, we want to do it for letters 
1000             key_code 
= toupper(key_code
); 
1002         else // non ASCII key, what to do? 
1004             // by default, ignore it 
1007             // but if we have cached information from the last KEY_PRESS 
1008             if ( gdk_event
->type 
== GDK_KEY_RELEASE 
) 
1011                 if ( keysym 
== s_lastKeyPress
.keysym 
) 
1013                     key_code 
= s_lastKeyPress
.keycode
; 
1018         if ( gdk_event
->type 
== GDK_KEY_PRESS 
) 
1020             // remember it to be reused for KEY_UP event later 
1021             s_lastKeyPress
.keysym 
= keysym
; 
1022             s_lastKeyPress
.keycode 
= key_code
; 
1026     wxLogTrace(TRACE_KEYS
, _T("\t-> wxKeyCode %d"), key_code
); 
1028     // sending unknown key events doesn't really make sense 
1032     // now fill all the other fields 
1035     GdkModifierType state
; 
1036     if (gdk_event
->window
) 
1037         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1039     event
.SetTimestamp( gdk_event
->time 
); 
1040     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
) != 0; 
1041     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
) != 0; 
1042     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
) != 0; 
1043     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
) != 0; 
1044     event
.m_keyCode 
= key_code
; 
1045     event
.m_scanCode 
= gdk_event
->keyval
; 
1046     event
.m_rawCode 
= (wxUint32
) gdk_event
->keyval
; 
1047     event
.m_rawFlags 
= 0; 
1050     event
.SetEventObject( win 
); 
1055 static gint 
gtk_window_key_press_callback( GtkWidget 
*widget
, 
1056                                            GdkEventKey 
*gdk_event
, 
1062         wxapp_install_idle_handler(); 
1066     if (g_blockEventsOnDrag
) 
1071     wxKeyEvent 
event( wxEVT_CHAR_HOOK 
);     
1072     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1074         // unknown key pressed, ignore (the event would be useless anyhow) 
1078     // Implement wxFrame::OnCharHook by checking ancestor. 
1079     wxWindow 
*parent 
= win
; 
1080     while (parent 
&& !parent
->IsTopLevel()) 
1081         parent 
= parent
->GetParent(); 
1084         ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1088         event
.SetEventType(wxEVT_KEY_DOWN
); 
1089         ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1095         wxWindowGTK 
*ancestor 
= win
; 
1098             int command 
= ancestor
->GetAcceleratorTable()->GetCommand( event 
); 
1101                 wxCommandEvent 
command_event( wxEVT_COMMAND_MENU_SELECTED
, command 
); 
1102                 ret 
= ancestor
->GetEventHandler()->ProcessEvent( command_event 
); 
1105             if (ancestor
->IsTopLevel()) 
1107             ancestor 
= ancestor
->GetParent(); 
1110 #endif // wxUSE_ACCEL 
1112     /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x 
1113        will only be sent if it is not in an accelerator table. */ 
1116         KeySym keysym 
= gdk_event
->keyval
; 
1117         long key_code 
= wxTranslateKeySymToWXKey(keysym
, TRUE 
/* isChar */); 
1120             if ( gdk_event
->length 
== 1 ) 
1122                 key_code 
= (unsigned char)gdk_event
->string
[0]; 
1124             else if ( wxIsAsciiKeysym(keysym
) ) 
1127                 key_code 
= (unsigned char)keysym
; 
1133             wxLogTrace(TRACE_KEYS
, _T("Char event: %ld"), key_code
); 
1135             // reuse the same event object, just change its type and use the 
1136             // translated keycode instead of the raw one 
1137             event
.SetEventType(wxEVT_CHAR
); 
1138             event
.m_keyCode 
= key_code
; 
1140             ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1144     /* win is a control: tab can be propagated up */ 
1146          ((gdk_event
->keyval 
== GDK_Tab
) || (gdk_event
->keyval 
== GDK_ISO_Left_Tab
)) && 
1147 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may 
1148 //     have this style, yet choose not to process this particular TAB in which 
1149 //     case TAB must still work as a navigational character 
1151          !win
->HasFlag(wxTE_PROCESS_TAB
) && 
1153          win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) ) 
1155         wxNavigationKeyEvent new_event
; 
1156         new_event
.SetEventObject( win
->GetParent() ); 
1157         /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */ 
1158         new_event
.SetDirection( (gdk_event
->keyval 
== GDK_Tab
) ); 
1159         /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */ 
1160         new_event
.SetWindowChange( (gdk_event
->state 
& GDK_CONTROL_MASK
) ); 
1161         new_event
.SetCurrentFocus( win 
); 
1162         ret 
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event 
); 
1165     /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */ 
1167          (gdk_event
->keyval 
== GDK_Escape
) ) 
1169         wxCommandEvent 
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
); 
1170         new_event
.SetEventObject( win 
); 
1171         ret 
= win
->GetEventHandler()->ProcessEvent( new_event 
); 
1175 #if 0 // (GTK_MINOR_VERSION > 0) 
1176     /* Pressing F10 will activate the menu bar of the top frame. */ 
1178          (gdk_event
->keyval 
== GDK_F10
) ) 
1180         wxWindowGTK 
*ancestor 
= win
; 
1183             if (wxIsKindOf(ancestor
,wxFrame
)) 
1185                 wxFrame 
*frame 
= (wxFrame
*) ancestor
; 
1186                 wxMenuBar 
*menubar 
= frame
->GetMenuBar(); 
1189                     wxNode 
*node 
= menubar
->GetMenus().First(); 
1192                         wxMenu 
*firstMenu 
= (wxMenu
*) node
->Data(); 
1193                         gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) ); 
1199             ancestor 
= ancestor
->GetParent(); 
1206         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" ); 
1213 //----------------------------------------------------------------------------- 
1214 // "key_release_event" from any window 
1215 //----------------------------------------------------------------------------- 
1217 static gint 
gtk_window_key_release_callback( GtkWidget 
*widget
, 
1218                                              GdkEventKey 
*gdk_event
, 
1224         wxapp_install_idle_handler(); 
1229     if (g_blockEventsOnDrag
) 
1232     wxKeyEvent 
event( wxEVT_KEY_UP 
); 
1233     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1235         // unknown key pressed, ignore (the event would be useless anyhow 
1239     if ( !win
->GetEventHandler()->ProcessEvent( event 
) ) 
1242     gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" ); 
1246 // ============================================================================ 
1248 // ============================================================================ 
1250 // ---------------------------------------------------------------------------- 
1251 // mouse event processing helpers 
1252 // ---------------------------------------------------------------------------- 
1254 // init wxMouseEvent with the info from gdk_event 
1255 #define InitMouseEvent(win, event, gdk_event) \ 
1257     event.SetTimestamp( gdk_event->time ); \ 
1258     event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \ 
1259     event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \ 
1260     event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \ 
1261     event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \ 
1262     event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \ 
1263     event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \ 
1264     event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \ 
1266     wxPoint pt = win->GetClientAreaOrigin(); \ 
1267     event.m_x = (wxCoord)gdk_event->x - pt.x; \ 
1268     event.m_y = (wxCoord)gdk_event->y - pt.y; \ 
1271 static void AdjustEventButtonState(wxMouseEvent
& event
) 
1273     // GDK reports the old state of the button for a button press event, but 
1274     // for compatibility with MSW and common sense we want m_leftDown be TRUE 
1275     // for a LEFT_DOWN event, not FALSE, so we will invert 
1276     // left/right/middleDown for the corresponding click events 
1278     if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) || 
1279         (event
.GetEventType() == wxEVT_LEFT_DCLICK
) || 
1280         (event
.GetEventType() == wxEVT_LEFT_UP
)) 
1282         event
.m_leftDown 
= !event
.m_leftDown
; 
1286     if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) || 
1287         (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) || 
1288         (event
.GetEventType() == wxEVT_MIDDLE_UP
)) 
1290         event
.m_middleDown 
= !event
.m_middleDown
; 
1294     if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) || 
1295         (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) || 
1296         (event
.GetEventType() == wxEVT_RIGHT_UP
)) 
1298         event
.m_rightDown 
= !event
.m_rightDown
; 
1303 // find the window to send the mouse event too 
1305 wxWindowGTK 
*FindWindowForMouseEvent(wxWindowGTK 
*win
, wxCoord
& x
, wxCoord
& y
) 
1310     if (win
->m_wxwindow
) 
1312         GtkPizza 
*pizza 
= GTK_PIZZA(win
->m_wxwindow
); 
1313         xx 
+= pizza
->xoffset
; 
1314         yy 
+= pizza
->yoffset
; 
1317     wxNode 
*node 
= win
->GetChildren().First(); 
1320         wxWindowGTK 
*child 
= (wxWindowGTK
*)node
->Data(); 
1322         node 
= node
->Next(); 
1323         if (!child
->IsShown()) 
1326         if (child
->IsTransparentForMouse()) 
1328             // wxStaticBox is transparent in the box itself 
1329             int xx1 
= child
->m_x
; 
1330             int yy1 
= child
->m_y
; 
1331             int xx2 
= child
->m_x 
+ child
->m_width
; 
1332             int yy2 
= child
->m_x 
+ child
->m_height
; 
1335             if (((xx 
>= xx1
) && (xx 
<= xx1
+10) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1337                 ((xx 
>= xx2
-10) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1339                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy1
+10)) || 
1341                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy2
-1) && (yy 
<= yy2
))) 
1352             if ((child
->m_wxwindow 
== (GtkWidget
*) NULL
) && 
1353                 (child
->m_x 
<= xx
) && 
1354                 (child
->m_y 
<= yy
) && 
1355                 (child
->m_x
+child
->m_width  
>= xx
) && 
1356                 (child
->m_y
+child
->m_height 
>= yy
)) 
1369 //----------------------------------------------------------------------------- 
1370 // "button_press_event" 
1371 //----------------------------------------------------------------------------- 
1373 static gint 
gtk_window_button_press_callback( GtkWidget 
*widget
, 
1374                                               GdkEventButton 
*gdk_event
, 
1380         wxapp_install_idle_handler(); 
1383     wxPrintf( wxT("1) OnButtonPress from ") ); 
1384     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1385         wxPrintf( win->GetClassInfo()->GetClassName() ); 
1386     wxPrintf( wxT(".\n") ); 
1388     if (!win
->m_hasVMT
) return FALSE
; 
1389     if (g_blockEventsOnDrag
) return TRUE
; 
1390     if (g_blockEventsOnScroll
) return TRUE
; 
1392     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1394     if (win
->m_wxwindow 
&& (g_focusWindow 
!= win
) && win
->AcceptsFocus()) 
1396         gtk_widget_grab_focus( win
->m_wxwindow 
); 
1398         wxPrintf( wxT("GrabFocus from ") ); 
1399         if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1400             wxPrintf( win->GetClassInfo()->GetClassName() ); 
1401         wxPrintf( wxT(".\n") ); 
1405     wxEventType event_type 
= wxEVT_NULL
; 
1407     if (gdk_event
->button 
== 1) 
1409         switch (gdk_event
->type
) 
1411             case GDK_BUTTON_PRESS
: event_type 
= wxEVT_LEFT_DOWN
; break; 
1412             case GDK_2BUTTON_PRESS
: event_type 
= wxEVT_LEFT_DCLICK
; break; 
1416     else if (gdk_event
->button 
== 2) 
1418         switch (gdk_event
->type
) 
1420             case GDK_BUTTON_PRESS
: event_type 
= wxEVT_MIDDLE_DOWN
; break; 
1421             case GDK_2BUTTON_PRESS
: event_type 
= wxEVT_MIDDLE_DCLICK
; break; 
1425     else if (gdk_event
->button 
== 3) 
1427         switch (gdk_event
->type
) 
1429             case GDK_BUTTON_PRESS
: event_type 
= wxEVT_RIGHT_DOWN
; break; 
1430             case GDK_2BUTTON_PRESS
: event_type 
= wxEVT_RIGHT_DCLICK
; break; 
1435     if ( event_type 
== wxEVT_NULL 
) 
1437         // unknown mouse button or click type 
1441     wxMouseEvent 
event( event_type 
); 
1442     InitMouseEvent( win
, event
, gdk_event 
); 
1444     AdjustEventButtonState(event
); 
1446     // wxListBox actually get mouse events from the item, so we need to give it 
1447     // a chance to correct this 
1448     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1450     // find the correct window to send the event too: it may be a different one 
1451     // from the one which got it at GTK+ level because some control don't have 
1452     // their own X window and thus cannot get any events. 
1453     if ( !g_captureWindow 
) 
1454         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1456     event
.SetEventObject( win 
); 
1458     gs_timeLastClick 
= gdk_event
->time
; 
1461     wxPrintf( wxT("2) OnButtonPress from ") ); 
1462     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1463         wxPrintf( win->GetClassInfo()->GetClassName() ); 
1464     wxPrintf( wxT(".\n") ); 
1467     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1469         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" ); 
1476 //----------------------------------------------------------------------------- 
1477 // "button_release_event" 
1478 //----------------------------------------------------------------------------- 
1480 static gint 
gtk_window_button_release_callback( GtkWidget 
*widget
, GdkEventButton 
*gdk_event
, wxWindowGTK 
*win 
) 
1485         wxapp_install_idle_handler(); 
1487     if (!win
->m_hasVMT
) return FALSE
; 
1488     if (g_blockEventsOnDrag
) return FALSE
; 
1489     if (g_blockEventsOnScroll
) return FALSE
; 
1491     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1494     printf( "OnButtonRelease from " ); 
1495     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1496         printf( win->GetClassInfo()->GetClassName() ); 
1500     wxEventType event_type 
= wxEVT_NULL
; 
1502     switch (gdk_event
->button
) 
1504         case 1: event_type 
= wxEVT_LEFT_UP
; break; 
1505         case 2: event_type 
= wxEVT_MIDDLE_UP
; break; 
1506         case 3: event_type 
= wxEVT_RIGHT_UP
; break; 
1507         default: return FALSE
; 
1510     wxMouseEvent 
event( event_type 
); 
1511     InitMouseEvent( win
, event
, gdk_event 
); 
1513     AdjustEventButtonState(event
); 
1515     // same wxListBox hack as above 
1516     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1518     if ( !g_captureWindow 
) 
1519         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1521     event
.SetEventObject( win 
); 
1523     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1525         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" ); 
1532 //----------------------------------------------------------------------------- 
1533 // "motion_notify_event" 
1534 //----------------------------------------------------------------------------- 
1536 static gint 
gtk_window_motion_notify_callback( GtkWidget 
*widget
, 
1537                                                GdkEventMotion 
*gdk_event
, 
1543         wxapp_install_idle_handler(); 
1545     if (!win
->m_hasVMT
) return FALSE
; 
1546     if (g_blockEventsOnDrag
) return FALSE
; 
1547     if (g_blockEventsOnScroll
) return FALSE
; 
1549     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1551     if (gdk_event
->is_hint
) 
1555         GdkModifierType state
; 
1556         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1562     printf( "OnMotion from " ); 
1563     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1564       printf( win->GetClassInfo()->GetClassName() ); 
1568     wxMouseEvent 
event( wxEVT_MOTION 
); 
1569     InitMouseEvent(win
, event
, gdk_event
); 
1571     if ( g_captureWindow 
) 
1573         // synthetize a mouse enter or leave event if needed 
1574         GdkWindow 
*winUnderMouse 
= gdk_window_at_pointer(NULL
, NULL
); 
1575         bool hasMouse 
= winUnderMouse 
== gdk_event
->window
; 
1576         if ( hasMouse 
!= g_captureWindowHasMouse 
) 
1578             // the mouse changed window 
1579             g_captureWindowHasMouse 
= hasMouse
; 
1581             wxMouseEvent 
event(g_captureWindowHasMouse 
? wxEVT_ENTER_WINDOW
 
1582                                                        : wxEVT_LEAVE_WINDOW
); 
1583             InitMouseEvent(win
, event
, gdk_event
); 
1584             event
.SetEventObject(win
); 
1585             win
->GetEventHandler()->ProcessEvent(event
); 
1590         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1593     event
.SetEventObject( win 
); 
1595     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1597         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" ); 
1604 //----------------------------------------------------------------------------- 
1606 //----------------------------------------------------------------------------- 
1608 // send the wxChildFocusEvent and wxFocusEvent, common code of 
1609 // gtk_window_focus_in_callback() and SetFocus() 
1610 static bool DoSendFocusEvents(wxWindow 
*win
) 
1612     // Notify the parent keeping track of focus for the kbd navigation 
1613     // purposes that we got it. 
1614     wxChildFocusEvent 
eventChildFocus(win
); 
1615     (void)win
->GetEventHandler()->ProcessEvent(eventChildFocus
); 
1617     wxFocusEvent 
eventFocus(wxEVT_SET_FOCUS
, win
->GetId()); 
1618     eventFocus
.SetEventObject(win
); 
1620     return win
->GetEventHandler()->ProcessEvent(eventFocus
); 
1623 static gint 
gtk_window_focus_in_callback( GtkWidget 
*widget
, 
1624                                           GdkEvent 
*WXUNUSED(event
), 
1630         wxapp_install_idle_handler(); 
1632     if (!win
->m_hasVMT
) return FALSE
; 
1633     if (g_blockEventsOnDrag
) return FALSE
; 
1635     switch ( g_sendActivateEvent 
) 
1638             // we've got focus from outside, synthetize wxActivateEvent 
1639             g_sendActivateEvent 
= 1; 
1643             // another our window just lost focus, it was already ours before 
1644             // - don't send any wxActivateEvent 
1645             g_sendActivateEvent 
= -1; 
1650     g_focusWindow 
= win
; 
1652     wxLogTrace(TRACE_FOCUS
, 
1653                _T("%s: focus in"), win
->GetName().c_str()); 
1657         gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
); 
1661     // caret needs to be informed about focus change 
1662     wxCaret 
*caret 
= win
->GetCaret(); 
1665         caret
->OnSetFocus(); 
1667 #endif // wxUSE_CARET 
1669     g_activeFrameLostFocus 
= FALSE
; 
1671     wxWindowGTK 
*active 
= wxGetTopLevelParent(win
); 
1672     if ( active 
!= g_activeFrame 
) 
1674         if ( g_activeFrame 
) 
1676             wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
); 
1677             wxActivateEvent 
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId()); 
1678             event
.SetEventObject(g_activeFrame
); 
1679             g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
1682         wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
); 
1683         g_activeFrame 
= active
; 
1684         wxActivateEvent 
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId()); 
1685         event
.SetEventObject(g_activeFrame
); 
1686         g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
1688         // Don't send focus events in addition to activate 
1689         // if (win == g_activeFrame) 
1693     // does the window itself think that it has the focus? 
1694     if ( !win
->m_hasFocus 
) 
1696         // not yet, notify it 
1697         win
->m_hasFocus 
= TRUE
; 
1699         if ( DoSendFocusEvents(win
) ) 
1701            gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" ); 
1709 //----------------------------------------------------------------------------- 
1710 // "focus_out_event" 
1711 //----------------------------------------------------------------------------- 
1713 static gint 
gtk_window_focus_out_callback( GtkWidget 
*widget
, GdkEventFocus 
*gdk_event
, wxWindowGTK 
*win 
) 
1718         wxapp_install_idle_handler(); 
1720     if (!win
->m_hasVMT
) return FALSE
; 
1721     if (g_blockEventsOnDrag
) return FALSE
; 
1723     wxLogTrace( TRACE_FOCUS
, 
1724                 _T("%s: focus out"), win
->GetName().c_str() ); 
1726     if ( !g_activeFrameLostFocus 
&& g_activeFrame 
) 
1728         // VZ: commenting this out because it does happen (although not easy 
1729         //     to reproduce, I only see it when using wxMiniFrame and not 
1730         //     always) and makes using Mahogany quite annoying 
1732         wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
, 
1733                         wxT("unfocusing window that hasn't gained focus properly") ) 
1736         g_activeFrameLostFocus 
= TRUE
; 
1739     // if the focus goes out of our app alltogether, OnIdle() will send 
1740     // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset 
1741     // g_sendActivateEvent to -1 
1742     g_sendActivateEvent 
= 0; 
1744     wxWindowGTK 
*winFocus 
= wxFindFocusedChild(win
); 
1748     g_focusWindow 
= (wxWindowGTK 
*)NULL
; 
1756     // caret needs to be informed about focus change 
1757     wxCaret 
*caret 
= win
->GetCaret(); 
1760         caret
->OnKillFocus(); 
1762 #endif // wxUSE_CARET 
1764     // don't send the window a kill focus event if it thinks that it doesn't 
1765     // have focus already 
1766     if ( win
->m_hasFocus 
) 
1768         win
->m_hasFocus 
= FALSE
; 
1770         wxFocusEvent 
event( wxEVT_KILL_FOCUS
, win
->GetId() ); 
1771         event
.SetEventObject( win 
); 
1773         if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1775             gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" ); 
1783 //----------------------------------------------------------------------------- 
1784 // "enter_notify_event" 
1785 //----------------------------------------------------------------------------- 
1787 static gint 
gtk_window_enter_callback( GtkWidget 
*widget
, GdkEventCrossing 
*gdk_event
, wxWindowGTK 
*win 
) 
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
; 
1799     wxMouseEvent 
event( wxEVT_ENTER_WINDOW 
); 
1800     event
.SetTimestamp( gdk_event
->time 
); 
1801     event
.SetEventObject( win 
); 
1805     GdkModifierType state 
= (GdkModifierType
)0; 
1807     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
1809     InitMouseEvent(win
, event
, gdk_event
); 
1810     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1811     event
.m_x 
= x 
+ pt
.x
; 
1812     event
.m_y 
= y 
+ pt
.y
; 
1814     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1816        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" ); 
1823 //----------------------------------------------------------------------------- 
1824 // "leave_notify_event" 
1825 //----------------------------------------------------------------------------- 
1827 static gint 
gtk_window_leave_callback( GtkWidget 
*widget
, GdkEventCrossing 
*gdk_event
, wxWindowGTK 
*win 
) 
1832         wxapp_install_idle_handler(); 
1834     if (!win
->m_hasVMT
) return FALSE
; 
1835     if (g_blockEventsOnDrag
) return FALSE
; 
1837     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1839     wxMouseEvent 
event( wxEVT_LEAVE_WINDOW 
); 
1840     event
.SetTimestamp( gdk_event
->time 
); 
1841     event
.SetEventObject( win 
); 
1845     GdkModifierType state 
= (GdkModifierType
)0; 
1847     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
1849     event
.m_shiftDown 
= (state 
& GDK_SHIFT_MASK
) != 0; 
1850     event
.m_controlDown 
= (state 
& GDK_CONTROL_MASK
) != 0; 
1851     event
.m_altDown 
= (state 
& GDK_MOD1_MASK
) != 0; 
1852     event
.m_metaDown 
= (state 
& GDK_MOD2_MASK
) != 0; 
1853     event
.m_leftDown 
= (state 
& GDK_BUTTON1_MASK
) != 0; 
1854     event
.m_middleDown 
= (state 
& GDK_BUTTON2_MASK
) != 0; 
1855     event
.m_rightDown 
= (state 
& GDK_BUTTON3_MASK
) != 0; 
1857     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1858     event
.m_x 
= x 
+ pt
.x
; 
1859     event
.m_y 
= y 
+ pt
.y
; 
1861     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1863         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" ); 
1870 //----------------------------------------------------------------------------- 
1871 // "value_changed" from m_vAdjust 
1872 //----------------------------------------------------------------------------- 
1874 static void gtk_window_vscroll_callback( GtkAdjustment 
*adjust
, 
1881         wxapp_install_idle_handler(); 
1883     if (g_blockEventsOnDrag
) return; 
1885     if (!win
->m_hasVMT
) return; 
1887     float diff 
= adjust
->value 
- win
->m_oldVerticalPos
; 
1888     if (fabs(diff
) < 0.2) return; 
1890     win
->m_oldVerticalPos 
= adjust
->value
; 
1892     GtkScrolledWindow   
*sw 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
1893     wxEventType         command 
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->vscrollbar
)); 
1895     int value 
= (int)(adjust
->value
+0.5); 
1897     wxScrollWinEvent 
event( command
, value
, wxVERTICAL 
); 
1898     event
.SetEventObject( win 
); 
1899     win
->GetEventHandler()->ProcessEvent( event 
); 
1902 //----------------------------------------------------------------------------- 
1903 // "value_changed" from m_hAdjust 
1904 //----------------------------------------------------------------------------- 
1906 static void gtk_window_hscroll_callback( GtkAdjustment 
*adjust
, 
1913         wxapp_install_idle_handler(); 
1915     if (g_blockEventsOnDrag
) return; 
1916     if (!win
->m_hasVMT
) return; 
1918     float diff 
= adjust
->value 
- win
->m_oldHorizontalPos
; 
1919     if (fabs(diff
) < 0.2) return; 
1921     GtkScrolledWindow   
*sw 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
1922     wxEventType         command 
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->hscrollbar
)); 
1924     win
->m_oldHorizontalPos 
= adjust
->value
; 
1926     int value 
= (int)(adjust
->value
+0.5); 
1928     wxScrollWinEvent 
event( command
, value
, wxHORIZONTAL 
); 
1929     event
.SetEventObject( win 
); 
1930     win
->GetEventHandler()->ProcessEvent( event 
); 
1933 //----------------------------------------------------------------------------- 
1934 // "button_press_event" from scrollbar 
1935 //----------------------------------------------------------------------------- 
1937 static gint 
gtk_scrollbar_button_press_callback( GtkRange 
*widget
, 
1938                                                  GdkEventButton 
*gdk_event
, 
1944         wxapp_install_idle_handler(); 
1947     g_blockEventsOnScroll 
= TRUE
; 
1949     // FIXME: there is no 'slider' field in GTK+ 2.0 any more 
1951     win
->m_isScrolling 
= (gdk_event
->window 
== widget
->slider
); 
1957 //----------------------------------------------------------------------------- 
1958 // "button_release_event" from scrollbar 
1959 //----------------------------------------------------------------------------- 
1961 static gint 
gtk_scrollbar_button_release_callback( GtkRange 
*widget
, 
1962                                                    GdkEventButton 
*WXUNUSED(gdk_event
), 
1967 //  don't test here as we can release the mouse while being over 
1968 //  a different window than the slider 
1970 //    if (gdk_event->window != widget->slider) return FALSE; 
1972     g_blockEventsOnScroll 
= FALSE
; 
1974     if (win
->m_isScrolling
) 
1976         wxEventType command 
= wxEVT_SCROLLWIN_THUMBRELEASE
; 
1980         GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
1981         if (widget 
== GTK_RANGE(scrolledWindow
->hscrollbar
)) 
1983             value 
= (int)(win
->m_hAdjust
->value
+0.5); 
1986         if (widget 
== GTK_RANGE(scrolledWindow
->vscrollbar
)) 
1988             value 
= (int)(win
->m_vAdjust
->value
+0.5); 
1992         wxScrollWinEvent 
event( command
, value
, dir 
); 
1993         event
.SetEventObject( win 
); 
1994         win
->GetEventHandler()->ProcessEvent( event 
); 
1997     win
->m_isScrolling 
= FALSE
; 
2002 // ---------------------------------------------------------------------------- 
2003 // this wxWindowBase function is implemented here (in platform-specific file) 
2004 // because it is static and so couldn't be made virtual 
2005 // ---------------------------------------------------------------------------- 
2007 wxWindow 
*wxWindowBase::FindFocus() 
2009     // the cast is necessary when we compile in wxUniversal mode 
2010     return (wxWindow 
*)g_focusWindow
; 
2013 //----------------------------------------------------------------------------- 
2015 //----------------------------------------------------------------------------- 
2017 static void gtk_window_destroy_callback( GtkWidget
* widget
, wxWindow 
*win 
) 
2019     wxWindowDestroyEvent 
event(win
); 
2020     win
->GetEventHandler()->ProcessEvent(event
); 
2023 //----------------------------------------------------------------------------- 
2024 // "realize" from m_widget 
2025 //----------------------------------------------------------------------------- 
2027 /* We cannot set colours and fonts before the widget has 
2028    been realized, so we do this directly after realization. */ 
2031 gtk_window_realized_callback( GtkWidget 
*WXUNUSED(m_widget
), wxWindow 
*win 
) 
2036         wxapp_install_idle_handler(); 
2038     if (win
->m_delayedBackgroundColour
) 
2039         win
->GtkSetBackgroundColour( win
->GetBackgroundColour() ); 
2041     if (win
->m_delayedForegroundColour
) 
2042         win
->GtkSetForegroundColour( win
->GetForegroundColour() ); 
2044     wxWindowCreateEvent 
event( win 
); 
2045     event
.SetEventObject( win 
); 
2046     win
->GetEventHandler()->ProcessEvent( event 
); 
2051 //----------------------------------------------------------------------------- 
2053 //----------------------------------------------------------------------------- 
2056 void gtk_window_size_callback( GtkWidget 
*WXUNUSED(widget
), 
2057                                GtkAllocation 
*WXUNUSED(alloc
), 
2061         wxapp_install_idle_handler(); 
2063     if (!win
->m_hasScrolling
) return; 
2065     int client_width 
= 0; 
2066     int client_height 
= 0; 
2067     win
->GetClientSize( &client_width
, &client_height 
); 
2068     if ((client_width 
== win
->m_oldClientWidth
) && (client_height 
== win
->m_oldClientHeight
)) 
2071     win
->m_oldClientWidth 
= client_width
; 
2072     win
->m_oldClientHeight 
= client_height
; 
2074     if (!win
->m_nativeSizeEvent
) 
2076         wxSizeEvent 
event( win
->GetSize(), win
->GetId() ); 
2077         event
.SetEventObject( win 
); 
2078         win
->GetEventHandler()->ProcessEvent( event 
); 
2084     #define WXUNUSED_UNLESS_XIM(param)  param 
2086     #define WXUNUSED_UNLESS_XIM(param)  WXUNUSED(param) 
2089 /* Resize XIM window */ 
2092 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
), 
2093                                  GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
), 
2094                                  wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) ) 
2097         wxapp_install_idle_handler(); 
2103     if  (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
) 
2107         gdk_window_get_size (widget
->window
, &width
, &height
); 
2108         win
->m_icattr
->preedit_area
.width 
= width
; 
2109         win
->m_icattr
->preedit_area
.height 
= height
; 
2110         gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
); 
2115 //----------------------------------------------------------------------------- 
2116 // "realize" from m_wxwindow 
2117 //----------------------------------------------------------------------------- 
2119 /* Initialize XIM support */ 
2122 gtk_wxwindow_realized_callback( GtkWidget 
* WXUNUSED_UNLESS_XIM(widget
), 
2123                                 wxWindowGTK 
* WXUNUSED_UNLESS_XIM(win
) ) 
2126         wxapp_install_idle_handler(); 
2129     if (win
->m_ic
) return FALSE
; 
2130     if (!widget
) return FALSE
; 
2131     if (!gdk_im_ready()) return FALSE
; 
2133     win
->m_icattr 
= gdk_ic_attr_new(); 
2134     if (!win
->m_icattr
) return FALSE
; 
2138     GdkColormap 
*colormap
; 
2139     GdkICAttr 
*attr 
= win
->m_icattr
; 
2140     unsigned attrmask 
= GDK_IC_ALL_REQ
; 
2142     GdkIMStyle supported_style 
= (GdkIMStyle
) 
2143                                   (GDK_IM_PREEDIT_NONE 
| 
2144                                    GDK_IM_PREEDIT_NOTHING 
| 
2145                                    GDK_IM_PREEDIT_POSITION 
| 
2146                                    GDK_IM_STATUS_NONE 
| 
2147                                    GDK_IM_STATUS_NOTHING
); 
2149     if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2150         supported_style 
= (GdkIMStyle
)(supported_style 
& ~GDK_IM_PREEDIT_POSITION
); 
2152     attr
->style 
= style 
= gdk_im_decide_style (supported_style
); 
2153     attr
->client_window 
= widget
->window
; 
2155     if ((colormap 
= gtk_widget_get_colormap (widget
)) != 
2156             gtk_widget_get_default_colormap ()) 
2158         attrmask 
|= GDK_IC_PREEDIT_COLORMAP
; 
2159         attr
->preedit_colormap 
= colormap
; 
2162     attrmask 
|= GDK_IC_PREEDIT_FOREGROUND
; 
2163     attrmask 
|= GDK_IC_PREEDIT_BACKGROUND
; 
2164     attr
->preedit_foreground 
= widget
->style
->fg
[GTK_STATE_NORMAL
]; 
2165     attr
->preedit_background 
= widget
->style
->base
[GTK_STATE_NORMAL
]; 
2167     switch (style 
& GDK_IM_PREEDIT_MASK
) 
2169         case GDK_IM_PREEDIT_POSITION
: 
2170             if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2172                 g_warning ("over-the-spot style requires fontset"); 
2176             gdk_window_get_size (widget
->window
, &width
, &height
); 
2178             attrmask 
|= GDK_IC_PREEDIT_POSITION_REQ
; 
2179             attr
->spot_location
.x 
= 0; 
2180             attr
->spot_location
.y 
= height
; 
2181             attr
->preedit_area
.x 
= 0; 
2182             attr
->preedit_area
.y 
= 0; 
2183             attr
->preedit_area
.width 
= width
; 
2184             attr
->preedit_area
.height 
= height
; 
2185             attr
->preedit_fontset 
= widget
->style
->font
; 
2190       win
->m_ic 
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
); 
2192       if (win
->m_ic 
== NULL
) 
2193           g_warning ("Can't create input context."); 
2196           mask 
= gdk_window_get_events (widget
->window
); 
2197           mask 
= (GdkEventMask
)(mask 
| gdk_ic_get_events (win
->m_ic
)); 
2198           gdk_window_set_events (widget
->window
, mask
); 
2200           if (GTK_WIDGET_HAS_FOCUS(widget
)) 
2201               gdk_im_begin (win
->m_ic
, widget
->window
); 
2208 //----------------------------------------------------------------------------- 
2209 // InsertChild for wxWindowGTK. 
2210 //----------------------------------------------------------------------------- 
2212 /* Callback for wxWindowGTK. This very strange beast has to be used because 
2213  * C++ has no virtual methods in a constructor. We have to emulate a 
2214  * virtual function here as wxNotebook requires a different way to insert 
2215  * a child in it. I had opted for creating a wxNotebookPage window class 
2216  * which would have made this superfluous (such in the MDI window system), 
2217  * but no-one was listening to me... */ 
2219 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child 
) 
2221     /* the window might have been scrolled already, do we 
2222        have to adapt the position */ 
2223     GtkPizza 
*pizza 
= GTK_PIZZA(parent
->m_wxwindow
); 
2224     child
->m_x 
+= pizza
->xoffset
; 
2225     child
->m_y 
+= pizza
->yoffset
; 
2227     gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
), 
2228                      GTK_WIDGET(child
->m_widget
), 
2235 //----------------------------------------------------------------------------- 
2237 //----------------------------------------------------------------------------- 
2239 wxWindow 
*wxGetActiveWindow() 
2241     return wxWindow::FindFocus(); 
2244 //----------------------------------------------------------------------------- 
2246 //----------------------------------------------------------------------------- 
2248 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
2250 #ifdef __WXUNIVERSAL__ 
2251     IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
) 
2253     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
2254 #endif // __WXUNIVERSAL__/__WXGTK__ 
2256 void wxWindowGTK::Init() 
2262     m_widget 
= (GtkWidget 
*) NULL
; 
2263     m_wxwindow 
= (GtkWidget 
*) NULL
; 
2264     m_focusWidget 
= (GtkWidget 
*) NULL
; 
2274     m_needParent 
= TRUE
; 
2275     m_isBeingDeleted 
= FALSE
; 
2278     m_nativeSizeEvent 
= FALSE
; 
2280     m_hasScrolling 
= FALSE
; 
2281     m_isScrolling 
= FALSE
; 
2283     m_hAdjust 
= (GtkAdjustment
*) NULL
; 
2284     m_vAdjust 
= (GtkAdjustment
*) NULL
; 
2285     m_oldHorizontalPos 
= 0.0; 
2286     m_oldVerticalPos 
= 0.0; 
2289     m_widgetStyle 
= (GtkStyle
*) NULL
; 
2291     m_insertCallback 
= (wxInsertChildFunction
) NULL
; 
2293     m_acceptsFocus 
= FALSE
; 
2296     m_clipPaintRegion 
= FALSE
; 
2298     m_cursor 
= *wxSTANDARD_CURSOR
; 
2300     m_delayedForegroundColour 
= FALSE
; 
2301     m_delayedBackgroundColour 
= FALSE
; 
2304     m_ic 
= (GdkIC
*) NULL
; 
2305     m_icattr 
= (GdkICAttr
*) NULL
; 
2309 wxWindowGTK::wxWindowGTK() 
2314 wxWindowGTK::wxWindowGTK( wxWindow 
*parent
, 
2319                           const wxString 
&name  
) 
2323     Create( parent
, id
, pos
, size
, style
, name 
); 
2326 bool wxWindowGTK::Create( wxWindow 
*parent
, 
2331                           const wxString 
&name  
) 
2333     if (!PreCreation( parent
, pos
, size 
) || 
2334         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
2336         wxFAIL_MSG( wxT("wxWindowGTK creation failed") ); 
2340     m_insertCallback 
= wxInsertChildInWindow
; 
2342     // always needed for background clearing 
2343     m_delayedBackgroundColour 
= TRUE
;  
2345     m_widget 
= gtk_scrolled_window_new( (GtkAdjustment 
*) NULL
, (GtkAdjustment 
*) NULL 
); 
2346     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
2348     GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
2350     GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2351     scroll_class
->scrollbar_spacing 
= 0; 
2353     gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
2355     m_hAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) ); 
2356     m_vAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) ); 
2358     m_wxwindow 
= gtk_pizza_new(); 
2360 #ifndef __WXUNIVERSAL__ 
2361     GtkPizza 
*pizza 
= GTK_PIZZA(m_wxwindow
); 
2363     if (HasFlag(wxRAISED_BORDER
)) 
2365         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT 
); 
2367     else if (HasFlag(wxSUNKEN_BORDER
)) 
2369         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN 
); 
2371     else if (HasFlag(wxSIMPLE_BORDER
)) 
2373         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN 
); 
2377         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE 
); 
2379 #endif // __WXUNIVERSAL__ 
2381     gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
2383     GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
2384     m_acceptsFocus 
= TRUE
; 
2386     // I _really_ don't want scrollbars in the beginning 
2387     m_vAdjust
->lower 
= 0.0; 
2388     m_vAdjust
->upper 
= 1.0; 
2389     m_vAdjust
->value 
= 0.0; 
2390     m_vAdjust
->step_increment 
= 1.0; 
2391     m_vAdjust
->page_increment 
= 1.0; 
2392     m_vAdjust
->page_size 
= 5.0; 
2393     gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
2394     m_hAdjust
->lower 
= 0.0; 
2395     m_hAdjust
->upper 
= 1.0; 
2396     m_hAdjust
->value 
= 0.0; 
2397     m_hAdjust
->step_increment 
= 1.0; 
2398     m_hAdjust
->page_increment 
= 1.0; 
2399     m_hAdjust
->page_size 
= 5.0; 
2400     gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
2402     // these handlers block mouse events to any window during scrolling such as 
2403     // motion events and prevent GTK and wxWindows from fighting over where the 
2406     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event", 
2407           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
2409     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event", 
2410           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
2412     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event", 
2413           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
2415     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event", 
2416           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
2418     // these handlers get notified when screen updates are required either when 
2419     // scrolling or when the window size (and therefore scrollbar configuration) 
2422     gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
2423           (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
2424     gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
2425           (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
2427     gtk_widget_show( m_wxwindow 
); 
2430         m_parent
->DoAddChild( this ); 
2432     m_focusWidget 
= m_wxwindow
; 
2441 wxWindowGTK::~wxWindowGTK() 
2443     if (g_focusWindow 
== this) 
2444         g_focusWindow 
= NULL
; 
2446     if (g_activeFrame 
== this) 
2447         g_activeFrame 
= NULL
; 
2449     if ( g_delayedFocus 
== this ) 
2450         g_delayedFocus 
= NULL
; 
2452     m_isBeingDeleted 
= TRUE
; 
2461         m_parent
->RemoveChild( this ); 
2465         gdk_ic_destroy (m_ic
); 
2467         gdk_ic_attr_destroy (m_icattr
); 
2472 #if DISABLE_STYLE_IF_BROKEN_THEME 
2473         // don't delete if it's a pixmap theme style 
2474         if (!m_widgetStyle
->engine_data
) 
2475             gtk_style_unref( m_widgetStyle 
); 
2477         m_widgetStyle 
= (GtkStyle
*) NULL
; 
2482         gtk_widget_destroy( m_wxwindow 
); 
2483         m_wxwindow 
= (GtkWidget
*) NULL
; 
2488         gtk_widget_destroy( m_widget 
); 
2489         m_widget 
= (GtkWidget
*) NULL
; 
2493 bool wxWindowGTK::PreCreation( wxWindowGTK 
*parent
, const wxPoint 
&pos
,  const wxSize 
&size 
) 
2495     wxCHECK_MSG( !m_needParent 
|| parent
, FALSE
, wxT("Need complete parent.") ); 
2497     /* this turns -1 into 20 so that a minimal window is 
2498        visible even although -1,-1 has been given as the 
2499        size of the window. the same trick is used in other 
2500        ports and should make debugging easier */ 
2501     m_width 
= WidthDefault(size
.x
); 
2502     m_height 
= HeightDefault(size
.y
); 
2507     /* some reasonable defaults */ 
2512             m_x 
= (gdk_screen_width () - m_width
) / 2; 
2513             if (m_x 
< 10) m_x 
= 10; 
2517             m_y 
= (gdk_screen_height () - m_height
) / 2; 
2518             if (m_y 
< 10) m_y 
= 10; 
2525 void wxWindowGTK::PostCreation() 
2527     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2533             // these get reported to wxWindows -> wxPaintEvent 
2535             gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE 
); 
2537             gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event", 
2538                 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this ); 
2541             gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw", 
2542                 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this ); 
2544             if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) 
2546                 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event", 
2547                     GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this ); 
2550             gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow
), HasFlag( wxNO_FULL_REPAINT_ON_RESIZE 
) ); 
2554         // these are called when the "sunken" or "raised" borders are drawn 
2555         gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event", 
2556           GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this ); 
2559         gtk_signal_connect( GTK_OBJECT(m_widget
), "draw", 
2560           GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this ); 
2566     if (m_focusWidget 
== NULL
) 
2567         m_focusWidget 
= m_widget
; 
2569     gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event", 
2570         GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this ); 
2572     gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event", 
2573          GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this ); 
2575     // connect to the various key and mouse handlers 
2577     GtkWidget 
*connect_widget 
= GetConnectWidget(); 
2579     ConnectWidget( connect_widget 
); 
2581     /* We cannot set colours, fonts and cursors before the widget has 
2582        been realized, so we do this directly after realization */ 
2583     gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize", 
2584                             GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this ); 
2588         // Catch native resize events 
2589         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate", 
2590                             GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this ); 
2592         // Initialize XIM support 
2593         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize", 
2594                             GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this ); 
2596         // And resize XIM window 
2597         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate", 
2598                             GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this ); 
2601     if (!GTK_IS_COMBO(m_widget
)) 
2603         // This is needed if we want to add our windows into native 
2604         // GTK control, such as the toolbar. With this callback, the 
2605         // toolbar gets to know the correct size (the one set by the 
2606         // programmer). Sadly, it misbehaves for wxComboBox. FIXME 
2607         // when moving to GTK 2.0. 
2608         gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request", 
2609                             GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this ); 
2615 void wxWindowGTK::ConnectWidget( GtkWidget 
*widget 
) 
2617     gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event", 
2618       GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this ); 
2620     gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event", 
2621       GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this ); 
2623     gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event", 
2624       GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this ); 
2626     gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event", 
2627       GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this ); 
2629     gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event", 
2630       GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this ); 
2632     gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event", 
2633       GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this ); 
2635     gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event", 
2636       GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this ); 
2638     gtk_signal_connect( GTK_OBJECT(widget
), "destroy", 
2639       GTK_SIGNAL_FUNC(gtk_window_destroy_callback
), (gpointer
)this ); 
2642 bool wxWindowGTK::Destroy() 
2644     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2648     return wxWindowBase::Destroy(); 
2651 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
) 
2653     gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height 
); 
2656 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
2658     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2659     wxASSERT_MSG( (m_parent 
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") ); 
2662     printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height ); 
2665     if (m_resizing
) return; /* I don't like recursions */ 
2668     int currentX
, currentY
; 
2669     GetPosition(¤tX
, ¤tY
); 
2674     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
2676     if (m_parent
->m_wxwindow 
== NULL
) /* i.e. wxNotebook */ 
2678         /* don't set the size for children of wxNotebook, just take the values. */ 
2686         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
2687         if ((sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) == 0) 
2689             if (x 
!= -1) m_x 
= x 
+ pizza
->xoffset
; 
2690             if (y 
!= -1) m_y 
= y 
+ pizza
->yoffset
; 
2691             if (width 
!= -1) m_width 
= width
; 
2692             if (height 
!= -1) m_height 
= height
; 
2696             m_x 
= x 
+ pizza
->xoffset
; 
2697             m_y 
= y 
+ pizza
->yoffset
; 
2702         if ((sizeFlags 
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
) 
2704              if (width 
== -1) m_width 
= 80; 
2707         if ((sizeFlags 
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
) 
2709              if (height 
== -1) m_height 
= 26; 
2712         int minWidth 
= GetMinWidth(), 
2713             minHeight 
= GetMinHeight(), 
2714             maxWidth 
= GetMaxWidth(), 
2715             maxHeight 
= GetMaxHeight(); 
2717         if ((minWidth 
!= -1) && (m_width 
< minWidth
)) m_width 
= minWidth
; 
2718         if ((minHeight 
!= -1) && (m_height 
< minHeight
)) m_height 
= minHeight
; 
2719         if ((maxWidth 
!= -1) && (m_width 
> maxWidth
)) m_width 
= maxWidth
; 
2720         if ((maxHeight 
!= -1) && (m_height 
> maxHeight
)) m_height 
= maxHeight
; 
2723         int bottom_border 
= 0; 
2726         if (GTK_WIDGET_CAN_DEFAULT(m_widget
)) 
2728             /* the default button has a border around it */ 
2734         DoMoveWindow( m_x
-border
, 
2737                       m_height
+border
+bottom_border 
); 
2742         /* Sometimes the client area changes size without the 
2743            whole windows's size changing, but if the whole 
2744            windows's size doesn't change, no wxSizeEvent will 
2745            normally be sent. Here we add an extra test if 
2746            the client test has been changed and this will 
2748         GetClientSize( &m_oldClientWidth
, &m_oldClientHeight 
); 
2752     wxPrintf( "OnSize sent from " ); 
2753     if (GetClassInfo() && GetClassInfo()->GetClassName()) 
2754         wxPrintf( GetClassInfo()->GetClassName() ); 
2755     wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height ); 
2758     if (!m_nativeSizeEvent
) 
2760         wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
2761         event
.SetEventObject( this ); 
2762         GetEventHandler()->ProcessEvent( event 
); 
2768 void wxWindowGTK::OnInternalIdle() 
2770     // Update invalidated regions. 
2773     // Synthetize activate events. 
2774     if ( g_sendActivateEvent 
!= -1 ) 
2776         bool activate 
= g_sendActivateEvent 
!= 0; 
2779         g_sendActivateEvent 
= -1; 
2781         wxTheApp
->SetActive(activate
, (wxWindow 
*)g_focusWindowLast
); 
2784     if ( g_activeFrameLostFocus 
) 
2786         if ( g_activeFrame 
) 
2788             wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
); 
2789             wxActivateEvent 
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId()); 
2790             event
.SetEventObject(g_activeFrame
); 
2791             g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
2792             g_activeFrame 
= NULL
; 
2794         g_activeFrameLostFocus 
= FALSE
; 
2797     wxCursor cursor 
= m_cursor
; 
2798     if (g_globalCursor
.Ok()) cursor 
= g_globalCursor
; 
2802         /* I now set the cursor anew in every OnInternalIdle call 
2803            as setting the cursor in a parent window also effects the 
2804            windows above so that checking for the current cursor is 
2809             GdkWindow 
*window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
2811                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2813             if (!g_globalCursor
.Ok()) 
2814                 cursor 
= *wxSTANDARD_CURSOR
; 
2816             window 
= m_widget
->window
; 
2817             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
2818                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2824             GdkWindow 
*window 
= m_widget
->window
; 
2825             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
2826                gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2834 void wxWindowGTK::DoGetSize( int *width
, int *height 
) const 
2836     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2838     if (width
) (*width
) = m_width
; 
2839     if (height
) (*height
) = m_height
; 
2842 void wxWindowGTK::DoSetClientSize( int width
, int height 
) 
2844     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2848         SetSize( width
, height 
); 
2855 #ifndef __WXUNIVERSAL__ 
2856         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
2858             /* when using GTK 1.2 we set the shadow border size to 2 */ 
2862         if (HasFlag(wxSIMPLE_BORDER
)) 
2864             /* when using GTK 1.2 we set the simple border size to 1 */ 
2868 #endif // __WXUNIVERSAL__ 
2872             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
2874             GtkRequisition vscroll_req
; 
2875             vscroll_req
.width 
= 2; 
2876             vscroll_req
.height 
= 2; 
2877             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
2878                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
2880             GtkRequisition hscroll_req
; 
2881             hscroll_req
.width 
= 2; 
2882             hscroll_req
.height 
= 2; 
2883             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
2884                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
2886             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2888             if (scroll_window
->vscrollbar_visible
) 
2890                 dw 
+= vscroll_req
.width
; 
2891                 dw 
+= scroll_class
->scrollbar_spacing
; 
2894             if (scroll_window
->hscrollbar_visible
) 
2896                 dh 
+= hscroll_req
.height
; 
2897                 dh 
+= scroll_class
->scrollbar_spacing
; 
2901        SetSize( width
+dw
, height
+dh 
); 
2905 void wxWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
2907     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2911         if (width
) (*width
) = m_width
; 
2912         if (height
) (*height
) = m_height
; 
2919 #ifndef __WXUNIVERSAL__ 
2920         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
2922             /* when using GTK 1.2 we set the shadow border size to 2 */ 
2926         if (HasFlag(wxSIMPLE_BORDER
)) 
2928             /* when using GTK 1.2 we set the simple border size to 1 */ 
2932 #endif // __WXUNIVERSAL__ 
2936             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
2938             GtkRequisition vscroll_req
; 
2939             vscroll_req
.width 
= 2; 
2940             vscroll_req
.height 
= 2; 
2941             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
2942                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
2944             GtkRequisition hscroll_req
; 
2945             hscroll_req
.width 
= 2; 
2946             hscroll_req
.height 
= 2; 
2947             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
2948                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
2950             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2952             if (scroll_window
->vscrollbar_visible
) 
2954                 dw 
+= vscroll_req
.width
; 
2955                 dw 
+= scroll_class
->scrollbar_spacing
; 
2958             if (scroll_window
->hscrollbar_visible
) 
2960                 dh 
+= hscroll_req
.height
; 
2961                 dh 
+= scroll_class
->scrollbar_spacing
; 
2965         if (width
) (*width
) = m_width 
- dw
; 
2966         if (height
) (*height
) = m_height 
- dh
; 
2970     printf( "GetClientSize, name %s ", GetName().c_str() ); 
2971     if (width) printf( " width = %d", (*width) ); 
2972     if (height) printf( " height = %d", (*height) ); 
2977 void wxWindowGTK::DoGetPosition( int *x
, int *y 
) const 
2979     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2983     if (m_parent 
&& m_parent
->m_wxwindow
) 
2985         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
2986         dx 
= pizza
->xoffset
; 
2987         dy 
= pizza
->yoffset
; 
2990     if (x
) (*x
) = m_x 
- dx
; 
2991     if (y
) (*y
) = m_y 
- dy
; 
2994 void wxWindowGTK::DoClientToScreen( int *x
, int *y 
) const 
2996     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2998     if (!m_widget
->window
) return; 
3000     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3002         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3004         source 
= m_widget
->window
; 
3008     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3012         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3014             org_x 
+= m_widget
->allocation
.x
; 
3015             org_y 
+= m_widget
->allocation
.y
; 
3023 void wxWindowGTK::DoScreenToClient( int *x
, int *y 
) const 
3025     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3027     if (!m_widget
->window
) return; 
3029     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3031         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3033         source 
= m_widget
->window
; 
3037     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3041         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3043             org_x 
+= m_widget
->allocation
.x
; 
3044             org_y 
+= m_widget
->allocation
.y
; 
3052 bool wxWindowGTK::Show( bool show 
) 
3054     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3056     if (!wxWindowBase::Show(show
)) 
3063         gtk_widget_show( m_widget 
); 
3065         gtk_widget_hide( m_widget 
); 
3070 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
) 
3072     win
->OnParentEnable(enable
); 
3074     // Recurse, so that children have the opportunity to Do The Right Thing 
3075     // and reset colours that have been messed up by a parent's (really ancestor's) 
3077     for ( wxWindowList::Node 
*node 
= win
->GetChildren().GetFirst(); 
3079           node 
= node
->GetNext() ) 
3081         wxWindow 
*child 
= node
->GetData(); 
3082         if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
))) 
3083             wxWindowNotifyEnable(child
, enable
); 
3087 bool wxWindowGTK::Enable( bool enable 
) 
3089     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3091     if (!wxWindowBase::Enable(enable
)) 
3097     gtk_widget_set_sensitive( m_widget
, enable 
); 
3099         gtk_widget_set_sensitive( m_wxwindow
, enable 
); 
3101     wxWindowNotifyEnable(this, enable
); 
3106 int wxWindowGTK::GetCharHeight() const 
3108     wxCHECK_MSG( (m_widget 
!= NULL
), 12, wxT("invalid window") ); 
3110     wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") ); 
3112     GdkFont 
*font 
= m_font
.GetInternalFont( 1.0 ); 
3114     return font
->ascent 
+ font
->descent
; 
3117 int wxWindowGTK::GetCharWidth() const 
3119     wxCHECK_MSG( (m_widget 
!= NULL
), 8, wxT("invalid window") ); 
3121     wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") ); 
3123     GdkFont 
*font 
= m_font
.GetInternalFont( 1.0 ); 
3125     return gdk_string_width( font
, "H" ); 
3128 void wxWindowGTK::GetTextExtent( const wxString
& string
, 
3132                               int *externalLeading
, 
3133                               const wxFont 
*theFont 
) const 
3135     wxFont fontToUse 
= m_font
; 
3136     if (theFont
) fontToUse 
= *theFont
; 
3138     wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") ); 
3140     GdkFont 
*font 
= fontToUse
.GetInternalFont( 1.0 ); 
3141     if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() ); 
3142     if (y
) (*y
) = font
->ascent 
+ font
->descent
; 
3143     if (descent
) (*descent
) = font
->descent
; 
3144     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3147 void wxWindowGTK::SetFocus() 
3149     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3153         // don't do anything if we already have focus 
3159         if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
)) 
3161             gtk_widget_grab_focus (m_wxwindow
); 
3166         if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) ) 
3168             if (!GTK_WIDGET_REALIZED(m_widget
)) 
3170                 // we can't set the focus to the widget now so we remember that 
3171                 // it should be focused and will do it later, during the idle 
3172                 // time, as soon as we can 
3173                 wxLogTrace(TRACE_FOCUS
, 
3174                            _T("Delaying setting focus to %s(%s)"), 
3175                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3177                 g_delayedFocus 
= this; 
3181                 wxLogTrace(TRACE_FOCUS
, 
3182                            _T("Setting focus to %s(%s)"), 
3183                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3185                 gtk_widget_grab_focus (m_widget
); 
3188         else if (GTK_IS_CONTAINER(m_widget
)) 
3190             SET_CONTAINER_FOCUS( m_widget
, GTK_DIR_TAB_FORWARD 
); 
3194            wxLogTrace(TRACE_FOCUS
, 
3195                       _T("Can't set focus to %s(%s)"), 
3196                       GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3201 bool wxWindowGTK::AcceptsFocus() const 
3203     return m_acceptsFocus 
&& wxWindowBase::AcceptsFocus(); 
3206 bool wxWindowGTK::Reparent( wxWindowBase 
*newParentBase 
) 
3208     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3210     wxWindowGTK 
*oldParent 
= m_parent
, 
3211              *newParent 
= (wxWindowGTK 
*)newParentBase
; 
3213     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3215     if ( !wxWindowBase::Reparent(newParent
) ) 
3218     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3220     /* prevent GTK from deleting the widget arbitrarily */ 
3221     gtk_widget_ref( m_widget 
); 
3225         gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget 
); 
3228     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3232         /* insert GTK representation */ 
3233         (*(newParent
->m_insertCallback
))(newParent
, this); 
3236     /* reverse: prevent GTK from deleting the widget arbitrarily */ 
3237     gtk_widget_unref( m_widget 
); 
3242 void wxWindowGTK::DoAddChild(wxWindowGTK 
*child
) 
3244     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3246     wxASSERT_MSG( (child 
!= NULL
), wxT("invalid child window") ); 
3248     wxASSERT_MSG( (m_insertCallback 
!= NULL
), wxT("invalid child insertion function") ); 
3253     /* insert GTK representation */ 
3254     (*m_insertCallback
)(this, child
); 
3257 void wxWindowGTK::Raise() 
3259     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3261     if (!m_widget
->window
) return; 
3263     gdk_window_raise( m_widget
->window 
); 
3266 void wxWindowGTK::Lower() 
3268     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3270     if (!m_widget
->window
) return; 
3272     gdk_window_lower( m_widget
->window 
); 
3275 bool wxWindowGTK::SetCursor( const wxCursor 
&cursor 
) 
3277     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3279     if (cursor 
== m_cursor
) 
3283         wxapp_install_idle_handler(); 
3285     if (cursor 
== wxNullCursor
) 
3286        return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR 
); 
3288        return wxWindowBase::SetCursor( cursor 
); 
3291 void wxWindowGTK::WarpPointer( int x
, int y 
) 
3293     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3295     // We provide this function ourselves as it is 
3296     // missing in GDK (top of this file). 
3298     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3300         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3302         window 
= GetConnectWidget()->window
; 
3305         gdk_window_warp_pointer( window
, x
, y 
); 
3308 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect 
*rect 
) 
3310     if (!m_widget
) return; 
3311     if (!m_widget
->window
) return; 
3315         wxapp_install_idle_handler(); 
3317     if (eraseBackground 
&& m_wxwindow 
&& m_wxwindow
->window
) 
3321             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3322             m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3326             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3327             m_clearRegion
.Clear(); 
3328             m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3336             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3337             m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3341             GdkRectangle gdk_rect
; 
3342             gdk_rect
.x 
= rect
->x
; 
3343             gdk_rect
.y 
= rect
->y
; 
3344             gdk_rect
.width 
= rect
->width
; 
3345             gdk_rect
.height 
= rect
->height
; 
3346             gtk_widget_draw( m_widget
, &gdk_rect 
); 
3353             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3354             m_updateRegion
.Clear(); 
3355             m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3359             gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL 
); 
3367             GdkRectangle gdk_rect
; 
3368             gdk_rect
.x 
= rect
->x
; 
3369             gdk_rect
.y 
= rect
->y
; 
3370             gdk_rect
.width 
= rect
->width
; 
3371             gdk_rect
.height 
= rect
->height
; 
3372             gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, &gdk_rect
, TRUE 
); 
3376             gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, NULL
, TRUE 
); 
3382 void wxWindowGTK::Update() 
3387 void wxWindowGTK::GtkUpdate() 
3390     if (m_wxwindow 
&& GTK_PIZZA(m_wxwindow
)->bin_window
) 
3391         gdk_window_process_updates( GTK_PIZZA(m_wxwindow
)->bin_window
, FALSE 
); 
3394     if (!m_updateRegion
.IsEmpty()) 
3395         GtkSendPaintEvents(); 
3398 void wxWindowGTK::GtkSendPaintEvents() 
3402         m_clearRegion
.Clear(); 
3403         m_updateRegion
.Clear(); 
3407     // widget to draw on 
3408     GtkPizza 
*pizza 
= GTK_PIZZA (m_wxwindow
); 
3410     // Clip to paint region in wxClientDC 
3411     m_clipPaintRegion 
= TRUE
; 
3413     if (GetThemeEnabled()) 
3415         // find ancestor from which to steal background 
3416         wxWindow 
*parent 
= GetParent(); 
3417         while (parent 
&& !parent
->IsTopLevel()) 
3418             parent 
= parent
->GetParent(); 
3420             parent 
= (wxWindow
*)this; 
3422         wxRegionIterator 
upd( m_updateRegion 
); 
3426             rect
.x 
= upd
.GetX(); 
3427             rect
.y 
= upd
.GetY(); 
3428             rect
.width 
= upd
.GetWidth(); 
3429             rect
.height 
= upd
.GetHeight(); 
3431             gtk_paint_flat_box( parent
->m_widget
->style
, 
3444     // if (!m_clearRegion.IsEmpty())   // always send an erase event 
3446         wxWindowDC 
dc( (wxWindow
*)this ); 
3447         dc
.SetClippingRegion( m_clearRegion 
); 
3449         wxEraseEvent 
erase_event( GetId(), &dc 
); 
3450         erase_event
.SetEventObject( this ); 
3452         if (!GetEventHandler()->ProcessEvent(erase_event
)) 
3456                 g_eraseGC 
= gdk_gc_new( pizza
->bin_window 
); 
3457                 gdk_gc_set_fill( g_eraseGC
, GDK_SOLID 
); 
3459             gdk_gc_set_foreground( g_eraseGC
, m_backgroundColour
.GetColor() ); 
3461             wxRegionIterator 
upd( m_clearRegion 
); 
3464                 gdk_draw_rectangle( pizza
->bin_window
, g_eraseGC
, 1, 
3465                                     upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() ); 
3469         m_clearRegion
.Clear(); 
3472     wxNcPaintEvent 
nc_paint_event( GetId() ); 
3473     nc_paint_event
.SetEventObject( this ); 
3474     GetEventHandler()->ProcessEvent( nc_paint_event 
); 
3476     wxPaintEvent 
paint_event( GetId() ); 
3477     paint_event
.SetEventObject( this ); 
3478     GetEventHandler()->ProcessEvent( paint_event 
); 
3480     m_clipPaintRegion 
= FALSE
; 
3482 #ifndef __WXUNIVERSAL__ 
3484     // The following code will result in all window-less widgets 
3485     // being redrawn because the wxWindows class is allowed to 
3486     // paint over the window-less widgets. 
3488     GList 
*children 
= pizza
->children
; 
3491         GtkPizzaChild 
*child 
= (GtkPizzaChild
*) children
->data
; 
3492         children 
= children
->next
; 
3494         if (GTK_WIDGET_NO_WINDOW (child
->widget
) && 
3495             GTK_WIDGET_DRAWABLE (child
->widget
)) 
3497             // Get intersection of widget area and update region 
3498             wxRegion 
region( m_updateRegion 
); 
3500             GdkEventExpose gdk_event
; 
3501             gdk_event
.type 
= GDK_EXPOSE
; 
3502             gdk_event
.window 
= pizza
->bin_window
; 
3503             gdk_event
.count 
= 0; 
3505             wxRegionIterator 
upd( m_updateRegion 
); 
3509                 rect
.x 
= upd
.GetX(); 
3510                 rect
.y 
= upd
.GetY(); 
3511                 rect
.width 
= upd
.GetWidth(); 
3512                 rect
.height 
= upd
.GetHeight(); 
3514                 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
)) 
3516                     gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
); 
3526     m_updateRegion
.Clear(); 
3529 void wxWindowGTK::Clear() 
3531     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3533     if (m_wxwindow 
&& m_wxwindow
->window
) 
3535         m_clearRegion
.Clear(); 
3536         wxSize 
size( GetClientSize() ); 
3537         m_clearRegion
.Union( 0,0,size
.x
,size
.y 
); 
3539         // Better do this in idle? 
3545 void wxWindowGTK::DoSetToolTip( wxToolTip 
*tip 
) 
3547     wxWindowBase::DoSetToolTip(tip
); 
3550         m_tooltip
->Apply( (wxWindow 
*)this ); 
3553 void wxWindowGTK::ApplyToolTip( GtkTooltips 
*tips
, const wxChar 
*tip 
) 
3555     gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL 
); 
3557 #endif // wxUSE_TOOLTIPS 
3559 void wxWindowGTK::GtkSetBackgroundColour( const wxColour 
&colour 
) 
3561     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3563         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3565         window 
= GetConnectWidget()->window
; 
3569     // We need the pixel value e.g. for background clearing. 
3570     m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window 
) ); 
3574         // wxMSW doesn't clear the window here, either. 
3575         gdk_window_set_background( window
, m_backgroundColour
.GetColor() ); 
3581 bool wxWindowGTK::SetBackgroundColour( const wxColour 
&colour 
) 
3583     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
3585     if (!wxWindowBase::SetBackgroundColour(colour
)) 
3588     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3590         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3592         window 
= GetConnectWidget()->window
; 
3596         // indicate that a new style has been set 
3597         // but it couldn't get applied as the 
3598         // widget hasn't been realized yet. 
3599         m_delayedBackgroundColour 
= TRUE
; 
3604         GtkSetBackgroundColour( colour 
); 
3610 void wxWindowGTK::GtkSetForegroundColour( const wxColour 
&colour 
) 
3612     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3614         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3616         window 
= GetConnectWidget()->window
; 
3623 bool wxWindowGTK::SetForegroundColour( const wxColour 
&colour 
) 
3625     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
3627     if (!wxWindowBase::SetForegroundColour(colour
)) 
3629         // don't leave if the GTK widget has just 
3631         if (!m_delayedForegroundColour
) return FALSE
; 
3634     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3636         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3638         window 
= GetConnectWidget()->window
; 
3642         // indicate that a new style has been set 
3643         // but it couldn't get applied as the 
3644         // widget hasn't been realized yet. 
3645         m_delayedForegroundColour 
= TRUE
; 
3649        GtkSetForegroundColour( colour 
); 
3655 GtkStyle 
*wxWindowGTK::GetWidgetStyle() 
3659         GtkStyle 
*remake 
= gtk_style_copy( m_widgetStyle 
); 
3661         // FIXME: no more klass in 2.0 
3663         remake
->klass 
= m_widgetStyle
->klass
; 
3666         gtk_style_unref( m_widgetStyle 
); 
3667         m_widgetStyle 
= remake
; 
3671         GtkStyle 
*def 
= gtk_rc_get_style( m_widget 
); 
3674             def 
= gtk_widget_get_default_style(); 
3676         m_widgetStyle 
= gtk_style_copy( def 
); 
3678         // FIXME: no more klass in 2.0 
3680         m_widgetStyle
->klass 
= def
->klass
; 
3684     return m_widgetStyle
; 
3687 void wxWindowGTK::SetWidgetStyle() 
3689 #if DISABLE_STYLE_IF_BROKEN_THEME 
3690     if (m_widget
->style
->engine_data
) 
3692         static bool s_warningPrinted 
= FALSE
; 
3693         if (!s_warningPrinted
) 
3695             printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" ); 
3696             s_warningPrinted 
= TRUE
; 
3698         m_widgetStyle 
= m_widget
->style
; 
3703     GtkStyle 
*style 
= GetWidgetStyle(); 
3705     if (m_font 
!= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT 
)) 
3707         SET_STYLE_FONT(style
, m_font
.GetInternalFont( 1.0 )); 
3710     if (m_foregroundColour
.Ok()) 
3712         m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget 
) ); 
3713         if (m_foregroundColour 
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT
)) 
3715             style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor(); 
3716             style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor(); 
3717             style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor(); 
3721             // Try to restore the gtk default style.  This is still a little 
3722             // oversimplified for what is probably really needed here for controls 
3723             // other than buttons, but is better than not being able to (re)set a 
3724             // control's foreground colour to *wxBLACK -- RL 
3725             GtkStyle 
*def 
= gtk_rc_get_style( m_widget 
); 
3728                 def 
= gtk_widget_get_default_style(); 
3730             style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
]; 
3731             style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
]; 
3732             style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
]; 
3736     if (m_backgroundColour
.Ok()) 
3738         m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget 
) ); 
3739         if (m_backgroundColour 
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
)) 
3741             style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor(); 
3742             style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor(); 
3743             style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor(); 
3744             style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor(); 
3745             style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor(); 
3746             style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor(); 
3747             style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor(); 
3748             style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor(); 
3752             // Try to restore the gtk default style.  This is still a little 
3753             // oversimplified for what is probably really needed here for controls 
3754             // other than buttons, but is better than not being able to (re)set a 
3755             // control's background colour to default grey and means resetting a 
3756             // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting 
3758             GtkStyle 
*def 
= gtk_rc_get_style( m_widget 
); 
3761                 def 
= gtk_widget_get_default_style(); 
3763             style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
]; 
3764             style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
]; 
3765             style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
]; 
3766             style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
]; 
3767             style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
]; 
3768             style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
]; 
3769             style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
]; 
3770             style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
]; 
3775 void wxWindowGTK::ApplyWidgetStyle() 
3779 //----------------------------------------------------------------------------- 
3780 // Pop-up menu stuff 
3781 //----------------------------------------------------------------------------- 
3783 #if wxUSE_MENUS_NATIVE 
3786 void gtk_pop_hide_callback( GtkWidget 
*WXUNUSED(widget
), bool* is_waiting  
) 
3788     *is_waiting 
= FALSE
; 
3791 static void SetInvokingWindow( wxMenu 
*menu
, wxWindowGTK 
*win 
) 
3793     menu
->SetInvokingWindow( win 
); 
3794     wxMenuItemList::Node 
*node 
= menu
->GetMenuItems().GetFirst(); 
3797         wxMenuItem 
*menuitem 
= node
->GetData(); 
3798         if (menuitem
->IsSubMenu()) 
3800             SetInvokingWindow( menuitem
->GetSubMenu(), win 
); 
3803         node 
= node
->GetNext(); 
3807 // used to pass the coordinates from wxWindowGTK::DoPopupMenu() to 
3808 // wxPopupMenuPositionCallback() 
3810 // should be safe even in the MT case as the user can hardly popup 2 menus 
3811 // simultaneously, can he? 
3812 static gint gs_pop_x 
= 0; 
3813 static gint gs_pop_y 
= 0; 
3815 extern "C" void wxPopupMenuPositionCallback( GtkMenu 
*menu
, 
3818                                              gboolean 
* WXUNUSED(whatever
), 
3820                                              gpointer 
WXUNUSED(user_data
) ) 
3822     // ensure that the menu appears entirely on screen 
3824     gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
); 
3826     wxSize sizeScreen 
= wxGetDisplaySize(); 
3828     gint xmax 
= sizeScreen
.x 
- req
.width
, 
3829          ymax 
= sizeScreen
.y 
- req
.height
; 
3831     *x 
= gs_pop_x 
< xmax 
? gs_pop_x 
: xmax
; 
3832     *y 
= gs_pop_y 
< ymax 
? gs_pop_y 
: ymax
; 
3835 bool wxWindowGTK::DoPopupMenu( wxMenu 
*menu
, int x
, int y 
) 
3837     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
3839     wxCHECK_MSG( menu 
!= NULL
, FALSE
, wxT("invalid popup-menu") ); 
3841     SetInvokingWindow( menu
, this ); 
3847     ClientToScreen( &gs_pop_x
, &gs_pop_y 
); 
3849     bool is_waiting 
= TRUE
; 
3851     gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), 
3853                         GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), 
3854                         (gpointer
)&is_waiting 
); 
3857                   GTK_MENU(menu
->m_menu
), 
3858                   (GtkWidget 
*) NULL
,           // parent menu shell 
3859                   (GtkWidget 
*) NULL
,           // parent menu item 
3860                   wxPopupMenuPositionCallback
,  // function to position it 
3861                   NULL
,                         // client data 
3862                   0,                            // button used to activate it 
3863                   gs_timeLastClick              
// the time of activation 
3868         while (gtk_events_pending()) 
3869             gtk_main_iteration(); 
3875 #endif // wxUSE_MENUS_NATIVE 
3877 #if wxUSE_DRAG_AND_DROP 
3879 void wxWindowGTK::SetDropTarget( wxDropTarget 
*dropTarget 
) 
3881     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3883     GtkWidget 
*dnd_widget 
= GetConnectWidget(); 
3885     if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget 
); 
3887     if (m_dropTarget
) delete m_dropTarget
; 
3888     m_dropTarget 
= dropTarget
; 
3890     if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget 
); 
3893 #endif // wxUSE_DRAG_AND_DROP 
3895 GtkWidget
* wxWindowGTK::GetConnectWidget() 
3897     GtkWidget 
*connect_widget 
= m_widget
; 
3898     if (m_wxwindow
) connect_widget 
= m_wxwindow
; 
3900     return connect_widget
; 
3903 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow 
*window 
) 
3906         return (window 
== GTK_PIZZA(m_wxwindow
)->bin_window
); 
3908     return (window 
== m_widget
->window
); 
3911 bool wxWindowGTK::SetFont( const wxFont 
&font 
) 
3913     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
3915     if (!wxWindowBase::SetFont(font
)) 
3920     wxColour sysbg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE 
); 
3921     if ( sysbg 
== m_backgroundColour 
) 
3923         m_backgroundColour 
= wxNullColour
; 
3925         m_backgroundColour 
= sysbg
; 
3935 void wxWindowGTK::DoCaptureMouse() 
3937     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3939     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3941         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3943         window 
= GetConnectWidget()->window
; 
3945     wxCHECK_RET( window
, _T("CaptureMouse() failed") ); 
3947     wxCursor
* cursor 
= & m_cursor
; 
3949         cursor 
= wxSTANDARD_CURSOR
; 
3951     gdk_pointer_grab( window
, FALSE
, 
3953                          (GDK_BUTTON_PRESS_MASK 
| 
3954                           GDK_BUTTON_RELEASE_MASK 
| 
3955                           GDK_POINTER_MOTION_HINT_MASK 
| 
3956                           GDK_POINTER_MOTION_MASK
), 
3958                       cursor
->GetCursor(), 
3959                       (guint32
)GDK_CURRENT_TIME 
); 
3960     g_captureWindow 
= this; 
3961     g_captureWindowHasMouse 
= TRUE
; 
3964 void wxWindowGTK::DoReleaseMouse() 
3966     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3968     wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") ); 
3970     g_captureWindow 
= (wxWindowGTK
*) NULL
; 
3972     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3974         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3976         window 
= GetConnectWidget()->window
; 
3981     gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME 
); 
3985 wxWindow 
*wxWindowBase::GetCapture() 
3987     return (wxWindow 
*)g_captureWindow
; 
3990 bool wxWindowGTK::IsRetained() const 
3995 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
, 
3996       int range
, bool refresh 
) 
3998     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4000     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4002     m_hasScrolling 
= TRUE
; 
4004     if (orient 
== wxHORIZONTAL
) 
4006         float fpos 
= (float)pos
; 
4007         float frange 
= (float)range
; 
4008         float fthumb 
= (float)thumbVisible
; 
4009         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4010         if (fpos 
< 0.0) fpos 
= 0.0; 
4012         if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) && 
4013             (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2)) 
4015             SetScrollPos( orient
, pos
, refresh 
); 
4019         m_oldHorizontalPos 
= fpos
; 
4021         m_hAdjust
->lower 
= 0.0; 
4022         m_hAdjust
->upper 
= frange
; 
4023         m_hAdjust
->value 
= fpos
; 
4024         m_hAdjust
->step_increment 
= 1.0; 
4025         m_hAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4026         m_hAdjust
->page_size 
= fthumb
; 
4030         float fpos 
= (float)pos
; 
4031         float frange 
= (float)range
; 
4032         float fthumb 
= (float)thumbVisible
; 
4033         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4034         if (fpos 
< 0.0) fpos 
= 0.0; 
4036         if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) && 
4037             (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2)) 
4039             SetScrollPos( orient
, pos
, refresh 
); 
4043         m_oldVerticalPos 
= fpos
; 
4045         m_vAdjust
->lower 
= 0.0; 
4046         m_vAdjust
->upper 
= frange
; 
4047         m_vAdjust
->value 
= fpos
; 
4048         m_vAdjust
->step_increment 
= 1.0; 
4049         m_vAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4050         m_vAdjust
->page_size 
= fthumb
; 
4053     if (orient 
== wxHORIZONTAL
) 
4054         gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
4056         gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
4059 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) ) 
4061     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4063     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4065     if (orient 
== wxHORIZONTAL
) 
4067         float fpos 
= (float)pos
; 
4068         if (fpos 
> m_hAdjust
->upper 
- m_hAdjust
->page_size
) fpos 
= m_hAdjust
->upper 
- m_hAdjust
->page_size
; 
4069         if (fpos 
< 0.0) fpos 
= 0.0; 
4070         m_oldHorizontalPos 
= fpos
; 
4072         if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return; 
4073         m_hAdjust
->value 
= fpos
; 
4077         float fpos 
= (float)pos
; 
4078         if (fpos 
> m_vAdjust
->upper 
- m_vAdjust
->page_size
) fpos 
= m_vAdjust
->upper 
- m_vAdjust
->page_size
; 
4079         if (fpos 
< 0.0) fpos 
= 0.0; 
4080         m_oldVerticalPos 
= fpos
; 
4082         if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return; 
4083         m_vAdjust
->value 
= fpos
; 
4086     if (m_wxwindow
->window
) 
4088         if (orient 
== wxHORIZONTAL
) 
4090             gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
), 
4091                 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
4093             gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" ); 
4095             gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
4096                 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
4100             gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
), 
4101                 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
4103             gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" ); 
4105             gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
4106                 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
4111 int wxWindowGTK::GetScrollThumb( int orient 
) const 
4113     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4115     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4117     if (orient 
== wxHORIZONTAL
) 
4118         return (int)(m_hAdjust
->page_size
+0.5); 
4120         return (int)(m_vAdjust
->page_size
+0.5); 
4123 int wxWindowGTK::GetScrollPos( int orient 
) const 
4125     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4127     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4129     if (orient 
== wxHORIZONTAL
) 
4130         return (int)(m_hAdjust
->value
+0.5); 
4132         return (int)(m_vAdjust
->value
+0.5); 
4135 int wxWindowGTK::GetScrollRange( int orient 
) const 
4137     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4139     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4141     if (orient 
== wxHORIZONTAL
) 
4142         return (int)(m_hAdjust
->upper
+0.5); 
4144         return (int)(m_vAdjust
->upper
+0.5); 
4147 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) ) 
4149     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4151     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4153     // No scrolling requested. 
4154     if ((dx 
== 0) && (dy 
== 0)) return; 
4157     if (!m_updateRegion
.IsEmpty()) 
4159         m_updateRegion
.Offset( dx
, dy 
); 
4163         GetClientSize( &cw
, &ch 
); 
4164         m_updateRegion
.Intersect( 0, 0, cw
, ch 
); 
4167     if (!m_clearRegion
.IsEmpty()) 
4169         m_clearRegion
.Offset( dx
, dy 
); 
4173         GetClientSize( &cw
, &ch 
); 
4174         m_clearRegion
.Intersect( 0, 0, cw
, ch 
); 
4176     m_clipPaintRegion 
= TRUE
; 
4178     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy 
); 
4180     m_clipPaintRegion 
= FALSE
; 
4183     gdk_window_scroll( GTK_PIZZA(m_wxwindow
)->bin_window
, dx
, dy 
); 
4185     GTK_PIZZA(m_wxwindow
)->xoffset 
+= dx
; 
4186     GTK_PIZZA(m_wxwindow
)->yoffset 
+= dy
; 
4193 // Find the wxWindow at the current mouse position, also returning the mouse 
4195 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
4197     pt 
= wxGetMousePosition(); 
4198     wxWindow
* found 
= wxFindWindowAtPoint(pt
); 
4202 // Get the current mouse position. 
4203 wxPoint 
wxGetMousePosition() 
4205   /* This crashes when used within wxHelpContext, 
4206      so we have to use the X-specific implementation below. 
4208     GdkModifierType *mask; 
4209     (void) gdk_window_get_pointer(NULL, &x, &y, mask); 
4211     return wxPoint(x, y); 
4215     GdkWindow
* windowAtPtr 
= gdk_window_at_pointer(& x
, & y
); 
4217       return wxPoint(-999, -999); 
4219     Display 
*display 
= GDK_WINDOW_XDISPLAY(windowAtPtr
); 
4220     Window rootWindow 
= RootWindowOfScreen (DefaultScreenOfDisplay(display
)); 
4221     Window rootReturn
, childReturn
; 
4222     int rootX
, rootY
, winX
, winY
; 
4223     unsigned int maskReturn
; 
4225     XQueryPointer (display
, 
4229                    &rootX
, &rootY
, &winX
, &winY
, &maskReturn
); 
4230     return wxPoint(rootX
, rootY
); 
4234 // ---------------------------------------------------------------------------- 
4236 // ---------------------------------------------------------------------------- 
4238 class wxWinModule 
: public wxModule
 
4245     DECLARE_DYNAMIC_CLASS(wxWinModule
) 
4248 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
) 
4250 bool wxWinModule::OnInit() 
4252     // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() ); 
4253     // gdk_gc_set_fill( g_eraseGC, GDK_SOLID ); 
4258 void wxWinModule::OnExit() 
4261         gdk_gc_unref( g_eraseGC 
);