1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        gtk/window.cpp 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling, Julian Smart 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  12     #pragma implementation "window.h" 
  16 #define XWarpPointer XWARPPOINTER 
  20 #include "wx/window.h" 
  21 #include "wx/dcclient.h" 
  24 #include "wx/layout.h" 
  26 #include "wx/dialog.h" 
  27 #include "wx/msgdlg.h" 
  28 #include "wx/module.h" 
  30 #if wxUSE_DRAG_AND_DROP 
  35     #include "wx/tooltip.h" 
  43     #include "wx/textctrl.h" 
  47 #include "wx/statusbr.h" 
  49 #include "wx/settings.h" 
  51 #include "wx/fontutil.h" 
  54     #include "wx/thread.h" 
  60 #include "wx/gtk/private.h" 
  61 #include <gdk/gdkprivate.h> 
  62 #include <gdk/gdkkeysyms.h> 
  66 #include <gtk/gtkprivate.h> 
  68 #include "wx/gtk/win_gtk.h" 
  71     #define SET_CONTAINER_FOCUS(w, d) gtk_widget_child_focus((w), (d)) 
  73     #define SET_CONTAINER_FOCUS(w, d) gtk_container_focus(GTK_CONTAINER(w), (d)) 
  83 extern GtkContainerClass 
*pizza_parent_class
; 
  86 //----------------------------------------------------------------------------- 
  87 // documentation on internals 
  88 //----------------------------------------------------------------------------- 
  91    I have been asked several times about writing some documentation about 
  92    the GTK port of wxWindows, especially its internal structures. Obviously, 
  93    you cannot understand wxGTK without knowing a little about the GTK, but 
  94    some more information about what the wxWindow, which is the base class 
  95    for all other window classes, does seems required as well. 
  99    What does wxWindow do? It contains the common interface for the following 
 100    jobs of its descendants: 
 102    1) Define the rudimentary behaviour common to all window classes, such as 
 103    resizing, intercepting user input (so as to make it possible to use these 
 104    events for special purposes in a derived class), window names etc. 
 106    2) Provide the possibility to contain and manage children, if the derived 
 107    class is allowed to contain children, which holds true for those window 
 108    classes which do not display a native GTK widget. To name them, these 
 109    classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame- 
 110    work classes are a special case and are handled a bit differently from 
 111    the rest. The same holds true for the wxNotebook class. 
 113    3) Provide the possibility to draw into a client area of a window. This, 
 114    too, only holds true for classes that do not display a native GTK widget 
 117    4) Provide the entire mechanism for scrolling widgets. This actual inter- 
 118    face for this is usually in wxScrolledWindow, but the GTK implementation 
 121    5) A multitude of helper or extra methods for special purposes, such as 
 122    Drag'n'Drop, managing validators etc. 
 124    6) Display a border (sunken, raised, simple or none). 
 126    Normally one might expect, that one wxWindows window would always correspond 
 127    to one GTK widget. Under GTK, there is no such allround widget that has all 
 128    the functionality. Moreover, the GTK defines a client area as a different 
 129    widget from the actual widget you are handling. Last but not least some 
 130    special classes (e.g. wxFrame) handle different categories of widgets and 
 131    still have the possibility to draw something in the client area. 
 132    It was therefore required to write a special purpose GTK widget, that would 
 133    represent a client area in the sense of wxWindows capable to do the jobs 
 134    2), 3) and 4). I have written this class and it resides in win_gtk.c of 
 137    All windows must have a widget, with which they interact with other under- 
 138    lying GTK widgets. It is this widget, e.g. that has to be resized etc and 
 139    thw wxWindow class has a member variable called m_widget which holds a 
 140    pointer to this widget. When the window class represents a GTK native widget, 
 141    this is (in most cases) the only GTK widget the class manages. E.g. the 
 142    wxStatitText class handles only a GtkLabel widget a pointer to which you 
 143    can find in m_widget (defined in wxWindow) 
 145    When the class has a client area for drawing into and for containing children 
 146    it has to handle the client area widget (of the type GtkPizza, defined in 
 147    win_gtk.c), but there could be any number of widgets, handled by a class 
 148    The common rule for all windows is only, that the widget that interacts with 
 149    the rest of GTK must be referenced in m_widget and all other widgets must be 
 150    children of this widget on the GTK level. The top-most widget, which also 
 151    represents the client area, must be in the m_wxwindow field and must be of 
 154    As I said, the window classes that display a GTK native widget only have 
 155    one widget, so in the case of e.g. the wxButton class m_widget holds a 
 156    pointer to a GtkButton widget. But windows with client areas (for drawing 
 157    and children) have a m_widget field that is a pointer to a GtkScrolled- 
 158    Window and a m_wxwindow field that is pointer to a GtkPizza and this 
 159    one is (in the GTK sense) a child of the GtkScrolledWindow. 
 161    If the m_wxwindow field is set, then all input to this widget is inter- 
 162    cepted and sent to the wxWindows class. If not, all input to the widget 
 163    that gets pointed to by m_widget gets intercepted and sent to the class. 
 167    The design of scrolling in wxWindows is markedly different from that offered 
 168    by the GTK itself and therefore we cannot simply take it as it is. In GTK, 
 169    clicking on a scrollbar belonging to scrolled window will inevitably move 
 170    the window. In wxWindows, the scrollbar will only emit an event, send this 
 171    to (normally) a wxScrolledWindow and that class will call ScrollWindow() 
 172    which actually moves the window and its subchildren. Note that GtkPizza 
 173    memorizes how much it has been scrolled but that wxWindows forgets this 
 174    so that the two coordinates systems have to be kept in synch. This is done 
 175    in various places using the pizza->xoffset and pizza->yoffset values. 
 179    Singularily the most broken code in GTK is the code that is supposes to 
 180    inform subwindows (child windows) about new positions. Very often, duplicate 
 181    events are sent without changes in size or position, equally often no 
 182    events are sent at all (All this is due to a bug in the GtkContainer code 
 183    which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores 
 184    GTK's own system and it simply waits for size events for toplevel windows 
 185    and then iterates down the respective size events to all window. This has 
 186    the disadvantage, that windows might get size events before the GTK widget 
 187    actually has the reported size. This doesn't normally pose any problem, but 
 188    the OpenGl drawing routines rely on correct behaviour. Therefore, I have 
 189    added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas, 
 190    i.e. the wxGLCanvas will emit a size event, when (and not before) the X11 
 191    window that is used for OpenGl output really has that size (as reported by 
 196    If someone at some point of time feels the immense desire to have a look at, 
 197    change or attempt to optimse the Refresh() logic, this person will need an 
 198    intimate understanding of what a "draw" and what an "expose" events are and 
 199    what there are used for, in particular when used in connection with GTK's 
 200    own windowless widgets. Beware. 
 204    Cursors, too, have been a constant source of pleasure. The main difficulty 
 205    is that a GdkWindow inherits a cursor if the programmer sets a new cursor 
 206    for the parent. To prevent this from doing too much harm, I use idle time 
 207    to set the cursor over and over again, starting from the toplevel windows 
 208    and ending with the youngest generation (speaking of parent and child windows). 
 209    Also don't forget that cursors (like much else) are connected to GdkWindows, 
 210    not GtkWidgets and that the "window" field of a GtkWidget might very well 
 211    point to the GdkWindow of the parent widget (-> "window less widget") and 
 212    that the two obviously have very different meanings. 
 216 //----------------------------------------------------------------------------- 
 218 //----------------------------------------------------------------------------- 
 220 extern wxList     wxPendingDelete
; 
 221 extern bool       g_blockEventsOnDrag
; 
 222 extern bool       g_blockEventsOnScroll
; 
 223 extern wxCursor   g_globalCursor
; 
 225 static GdkGC 
*g_eraseGC 
= NULL
; 
 227 // mouse capture state: the window which has it and if the mouse is currently 
 229 static wxWindowGTK  
*g_captureWindow 
= (wxWindowGTK
*) NULL
; 
 230 static bool g_captureWindowHasMouse 
= FALSE
; 
 232 /* extern */ wxWindowGTK  
*g_focusWindow 
= (wxWindowGTK
*) NULL
; 
 234 // the last window which had the focus - this is normally never NULL (except 
 235 // if we never had focus at all) as even when g_focusWindow is NULL it still 
 236 // keeps its previous value 
 237 static wxWindowGTK 
*g_focusWindowLast 
= (wxWindowGTK
*) NULL
; 
 239 // the frame that is currently active (i.e. its child has focus). It is 
 240 // used to generate wxActivateEvents 
 241 static wxWindowGTK 
*g_activeFrame 
= (wxWindowGTK
*) NULL
; 
 242 static bool g_activeFrameLostFocus 
= FALSE
; 
 244 // If a window get the focus set but has not been realized 
 245 // yet, defer setting the focus to idle time. 
 246 wxWindowGTK 
*g_delayedFocus 
= (wxWindowGTK
*) NULL
; 
 248 // if we detect that the app has got/lost the focus, we set this variable to 
 249 // either TRUE or FALSE and an activate event will be sent during the next 
 250 // OnIdle() call and it is reset to -1: this value means that we shouldn't 
 251 // send any activate events at all 
 252 static int        g_sendActivateEvent 
= -1; 
 254 /* hack: we need something to pass to gtk_menu_popup, so we store the time of 
 255    the last click here */ 
 256 static guint32 gs_timeLastClick 
= 0; 
 258 extern bool g_mainThreadLocked
; 
 260 //----------------------------------------------------------------------------- 
 262 //----------------------------------------------------------------------------- 
 265 #define DISABLE_STYLE_IF_BROKEN_THEME 1 
 271 #   define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance"); 
 273 #   define DEBUG_MAIN_THREAD 
 276 #define DEBUG_MAIN_THREAD 
 279 // the trace mask used for the focus debugging messages 
 280 #define TRACE_FOCUS _T("focus") 
 282 //----------------------------------------------------------------------------- 
 283 // missing gdk functions 
 284 //----------------------------------------------------------------------------- 
 287 gdk_window_warp_pointer (GdkWindow      
*window
, 
 292   GdkWindowPrivate 
*priv
; 
 296     window 
= GDK_ROOT_PARENT(); 
 299   if (!GDK_WINDOW_DESTROYED(window
)) 
 301       XWarpPointer (GDK_WINDOW_XDISPLAY(window
), 
 302                     None
,              /* not source window -> move from anywhere */ 
 303                     GDK_WINDOW_XID(window
),  /* dest window */ 
 304                     0, 0, 0, 0,        /* not source window -> move from anywhere */ 
 308   priv 
= (GdkWindowPrivate
*) window
; 
 310   if (!priv
->destroyed
) 
 312       XWarpPointer (priv
->xdisplay
, 
 313                     None
,              /* not source window -> move from anywhere */ 
 314                     priv
->xwindow
,  /* dest window */ 
 315                     0, 0, 0, 0,        /* not source window -> move from anywhere */ 
 321 //----------------------------------------------------------------------------- 
 323 //----------------------------------------------------------------------------- 
 325 extern void wxapp_install_idle_handler(); 
 326 extern bool g_isIdle
; 
 328 //----------------------------------------------------------------------------- 
 329 // local code (see below) 
 330 //----------------------------------------------------------------------------- 
 332 // returns the child of win which currently has focus or NULL if not found 
 334 // Note: can't be static, needed by textctrl.cpp. 
 335 wxWindow 
*wxFindFocusedChild(wxWindowGTK 
*win
) 
 337     wxWindow 
*winFocus 
= wxWindowGTK::FindFocus(); 
 339         return (wxWindow 
*)NULL
; 
 341     if ( winFocus 
== win 
) 
 342         return (wxWindow 
*)win
; 
 344     for ( wxWindowList::Node 
*node 
= win
->GetChildren().GetFirst(); 
 346           node 
= node
->GetNext() ) 
 348         wxWindow 
*child 
= wxFindFocusedChild(node
->GetData()); 
 353     return (wxWindow 
*)NULL
; 
 356 static void draw_frame( GtkWidget 
*widget
, wxWindowGTK 
*win 
) 
 358     // wxUniversal widgets draw the borders and scrollbars themselves 
 359 #ifndef __WXUNIVERSAL__ 
 366     if (win
->m_hasScrolling
) 
 368         GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(widget
); 
 370         GtkRequisition vscroll_req
; 
 371         vscroll_req
.width 
= 2; 
 372         vscroll_req
.height 
= 2; 
 373         (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
 374             (scroll_window
->vscrollbar
, &vscroll_req 
); 
 376         GtkRequisition hscroll_req
; 
 377         hscroll_req
.width 
= 2; 
 378         hscroll_req
.height 
= 2; 
 379         (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
 380             (scroll_window
->hscrollbar
, &hscroll_req 
); 
 382         GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) ); 
 384         if (scroll_window
->vscrollbar_visible
) 
 386             dw 
+= vscroll_req
.width
; 
 387             dw 
+= scroll_class
->scrollbar_spacing
; 
 390         if (scroll_window
->hscrollbar_visible
) 
 392             dh 
+= hscroll_req
.height
; 
 393             dh 
+= scroll_class
->scrollbar_spacing
; 
 399     if (GTK_WIDGET_NO_WINDOW (widget
)) 
 401         dx 
+= widget
->allocation
.x
; 
 402         dy 
+= widget
->allocation
.y
; 
 405     if (win
->HasFlag(wxRAISED_BORDER
)) 
 407         gtk_draw_shadow( widget
->style
, 
 412                          widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh 
); 
 416     if (win
->HasFlag(wxSUNKEN_BORDER
)) 
 418         gtk_draw_shadow( widget
->style
, 
 423                          widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh 
); 
 427     if (win
->HasFlag(wxSIMPLE_BORDER
)) 
 430         gc 
= gdk_gc_new( widget
->window 
); 
 431         gdk_gc_set_foreground( gc
, &widget
->style
->black 
); 
 432         gdk_draw_rectangle( widget
->window
, gc
, FALSE
, 
 434                          widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 ); 
 438 #endif // __WXUNIVERSAL__ 
 441 //----------------------------------------------------------------------------- 
 442 // "expose_event" of m_widget 
 443 //----------------------------------------------------------------------------- 
 445 gint 
gtk_window_own_expose_callback( GtkWidget 
*widget
, GdkEventExpose 
*gdk_event
, wxWindowGTK 
*win 
) 
 447     if (gdk_event
->count 
> 0) return FALSE
; 
 449     draw_frame( widget
, win 
); 
 453     (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
); 
 459 //----------------------------------------------------------------------------- 
 460 // "draw" of m_widget 
 461 //----------------------------------------------------------------------------- 
 465 static void gtk_window_own_draw_callback( GtkWidget 
*widget
, GdkRectangle 
*WXUNUSED(rect
), wxWindowGTK 
*win 
) 
 467     draw_frame( widget
, win 
); 
 472 //----------------------------------------------------------------------------- 
 473 // "size_request" of m_widget 
 474 //----------------------------------------------------------------------------- 
 476 static void gtk_window_size_request_callback( GtkWidget 
*widget
, GtkRequisition 
*requisition
, wxWindow 
*win 
) 
 479     win
->GetSize( &w
, &h 
); 
 483     requisition
->height 
= h
; 
 484     requisition
->width 
= w
; 
 487 //----------------------------------------------------------------------------- 
 488 // "expose_event" of m_wxwindow 
 489 //----------------------------------------------------------------------------- 
 491 static int gtk_window_expose_callback( GtkWidget 
*widget
, 
 492                                        GdkEventExpose 
*gdk_event
, 
 498         wxapp_install_idle_handler(); 
 503         wxPrintf( wxT("OnExpose from ") ); 
 504         if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName()) 
 505             wxPrintf( win
->GetClassInfo()->GetClassName() ); 
 506         wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event
->area
.x
, 
 507                                          (int)gdk_event
->area
.y
, 
 508                                          (int)gdk_event
->area
.width
, 
 509                                          (int)gdk_event
->area
.height 
); 
 514     // This callback gets called in drawing-idle time under 
 515     // GTK 2.0, so we don't need to defer anything to idle 
 518     win
->GetUpdateRegion() = wxRegion( gdk_event
->region 
); 
 520     win
->GtkSendPaintEvents(); 
 522     // Draw window less widgets 
 523     (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
); 
 525     // This gets called immediately after an expose event 
 526     // under GTK 1.2 so we collect the calls and wait for 
 527     // the idle handler to pick things up. 
 529     win
->GetUpdateRegion().Union( gdk_event
->area
.x
, 
 531                                   gdk_event
->area
.width
, 
 532                                   gdk_event
->area
.height 
); 
 533     win
->m_clearRegion
.Union( gdk_event
->area
.x
, 
 535                                   gdk_event
->area
.width
, 
 536                                   gdk_event
->area
.height 
); 
 538     // Actual redrawing takes place in idle time. 
 546 //----------------------------------------------------------------------------- 
 547 // "event" of m_wxwindow 
 548 //----------------------------------------------------------------------------- 
 550 // GTK thinks it is clever and filters out a certain amount of "unneeded" 
 551 // expose events. We need them, of course, so we override the main event 
 552 // procedure in GtkWidget by giving our own handler for all system events. 
 553 // There, we look for expose events ourselves whereas all other events are 
 556 gint 
gtk_window_event_event_callback( GtkWidget 
*widget
, 
 557                                       GdkEventExpose 
*event
, 
 560     if (event
->type 
== GDK_EXPOSE
) 
 562         gint ret 
= gtk_window_expose_callback( widget
, event
, win 
); 
 569 //----------------------------------------------------------------------------- 
 570 // "draw" of m_wxwindow 
 571 //----------------------------------------------------------------------------- 
 575 // This callback is a complete replacement of the gtk_pizza_draw() function, 
 576 // which is disabled. 
 578 static void gtk_window_draw_callback( GtkWidget 
*widget
, 
 585         wxapp_install_idle_handler(); 
 587     // The wxNO_FULL_REPAINT_ON_RESIZE flag only works if 
 588     // there are no child windows. 
 589     if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) && 
 590         (win
->GetChildren().GetCount() == 0)) 
 598         wxPrintf( wxT("OnDraw from ") ); 
 599         if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName()) 
 600             wxPrintf( win
->GetClassInfo()->GetClassName() ); 
 601         wxPrintf( wxT(" %d %d %d %d\n"), (int)rect
->x
, 
 608 #ifndef __WXUNIVERSAL__ 
 609     GtkPizza 
*pizza 
= GTK_PIZZA (widget
); 
 611     if (win
->GetThemeEnabled()) 
 613         wxWindow 
*parent 
= win
->GetParent(); 
 614         while (parent 
&& !parent
->IsTopLevel()) 
 615             parent 
= parent
->GetParent(); 
 619         gtk_paint_flat_box (parent
->m_widget
->style
, 
 630     win
->m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
 631     win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
 633     // Update immediately, not in idle time. 
 636 #ifndef __WXUNIVERSAL__ 
 637     // Redraw child widgets 
 638     GList 
*children 
= pizza
->children
; 
 641         GtkPizzaChild 
*child 
= (GtkPizzaChild
*) children
->data
; 
 642         children 
= children
->next
; 
 644         GdkRectangle child_area
; 
 645         if (gtk_widget_intersect (child
->widget
, rect
, &child_area
)) 
 647             gtk_widget_draw (child
->widget
, &child_area 
/* (GdkRectangle*) NULL*/ ); 
 655 //----------------------------------------------------------------------------- 
 656 // "key_press_event" from any window 
 657 //----------------------------------------------------------------------------- 
 659 // set WXTRACE to this to see the key event codes on the console 
 660 #define TRACE_KEYS  _T("keyevent") 
 662 // translates an X key symbol to WXK_XXX value 
 664 // if isChar is true it means that the value returned will be used for EVT_CHAR 
 665 // event and then we choose the logical WXK_XXX, i.e. '/' for GDK_KP_Divide, 
 666 // for example, while if it is false it means that the value is going to be 
 667 // used for KEY_DOWN/UP events and then we translate GDK_KP_Divide to 
 669 static long wxTranslateKeySymToWXKey(KeySym keysym
, bool isChar
) 
 675         // Shift, Control and Alt don't generate the CHAR events at all 
 678             key_code 
= isChar 
? 0 : WXK_SHIFT
; 
 682             key_code 
= isChar 
? 0 : WXK_CONTROL
; 
 690             key_code 
= isChar 
? 0 : WXK_ALT
; 
 693         // neither do the toggle modifies 
 694         case GDK_Scroll_Lock
: 
 695             key_code 
= isChar 
? 0 : WXK_SCROLL
; 
 699             key_code 
= isChar 
? 0 : WXK_CAPITAL
; 
 703             key_code 
= isChar 
? 0 : WXK_NUMLOCK
; 
 707         // various other special keys 
 720         case GDK_ISO_Left_Tab
: 
 727             key_code 
= WXK_RETURN
; 
 731             key_code 
= WXK_CLEAR
; 
 735             key_code 
= WXK_PAUSE
; 
 739             key_code 
= WXK_SELECT
; 
 743             key_code 
= WXK_PRINT
; 
 747             key_code 
= WXK_EXECUTE
; 
 751             key_code 
= WXK_ESCAPE
; 
 754         // cursor and other extended keyboard keys 
 756             key_code 
= WXK_DELETE
; 
 772             key_code 
= WXK_RIGHT
; 
 779         case GDK_Prior
:     // == GDK_Page_Up 
 780             key_code 
= WXK_PRIOR
; 
 783         case GDK_Next
:      // == GDK_Page_Down 
 796             key_code 
= WXK_INSERT
; 
 811             key_code 
= (isChar 
? '0' : WXK_NUMPAD0
) + keysym 
- GDK_KP_0
; 
 815             key_code 
= isChar 
? ' ' : WXK_NUMPAD_SPACE
; 
 819             key_code 
= isChar 
? WXK_TAB 
: WXK_NUMPAD_TAB
; 
 823             key_code 
= isChar 
? WXK_RETURN 
: WXK_NUMPAD_ENTER
; 
 827             key_code 
= isChar 
? WXK_F1 
: WXK_NUMPAD_F1
; 
 831             key_code 
= isChar 
? WXK_F2 
: WXK_NUMPAD_F2
; 
 835             key_code 
= isChar 
? WXK_F3 
: WXK_NUMPAD_F3
; 
 839             key_code 
= isChar 
? WXK_F4 
: WXK_NUMPAD_F4
; 
 843             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_HOME
; 
 847             key_code 
= isChar 
? WXK_LEFT 
: WXK_NUMPAD_LEFT
; 
 851             key_code 
= isChar 
? WXK_UP 
: WXK_NUMPAD_UP
; 
 855             key_code 
= isChar 
? WXK_RIGHT 
: WXK_NUMPAD_RIGHT
; 
 859             key_code 
= isChar 
? WXK_DOWN 
: WXK_NUMPAD_DOWN
; 
 862         case GDK_KP_Prior
: // == GDK_KP_Page_Up 
 863             key_code 
= isChar 
? WXK_PRIOR 
: WXK_NUMPAD_PRIOR
; 
 866         case GDK_KP_Next
: // == GDK_KP_Page_Down 
 867             key_code 
= isChar 
? WXK_NEXT 
: WXK_NUMPAD_NEXT
; 
 871             key_code 
= isChar 
? WXK_END 
: WXK_NUMPAD_END
; 
 875             key_code 
= isChar 
? WXK_HOME 
: WXK_NUMPAD_BEGIN
; 
 879             key_code 
= isChar 
? WXK_INSERT 
: WXK_NUMPAD_INSERT
; 
 883             key_code 
= isChar 
? WXK_DELETE 
: WXK_NUMPAD_DELETE
; 
 887             key_code 
= isChar 
? '=' : WXK_NUMPAD_EQUAL
; 
 890         case GDK_KP_Multiply
: 
 891             key_code 
= isChar 
? '*' : WXK_NUMPAD_MULTIPLY
; 
 895             key_code 
= isChar 
? '+' : WXK_NUMPAD_ADD
; 
 898         case GDK_KP_Separator
: 
 899             // FIXME: what is this? 
 900             key_code 
= isChar 
? '.' : WXK_NUMPAD_SEPARATOR
; 
 903         case GDK_KP_Subtract
: 
 904             key_code 
= isChar 
? '-' : WXK_NUMPAD_SUBTRACT
; 
 908             key_code 
= isChar 
? '.' : WXK_NUMPAD_DECIMAL
; 
 912             key_code 
= isChar 
? '/' : WXK_NUMPAD_DIVIDE
; 
 929             key_code 
= WXK_F1 
+ keysym 
- GDK_F1
; 
 939 static inline bool wxIsAsciiKeysym(KeySym ks
) 
 945 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
, 
 947                            GdkEventKey 
*gdk_event
) 
 949     // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string 
 950     //     but only event->keyval which is quite useless to us, so remember 
 951     //     the last character from GDK_KEY_PRESS and reuse it as last resort 
 953     // NB: should be MT-safe as we're always called from the main thread only 
 958     } s_lastKeyPress 
= { 0, 0 }; 
 960     KeySym keysym 
= gdk_event
->keyval
; 
 962     wxLogTrace(TRACE_KEYS
, _T("Key %s event: keysym = %ld"), 
 963                event
.GetEventType() == wxEVT_KEY_UP 
? _T("release") 
 967     long key_code 
= wxTranslateKeySymToWXKey(keysym
, FALSE 
/* !isChar */); 
 971         // do we have the translation or is it a plain ASCII character? 
 972         if ( (gdk_event
->length 
== 1) || wxIsAsciiKeysym(keysym
) ) 
 974             // we should use keysym if it is ASCII as X does some translations 
 975             // like "I pressed while Control is down" => "Ctrl-I" == "TAB" 
 976             // which we don't want here (but which we do use for OnChar()) 
 977             if ( !wxIsAsciiKeysym(keysym
) ) 
 979                 keysym 
= (KeySym
)gdk_event
->string
[0]; 
 982             // we want to always get the same key code when the same key is 
 983             // pressed regardless of the state of the modifies, i.e. on a 
 984             // standard US keyboard pressing '5' or '%' ('5' key with 
 985             // Shift) should result in the same key code in OnKeyDown(): 
 986             // '5' (although OnChar() will get either '5' or '%'). 
 988             // to do it we first translate keysym to keycode (== scan code) 
 989             // and then back but always using the lower register 
 990             Display 
*dpy 
= (Display 
*)wxGetDisplay(); 
 991             KeyCode keycode 
= XKeysymToKeycode(dpy
, keysym
); 
 993             wxLogTrace(TRACE_KEYS
, _T("\t-> keycode %d"), keycode
); 
 995             KeySym keysymNormalized 
= XKeycodeToKeysym(dpy
, keycode
, 0); 
 997             // use the normalized, i.e. lower register, keysym if we've 
 999             key_code 
= keysymNormalized 
? keysymNormalized 
: keysym
; 
1001             // as explained above, we want to have lower register key codes 
1002             // normally but for the letter keys we want to have the upper ones 
1004             // NB: don't use XConvertCase() here, we want to do it for letters 
1006             key_code 
= toupper(key_code
); 
1008         else // non ASCII key, what to do? 
1010             // by default, ignore it 
1013             // but if we have cached information from the last KEY_PRESS 
1014             if ( gdk_event
->type 
== GDK_KEY_RELEASE 
) 
1017                 if ( keysym 
== s_lastKeyPress
.keysym 
) 
1019                     key_code 
= s_lastKeyPress
.keycode
; 
1024         if ( gdk_event
->type 
== GDK_KEY_PRESS 
) 
1026             // remember it to be reused for KEY_UP event later 
1027             s_lastKeyPress
.keysym 
= keysym
; 
1028             s_lastKeyPress
.keycode 
= key_code
; 
1032     wxLogTrace(TRACE_KEYS
, _T("\t-> wxKeyCode %ld"), key_code
); 
1034     // sending unknown key events doesn't really make sense 
1038     // now fill all the other fields 
1041     GdkModifierType state
; 
1042     if (gdk_event
->window
) 
1043         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1045     event
.SetTimestamp( gdk_event
->time 
); 
1046     event
.m_shiftDown 
= (gdk_event
->state 
& GDK_SHIFT_MASK
) != 0; 
1047     event
.m_controlDown 
= (gdk_event
->state 
& GDK_CONTROL_MASK
) != 0; 
1048     event
.m_altDown 
= (gdk_event
->state 
& GDK_MOD1_MASK
) != 0; 
1049     event
.m_metaDown 
= (gdk_event
->state 
& GDK_MOD2_MASK
) != 0; 
1050     event
.m_keyCode 
= key_code
; 
1051     event
.m_scanCode 
= gdk_event
->keyval
; 
1052     event
.m_rawCode 
= (wxUint32
) gdk_event
->keyval
; 
1053     event
.m_rawFlags 
= 0; 
1056     event
.SetEventObject( win 
); 
1061 static gint 
gtk_window_key_press_callback( GtkWidget 
*widget
, 
1062                                            GdkEventKey 
*gdk_event
, 
1068         wxapp_install_idle_handler(); 
1072     if (g_blockEventsOnDrag
) 
1076     wxKeyEvent 
event( wxEVT_KEY_DOWN 
); 
1077     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1079         // unknown key pressed, ignore (the event would be useless anyhow) 
1083     // Emit KEY_DOWN event 
1084     bool ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1089         wxWindowGTK 
*ancestor 
= win
; 
1092             int command 
= ancestor
->GetAcceleratorTable()->GetCommand( event 
); 
1095                 wxCommandEvent 
command_event( wxEVT_COMMAND_MENU_SELECTED
, command 
); 
1096                 ret 
= ancestor
->GetEventHandler()->ProcessEvent( command_event 
); 
1099             if (ancestor
->IsTopLevel()) 
1101             ancestor 
= ancestor
->GetParent(); 
1104 #endif // wxUSE_ACCEL 
1106     // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x 
1107     // will only be sent if it is not in an accelerator table. 
1110         // Find key code for EVT_CHAR and EVT_CHAR_HOOK events 
1111         KeySym keysym 
= gdk_event
->keyval
; 
1112         long key_code 
= wxTranslateKeySymToWXKey(keysym
, TRUE 
/* isChar */); 
1115             if ( gdk_event
->length 
== 1 ) 
1117                 key_code 
= (unsigned char)gdk_event
->string
[0]; 
1119             else if ( wxIsAsciiKeysym(keysym
) ) 
1122                 key_code 
= (unsigned char)keysym
; 
1128             wxLogTrace(TRACE_KEYS
, _T("Char event: %ld"), key_code
); 
1130             event
.m_keyCode 
= key_code
; 
1132             // Implement OnCharHook by checking ancesteror top level windows 
1133             wxWindow 
*parent 
= win
; 
1134             while (parent 
&& !parent
->IsTopLevel()) 
1135             parent 
= parent
->GetParent(); 
1138                 event
.SetEventType( wxEVT_CHAR_HOOK 
); 
1139                 ret 
= parent
->GetEventHandler()->ProcessEvent( event 
); 
1144                 event
.SetEventType(wxEVT_CHAR
); 
1145                 ret 
= win
->GetEventHandler()->ProcessEvent( event 
); 
1150     // win is a control: tab can be propagated up 
1152          ((gdk_event
->keyval 
== GDK_Tab
) || (gdk_event
->keyval 
== GDK_ISO_Left_Tab
)) && 
1153 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may 
1154 //     have this style, yet choose not to process this particular TAB in which 
1155 //     case TAB must still work as a navigational character 
1157          !win
->HasFlag(wxTE_PROCESS_TAB
) && 
1159          win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) ) 
1161         wxNavigationKeyEvent new_event
; 
1162         new_event
.SetEventObject( win
->GetParent() ); 
1163         // GDK reports GDK_ISO_Left_Tab for SHIFT-TAB 
1164         new_event
.SetDirection( (gdk_event
->keyval 
== GDK_Tab
) ); 
1165         // CTRL-TAB changes the (parent) window, i.e. switch notebook page 
1166         new_event
.SetWindowChange( (gdk_event
->state 
& GDK_CONTROL_MASK
) ); 
1167         new_event
.SetCurrentFocus( win 
); 
1168         ret 
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event 
); 
1171     // generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) 
1173          (gdk_event
->keyval 
== GDK_Escape
) ) 
1175         wxCommandEvent 
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
); 
1176         new_event
.SetEventObject( win 
); 
1177         ret 
= win
->GetEventHandler()->ProcessEvent( new_event 
); 
1182     // Pressing F10 will activate the menu bar of the top frame 
1184          (gdk_event
->keyval 
== GDK_F10
) ) 
1186         wxWindowGTK 
*ancestor 
= win
; 
1189             if (wxIsKindOf(ancestor
,wxFrame
)) 
1191                 wxFrame 
*frame 
= (wxFrame
*) ancestor
; 
1192                 wxMenuBar 
*menubar 
= frame
->GetMenuBar(); 
1195                     wxNode 
*node 
= menubar
->GetMenus().First(); 
1198                         wxMenu 
*firstMenu 
= (wxMenu
*) node
->Data(); 
1199                         gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) ); 
1205             ancestor 
= ancestor
->GetParent(); 
1212         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" ); 
1219 //----------------------------------------------------------------------------- 
1220 // "key_release_event" from any window 
1221 //----------------------------------------------------------------------------- 
1223 static gint 
gtk_window_key_release_callback( GtkWidget 
*widget
, 
1224                                              GdkEventKey 
*gdk_event
, 
1230         wxapp_install_idle_handler(); 
1235     if (g_blockEventsOnDrag
) 
1238     wxKeyEvent 
event( wxEVT_KEY_UP 
); 
1239     if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) ) 
1241         // unknown key pressed, ignore (the event would be useless anyhow 
1245     if ( !win
->GetEventHandler()->ProcessEvent( event 
) ) 
1248     gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" ); 
1252 // ============================================================================ 
1254 // ============================================================================ 
1256 // ---------------------------------------------------------------------------- 
1257 // mouse event processing helpers 
1258 // ---------------------------------------------------------------------------- 
1260 // init wxMouseEvent with the info from gdk_event 
1262 // NB: this has to be a macro as gdk_event type is different for different 
1263 //     events we're used with 
1264 #define InitMouseEvent(/* wxWindowGTK * */ win,                               \ 
1265                        /* wxMouseEvent& */ event,                             \ 
1266                        /* GdkEventXXX * */ gdk_event)                         \ 
1268     event.SetTimestamp( gdk_event->time );                                    \ 
1269     event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);                  \ 
1270     event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);              \ 
1271     event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);                     \ 
1272     event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);                    \ 
1273     event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);                 \ 
1274     event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);               \ 
1275     event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);                \ 
1277     wxPoint pt = win->GetClientAreaOrigin();                                  \ 
1278     event.m_x = (wxCoord)gdk_event->x - pt.x;                                 \ 
1279     event.m_y = (wxCoord)gdk_event->y - pt.y;                                 \ 
1281     event.SetEventObject( win );                                              \ 
1282     event.SetId( win->GetId() );                                              \ 
1283     event.SetTimestamp( gdk_event->time );                                    \ 
1286 static void AdjustEventButtonState(wxMouseEvent& event) 
1288     // GDK reports the old state of the button for a button press event, but 
1289     // for compatibility with MSW and common sense we want m_leftDown be TRUE 
1290     // for a LEFT_DOWN event, not FALSE, so we will invert 
1291     // left/right/middleDown for the corresponding click events 
1293     if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) || 
1294         (event
.GetEventType() == wxEVT_LEFT_DCLICK
) || 
1295         (event
.GetEventType() == wxEVT_LEFT_UP
)) 
1297         event
.m_leftDown 
= !event
.m_leftDown
; 
1301     if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) || 
1302         (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) || 
1303         (event
.GetEventType() == wxEVT_MIDDLE_UP
)) 
1305         event
.m_middleDown 
= !event
.m_middleDown
; 
1309     if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) || 
1310         (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) || 
1311         (event
.GetEventType() == wxEVT_RIGHT_UP
)) 
1313         event
.m_rightDown 
= !event
.m_rightDown
; 
1318 // find the window to send the mouse event too 
1320 wxWindowGTK 
*FindWindowForMouseEvent(wxWindowGTK 
*win
, wxCoord
& x
, wxCoord
& y
) 
1325     if (win
->m_wxwindow
) 
1327         GtkPizza 
*pizza 
= GTK_PIZZA(win
->m_wxwindow
); 
1328         xx 
+= pizza
->xoffset
; 
1329         yy 
+= pizza
->yoffset
; 
1332     wxNode 
*node 
= win
->GetChildren().First(); 
1335         wxWindowGTK 
*child 
= (wxWindowGTK
*)node
->Data(); 
1337         node 
= node
->Next(); 
1338         if (!child
->IsShown()) 
1341         if (child
->IsTransparentForMouse()) 
1343             // wxStaticBox is transparent in the box itself 
1344             int xx1 
= child
->m_x
; 
1345             int yy1 
= child
->m_y
; 
1346             int xx2 
= child
->m_x 
+ child
->m_width
; 
1347             int yy2 
= child
->m_x 
+ child
->m_height
; 
1350             if (((xx 
>= xx1
) && (xx 
<= xx1
+10) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1352                 ((xx 
>= xx2
-10) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy2
)) || 
1354                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy1
) && (yy 
<= yy1
+10)) || 
1356                 ((xx 
>= xx1
) && (xx 
<= xx2
) && (yy 
>= yy2
-1) && (yy 
<= yy2
))) 
1367             if ((child
->m_wxwindow 
== (GtkWidget
*) NULL
) && 
1368                 (child
->m_x 
<= xx
) && 
1369                 (child
->m_y 
<= yy
) && 
1370                 (child
->m_x
+child
->m_width  
>= xx
) && 
1371                 (child
->m_y
+child
->m_height 
>= yy
)) 
1384 //----------------------------------------------------------------------------- 
1385 // "button_press_event" 
1386 //----------------------------------------------------------------------------- 
1388 static gint 
gtk_window_button_press_callback( GtkWidget 
*widget
, 
1389                                               GdkEventButton 
*gdk_event
, 
1395         wxapp_install_idle_handler(); 
1398     wxPrintf( wxT("1) OnButtonPress from ") ); 
1399     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1400         wxPrintf( win->GetClassInfo()->GetClassName() ); 
1401     wxPrintf( wxT(".\n") ); 
1403     if (!win
->m_hasVMT
) return FALSE
; 
1404     if (g_blockEventsOnDrag
) return TRUE
; 
1405     if (g_blockEventsOnScroll
) return TRUE
; 
1407     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1409     if (win
->m_wxwindow 
&& (g_focusWindow 
!= win
) && win
->AcceptsFocus()) 
1411         gtk_widget_grab_focus( win
->m_wxwindow 
); 
1413         wxPrintf( wxT("GrabFocus from ") ); 
1414         if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1415             wxPrintf( win->GetClassInfo()->GetClassName() ); 
1416         wxPrintf( wxT(".\n") ); 
1420     wxEventType event_type 
= wxEVT_NULL
; 
1422     if (gdk_event
->button 
== 1) 
1424         switch (gdk_event
->type
) 
1426             case GDK_BUTTON_PRESS
: event_type 
= wxEVT_LEFT_DOWN
; break; 
1427             case GDK_2BUTTON_PRESS
: event_type 
= wxEVT_LEFT_DCLICK
; break; 
1431     else if (gdk_event
->button 
== 2) 
1433         switch (gdk_event
->type
) 
1435             case GDK_BUTTON_PRESS
: event_type 
= wxEVT_MIDDLE_DOWN
; break; 
1436             case GDK_2BUTTON_PRESS
: event_type 
= wxEVT_MIDDLE_DCLICK
; break; 
1440     else if (gdk_event
->button 
== 3) 
1442         switch (gdk_event
->type
) 
1444             case GDK_BUTTON_PRESS
: event_type 
= wxEVT_RIGHT_DOWN
; break; 
1445             case GDK_2BUTTON_PRESS
: event_type 
= wxEVT_RIGHT_DCLICK
; break; 
1450     if ( event_type 
== wxEVT_NULL 
) 
1452         // unknown mouse button or click type 
1456     wxMouseEvent 
event( event_type 
); 
1457     InitMouseEvent( win
, event
, gdk_event 
); 
1459     AdjustEventButtonState(event
); 
1461     // wxListBox actually get mouse events from the item, so we need to give it 
1462     // a chance to correct this 
1463     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1465     // find the correct window to send the event too: it may be a different one 
1466     // from the one which got it at GTK+ level because some control don't have 
1467     // their own X window and thus cannot get any events. 
1468     if ( !g_captureWindow 
) 
1469         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1471     gs_timeLastClick 
= gdk_event
->time
; 
1474     wxPrintf( wxT("2) OnButtonPress from ") ); 
1475     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1476         wxPrintf( win->GetClassInfo()->GetClassName() ); 
1477     wxPrintf( wxT(".\n") ); 
1480     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1482         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" ); 
1489 //----------------------------------------------------------------------------- 
1490 // "button_release_event" 
1491 //----------------------------------------------------------------------------- 
1493 static gint 
gtk_window_button_release_callback( GtkWidget 
*widget
, GdkEventButton 
*gdk_event
, wxWindowGTK 
*win 
) 
1498         wxapp_install_idle_handler(); 
1500     if (!win
->m_hasVMT
) return FALSE
; 
1501     if (g_blockEventsOnDrag
) return FALSE
; 
1502     if (g_blockEventsOnScroll
) return FALSE
; 
1504     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1507     printf( "OnButtonRelease from " ); 
1508     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1509         printf( win->GetClassInfo()->GetClassName() ); 
1513     wxEventType event_type 
= wxEVT_NULL
; 
1515     switch (gdk_event
->button
) 
1517         case 1: event_type 
= wxEVT_LEFT_UP
; break; 
1518         case 2: event_type 
= wxEVT_MIDDLE_UP
; break; 
1519         case 3: event_type 
= wxEVT_RIGHT_UP
; break; 
1520         default: return FALSE
; 
1523     wxMouseEvent 
event( event_type 
); 
1524     InitMouseEvent( win
, event
, gdk_event 
); 
1526     AdjustEventButtonState(event
); 
1528     // same wxListBox hack as above 
1529     win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
); 
1531     if ( !g_captureWindow 
) 
1532         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1534     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1536         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" ); 
1543 //----------------------------------------------------------------------------- 
1544 // "motion_notify_event" 
1545 //----------------------------------------------------------------------------- 
1547 static gint 
gtk_window_motion_notify_callback( GtkWidget 
*widget
, 
1548                                                GdkEventMotion 
*gdk_event
, 
1554         wxapp_install_idle_handler(); 
1556     if (!win
->m_hasVMT
) return FALSE
; 
1557     if (g_blockEventsOnDrag
) return FALSE
; 
1558     if (g_blockEventsOnScroll
) return FALSE
; 
1560     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1562     if (gdk_event
->is_hint
) 
1566         GdkModifierType state
; 
1567         gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
1573     printf( "OnMotion from " ); 
1574     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
1575       printf( win->GetClassInfo()->GetClassName() ); 
1579     wxMouseEvent 
event( wxEVT_MOTION 
); 
1580     InitMouseEvent(win
, event
, gdk_event
); 
1582     if ( g_captureWindow 
) 
1584         // synthetize a mouse enter or leave event if needed 
1585         GdkWindow 
*winUnderMouse 
= gdk_window_at_pointer(NULL
, NULL
); 
1586         bool hasMouse 
= winUnderMouse 
== gdk_event
->window
; 
1587         if ( hasMouse 
!= g_captureWindowHasMouse 
) 
1589             // the mouse changed window 
1590             g_captureWindowHasMouse 
= hasMouse
; 
1592             wxMouseEvent 
event(g_captureWindowHasMouse 
? wxEVT_ENTER_WINDOW
 
1593                                                        : wxEVT_LEAVE_WINDOW
); 
1594             InitMouseEvent(win
, event
, gdk_event
); 
1595             event
.SetEventObject(win
); 
1596             win
->GetEventHandler()->ProcessEvent(event
); 
1601         win 
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
); 
1604     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1606         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" ); 
1613 //----------------------------------------------------------------------------- 
1615 //----------------------------------------------------------------------------- 
1617 // send the wxChildFocusEvent and wxFocusEvent, common code of 
1618 // gtk_window_focus_in_callback() and SetFocus() 
1619 static bool DoSendFocusEvents(wxWindow 
*win
) 
1621     // Notify the parent keeping track of focus for the kbd navigation 
1622     // purposes that we got it. 
1623     wxChildFocusEvent 
eventChildFocus(win
); 
1624     (void)win
->GetEventHandler()->ProcessEvent(eventChildFocus
); 
1626     wxFocusEvent 
eventFocus(wxEVT_SET_FOCUS
, win
->GetId()); 
1627     eventFocus
.SetEventObject(win
); 
1629     return win
->GetEventHandler()->ProcessEvent(eventFocus
); 
1632 static gint 
gtk_window_focus_in_callback( GtkWidget 
*widget
, 
1633                                           GdkEvent 
*WXUNUSED(event
), 
1639         wxapp_install_idle_handler(); 
1641     if (!win
->m_hasVMT
) return FALSE
; 
1642     if (g_blockEventsOnDrag
) return FALSE
; 
1644     switch ( g_sendActivateEvent 
) 
1647             // we've got focus from outside, synthetize wxActivateEvent 
1648             g_sendActivateEvent 
= 1; 
1652             // another our window just lost focus, it was already ours before 
1653             // - don't send any wxActivateEvent 
1654             g_sendActivateEvent 
= -1; 
1659     g_focusWindow 
= win
; 
1661     wxLogTrace(TRACE_FOCUS
, 
1662                _T("%s: focus in"), win
->GetName().c_str()); 
1666         gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
); 
1670     // caret needs to be informed about focus change 
1671     wxCaret 
*caret 
= win
->GetCaret(); 
1674         caret
->OnSetFocus(); 
1676 #endif // wxUSE_CARET 
1678     g_activeFrameLostFocus 
= FALSE
; 
1680     wxWindowGTK 
*active 
= wxGetTopLevelParent(win
); 
1681     if ( active 
!= g_activeFrame 
) 
1683         if ( g_activeFrame 
) 
1685             wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
); 
1686             wxActivateEvent 
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId()); 
1687             event
.SetEventObject(g_activeFrame
); 
1688             g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
1691         wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
); 
1692         g_activeFrame 
= active
; 
1693         wxActivateEvent 
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId()); 
1694         event
.SetEventObject(g_activeFrame
); 
1695         g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
1697         // Don't send focus events in addition to activate 
1698         // if (win == g_activeFrame) 
1702     // does the window itself think that it has the focus? 
1703     if ( !win
->m_hasFocus 
) 
1705         // not yet, notify it 
1706         win
->m_hasFocus 
= TRUE
; 
1708         if ( DoSendFocusEvents(win
) ) 
1710            gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" ); 
1718 //----------------------------------------------------------------------------- 
1719 // "focus_out_event" 
1720 //----------------------------------------------------------------------------- 
1722 static gint 
gtk_window_focus_out_callback( GtkWidget 
*widget
, GdkEventFocus 
*gdk_event
, wxWindowGTK 
*win 
) 
1727         wxapp_install_idle_handler(); 
1729     if (!win
->m_hasVMT
) return FALSE
; 
1730     if (g_blockEventsOnDrag
) return FALSE
; 
1732     wxLogTrace( TRACE_FOCUS
, 
1733                 _T("%s: focus out"), win
->GetName().c_str() ); 
1735     if ( !g_activeFrameLostFocus 
&& g_activeFrame 
) 
1737         // VZ: commenting this out because it does happen (although not easy 
1738         //     to reproduce, I only see it when using wxMiniFrame and not 
1739         //     always) and makes using Mahogany quite annoying 
1741         wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
, 
1742                         wxT("unfocusing window that hasn't gained focus properly") ); 
1745         g_activeFrameLostFocus 
= TRUE
; 
1748     // if the focus goes out of our app alltogether, OnIdle() will send 
1749     // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset 
1750     // g_sendActivateEvent to -1 
1751     g_sendActivateEvent 
= 0; 
1753     wxWindowGTK 
*winFocus 
= wxFindFocusedChild(win
); 
1757     g_focusWindow 
= (wxWindowGTK 
*)NULL
; 
1765     // caret needs to be informed about focus change 
1766     wxCaret 
*caret 
= win
->GetCaret(); 
1769         caret
->OnKillFocus(); 
1771 #endif // wxUSE_CARET 
1773     // don't send the window a kill focus event if it thinks that it doesn't 
1774     // have focus already 
1775     if ( win
->m_hasFocus 
) 
1777         win
->m_hasFocus 
= FALSE
; 
1779         wxFocusEvent 
event( wxEVT_KILL_FOCUS
, win
->GetId() ); 
1780         event
.SetEventObject( win 
); 
1782         if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1784             gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" ); 
1792 //----------------------------------------------------------------------------- 
1793 // "enter_notify_event" 
1794 //----------------------------------------------------------------------------- 
1797 gint 
gtk_window_enter_callback( GtkWidget 
*widget
, 
1798                                 GdkEventCrossing 
*gdk_event
, 
1804         wxapp_install_idle_handler(); 
1806     if (!win
->m_hasVMT
) return FALSE
; 
1807     if (g_blockEventsOnDrag
) return FALSE
; 
1809     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1813     GdkModifierType state 
= (GdkModifierType
)0; 
1815     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
1817     wxMouseEvent 
event( wxEVT_ENTER_WINDOW 
); 
1818     InitMouseEvent(win
, event
, gdk_event
); 
1819     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1820     event
.m_x 
= x 
+ pt
.x
; 
1821     event
.m_y 
= y 
+ pt
.y
; 
1823     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1825        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" ); 
1832 //----------------------------------------------------------------------------- 
1833 // "leave_notify_event" 
1834 //----------------------------------------------------------------------------- 
1836 static gint 
gtk_window_leave_callback( GtkWidget 
*widget
, GdkEventCrossing 
*gdk_event
, wxWindowGTK 
*win 
) 
1841         wxapp_install_idle_handler(); 
1843     if (!win
->m_hasVMT
) return FALSE
; 
1844     if (g_blockEventsOnDrag
) return FALSE
; 
1846     if (!win
->IsOwnGtkWindow( gdk_event
->window 
)) return FALSE
; 
1848     wxMouseEvent 
event( wxEVT_LEAVE_WINDOW 
); 
1849     event
.SetTimestamp( gdk_event
->time 
); 
1850     event
.SetEventObject( win 
); 
1854     GdkModifierType state 
= (GdkModifierType
)0; 
1856     gdk_window_get_pointer( widget
->window
, &x
, &y
, &state 
); 
1858     event
.m_shiftDown 
= (state 
& GDK_SHIFT_MASK
) != 0; 
1859     event
.m_controlDown 
= (state 
& GDK_CONTROL_MASK
) != 0; 
1860     event
.m_altDown 
= (state 
& GDK_MOD1_MASK
) != 0; 
1861     event
.m_metaDown 
= (state 
& GDK_MOD2_MASK
) != 0; 
1862     event
.m_leftDown 
= (state 
& GDK_BUTTON1_MASK
) != 0; 
1863     event
.m_middleDown 
= (state 
& GDK_BUTTON2_MASK
) != 0; 
1864     event
.m_rightDown 
= (state 
& GDK_BUTTON3_MASK
) != 0; 
1866     wxPoint pt 
= win
->GetClientAreaOrigin(); 
1867     event
.m_x 
= x 
+ pt
.x
; 
1868     event
.m_y 
= y 
+ pt
.y
; 
1870     if (win
->GetEventHandler()->ProcessEvent( event 
)) 
1872         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" ); 
1879 //----------------------------------------------------------------------------- 
1880 // "value_changed" from m_vAdjust 
1881 //----------------------------------------------------------------------------- 
1883 static void gtk_window_vscroll_callback( GtkAdjustment 
*adjust
, 
1890         wxapp_install_idle_handler(); 
1892     if (g_blockEventsOnDrag
) return; 
1894     if (!win
->m_hasVMT
) return; 
1896     float diff 
= adjust
->value 
- win
->m_oldVerticalPos
; 
1897     if (fabs(diff
) < 0.2) return; 
1899     win
->m_oldVerticalPos 
= adjust
->value
; 
1901     GtkScrolledWindow   
*sw 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
1902     wxEventType         command 
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->vscrollbar
)); 
1904     int value 
= (int)(adjust
->value
+0.5); 
1906     wxScrollWinEvent 
event( command
, value
, wxVERTICAL 
); 
1907     event
.SetEventObject( win 
); 
1908     win
->GetEventHandler()->ProcessEvent( event 
); 
1911 //----------------------------------------------------------------------------- 
1912 // "value_changed" from m_hAdjust 
1913 //----------------------------------------------------------------------------- 
1915 static void gtk_window_hscroll_callback( GtkAdjustment 
*adjust
, 
1922         wxapp_install_idle_handler(); 
1924     if (g_blockEventsOnDrag
) return; 
1925     if (!win
->m_hasVMT
) return; 
1927     float diff 
= adjust
->value 
- win
->m_oldHorizontalPos
; 
1928     if (fabs(diff
) < 0.2) return; 
1930     GtkScrolledWindow   
*sw 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
1931     wxEventType         command 
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->hscrollbar
)); 
1933     win
->m_oldHorizontalPos 
= adjust
->value
; 
1935     int value 
= (int)(adjust
->value
+0.5); 
1937     wxScrollWinEvent 
event( command
, value
, wxHORIZONTAL 
); 
1938     event
.SetEventObject( win 
); 
1939     win
->GetEventHandler()->ProcessEvent( event 
); 
1942 //----------------------------------------------------------------------------- 
1943 // "button_press_event" from scrollbar 
1944 //----------------------------------------------------------------------------- 
1946 static gint 
gtk_scrollbar_button_press_callback( GtkRange 
*widget
, 
1947                                                  GdkEventButton 
*gdk_event
, 
1953         wxapp_install_idle_handler(); 
1956     g_blockEventsOnScroll 
= TRUE
; 
1958     // FIXME: there is no 'slider' field in GTK+ 2.0 any more 
1960     win
->m_isScrolling 
= (gdk_event
->window 
== widget
->slider
); 
1966 //----------------------------------------------------------------------------- 
1967 // "button_release_event" from scrollbar 
1968 //----------------------------------------------------------------------------- 
1970 static gint 
gtk_scrollbar_button_release_callback( GtkRange 
*widget
, 
1971                                                    GdkEventButton 
*WXUNUSED(gdk_event
), 
1976 //  don't test here as we can release the mouse while being over 
1977 //  a different window than the slider 
1979 //    if (gdk_event->window != widget->slider) return FALSE; 
1981     g_blockEventsOnScroll 
= FALSE
; 
1983     if (win
->m_isScrolling
) 
1985         wxEventType command 
= wxEVT_SCROLLWIN_THUMBRELEASE
; 
1989         GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
1990         if (widget 
== GTK_RANGE(scrolledWindow
->hscrollbar
)) 
1992             value 
= (int)(win
->m_hAdjust
->value
+0.5); 
1995         if (widget 
== GTK_RANGE(scrolledWindow
->vscrollbar
)) 
1997             value 
= (int)(win
->m_vAdjust
->value
+0.5); 
2001         wxScrollWinEvent 
event( command
, value
, dir 
); 
2002         event
.SetEventObject( win 
); 
2003         win
->GetEventHandler()->ProcessEvent( event 
); 
2006     win
->m_isScrolling 
= FALSE
; 
2011 // ---------------------------------------------------------------------------- 
2012 // this wxWindowBase function is implemented here (in platform-specific file) 
2013 // because it is static and so couldn't be made virtual 
2014 // ---------------------------------------------------------------------------- 
2016 wxWindow 
*wxWindowBase::FindFocus() 
2018     // the cast is necessary when we compile in wxUniversal mode 
2019     return (wxWindow 
*)g_focusWindow
; 
2022 //----------------------------------------------------------------------------- 
2024 //----------------------------------------------------------------------------- 
2026 // VZ: Robert commented the code using out so it generates warnings: should 
2027 //     be either fixed or removed completely 
2030 static void gtk_window_destroy_callback( GtkWidget
* widget
, wxWindow 
*win 
) 
2032     wxWindowDestroyEvent 
event(win
); 
2033     win
->GetEventHandler()->ProcessEvent(event
); 
2038 //----------------------------------------------------------------------------- 
2039 // "realize" from m_widget 
2040 //----------------------------------------------------------------------------- 
2042 /* We cannot set colours and fonts before the widget has 
2043    been realized, so we do this directly after realization. */ 
2046 gtk_window_realized_callback( GtkWidget 
*WXUNUSED(m_widget
), wxWindow 
*win 
) 
2051         wxapp_install_idle_handler(); 
2053     if (win
->m_delayedBackgroundColour
) 
2054         win
->GtkSetBackgroundColour( win
->GetBackgroundColour() ); 
2056     if (win
->m_delayedForegroundColour
) 
2057         win
->GtkSetForegroundColour( win
->GetForegroundColour() ); 
2059     wxWindowCreateEvent 
event( win 
); 
2060     event
.SetEventObject( win 
); 
2061     win
->GetEventHandler()->ProcessEvent( event 
); 
2066 //----------------------------------------------------------------------------- 
2068 //----------------------------------------------------------------------------- 
2071 void gtk_window_size_callback( GtkWidget 
*WXUNUSED(widget
), 
2072                                GtkAllocation 
*WXUNUSED(alloc
), 
2076         wxapp_install_idle_handler(); 
2078     if (!win
->m_hasScrolling
) return; 
2080     int client_width 
= 0; 
2081     int client_height 
= 0; 
2082     win
->GetClientSize( &client_width
, &client_height 
); 
2083     if ((client_width 
== win
->m_oldClientWidth
) && (client_height 
== win
->m_oldClientHeight
)) 
2086     win
->m_oldClientWidth 
= client_width
; 
2087     win
->m_oldClientHeight 
= client_height
; 
2089     if (!win
->m_nativeSizeEvent
) 
2091         wxSizeEvent 
event( win
->GetSize(), win
->GetId() ); 
2092         event
.SetEventObject( win 
); 
2093         win
->GetEventHandler()->ProcessEvent( event 
); 
2099     #define WXUNUSED_UNLESS_XIM(param)  param 
2101     #define WXUNUSED_UNLESS_XIM(param)  WXUNUSED(param) 
2104 /* Resize XIM window */ 
2107 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
), 
2108                                  GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
), 
2109                                  wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) ) 
2112         wxapp_install_idle_handler(); 
2118     if  (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
) 
2122         gdk_window_get_size (widget
->window
, &width
, &height
); 
2123         win
->m_icattr
->preedit_area
.width 
= width
; 
2124         win
->m_icattr
->preedit_area
.height 
= height
; 
2125         gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
); 
2130 //----------------------------------------------------------------------------- 
2131 // "realize" from m_wxwindow 
2132 //----------------------------------------------------------------------------- 
2134 /* Initialize XIM support */ 
2137 gtk_wxwindow_realized_callback( GtkWidget 
* WXUNUSED_UNLESS_XIM(widget
), 
2138                                 wxWindowGTK 
* WXUNUSED_UNLESS_XIM(win
) ) 
2141         wxapp_install_idle_handler(); 
2144     if (win
->m_ic
) return FALSE
; 
2145     if (!widget
) return FALSE
; 
2146     if (!gdk_im_ready()) return FALSE
; 
2148     win
->m_icattr 
= gdk_ic_attr_new(); 
2149     if (!win
->m_icattr
) return FALSE
; 
2153     GdkColormap 
*colormap
; 
2154     GdkICAttr 
*attr 
= win
->m_icattr
; 
2155     unsigned attrmask 
= GDK_IC_ALL_REQ
; 
2157     GdkIMStyle supported_style 
= (GdkIMStyle
) 
2158                                   (GDK_IM_PREEDIT_NONE 
| 
2159                                    GDK_IM_PREEDIT_NOTHING 
| 
2160                                    GDK_IM_PREEDIT_POSITION 
| 
2161                                    GDK_IM_STATUS_NONE 
| 
2162                                    GDK_IM_STATUS_NOTHING
); 
2164     if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2165         supported_style 
= (GdkIMStyle
)(supported_style 
& ~GDK_IM_PREEDIT_POSITION
); 
2167     attr
->style 
= style 
= gdk_im_decide_style (supported_style
); 
2168     attr
->client_window 
= widget
->window
; 
2170     if ((colormap 
= gtk_widget_get_colormap (widget
)) != 
2171             gtk_widget_get_default_colormap ()) 
2173         attrmask 
|= GDK_IC_PREEDIT_COLORMAP
; 
2174         attr
->preedit_colormap 
= colormap
; 
2177     attrmask 
|= GDK_IC_PREEDIT_FOREGROUND
; 
2178     attrmask 
|= GDK_IC_PREEDIT_BACKGROUND
; 
2179     attr
->preedit_foreground 
= widget
->style
->fg
[GTK_STATE_NORMAL
]; 
2180     attr
->preedit_background 
= widget
->style
->base
[GTK_STATE_NORMAL
]; 
2182     switch (style 
& GDK_IM_PREEDIT_MASK
) 
2184         case GDK_IM_PREEDIT_POSITION
: 
2185             if (widget
->style 
&& widget
->style
->font
->type 
!= GDK_FONT_FONTSET
) 
2187                 g_warning ("over-the-spot style requires fontset"); 
2191             gdk_window_get_size (widget
->window
, &width
, &height
); 
2193             attrmask 
|= GDK_IC_PREEDIT_POSITION_REQ
; 
2194             attr
->spot_location
.x 
= 0; 
2195             attr
->spot_location
.y 
= height
; 
2196             attr
->preedit_area
.x 
= 0; 
2197             attr
->preedit_area
.y 
= 0; 
2198             attr
->preedit_area
.width 
= width
; 
2199             attr
->preedit_area
.height 
= height
; 
2200             attr
->preedit_fontset 
= widget
->style
->font
; 
2205       win
->m_ic 
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
); 
2207       if (win
->m_ic 
== NULL
) 
2208           g_warning ("Can't create input context."); 
2211           mask 
= gdk_window_get_events (widget
->window
); 
2212           mask 
= (GdkEventMask
)(mask 
| gdk_ic_get_events (win
->m_ic
)); 
2213           gdk_window_set_events (widget
->window
, mask
); 
2215           if (GTK_WIDGET_HAS_FOCUS(widget
)) 
2216               gdk_im_begin (win
->m_ic
, widget
->window
); 
2223 //----------------------------------------------------------------------------- 
2224 // InsertChild for wxWindowGTK. 
2225 //----------------------------------------------------------------------------- 
2227 /* Callback for wxWindowGTK. This very strange beast has to be used because 
2228  * C++ has no virtual methods in a constructor. We have to emulate a 
2229  * virtual function here as wxNotebook requires a different way to insert 
2230  * a child in it. I had opted for creating a wxNotebookPage window class 
2231  * which would have made this superfluous (such in the MDI window system), 
2232  * but no-one was listening to me... */ 
2234 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child 
) 
2236     /* the window might have been scrolled already, do we 
2237        have to adapt the position */ 
2238     GtkPizza 
*pizza 
= GTK_PIZZA(parent
->m_wxwindow
); 
2239     child
->m_x 
+= pizza
->xoffset
; 
2240     child
->m_y 
+= pizza
->yoffset
; 
2242     gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
), 
2243                      GTK_WIDGET(child
->m_widget
), 
2250 //----------------------------------------------------------------------------- 
2252 //----------------------------------------------------------------------------- 
2254 wxWindow 
*wxGetActiveWindow() 
2256     return wxWindow::FindFocus(); 
2259 //----------------------------------------------------------------------------- 
2261 //----------------------------------------------------------------------------- 
2263 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
2265 #ifdef __WXUNIVERSAL__ 
2266     IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
) 
2268     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
2269 #endif // __WXUNIVERSAL__/__WXGTK__ 
2271 void wxWindowGTK::Init() 
2277     m_widget 
= (GtkWidget 
*) NULL
; 
2278     m_wxwindow 
= (GtkWidget 
*) NULL
; 
2279     m_focusWidget 
= (GtkWidget 
*) NULL
; 
2289     m_needParent 
= TRUE
; 
2290     m_isBeingDeleted 
= FALSE
; 
2293     m_nativeSizeEvent 
= FALSE
; 
2295     m_hasScrolling 
= FALSE
; 
2296     m_isScrolling 
= FALSE
; 
2298     m_hAdjust 
= (GtkAdjustment
*) NULL
; 
2299     m_vAdjust 
= (GtkAdjustment
*) NULL
; 
2300     m_oldHorizontalPos 
= 0.0; 
2301     m_oldVerticalPos 
= 0.0; 
2304     m_widgetStyle 
= (GtkStyle
*) NULL
; 
2306     m_insertCallback 
= (wxInsertChildFunction
) NULL
; 
2308     m_acceptsFocus 
= FALSE
; 
2311     m_clipPaintRegion 
= FALSE
; 
2313     m_cursor 
= *wxSTANDARD_CURSOR
; 
2315     m_delayedForegroundColour 
= FALSE
; 
2316     m_delayedBackgroundColour 
= FALSE
; 
2319     m_ic 
= (GdkIC
*) NULL
; 
2320     m_icattr 
= (GdkICAttr
*) NULL
; 
2324 wxWindowGTK::wxWindowGTK() 
2329 wxWindowGTK::wxWindowGTK( wxWindow 
*parent
, 
2334                           const wxString 
&name  
) 
2338     Create( parent
, id
, pos
, size
, style
, name 
); 
2341 bool wxWindowGTK::Create( wxWindow 
*parent
, 
2346                           const wxString 
&name  
) 
2348     if (!PreCreation( parent
, pos
, size 
) || 
2349         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
2351         wxFAIL_MSG( wxT("wxWindowGTK creation failed") ); 
2355     m_insertCallback 
= wxInsertChildInWindow
; 
2357     // always needed for background clearing 
2358     m_delayedBackgroundColour 
= TRUE
;  
2360     m_widget 
= gtk_scrolled_window_new( (GtkAdjustment 
*) NULL
, (GtkAdjustment 
*) NULL 
); 
2361     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
2363     GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
2365     GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2366     scroll_class
->scrollbar_spacing 
= 0; 
2368     gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
2370     m_hAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) ); 
2371     m_vAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) ); 
2373     m_wxwindow 
= gtk_pizza_new(); 
2375 #ifndef __WXUNIVERSAL__ 
2376     GtkPizza 
*pizza 
= GTK_PIZZA(m_wxwindow
); 
2378     if (HasFlag(wxRAISED_BORDER
)) 
2380         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT 
); 
2382     else if (HasFlag(wxSUNKEN_BORDER
)) 
2384         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN 
); 
2386     else if (HasFlag(wxSIMPLE_BORDER
)) 
2388         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN 
); 
2392         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE 
); 
2394 #endif // __WXUNIVERSAL__ 
2396     gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
2398     GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
2399     m_acceptsFocus 
= TRUE
; 
2401     // I _really_ don't want scrollbars in the beginning 
2402     m_vAdjust
->lower 
= 0.0; 
2403     m_vAdjust
->upper 
= 1.0; 
2404     m_vAdjust
->value 
= 0.0; 
2405     m_vAdjust
->step_increment 
= 1.0; 
2406     m_vAdjust
->page_increment 
= 1.0; 
2407     m_vAdjust
->page_size 
= 5.0; 
2408     gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
2409     m_hAdjust
->lower 
= 0.0; 
2410     m_hAdjust
->upper 
= 1.0; 
2411     m_hAdjust
->value 
= 0.0; 
2412     m_hAdjust
->step_increment 
= 1.0; 
2413     m_hAdjust
->page_increment 
= 1.0; 
2414     m_hAdjust
->page_size 
= 5.0; 
2415     gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
2417     // these handlers block mouse events to any window during scrolling such as 
2418     // motion events and prevent GTK and wxWindows from fighting over where the 
2421     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event", 
2422           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
2424     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event", 
2425           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
2427     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event", 
2428           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
2430     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event", 
2431           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
2433     // these handlers get notified when screen updates are required either when 
2434     // scrolling or when the window size (and therefore scrollbar configuration) 
2437     gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
2438           (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
2439     gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
2440           (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
2442     gtk_widget_show( m_wxwindow 
); 
2445         m_parent
->DoAddChild( this ); 
2447     m_focusWidget 
= m_wxwindow
; 
2456 wxWindowGTK::~wxWindowGTK() 
2458     if (g_focusWindow 
== this) 
2459         g_focusWindow 
= NULL
; 
2461     if (g_activeFrame 
== this) 
2462         g_activeFrame 
= NULL
; 
2464     if ( g_delayedFocus 
== this ) 
2465         g_delayedFocus 
= NULL
; 
2467     m_isBeingDeleted 
= TRUE
; 
2476         m_parent
->RemoveChild( this ); 
2480         gdk_ic_destroy (m_ic
); 
2482         gdk_ic_attr_destroy (m_icattr
); 
2487 #if DISABLE_STYLE_IF_BROKEN_THEME 
2488         // don't delete if it's a pixmap theme style 
2489         if (!m_widgetStyle
->engine_data
) 
2490             gtk_style_unref( m_widgetStyle 
); 
2492         m_widgetStyle 
= (GtkStyle
*) NULL
; 
2497         gtk_widget_destroy( m_wxwindow 
); 
2498         m_wxwindow 
= (GtkWidget
*) NULL
; 
2503         gtk_widget_destroy( m_widget 
); 
2504         m_widget 
= (GtkWidget
*) NULL
; 
2508 bool wxWindowGTK::PreCreation( wxWindowGTK 
*parent
, const wxPoint 
&pos
,  const wxSize 
&size 
) 
2510     wxCHECK_MSG( !m_needParent 
|| parent
, FALSE
, wxT("Need complete parent.") ); 
2512     // This turns -1 into 30 so that a minimal window is 
2513     // visible even although -1,-1 has been given as the 
2514     // size of the window. the same trick is used in other 
2515     // ports and should make debugging easier. 
2516     m_width 
= WidthDefault(size
.x
) ; 
2517     m_height 
= HeightDefault(size
.y
); 
2522     // some reasonable defaults 
2527             m_x 
= (gdk_screen_width () - m_width
) / 2; 
2528             if (m_x 
< 10) m_x 
= 10; 
2532             m_y 
= (gdk_screen_height () - m_height
) / 2; 
2533             if (m_y 
< 10) m_y 
= 10; 
2540 void wxWindowGTK::PostCreation() 
2542     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2548             // these get reported to wxWindows -> wxPaintEvent 
2550             gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE 
); 
2552             gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event", 
2553                 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this ); 
2556             gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw", 
2557                 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this ); 
2559             if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) 
2561                 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event", 
2562                     GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this ); 
2565             gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow
), HasFlag( wxNO_FULL_REPAINT_ON_RESIZE 
) ); 
2569         // these are called when the "sunken" or "raised" borders are drawn 
2570         gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event", 
2571           GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this ); 
2574         gtk_signal_connect( GTK_OBJECT(m_widget
), "draw", 
2575           GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this ); 
2581     if (m_focusWidget 
== NULL
) 
2582         m_focusWidget 
= m_widget
; 
2584     gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event", 
2585         GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this ); 
2587     gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event", 
2588          GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this ); 
2590     // connect to the various key and mouse handlers 
2592     GtkWidget 
*connect_widget 
= GetConnectWidget(); 
2594     ConnectWidget( connect_widget 
); 
2596     /* We cannot set colours, fonts and cursors before the widget has 
2597        been realized, so we do this directly after realization */ 
2598     gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize", 
2599                             GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this ); 
2603         // Catch native resize events 
2604         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate", 
2605                             GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this ); 
2607         // Initialize XIM support 
2608         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize", 
2609                             GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this ); 
2611         // And resize XIM window 
2612         gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate", 
2613                             GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this ); 
2616     if (!GTK_IS_COMBO(m_widget
)) 
2618         // This is needed if we want to add our windows into native 
2619         // GTK control, such as the toolbar. With this callback, the 
2620         // toolbar gets to know the correct size (the one set by the 
2621         // programmer). Sadly, it misbehaves for wxComboBox. FIXME 
2622         // when moving to GTK 2.0. 
2623         gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request", 
2624                             GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this ); 
2630 void wxWindowGTK::ConnectWidget( GtkWidget 
*widget 
) 
2632     gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event", 
2633       GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this ); 
2635     gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event", 
2636       GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this ); 
2638     gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event", 
2639       GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this ); 
2641     gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event", 
2642       GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this ); 
2644     gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event", 
2645       GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this ); 
2647     gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event", 
2648       GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this ); 
2650     gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event", 
2651       GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this ); 
2653     // This keeps crashing on me. RR. 
2655     // gtk_signal_connect( GTK_OBJECT(widget), "destroy", 
2656     //  GTK_SIGNAL_FUNC(gtk_window_destroy_callback), (gpointer)this ); 
2659 bool wxWindowGTK::Destroy() 
2661     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2665     return wxWindowBase::Destroy(); 
2668 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
) 
2670     gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height 
); 
2673 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
2675     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
2676     wxASSERT_MSG( (m_parent 
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") ); 
2679     printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height ); 
2682     if (m_resizing
) return; /* I don't like recursions */ 
2685     int currentX
, currentY
; 
2686     GetPosition(¤tX
, ¤tY
); 
2691     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
2693     if (m_parent
->m_wxwindow 
== NULL
) /* i.e. wxNotebook */ 
2695         /* don't set the size for children of wxNotebook, just take the values. */ 
2703         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
2704         if ((sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) == 0) 
2706             if (x 
!= -1) m_x 
= x 
+ pizza
->xoffset
; 
2707             if (y 
!= -1) m_y 
= y 
+ pizza
->yoffset
; 
2711             m_x 
= x 
+ pizza
->xoffset
; 
2712             m_y 
= y 
+ pizza
->yoffset
; 
2714         if (width 
!= -1) m_width 
= width
; 
2715         if (height 
!= -1) m_height 
= height
; 
2717         if ((sizeFlags 
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
) 
2719              if (width 
== -1) m_width 
= 80; 
2722         if ((sizeFlags 
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
) 
2724              if (height 
== -1) m_height 
= 26; 
2727         int minWidth 
= GetMinWidth(), 
2728             minHeight 
= GetMinHeight(), 
2729             maxWidth 
= GetMaxWidth(), 
2730             maxHeight 
= GetMaxHeight(); 
2732         if ((minWidth 
!= -1) && (m_width 
< minWidth
)) m_width 
= minWidth
; 
2733         if ((minHeight 
!= -1) && (m_height 
< minHeight
)) m_height 
= minHeight
; 
2734         if ((maxWidth 
!= -1) && (m_width 
> maxWidth
)) m_width 
= maxWidth
; 
2735         if ((maxHeight 
!= -1) && (m_height 
> maxHeight
)) m_height 
= maxHeight
; 
2738         int bottom_border 
= 0; 
2741         if (GTK_WIDGET_CAN_DEFAULT(m_widget
)) 
2743             /* the default button has a border around it */ 
2749         DoMoveWindow( m_x
-border
, 
2752                       m_height
+border
+bottom_border 
); 
2757         /* Sometimes the client area changes size without the 
2758            whole windows's size changing, but if the whole 
2759            windows's size doesn't change, no wxSizeEvent will 
2760            normally be sent. Here we add an extra test if 
2761            the client test has been changed and this will 
2763         GetClientSize( &m_oldClientWidth
, &m_oldClientHeight 
); 
2767     wxPrintf( "OnSize sent from " ); 
2768     if (GetClassInfo() && GetClassInfo()->GetClassName()) 
2769         wxPrintf( GetClassInfo()->GetClassName() ); 
2770     wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height ); 
2773     if (!m_nativeSizeEvent
) 
2775         wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
2776         event
.SetEventObject( this ); 
2777         GetEventHandler()->ProcessEvent( event 
); 
2783 void wxWindowGTK::OnInternalIdle() 
2785     // Update invalidated regions. 
2788     // Synthetize activate events. 
2789     if ( g_sendActivateEvent 
!= -1 ) 
2791         bool activate 
= g_sendActivateEvent 
!= 0; 
2794         g_sendActivateEvent 
= -1; 
2796         wxTheApp
->SetActive(activate
, (wxWindow 
*)g_focusWindowLast
); 
2799     if ( g_activeFrameLostFocus 
) 
2801         if ( g_activeFrame 
) 
2803             wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
); 
2804             wxActivateEvent 
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId()); 
2805             event
.SetEventObject(g_activeFrame
); 
2806             g_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
2807             g_activeFrame 
= NULL
; 
2809         g_activeFrameLostFocus 
= FALSE
; 
2812     wxCursor cursor 
= m_cursor
; 
2813     if (g_globalCursor
.Ok()) cursor 
= g_globalCursor
; 
2817         /* I now set the cursor anew in every OnInternalIdle call 
2818            as setting the cursor in a parent window also effects the 
2819            windows above so that checking for the current cursor is 
2824             GdkWindow 
*window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
2826                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2828             if (!g_globalCursor
.Ok()) 
2829                 cursor 
= *wxSTANDARD_CURSOR
; 
2831             window 
= m_widget
->window
; 
2832             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
2833                 gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2839             GdkWindow 
*window 
= m_widget
->window
; 
2840             if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
))) 
2841                gdk_window_set_cursor( window
, cursor
.GetCursor() ); 
2849 void wxWindowGTK::DoGetSize( int *width
, int *height 
) const 
2851     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2853     if (width
) (*width
) = m_width
; 
2854     if (height
) (*height
) = m_height
; 
2857 void wxWindowGTK::DoSetClientSize( int width
, int height 
) 
2859     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2863         SetSize( width
, height 
); 
2870 #ifndef __WXUNIVERSAL__ 
2871         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
2873             /* when using GTK 1.2 we set the shadow border size to 2 */ 
2877         if (HasFlag(wxSIMPLE_BORDER
)) 
2879             /* when using GTK 1.2 we set the simple border size to 1 */ 
2883 #endif // __WXUNIVERSAL__ 
2887             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
2889             GtkRequisition vscroll_req
; 
2890             vscroll_req
.width 
= 2; 
2891             vscroll_req
.height 
= 2; 
2892             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
2893                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
2895             GtkRequisition hscroll_req
; 
2896             hscroll_req
.width 
= 2; 
2897             hscroll_req
.height 
= 2; 
2898             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
2899                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
2901             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2903             if (scroll_window
->vscrollbar_visible
) 
2905                 dw 
+= vscroll_req
.width
; 
2906                 dw 
+= scroll_class
->scrollbar_spacing
; 
2909             if (scroll_window
->hscrollbar_visible
) 
2911                 dh 
+= hscroll_req
.height
; 
2912                 dh 
+= scroll_class
->scrollbar_spacing
; 
2916        SetSize( width
+dw
, height
+dh 
); 
2920 void wxWindowGTK::DoGetClientSize( int *width
, int *height 
) const 
2922     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2926         if (width
) (*width
) = m_width
; 
2927         if (height
) (*height
) = m_height
; 
2934 #ifndef __WXUNIVERSAL__ 
2935         if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
)) 
2937             /* when using GTK 1.2 we set the shadow border size to 2 */ 
2941         if (HasFlag(wxSIMPLE_BORDER
)) 
2943             /* when using GTK 1.2 we set the simple border size to 1 */ 
2947 #endif // __WXUNIVERSAL__ 
2951             GtkScrolledWindow 
*scroll_window 
= GTK_SCROLLED_WINDOW(m_widget
); 
2953             GtkRequisition vscroll_req
; 
2954             vscroll_req
.width 
= 2; 
2955             vscroll_req
.height 
= 2; 
2956             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request 
) 
2957                 (scroll_window
->vscrollbar
, &vscroll_req 
); 
2959             GtkRequisition hscroll_req
; 
2960             hscroll_req
.width 
= 2; 
2961             hscroll_req
.height 
= 2; 
2962             (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request 
) 
2963                 (scroll_window
->hscrollbar
, &hscroll_req 
); 
2965             GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
2967             if (scroll_window
->vscrollbar_visible
) 
2969                 dw 
+= vscroll_req
.width
; 
2970                 dw 
+= scroll_class
->scrollbar_spacing
; 
2973             if (scroll_window
->hscrollbar_visible
) 
2975                 dh 
+= hscroll_req
.height
; 
2976                 dh 
+= scroll_class
->scrollbar_spacing
; 
2980         if (width
) (*width
) = m_width 
- dw
; 
2981         if (height
) (*height
) = m_height 
- dh
; 
2985     printf( "GetClientSize, name %s ", GetName().c_str() ); 
2986     if (width) printf( " width = %d", (*width) ); 
2987     if (height) printf( " height = %d", (*height) ); 
2992 void wxWindowGTK::DoGetPosition( int *x
, int *y 
) const 
2994     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
2998     if (m_parent 
&& m_parent
->m_wxwindow
) 
3000         GtkPizza 
*pizza 
= GTK_PIZZA(m_parent
->m_wxwindow
); 
3001         dx 
= pizza
->xoffset
; 
3002         dy 
= pizza
->yoffset
; 
3005     if (x
) (*x
) = m_x 
- dx
; 
3006     if (y
) (*y
) = m_y 
- dy
; 
3009 void wxWindowGTK::DoClientToScreen( int *x
, int *y 
) const 
3011     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3013     if (!m_widget
->window
) return; 
3015     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3017         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3019         source 
= m_widget
->window
; 
3023     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3027         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3029             org_x 
+= m_widget
->allocation
.x
; 
3030             org_y 
+= m_widget
->allocation
.y
; 
3038 void wxWindowGTK::DoScreenToClient( int *x
, int *y 
) const 
3040     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3042     if (!m_widget
->window
) return; 
3044     GdkWindow 
*source 
= (GdkWindow 
*) NULL
; 
3046         source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3048         source 
= m_widget
->window
; 
3052     gdk_window_get_origin( source
, &org_x
, &org_y 
); 
3056         if (GTK_WIDGET_NO_WINDOW (m_widget
)) 
3058             org_x 
+= m_widget
->allocation
.x
; 
3059             org_y 
+= m_widget
->allocation
.y
; 
3067 bool wxWindowGTK::Show( bool show 
) 
3069     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3071     if (!wxWindowBase::Show(show
)) 
3078         gtk_widget_show( m_widget 
); 
3080         gtk_widget_hide( m_widget 
); 
3085 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
) 
3087     win
->OnParentEnable(enable
); 
3089     // Recurse, so that children have the opportunity to Do The Right Thing 
3090     // and reset colours that have been messed up by a parent's (really ancestor's) 
3092     for ( wxWindowList::Node 
*node 
= win
->GetChildren().GetFirst(); 
3094           node 
= node
->GetNext() ) 
3096         wxWindow 
*child 
= node
->GetData(); 
3097         if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
))) 
3098             wxWindowNotifyEnable(child
, enable
); 
3102 bool wxWindowGTK::Enable( bool enable 
) 
3104     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3106     if (!wxWindowBase::Enable(enable
)) 
3112     gtk_widget_set_sensitive( m_widget
, enable 
); 
3114         gtk_widget_set_sensitive( m_wxwindow
, enable 
); 
3116     wxWindowNotifyEnable(this, enable
); 
3121 int wxWindowGTK::GetCharHeight() const 
3123     wxCHECK_MSG( (m_widget 
!= NULL
), 12, wxT("invalid window") ); 
3125     wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") ); 
3127     GdkFont 
*font 
= m_font
.GetInternalFont( 1.0 ); 
3129     return font
->ascent 
+ font
->descent
; 
3132 int wxWindowGTK::GetCharWidth() const 
3134     wxCHECK_MSG( (m_widget 
!= NULL
), 8, wxT("invalid window") ); 
3136     wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") ); 
3138     GdkFont 
*font 
= m_font
.GetInternalFont( 1.0 ); 
3140     return gdk_string_width( font
, "H" ); 
3143 void wxWindowGTK::GetTextExtent( const wxString
& string
, 
3147                               int *externalLeading
, 
3148                               const wxFont 
*theFont 
) const 
3150     wxFont fontToUse 
= m_font
; 
3151     if (theFont
) fontToUse 
= *theFont
; 
3153     wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") ); 
3155     if (string
.IsEmpty()) 
3163     PangoContext 
*context 
= NULL
; 
3165         gtk_widget_get_pango_context( m_widget 
); 
3174     PangoFontDescription 
*desc 
= fontToUse
.GetNativeFontInfo()->description
; 
3175     PangoLayout 
*layout 
= pango_layout_new(context
); 
3176     pango_layout_set_font_description(layout
, desc
); 
3179         const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( string 
); 
3180         pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data 
)); 
3182         const wxWCharBuffer wdata 
= wxConvLocal
.cMB2WC( string 
); 
3183         const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( wdata 
); 
3184         pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data 
)); 
3187     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
3189     PangoRectangle rect
; 
3190     pango_layout_line_get_extents(line
, NULL
, &rect
); 
3192     if (x
) (*x
) = (wxCoord
) (rect
.width 
/ PANGO_SCALE
); 
3193     if (y
) (*y
) = (wxCoord
) (rect
.height 
/ PANGO_SCALE
); 
3196         // Do something about metrics here 
3199     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3201     g_object_unref( G_OBJECT( layout 
) ); 
3203     GdkFont 
*font 
= fontToUse
.GetInternalFont( 1.0 ); 
3204     if (x
) (*x
) = gdk_string_width( font
, wxGTK_CONV( string 
) ); 
3205     if (y
) (*y
) = font
->ascent 
+ font
->descent
; 
3206     if (descent
) (*descent
) = font
->descent
; 
3207     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
3211 void wxWindowGTK::SetFocus() 
3213     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3217         // don't do anything if we already have focus 
3223         if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
)) 
3225             gtk_widget_grab_focus (m_wxwindow
); 
3230         if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) ) 
3232             if (!GTK_WIDGET_REALIZED(m_widget
)) 
3234                 // we can't set the focus to the widget now so we remember that 
3235                 // it should be focused and will do it later, during the idle 
3236                 // time, as soon as we can 
3237                 wxLogTrace(TRACE_FOCUS
, 
3238                            _T("Delaying setting focus to %s(%s)"), 
3239                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3241                 g_delayedFocus 
= this; 
3245                 wxLogTrace(TRACE_FOCUS
, 
3246                            _T("Setting focus to %s(%s)"), 
3247                            GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3249                 gtk_widget_grab_focus (m_widget
); 
3252         else if (GTK_IS_CONTAINER(m_widget
)) 
3254             SET_CONTAINER_FOCUS( m_widget
, GTK_DIR_TAB_FORWARD 
); 
3258            wxLogTrace(TRACE_FOCUS
, 
3259                       _T("Can't set focus to %s(%s)"), 
3260                       GetClassInfo()->GetClassName(), GetLabel().c_str()); 
3265 bool wxWindowGTK::AcceptsFocus() const 
3267     return m_acceptsFocus 
&& wxWindowBase::AcceptsFocus(); 
3270 bool wxWindowGTK::Reparent( wxWindowBase 
*newParentBase 
) 
3272     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3274     wxWindowGTK 
*oldParent 
= m_parent
, 
3275              *newParent 
= (wxWindowGTK 
*)newParentBase
; 
3277     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3279     if ( !wxWindowBase::Reparent(newParent
) ) 
3282     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3284     /* prevent GTK from deleting the widget arbitrarily */ 
3285     gtk_widget_ref( m_widget 
); 
3289         gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget 
); 
3292     wxASSERT( GTK_IS_WIDGET(m_widget
) ); 
3296         /* insert GTK representation */ 
3297         (*(newParent
->m_insertCallback
))(newParent
, this); 
3300     /* reverse: prevent GTK from deleting the widget arbitrarily */ 
3301     gtk_widget_unref( m_widget 
); 
3306 void wxWindowGTK::DoAddChild(wxWindowGTK 
*child
) 
3308     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid window") ); 
3310     wxASSERT_MSG( (child 
!= NULL
), wxT("invalid child window") ); 
3312     wxASSERT_MSG( (m_insertCallback 
!= NULL
), wxT("invalid child insertion function") ); 
3317     /* insert GTK representation */ 
3318     (*m_insertCallback
)(this, child
); 
3321 void wxWindowGTK::Raise() 
3323     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3325     if (!m_widget
->window
) return; 
3327     gdk_window_raise( m_widget
->window 
); 
3330 void wxWindowGTK::Lower() 
3332     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3334     if (!m_widget
->window
) return; 
3336     gdk_window_lower( m_widget
->window 
); 
3339 bool wxWindowGTK::SetCursor( const wxCursor 
&cursor 
) 
3341     wxCHECK_MSG( (m_widget 
!= NULL
), FALSE
, wxT("invalid window") ); 
3343     if (cursor 
== m_cursor
) 
3347         wxapp_install_idle_handler(); 
3349     if (cursor 
== wxNullCursor
) 
3350        return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR 
); 
3352        return wxWindowBase::SetCursor( cursor 
); 
3355 void wxWindowGTK::WarpPointer( int x
, int y 
) 
3357     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid window") ); 
3359     // We provide this function ourselves as it is 
3360     // missing in GDK (top of this file). 
3362     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3364         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3366         window 
= GetConnectWidget()->window
; 
3369         gdk_window_warp_pointer( window
, x
, y 
); 
3373 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect 
*rect 
) 
3375     if (!m_widget
) return; 
3376     if (!m_widget
->window
) return; 
3380         wxapp_install_idle_handler(); 
3382     if (eraseBackground 
&& m_wxwindow 
&& m_wxwindow
->window
) 
3386             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3387             m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3391             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3392             m_clearRegion
.Clear(); 
3393             m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3401             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3402             m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height 
); 
3406             GdkRectangle gdk_rect
; 
3407             gdk_rect
.x 
= rect
->x
; 
3408             gdk_rect
.y 
= rect
->y
; 
3409             gdk_rect
.width 
= rect
->width
; 
3410             gdk_rect
.height 
= rect
->height
; 
3411             gtk_widget_draw( m_widget
, &gdk_rect 
); 
3418             // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 
3419             m_updateRegion
.Clear(); 
3420             m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height 
); 
3424             gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL 
); 
3432             GdkRectangle gdk_rect
; 
3433             gdk_rect
.x 
= rect
->x
; 
3434             gdk_rect
.y 
= rect
->y
; 
3435             gdk_rect
.width 
= rect
->width
; 
3436             gdk_rect
.height 
= rect
->height
; 
3437             gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, &gdk_rect
, TRUE 
); 
3441             gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, NULL
, TRUE 
); 
3447 void wxWindowGTK::Update() 
3452 void wxWindowGTK::GtkUpdate() 
3455     if (m_wxwindow 
&& GTK_PIZZA(m_wxwindow
)->bin_window
) 
3456         gdk_window_process_updates( GTK_PIZZA(m_wxwindow
)->bin_window
, FALSE 
); 
3458     if (!m_updateRegion
.IsEmpty()) 
3459         GtkSendPaintEvents(); 
3463 void wxWindowGTK::GtkSendPaintEvents() 
3468         m_clearRegion
.Clear(); 
3470         m_updateRegion
.Clear(); 
3474     // Clip to paint region in wxClientDC 
3475     m_clipPaintRegion 
= TRUE
; 
3478     // widget to draw on 
3479     GtkPizza 
*pizza 
= GTK_PIZZA (m_wxwindow
); 
3481     // later for GTK 2.0, too. 
3482     if (GetThemeEnabled()) 
3484         // find ancestor from which to steal background 
3485         wxWindow 
*parent 
= GetParent(); 
3486         while (parent 
&& !parent
->IsTopLevel()) 
3487             parent 
= parent
->GetParent(); 
3489             parent 
= (wxWindow
*)this; 
3491         wxRegionIterator 
upd( m_updateRegion 
); 
3495             rect
.x 
= upd
.GetX(); 
3496             rect
.y 
= upd
.GetY(); 
3497             rect
.width 
= upd
.GetWidth(); 
3498             rect
.height 
= upd
.GetHeight(); 
3500             gtk_paint_flat_box( parent
->m_widget
->style
, 
3517         wxWindowDC 
dc( (wxWindow
*)this ); 
3518         dc
.SetClippingRegion( m_updateRegion 
); 
3520         wxEraseEvent 
erase_event( GetId(), &dc 
); 
3521         erase_event
.SetEventObject( this ); 
3523         GetEventHandler()->ProcessEvent(erase_event
); 
3526     // if (!m_clearRegion.IsEmpty())   // Always send an erase event under GTK 1.2 
3528         wxWindowDC 
dc( (wxWindow
*)this ); 
3529         if (m_clearRegion
.IsEmpty()) 
3530             dc
.SetClippingRegion( m_updateRegion 
); 
3532             dc
.SetClippingRegion( m_clearRegion 
); 
3534         wxEraseEvent 
erase_event( GetId(), &dc 
); 
3535         erase_event
.SetEventObject( this ); 
3537         if (!GetEventHandler()->ProcessEvent(erase_event
)) 
3541                 g_eraseGC 
= gdk_gc_new( pizza
->bin_window 
); 
3542                 gdk_gc_set_fill( g_eraseGC
, GDK_SOLID 
); 
3544             gdk_gc_set_foreground( g_eraseGC
, m_backgroundColour
.GetColor() ); 
3546             wxRegionIterator 
upd( m_clearRegion 
); 
3549                 gdk_draw_rectangle( pizza
->bin_window
, g_eraseGC
, 1, 
3550                                     upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() ); 
3554         m_clearRegion
.Clear(); 
3558     wxNcPaintEvent 
nc_paint_event( GetId() ); 
3559     nc_paint_event
.SetEventObject( this ); 
3560     GetEventHandler()->ProcessEvent( nc_paint_event 
); 
3562     wxPaintEvent 
paint_event( GetId() ); 
3563     paint_event
.SetEventObject( this ); 
3564     GetEventHandler()->ProcessEvent( paint_event 
); 
3566     m_clipPaintRegion 
= FALSE
; 
3568 #ifndef __WXUNIVERSAL__ 
3570     // The following code will result in all window-less widgets 
3571     // being redrawn because the wxWindows class is allowed to 
3572     // paint over the window-less widgets. 
3574     GList 
*children 
= pizza
->children
; 
3577         GtkPizzaChild 
*child 
= (GtkPizzaChild
*) children
->data
; 
3578         children 
= children
->next
; 
3580         if (GTK_WIDGET_NO_WINDOW (child
->widget
) && 
3581             GTK_WIDGET_DRAWABLE (child
->widget
)) 
3583             // Get intersection of widget area and update region 
3584             wxRegion 
region( m_updateRegion 
); 
3586             GdkEventExpose gdk_event
; 
3587             gdk_event
.type 
= GDK_EXPOSE
; 
3588             gdk_event
.window 
= pizza
->bin_window
; 
3589             gdk_event
.count 
= 0; 
3591             wxRegionIterator 
upd( m_updateRegion 
); 
3595                 rect
.x 
= upd
.GetX(); 
3596                 rect
.y 
= upd
.GetY(); 
3597                 rect
.width 
= upd
.GetWidth(); 
3598                 rect
.height 
= upd
.GetHeight(); 
3600                 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
)) 
3602                     gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
); 
3612     m_updateRegion
.Clear(); 
3615 void wxWindowGTK::Clear() 
3617     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3620     if (m_wxwindow 
&& m_wxwindow
->window
) 
3622         m_clearRegion
.Clear(); 
3623         wxSize 
size( GetClientSize() ); 
3624         m_clearRegion
.Union( 0,0,size
.x
,size
.y 
); 
3626         // Better do this in idle? 
3633 void wxWindowGTK::DoSetToolTip( wxToolTip 
*tip 
) 
3635     wxWindowBase::DoSetToolTip(tip
); 
3638         m_tooltip
->Apply( (wxWindow 
*)this ); 
3641 void wxWindowGTK::ApplyToolTip( GtkTooltips 
*tips
, const wxChar 
*tip 
) 
3643     gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL 
); 
3645 #endif // wxUSE_TOOLTIPS 
3647 void wxWindowGTK::GtkSetBackgroundColour( const wxColour 
&colour 
) 
3649     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3651         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3653         window 
= GetConnectWidget()->window
; 
3657     // We need the pixel value e.g. for background clearing. 
3658     m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window 
) ); 
3662         // wxMSW doesn't clear the window here, either. 
3663         gdk_window_set_background( window
, m_backgroundColour
.GetColor() ); 
3669 bool wxWindowGTK::SetBackgroundColour( const wxColour 
&colour 
) 
3671     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
3673     if (!wxWindowBase::SetBackgroundColour(colour
)) 
3676     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3678         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3680         window 
= GetConnectWidget()->window
; 
3684         // indicate that a new style has been set 
3685         // but it couldn't get applied as the 
3686         // widget hasn't been realized yet. 
3687         m_delayedBackgroundColour 
= TRUE
; 
3692         GtkSetBackgroundColour( colour 
); 
3698 void wxWindowGTK::GtkSetForegroundColour( const wxColour 
&colour 
) 
3700     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3702         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3704         window 
= GetConnectWidget()->window
; 
3711 bool wxWindowGTK::SetForegroundColour( const wxColour 
&colour 
) 
3713     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
3715     if (!wxWindowBase::SetForegroundColour(colour
)) 
3717         // don't leave if the GTK widget has just 
3719         if (!m_delayedForegroundColour
) return FALSE
; 
3722     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
3724         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
3726         window 
= GetConnectWidget()->window
; 
3730         // indicate that a new style has been set 
3731         // but it couldn't get applied as the 
3732         // widget hasn't been realized yet. 
3733         m_delayedForegroundColour 
= TRUE
; 
3737        GtkSetForegroundColour( colour 
); 
3743 GtkStyle 
*wxWindowGTK::GetWidgetStyle() 
3747         GtkStyle 
*remake 
= gtk_style_copy( m_widgetStyle 
); 
3749         // FIXME: no more klass in 2.0 
3751         remake
->klass 
= m_widgetStyle
->klass
; 
3754         gtk_style_unref( m_widgetStyle 
); 
3755         m_widgetStyle 
= remake
; 
3759         GtkStyle 
*def 
= gtk_rc_get_style( m_widget 
); 
3762             def 
= gtk_widget_get_default_style(); 
3764         m_widgetStyle 
= gtk_style_copy( def 
); 
3766         // FIXME: no more klass in 2.0 
3768         m_widgetStyle
->klass 
= def
->klass
; 
3772     return m_widgetStyle
; 
3775 void wxWindowGTK::SetWidgetStyle() 
3777 #if DISABLE_STYLE_IF_BROKEN_THEME 
3778     if (m_widget
->style
->engine_data
) 
3780         static bool s_warningPrinted 
= FALSE
; 
3781         if (!s_warningPrinted
) 
3783             printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" ); 
3784             s_warningPrinted 
= TRUE
; 
3786         m_widgetStyle 
= m_widget
->style
; 
3791     GtkStyle 
*style 
= GetWidgetStyle(); 
3793     if (m_font 
!= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT 
)) 
3795         SET_STYLE_FONT(style
, m_font
.GetInternalFont( 1.0 )); 
3798     if (m_foregroundColour
.Ok()) 
3800         m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget 
) ); 
3801         if (m_foregroundColour 
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT
)) 
3803             style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor(); 
3804             style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor(); 
3805             style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor(); 
3809             // Try to restore the gtk default style.  This is still a little 
3810             // oversimplified for what is probably really needed here for controls 
3811             // other than buttons, but is better than not being able to (re)set a 
3812             // control's foreground colour to *wxBLACK -- RL 
3813             GtkStyle 
*def 
= gtk_rc_get_style( m_widget 
); 
3816                 def 
= gtk_widget_get_default_style(); 
3818             style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
]; 
3819             style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
]; 
3820             style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
]; 
3824     if (m_backgroundColour
.Ok()) 
3826         m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget 
) ); 
3827         if (m_backgroundColour 
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
)) 
3829             style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor(); 
3830             style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor(); 
3831             style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor(); 
3832             style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor(); 
3833             style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor(); 
3834             style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor(); 
3835             style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor(); 
3836             style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor(); 
3840             // Try to restore the gtk default style.  This is still a little 
3841             // oversimplified for what is probably really needed here for controls 
3842             // other than buttons, but is better than not being able to (re)set a 
3843             // control's background colour to default grey and means resetting a 
3844             // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting 
3846             GtkStyle 
*def 
= gtk_rc_get_style( m_widget 
); 
3849                 def 
= gtk_widget_get_default_style(); 
3851             style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
]; 
3852             style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
]; 
3853             style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
]; 
3854             style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
]; 
3855             style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
]; 
3856             style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
]; 
3857             style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
]; 
3858             style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
]; 
3863 void wxWindowGTK::ApplyWidgetStyle() 
3867 //----------------------------------------------------------------------------- 
3868 // Pop-up menu stuff 
3869 //----------------------------------------------------------------------------- 
3871 #if wxUSE_MENUS_NATIVE 
3874 void gtk_pop_hide_callback( GtkWidget 
*WXUNUSED(widget
), bool* is_waiting  
) 
3876     *is_waiting 
= FALSE
; 
3879 static void SetInvokingWindow( wxMenu 
*menu
, wxWindowGTK 
*win 
) 
3881     menu
->SetInvokingWindow( win 
); 
3882     wxMenuItemList::Node 
*node 
= menu
->GetMenuItems().GetFirst(); 
3885         wxMenuItem 
*menuitem 
= node
->GetData(); 
3886         if (menuitem
->IsSubMenu()) 
3888             SetInvokingWindow( menuitem
->GetSubMenu(), win 
); 
3891         node 
= node
->GetNext(); 
3895 // used to pass the coordinates from wxWindowGTK::DoPopupMenu() to 
3896 // wxPopupMenuPositionCallback() 
3898 // should be safe even in the MT case as the user can hardly popup 2 menus 
3899 // simultaneously, can he? 
3900 static gint gs_pop_x 
= 0; 
3901 static gint gs_pop_y 
= 0; 
3903 extern "C" void wxPopupMenuPositionCallback( GtkMenu 
*menu
, 
3906                                              gboolean 
* WXUNUSED(whatever
), 
3908                                              gpointer 
WXUNUSED(user_data
) ) 
3910     // ensure that the menu appears entirely on screen 
3912     gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
); 
3914     wxSize sizeScreen 
= wxGetDisplaySize(); 
3916     gint xmax 
= sizeScreen
.x 
- req
.width
, 
3917          ymax 
= sizeScreen
.y 
- req
.height
; 
3919     *x 
= gs_pop_x 
< xmax 
? gs_pop_x 
: xmax
; 
3920     *y 
= gs_pop_y 
< ymax 
? gs_pop_y 
: ymax
; 
3923 bool wxWindowGTK::DoPopupMenu( wxMenu 
*menu
, int x
, int y 
) 
3925     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
3927     wxCHECK_MSG( menu 
!= NULL
, FALSE
, wxT("invalid popup-menu") ); 
3929     SetInvokingWindow( menu
, this ); 
3935     ClientToScreen( &gs_pop_x
, &gs_pop_y 
); 
3937     bool is_waiting 
= TRUE
; 
3939     gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), 
3941                         GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), 
3942                         (gpointer
)&is_waiting 
); 
3945                   GTK_MENU(menu
->m_menu
), 
3946                   (GtkWidget 
*) NULL
,           // parent menu shell 
3947                   (GtkWidget 
*) NULL
,           // parent menu item 
3948                   wxPopupMenuPositionCallback
,  // function to position it 
3949                   NULL
,                         // client data 
3950                   0,                            // button used to activate it 
3951                   gs_timeLastClick              
// the time of activation 
3956         while (gtk_events_pending()) 
3957             gtk_main_iteration(); 
3963 #endif // wxUSE_MENUS_NATIVE 
3965 #if wxUSE_DRAG_AND_DROP 
3967 void wxWindowGTK::SetDropTarget( wxDropTarget 
*dropTarget 
) 
3969     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
3971     GtkWidget 
*dnd_widget 
= GetConnectWidget(); 
3973     if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget 
); 
3975     if (m_dropTarget
) delete m_dropTarget
; 
3976     m_dropTarget 
= dropTarget
; 
3978     if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget 
); 
3981 #endif // wxUSE_DRAG_AND_DROP 
3983 GtkWidget
* wxWindowGTK::GetConnectWidget() 
3985     GtkWidget 
*connect_widget 
= m_widget
; 
3986     if (m_wxwindow
) connect_widget 
= m_wxwindow
; 
3988     return connect_widget
; 
3991 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow 
*window 
) 
3994         return (window 
== GTK_PIZZA(m_wxwindow
)->bin_window
); 
3996     return (window 
== m_widget
->window
); 
3999 bool wxWindowGTK::SetFont( const wxFont 
&font 
) 
4001     wxCHECK_MSG( m_widget 
!= NULL
, FALSE
, wxT("invalid window") ); 
4003     if (!wxWindowBase::SetFont(font
)) 
4008     wxColour sysbg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE 
); 
4009     if ( sysbg 
== m_backgroundColour 
) 
4011         m_backgroundColour 
= wxNullColour
; 
4013         m_backgroundColour 
= sysbg
; 
4023 void wxWindowGTK::DoCaptureMouse() 
4025     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4027     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4029         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4031         window 
= GetConnectWidget()->window
; 
4033     wxCHECK_RET( window
, _T("CaptureMouse() failed") ); 
4035     wxCursor
* cursor 
= & m_cursor
; 
4037         cursor 
= wxSTANDARD_CURSOR
; 
4039     gdk_pointer_grab( window
, FALSE
, 
4041                          (GDK_BUTTON_PRESS_MASK 
| 
4042                           GDK_BUTTON_RELEASE_MASK 
| 
4043                           GDK_POINTER_MOTION_HINT_MASK 
| 
4044                           GDK_POINTER_MOTION_MASK
), 
4046                       cursor
->GetCursor(), 
4047                       (guint32
)GDK_CURRENT_TIME 
); 
4048     g_captureWindow 
= this; 
4049     g_captureWindowHasMouse 
= TRUE
; 
4052 void wxWindowGTK::DoReleaseMouse() 
4054     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4056     wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") ); 
4058     g_captureWindow 
= (wxWindowGTK
*) NULL
; 
4060     GdkWindow 
*window 
= (GdkWindow
*) NULL
; 
4062         window 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
4064         window 
= GetConnectWidget()->window
; 
4069     gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME 
); 
4073 wxWindow 
*wxWindowBase::GetCapture() 
4075     return (wxWindow 
*)g_captureWindow
; 
4078 bool wxWindowGTK::IsRetained() const 
4083 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
, 
4084       int range
, bool refresh 
) 
4086     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4088     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4090     m_hasScrolling 
= TRUE
; 
4092     if (orient 
== wxHORIZONTAL
) 
4094         float fpos 
= (float)pos
; 
4095         float frange 
= (float)range
; 
4096         float fthumb 
= (float)thumbVisible
; 
4097         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4098         if (fpos 
< 0.0) fpos 
= 0.0; 
4100         if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) && 
4101             (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2)) 
4103             SetScrollPos( orient
, pos
, refresh 
); 
4107         m_oldHorizontalPos 
= fpos
; 
4109         m_hAdjust
->lower 
= 0.0; 
4110         m_hAdjust
->upper 
= frange
; 
4111         m_hAdjust
->value 
= fpos
; 
4112         m_hAdjust
->step_increment 
= 1.0; 
4113         m_hAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4114         m_hAdjust
->page_size 
= fthumb
; 
4118         float fpos 
= (float)pos
; 
4119         float frange 
= (float)range
; 
4120         float fthumb 
= (float)thumbVisible
; 
4121         if (fpos 
> frange
-fthumb
) fpos 
= frange
-fthumb
; 
4122         if (fpos 
< 0.0) fpos 
= 0.0; 
4124         if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) && 
4125             (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2)) 
4127             SetScrollPos( orient
, pos
, refresh 
); 
4131         m_oldVerticalPos 
= fpos
; 
4133         m_vAdjust
->lower 
= 0.0; 
4134         m_vAdjust
->upper 
= frange
; 
4135         m_vAdjust
->value 
= fpos
; 
4136         m_vAdjust
->step_increment 
= 1.0; 
4137         m_vAdjust
->page_increment 
= (float)(wxMax(fthumb
,0)); 
4138         m_vAdjust
->page_size 
= fthumb
; 
4141     if (orient 
== wxHORIZONTAL
) 
4142         gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
4144         gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
4147 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) ) 
4149     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4151     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4153     if (orient 
== wxHORIZONTAL
) 
4155         float fpos 
= (float)pos
; 
4156         if (fpos 
> m_hAdjust
->upper 
- m_hAdjust
->page_size
) fpos 
= m_hAdjust
->upper 
- m_hAdjust
->page_size
; 
4157         if (fpos 
< 0.0) fpos 
= 0.0; 
4158         m_oldHorizontalPos 
= fpos
; 
4160         if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return; 
4161         m_hAdjust
->value 
= fpos
; 
4165         float fpos 
= (float)pos
; 
4166         if (fpos 
> m_vAdjust
->upper 
- m_vAdjust
->page_size
) fpos 
= m_vAdjust
->upper 
- m_vAdjust
->page_size
; 
4167         if (fpos 
< 0.0) fpos 
= 0.0; 
4168         m_oldVerticalPos 
= fpos
; 
4170         if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return; 
4171         m_vAdjust
->value 
= fpos
; 
4174     if (m_wxwindow
->window
) 
4176         if (orient 
== wxHORIZONTAL
) 
4178             gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
), 
4179                 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
4181             gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" ); 
4183             gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
4184                 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this ); 
4188             gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
), 
4189                 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
4191             gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" ); 
4193             gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
4194                 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this ); 
4199 int wxWindowGTK::GetScrollThumb( int orient 
) const 
4201     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4203     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4205     if (orient 
== wxHORIZONTAL
) 
4206         return (int)(m_hAdjust
->page_size
+0.5); 
4208         return (int)(m_vAdjust
->page_size
+0.5); 
4211 int wxWindowGTK::GetScrollPos( int orient 
) const 
4213     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4215     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4217     if (orient 
== wxHORIZONTAL
) 
4218         return (int)(m_hAdjust
->value
+0.5); 
4220         return (int)(m_vAdjust
->value
+0.5); 
4223 int wxWindowGTK::GetScrollRange( int orient 
) const 
4225     wxCHECK_MSG( m_widget 
!= NULL
, 0, wxT("invalid window") ); 
4227     wxCHECK_MSG( m_wxwindow 
!= NULL
, 0, wxT("window needs client area for scrolling") ); 
4229     if (orient 
== wxHORIZONTAL
) 
4230         return (int)(m_hAdjust
->upper
+0.5); 
4232         return (int)(m_vAdjust
->upper
+0.5); 
4235 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) ) 
4237     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
4239     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
4241     // No scrolling requested. 
4242     if ((dx 
== 0) && (dy 
== 0)) return; 
4245     if (!m_updateRegion
.IsEmpty()) 
4247         m_updateRegion
.Offset( dx
, dy 
); 
4251         GetClientSize( &cw
, &ch 
); 
4252         m_updateRegion
.Intersect( 0, 0, cw
, ch 
); 
4255     if (!m_clearRegion
.IsEmpty()) 
4257         m_clearRegion
.Offset( dx
, dy 
); 
4261         GetClientSize( &cw
, &ch 
); 
4262         m_clearRegion
.Intersect( 0, 0, cw
, ch 
); 
4264     m_clipPaintRegion 
= TRUE
; 
4266     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy 
); 
4268     m_clipPaintRegion 
= FALSE
; 
4270     wxCHECK_RET( GTK_PIZZA(m_wxwindow
)->bin_window 
!= NULL
, wxT("window needs client area for scrolling") ); 
4272     gdk_window_scroll( GTK_PIZZA(m_wxwindow
)->bin_window
, dx
, dy 
); 
4274     GTK_PIZZA(m_wxwindow
)->xoffset 
+= dx
; 
4275     GTK_PIZZA(m_wxwindow
)->yoffset 
+= dy
; 
4282 // Find the wxWindow at the current mouse position, also returning the mouse 
4284 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
4286     pt 
= wxGetMousePosition(); 
4287     wxWindow
* found 
= wxFindWindowAtPoint(pt
); 
4291 // Get the current mouse position. 
4292 wxPoint 
wxGetMousePosition() 
4294   /* This crashes when used within wxHelpContext, 
4295      so we have to use the X-specific implementation below. 
4297     GdkModifierType *mask; 
4298     (void) gdk_window_get_pointer(NULL, &x, &y, mask); 
4300     return wxPoint(x, y); 
4304     GdkWindow
* windowAtPtr 
= gdk_window_at_pointer(& x
, & y
); 
4306       return wxPoint(-999, -999); 
4308     Display 
*display 
= GDK_WINDOW_XDISPLAY(windowAtPtr
); 
4309     Window rootWindow 
= RootWindowOfScreen (DefaultScreenOfDisplay(display
)); 
4310     Window rootReturn
, childReturn
; 
4311     int rootX
, rootY
, winX
, winY
; 
4312     unsigned int maskReturn
; 
4314     XQueryPointer (display
, 
4318                    &rootX
, &rootY
, &winX
, &winY
, &maskReturn
); 
4319     return wxPoint(rootX
, rootY
); 
4323 // ---------------------------------------------------------------------------- 
4325 // ---------------------------------------------------------------------------- 
4327 class wxWinModule 
: public wxModule
 
4334     DECLARE_DYNAMIC_CLASS(wxWinModule
) 
4337 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
) 
4339 bool wxWinModule::OnInit() 
4341     // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() ); 
4342     // gdk_gc_set_fill( g_eraseGC, GDK_SOLID ); 
4347 void wxWinModule::OnExit() 
4350         gdk_gc_unref( g_eraseGC 
);