]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/window.cpp
typo in IMPLEMENT_DYNAMIC_CLASS fixed
[wxWidgets.git] / src / gtk1 / window.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
f6bcfd97 2// Name: gtk/window.cpp
c801d85f
KB
3// Purpose:
4// Author: Robert Roebling
c67d8618 5// Id: $Id$
01111366 6// Copyright: (c) 1998 Robert Roebling, Julian Smart
5e0aa05a 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
10
11#ifdef __GNUG__
bfc6fde4 12 #pragma implementation "window.h"
c801d85f
KB
13#endif
14
d02af7bb
JJ
15#ifdef __VMS
16#define XWarpPointer XWARPPOINTER
17#endif
18
c801d85f
KB
19#include "wx/defs.h"
20#include "wx/window.h"
33611ebb 21#include "wx/dcclient.h"
c801d85f
KB
22#include "wx/frame.h"
23#include "wx/app.h"
24#include "wx/layout.h"
25#include "wx/utils.h"
26#include "wx/dialog.h"
27#include "wx/msgdlg.h"
bfc6fde4 28
06cfab17 29#if wxUSE_DRAG_AND_DROP
bfc6fde4 30 #include "wx/dnd.h"
ac57418f 31#endif
bfc6fde4 32
cad880f5 33#if wxUSE_TOOLTIPS
bfc6fde4 34 #include "wx/tooltip.h"
cad880f5 35#endif
bfc6fde4 36
f6bcfd97
BP
37#if wxUSE_CARET
38 #include "wx/caret.h"
39#endif // wxUSE_CARET
40
ab93a576
RD
41#if wxUSE_TEXTCTRL
42#include "wx/textctrl.h"
43#endif
44
30dea054 45#include "wx/menu.h"
d4c99d6f 46#include "wx/statusbr.h"
b4071e91 47#include "wx/intl.h"
3bc755fc 48#include "wx/settings.h"
3069ac4e 49#include "wx/log.h"
b4071e91 50
3ac8d3bc
RR
51#ifdef __WXDEBUG__
52 #include "wx/thread.h"
53#endif
54
b4071e91 55#include <math.h>
c801d85f 56
3ac8d3bc
RR
57#include <gdk/gdk.h>
58#include <gtk/gtk.h>
59#include <gdk/gdkprivate.h>
60#include <gdk/gdkkeysyms.h>
3ac8d3bc 61#include <gdk/gdkx.h>
6bc8a1c8 62
8cb9f0d0
RR
63#include <gtk/gtk.h>
64#include <gtk/gtkprivate.h>
65
66#include "wx/gtk/win_gtk.h"
67
868a2826
RR
68//-----------------------------------------------------------------------------
69// documentation on internals
70//-----------------------------------------------------------------------------
71
72/*
73 I have been asked several times about writing some documentation about
74 the GTK port of wxWindows, especially its internal structures. Obviously,
75 you cannot understand wxGTK without knowing a little about the GTK, but
47d67540 76 some more information about what the wxWindow, which is the base class
868a2826 77 for all other window classes, does seems required as well.
47d67540 78
30760ce7
RR
79 I)
80
868a2826 81 What does wxWindow do? It contains the common interface for the following
e380f72b 82 jobs of its descendants:
47d67540 83
868a2826 84 1) Define the rudimentary behaviour common to all window classes, such as
e380f72b
RR
85 resizing, intercepting user input (so as to make it possible to use these
86 events for special purposes in a derived class), window names etc.
868a2826
RR
87
88 2) Provide the possibility to contain and manage children, if the derived
89 class is allowed to contain children, which holds true for those window
e380f72b 90 classes which do not display a native GTK widget. To name them, these
868a2826 91 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
47d67540 92 work classes are a special case and are handled a bit differently from
e380f72b 93 the rest. The same holds true for the wxNotebook class.
47d67540 94
868a2826
RR
95 3) Provide the possibility to draw into a client area of a window. This,
96 too, only holds true for classes that do not display a native GTK widget
97 as above.
47d67540 98
e380f72b
RR
99 4) Provide the entire mechanism for scrolling widgets. This actual inter-
100 face for this is usually in wxScrolledWindow, but the GTK implementation
868a2826 101 is in this class.
47d67540 102
868a2826
RR
103 5) A multitude of helper or extra methods for special purposes, such as
104 Drag'n'Drop, managing validators etc.
47d67540 105
30760ce7
RR
106 6) Display a border (sunken, raised, simple or none).
107
e380f72b
RR
108 Normally one might expect, that one wxWindows window would always correspond
109 to one GTK widget. Under GTK, there is no such allround widget that has all
868a2826
RR
110 the functionality. Moreover, the GTK defines a client area as a different
111 widget from the actual widget you are handling. Last but not least some
112 special classes (e.g. wxFrame) handle different categories of widgets and
113 still have the possibility to draw something in the client area.
114 It was therefore required to write a special purpose GTK widget, that would
115 represent a client area in the sense of wxWindows capable to do the jobs
116 2), 3) and 4). I have written this class and it resides in win_gtk.c of
117 this directory.
47d67540 118
868a2826 119 All windows must have a widget, with which they interact with other under-
e380f72b 120 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
868a2826 121 thw wxWindow class has a member variable called m_widget which holds a
e380f72b
RR
122 pointer to this widget. When the window class represents a GTK native widget,
123 this is (in most cases) the only GTK widget the class manages. E.g. the
124 wxStatitText class handles only a GtkLabel widget a pointer to which you
125 can find in m_widget (defined in wxWindow)
8bbe427f 126
e380f72b 127 When the class has a client area for drawing into and for containing children
da048e3d 128 it has to handle the client area widget (of the type GtkPizza, defined in
8bbe427f
VZ
129 win_gtk.c), but there could be any number of widgets, handled by a class
130 The common rule for all windows is only, that the widget that interacts with
131 the rest of GTK must be referenced in m_widget and all other widgets must be
132 children of this widget on the GTK level. The top-most widget, which also
133 represents the client area, must be in the m_wxwindow field and must be of
da048e3d 134 the type GtkPizza.
47d67540 135
868a2826
RR
136 As I said, the window classes that display a GTK native widget only have
137 one widget, so in the case of e.g. the wxButton class m_widget holds a
138 pointer to a GtkButton widget. But windows with client areas (for drawing
139 and children) have a m_widget field that is a pointer to a GtkScrolled-
da048e3d 140 Window and a m_wxwindow field that is pointer to a GtkPizza and this
868a2826 141 one is (in the GTK sense) a child of the GtkScrolledWindow.
47d67540 142
868a2826
RR
143 If the m_wxwindow field is set, then all input to this widget is inter-
144 cepted and sent to the wxWindows class. If not, all input to the widget
145 that gets pointed to by m_widget gets intercepted and sent to the class.
148cd9b6 146
30760ce7 147 II)
148cd9b6 148
30760ce7
RR
149 The design of scrolling in wxWindows is markedly different from that offered
150 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
151 clicking on a scrollbar belonging to scrolled window will inevitably move
152 the window. In wxWindows, the scrollbar will only emit an event, send this
153 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
da048e3d 154 which actually moves the window and its subchildren. Note that GtkPizza
30760ce7
RR
155 memorizes how much it has been scrolled but that wxWindows forgets this
156 so that the two coordinates systems have to be kept in synch. This is done
da048e3d 157 in various places using the pizza->xoffset and pizza->yoffset values.
148cd9b6
VZ
158
159 III)
160
30760ce7
RR
161 Singularily the most broken code in GTK is the code that is supposes to
162 inform subwindows (child windows) about new positions. Very often, duplicate
163 events are sent without changes in size or position, equally often no
164 events are sent at all (All this is due to a bug in the GtkContainer code
165 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
166 GTK's own system and it simply waits for size events for toplevel windows
167 and then iterates down the respective size events to all window. This has
168 the disadvantage, that windows might get size events before the GTK widget
169 actually has the reported size. This doesn't normally pose any problem, but
3017f78d 170 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
30760ce7
RR
171 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
172 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
173 window that is used for OpenGl output really has that size (as reported by
174 GTK).
175
176 IV)
148cd9b6 177
30760ce7
RR
178 If someone at some point of time feels the immense desire to have a look at,
179 change or attempt to optimse the Refresh() logic, this person will need an
180 intimate understanding of what a "draw" and what an "expose" events are and
181 what there are used for, in particular when used in connection with GTK's
182 own windowless widgets. Beware.
148cd9b6 183
30760ce7 184 V)
148cd9b6 185
30760ce7
RR
186 Cursors, too, have been a constant source of pleasure. The main difficulty
187 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
188 for the parent. To prevent this from doing too much harm, I use idle time
189 to set the cursor over and over again, starting from the toplevel windows
190 and ending with the youngest generation (speaking of parent and child windows).
191 Also don't forget that cursors (like much else) are connected to GdkWindows,
192 not GtkWidgets and that the "window" field of a GtkWidget might very well
148cd9b6 193 point to the GdkWindow of the parent widget (-> "window less widget") and
30760ce7 194 that the two obviously have very different meanings.
868a2826
RR
195
196*/
197
f03fc89f
VZ
198//-----------------------------------------------------------------------------
199// data
200//-----------------------------------------------------------------------------
201
202extern wxList wxPendingDelete;
203extern bool g_blockEventsOnDrag;
204extern bool g_blockEventsOnScroll;
238d735d 205extern wxCursor g_globalCursor;
f68586e5 206
1e6feb95
VZ
207// mouse capture state: the window which has it and if the mouse is currently
208// inside it
209static wxWindowGTK *g_captureWindow = (wxWindowGTK*) NULL;
210static bool g_captureWindowHasMouse = FALSE;
211
212/* extern */ wxWindowGTK *g_focusWindow = (wxWindowGTK*) NULL;
213
214// the last window which had the focus - this is normally never NULL (except
215// if we never had focus at all) as even when g_focusWindow is NULL it still
216// keeps its previous value
217static wxWindowGTK *g_focusWindowLast = (wxWindowGTK *)NULL;
148cd9b6 218
e8c12a53
VS
219// the frame that is currently active (i.e. its child has focus). It is
220// used to generate wxActivateEvents
221static wxWindowGTK *g_activeFrame = (wxWindowGTK *)NULL;
222static bool g_activeFrameLostFocus = FALSE;
223
148cd9b6
VZ
224// if we detect that the app has got/lost the focus, we set this variable to
225// either TRUE or FALSE and an activate event will be sent during the next
226// OnIdle() call and it is reset to -1: this value means that we shouldn't
227// send any activate events at all
228static int g_sendActivateEvent = -1;
f03fc89f
VZ
229
230/* hack: we need something to pass to gtk_menu_popup, so we store the time of
231 the last click here */
232static guint32 gs_timeLastClick = 0;
233
3ac8d3bc
RR
234extern bool g_mainThreadLocked;
235
2e563988
RR
236//-----------------------------------------------------------------------------
237// debug
238//-----------------------------------------------------------------------------
239
d52e91c9 240#ifndef __WXGTK20__
a56fcaaf 241#define DISABLE_STYLE_IF_BROKEN_THEME 1
d52e91c9 242#endif
a56fcaaf 243
2e563988
RR
244#ifdef __WXDEBUG__
245
c6e62f74
KB
246#if wxUSE_THREADS
247# define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
248#else
249# define DEBUG_MAIN_THREAD
250#endif
3ac8d3bc 251
2e563988
RR
252static gint gtk_debug_focus_in_callback( GtkWidget *WXUNUSED(widget),
253 GdkEvent *WXUNUSED(event),
014b0d06 254 const wxChar *WXUNUSED(name) )
2e563988 255{
053dcf1a 256/*
167e3718
VZ
257 static bool s_done = FALSE;
258 if ( !s_done )
259 {
260 wxLog::AddTraceMask("focus");
261 s_done = TRUE;
262 }
223d09f6 263 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
053dcf1a 264*/
2e563988
RR
265
266 return FALSE;
267}
268
269void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window )
270{
9a8c7620
VZ
271 // suppress warnings about gtk_debug_focus_in_callback being unused with
272 // this "if ( 0 )"
273 if ( 0 )
274 {
275 wxString tmp = name;
276 tmp += wxT(" FROM ");
277 tmp += window;
2e563988 278
9a8c7620 279 wxChar *s = new wxChar[tmp.Length()+1];
2e563988 280
9a8c7620 281 wxStrcpy( s, tmp );
2e563988 282
9a8c7620
VZ
283 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
284 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback), (gpointer)s );
285 }
2e563988
RR
286}
287
559d79aa
BJ
288#else
289#define DEBUG_MAIN_THREAD
f03fc89f 290#endif // Debug
ff8bfdbb 291
85eb36c2
RR
292//-----------------------------------------------------------------------------
293// missing gdk functions
294//-----------------------------------------------------------------------------
295
296void
297gdk_window_warp_pointer (GdkWindow *window,
c50f1fb9
VZ
298 gint x,
299 gint y)
85eb36c2 300{
dd00f3f6 301#ifndef __WXGTK20__
85eb36c2 302 GdkWindowPrivate *priv;
dd00f3f6 303#endif
c50f1fb9 304
85eb36c2 305 if (!window)
27df579a 306 window = GDK_ROOT_PARENT();
c50f1fb9 307
dd00f3f6
OK
308#ifdef __WXGTK20__
309 if (!GDK_WINDOW_DESTROYED(window))
310 {
311 XWarpPointer (GDK_WINDOW_XDISPLAY(window),
312 None, /* not source window -> move from anywhere */
313 GDK_WINDOW_XID(window), /* dest window */
314 0, 0, 0, 0, /* not source window -> move from anywhere */
315 x, y );
316 }
317#else
85eb36c2 318 priv = (GdkWindowPrivate*) window;
c50f1fb9 319
85eb36c2
RR
320 if (!priv->destroyed)
321 {
c50f1fb9 322 XWarpPointer (priv->xdisplay,
85eb36c2 323 None, /* not source window -> move from anywhere */
c50f1fb9 324 priv->xwindow, /* dest window */
85eb36c2 325 0, 0, 0, 0, /* not source window -> move from anywhere */
c50f1fb9 326 x, y );
85eb36c2 327 }
dd00f3f6 328#endif
85eb36c2
RR
329}
330
acfd422a 331//-----------------------------------------------------------------------------
a2053b27 332// idle system
acfd422a
RR
333//-----------------------------------------------------------------------------
334
a2053b27
RR
335extern void wxapp_install_idle_handler();
336extern bool g_isIdle;
337
ed673c6a
RR
338//-----------------------------------------------------------------------------
339// local code (see below)
340//-----------------------------------------------------------------------------
341
f6bcfd97 342// returns the child of win which currently has focus or NULL if not found
1e6feb95 343//
fc71ef6e 344// Note: can't be static, needed by textctrl.cpp.
3379ed37 345wxWindow *wxFindFocusedChild(wxWindowGTK *win)
f6bcfd97 346{
3379ed37 347 wxWindow *winFocus = wxWindowGTK::FindFocus();
f6bcfd97 348 if ( !winFocus )
3379ed37 349 return (wxWindow *)NULL;
f6bcfd97
BP
350
351 if ( winFocus == win )
3379ed37 352 return (wxWindow *)win;
f6bcfd97
BP
353
354 for ( wxWindowList::Node *node = win->GetChildren().GetFirst();
355 node;
356 node = node->GetNext() )
357 {
3379ed37 358 wxWindow *child = wxFindFocusedChild(node->GetData());
f6bcfd97
BP
359 if ( child )
360 return child;
361 }
362
3379ed37 363 return (wxWindow *)NULL;
f6bcfd97
BP
364}
365
e8c12a53
VS
366// Returns toplevel grandparent of given window:
367static wxWindowGTK* wxGetTopLevelParent(wxWindowGTK *win)
368{
369 wxWindowGTK *p = win;
370 while (p && !p->IsTopLevel())
371 p = p->GetParent();
372 return p;
373}
374
375
1e6feb95 376static void draw_frame( GtkWidget *widget, wxWindowGTK *win )
ed673c6a 377{
1e6feb95
VZ
378 // wxUniversal widgets draw the borders and scrollbars themselves
379#ifndef __WXUNIVERSAL__
ed673c6a
RR
380 if (!win->m_hasVMT)
381 return;
382
383 int dw = 0;
384 int dh = 0;
385
5b8a521e 386 if (win->m_hasScrolling)
ed673c6a 387 {
beab25bd 388 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(widget);
2daa0ce9 389
beab25bd
RR
390 GtkRequisition vscroll_req;
391 vscroll_req.width = 2;
392 vscroll_req.height = 2;
393 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
394 (scroll_window->vscrollbar, &vscroll_req );
2daa0ce9 395
beab25bd
RR
396 GtkRequisition hscroll_req;
397 hscroll_req.width = 2;
398 hscroll_req.height = 2;
399 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
400 (scroll_window->hscrollbar, &hscroll_req );
9000c624 401
beab25bd 402 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget) );
ed673c6a 403
beab25bd
RR
404 if (scroll_window->vscrollbar_visible)
405 {
406 dw += vscroll_req.width;
407 dw += scroll_class->scrollbar_spacing;
408 }
ed673c6a 409
beab25bd
RR
410 if (scroll_window->hscrollbar_visible)
411 {
412 dh += hscroll_req.height;
413 dh += scroll_class->scrollbar_spacing;
414 }
415}
ed673c6a
RR
416
417 int dx = 0;
418 int dy = 0;
419 if (GTK_WIDGET_NO_WINDOW (widget))
420 {
421 dx += widget->allocation.x;
422 dy += widget->allocation.y;
423 }
424
425 if (win->HasFlag(wxRAISED_BORDER))
426 {
427 gtk_draw_shadow( widget->style,
428 widget->window,
429 GTK_STATE_NORMAL,
430 GTK_SHADOW_OUT,
431 dx, dy,
07f5b19a 432 widget->allocation.width-dw, widget->allocation.height-dh );
ed673c6a
RR
433 return;
434 }
435
436 if (win->HasFlag(wxSUNKEN_BORDER))
437 {
438 gtk_draw_shadow( widget->style,
439 widget->window,
440 GTK_STATE_NORMAL,
441 GTK_SHADOW_IN,
442 dx, dy,
07f5b19a 443 widget->allocation.width-dw, widget->allocation.height-dh );
ed673c6a
RR
444 return;
445 }
148cd9b6 446
ed673c6a
RR
447 if (win->HasFlag(wxSIMPLE_BORDER))
448 {
449 GdkGC *gc;
b02da6b1 450 gc = gdk_gc_new( widget->window );
ed673c6a 451 gdk_gc_set_foreground( gc, &widget->style->black );
148cd9b6 452 gdk_draw_rectangle( widget->window, gc, FALSE,
ed673c6a 453 dx, dy,
07f5b19a 454 widget->allocation.width-dw-1, widget->allocation.height-dh-1 );
ed673c6a
RR
455 gdk_gc_unref( gc );
456 return;
457 }
1e6feb95 458#endif // __WXUNIVERSAL__
ed673c6a
RR
459}
460
461//-----------------------------------------------------------------------------
462// "expose_event" of m_widget
463//-----------------------------------------------------------------------------
464
1e6feb95 465gint gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindowGTK *win )
ed673c6a 466{
b6fa52db 467 if (gdk_event->count > 0) return FALSE;
1e6feb95 468
ed673c6a 469 draw_frame( widget, win );
1e6feb95 470
b6fa52db 471 return TRUE;
ed673c6a
RR
472}
473
474//-----------------------------------------------------------------------------
147bc491 475// "draw" of m_widget
ed673c6a
RR
476//-----------------------------------------------------------------------------
477
1e6feb95 478static void gtk_window_own_draw_callback( GtkWidget *widget, GdkRectangle *WXUNUSED(rect), wxWindowGTK *win )
ed673c6a
RR
479{
480 draw_frame( widget, win );
481}
482
c5b42c87 483//-----------------------------------------------------------------------------
da048e3d 484// key code mapping routines
c5b42c87
RR
485//-----------------------------------------------------------------------------
486
2d451165 487static long map_to_unmodified_wx_keysym( GdkEventKey *event )
c5b42c87 488{
654d9052
VZ
489 // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string
490 // but only event->keyval which is quite useless to us, so remember
491 // the last character from GDK_KEY_PRESS and resue it as last resort
492 //
493 // NB: should be MT-neutral as always called from main thread only
494 static struct
495 {
496 KeySym keysym;
497 long keycode;
498 } s_lastKeyPress = { 0, 0 };
499
2d451165 500 KeySym keysym = event->keyval;
f17393f1 501 long key_code;
c5b42c87 502
654d9052 503 switch ( keysym )
c5b42c87
RR
504 {
505 case GDK_Shift_L:
506 case GDK_Shift_R: key_code = WXK_SHIFT; break;
507 case GDK_Control_L:
508 case GDK_Control_R: key_code = WXK_CONTROL; break;
c50f1fb9
VZ
509 case GDK_Meta_L:
510 case GDK_Meta_R:
511 case GDK_Alt_L:
512 case GDK_Alt_R:
513 case GDK_Super_L:
514 case GDK_Super_R: key_code = WXK_ALT; break;
c5b42c87
RR
515 case GDK_Menu: key_code = WXK_MENU; break;
516 case GDK_Help: key_code = WXK_HELP; break;
517 case GDK_BackSpace: key_code = WXK_BACK; break;
518 case GDK_ISO_Left_Tab:
519 case GDK_Tab: key_code = WXK_TAB; break;
520 case GDK_Linefeed: key_code = WXK_RETURN; break;
521 case GDK_Clear: key_code = WXK_CLEAR; break;
522 case GDK_Return: key_code = WXK_RETURN; break;
523 case GDK_Pause: key_code = WXK_PAUSE; break;
524 case GDK_Scroll_Lock: key_code = WXK_SCROLL; break;
525 case GDK_Escape: key_code = WXK_ESCAPE; break;
526 case GDK_Delete: key_code = WXK_DELETE; break;
527 case GDK_Home: key_code = WXK_HOME; break;
528 case GDK_Left: key_code = WXK_LEFT; break;
529 case GDK_Up: key_code = WXK_UP; break;
530 case GDK_Right: key_code = WXK_RIGHT; break;
531 case GDK_Down: key_code = WXK_DOWN; break;
532 case GDK_Prior: key_code = WXK_PRIOR; break;
533// case GDK_Page_Up: key_code = WXK_PAGEUP; break;
534 case GDK_Next: key_code = WXK_NEXT; break;
535// case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
536 case GDK_End: key_code = WXK_END; break;
537 case GDK_Begin: key_code = WXK_HOME; break;
538 case GDK_Select: key_code = WXK_SELECT; break;
539 case GDK_Print: key_code = WXK_PRINT; break;
540 case GDK_Execute: key_code = WXK_EXECUTE; break;
541 case GDK_Insert: key_code = WXK_INSERT; break;
542 case GDK_Num_Lock: key_code = WXK_NUMLOCK; break;
543
544 case GDK_KP_0: key_code = WXK_NUMPAD0; break;
545 case GDK_KP_1: key_code = WXK_NUMPAD1; break;
546 case GDK_KP_2: key_code = WXK_NUMPAD2; break;
547 case GDK_KP_3: key_code = WXK_NUMPAD3; break;
548 case GDK_KP_4: key_code = WXK_NUMPAD4; break;
549 case GDK_KP_5: key_code = WXK_NUMPAD5; break;
550 case GDK_KP_6: key_code = WXK_NUMPAD6; break;
551 case GDK_KP_7: key_code = WXK_NUMPAD7; break;
552 case GDK_KP_8: key_code = WXK_NUMPAD8; break;
553 case GDK_KP_9: key_code = WXK_NUMPAD9; break;
554 case GDK_KP_Space: key_code = WXK_NUMPAD_SPACE; break;
555 case GDK_KP_Tab: key_code = WXK_NUMPAD_TAB; break;
556 case GDK_KP_Enter: key_code = WXK_NUMPAD_ENTER; break;
557 case GDK_KP_F1: key_code = WXK_NUMPAD_F1; break;
558 case GDK_KP_F2: key_code = WXK_NUMPAD_F2; break;
559 case GDK_KP_F3: key_code = WXK_NUMPAD_F3; break;
560 case GDK_KP_F4: key_code = WXK_NUMPAD_F4; break;
561 case GDK_KP_Home: key_code = WXK_NUMPAD_HOME; break;
562 case GDK_KP_Left: key_code = WXK_NUMPAD_LEFT; break;
563 case GDK_KP_Up: key_code = WXK_NUMPAD_UP; break;
564 case GDK_KP_Right: key_code = WXK_NUMPAD_RIGHT; break;
565 case GDK_KP_Down: key_code = WXK_NUMPAD_DOWN; break;
566 case GDK_KP_Prior: key_code = WXK_NUMPAD_PRIOR; break;
567// case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
21884766 568 case GDK_KP_Next: key_code = WXK_NUMPAD_NEXT; break;
c5b42c87
RR
569// case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
570 case GDK_KP_End: key_code = WXK_NUMPAD_END; break;
571 case GDK_KP_Begin: key_code = WXK_NUMPAD_BEGIN; break;
572 case GDK_KP_Insert: key_code = WXK_NUMPAD_INSERT; break;
573 case GDK_KP_Delete: key_code = WXK_NUMPAD_DELETE; break;
574 case GDK_KP_Equal: key_code = WXK_NUMPAD_EQUAL; break;
575 case GDK_KP_Multiply: key_code = WXK_NUMPAD_MULTIPLY; break;
576 case GDK_KP_Add: key_code = WXK_NUMPAD_ADD; break;
577 case GDK_KP_Separator: key_code = WXK_NUMPAD_SEPARATOR; break;
578 case GDK_KP_Subtract: key_code = WXK_NUMPAD_SUBTRACT; break;
579 case GDK_KP_Decimal: key_code = WXK_NUMPAD_DECIMAL; break;
580 case GDK_KP_Divide: key_code = WXK_NUMPAD_DIVIDE; break;
c50f1fb9 581
c5b42c87
RR
582 case GDK_F1: key_code = WXK_F1; break;
583 case GDK_F2: key_code = WXK_F2; break;
584 case GDK_F3: key_code = WXK_F3; break;
585 case GDK_F4: key_code = WXK_F4; break;
586 case GDK_F5: key_code = WXK_F5; break;
587 case GDK_F6: key_code = WXK_F6; break;
588 case GDK_F7: key_code = WXK_F7; break;
589 case GDK_F8: key_code = WXK_F8; break;
590 case GDK_F9: key_code = WXK_F9; break;
591 case GDK_F10: key_code = WXK_F10; break;
592 case GDK_F11: key_code = WXK_F11; break;
593 case GDK_F12: key_code = WXK_F12; break;
594 default:
654d9052
VZ
595 {
596 // do we have the translation?
597 if ( event->length == 1 )
c5b42c87 598 {
654d9052 599 keysym = (KeySym)event->string[0];
f17393f1 600 }
654d9052
VZ
601 else if ( (keysym & 0xFF) != keysym )
602 {
603 // non ASCII key, what to do?
604
605 if ( event->type == GDK_KEY_RELEASE )
606 {
607 // reuse the one from the last keypress if any
608 if ( keysym == s_lastKeyPress.keysym )
609 {
610 key_code = s_lastKeyPress.keycode;
611
612 // skip "return 0"
613 break;
614 }
615 }
616
617 // ignore this one, we don't know it
618 return 0;
619 }
620 //else: ASCII key, ok
621
622 guint upper = gdk_keyval_to_upper( (guint)keysym );
623 key_code = upper ? upper : keysym;
624
625 if ( event->type == GDK_KEY_PRESS )
f17393f1 626 {
654d9052
VZ
627 // remember it to be reused below later
628 s_lastKeyPress.keysym = keysym;
629 s_lastKeyPress.keycode = key_code;
c5b42c87 630 }
654d9052 631 }
c5b42c87
RR
632 }
633
f17393f1 634 return key_code;
c5b42c87
RR
635}
636
2d451165 637static long map_to_wx_keysym( GdkEventKey *event )
c5b42c87 638{
2d451165 639 KeySym keysym = event->keyval;
c5b42c87
RR
640 guint key_code = 0;
641
642 switch (keysym)
643 {
c5b42c87
RR
644 case GDK_Menu: key_code = WXK_MENU; break;
645 case GDK_Help: key_code = WXK_HELP; break;
646 case GDK_BackSpace: key_code = WXK_BACK; break;
647 case GDK_ISO_Left_Tab:
648 case GDK_Tab: key_code = WXK_TAB; break;
649 case GDK_Linefeed: key_code = WXK_RETURN; break;
650 case GDK_Clear: key_code = WXK_CLEAR; break;
651 case GDK_Return: key_code = WXK_RETURN; break;
652 case GDK_Pause: key_code = WXK_PAUSE; break;
653 case GDK_Scroll_Lock: key_code = WXK_SCROLL; break;
654 case GDK_Escape: key_code = WXK_ESCAPE; break;
655 case GDK_Delete: key_code = WXK_DELETE; break;
656 case GDK_Home: key_code = WXK_HOME; break;
657 case GDK_Left: key_code = WXK_LEFT; break;
658 case GDK_Up: key_code = WXK_UP; break;
659 case GDK_Right: key_code = WXK_RIGHT; break;
660 case GDK_Down: key_code = WXK_DOWN; break;
661 case GDK_Prior: key_code = WXK_PRIOR; break;
662// case GDK_Page_Up: key_code = WXK_PAGEUP; break;
663 case GDK_Next: key_code = WXK_NEXT; break;
664// case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
665 case GDK_End: key_code = WXK_END; break;
666 case GDK_Begin: key_code = WXK_HOME; break;
667 case GDK_Select: key_code = WXK_SELECT; break;
668 case GDK_Print: key_code = WXK_PRINT; break;
669 case GDK_Execute: key_code = WXK_EXECUTE; break;
670 case GDK_Insert: key_code = WXK_INSERT; break;
671 case GDK_Num_Lock: key_code = WXK_NUMLOCK; break;
672
673 case GDK_KP_0: key_code = '0'; break;
674 case GDK_KP_1: key_code = '1'; break;
675 case GDK_KP_2: key_code = '2'; break;
676 case GDK_KP_3: key_code = '3'; break;
677 case GDK_KP_4: key_code = '4'; break;
678 case GDK_KP_5: key_code = '5'; break;
679 case GDK_KP_6: key_code = '6'; break;
680 case GDK_KP_7: key_code = '7'; break;
681 case GDK_KP_8: key_code = '8'; break;
682 case GDK_KP_9: key_code = '9'; break;
683 case GDK_KP_Space: key_code = ' '; break;
684 case GDK_KP_Tab: key_code = WXK_TAB; break; /* or '\t' ??? */
685 case GDK_KP_Enter: key_code = WXK_RETURN; break; /* or '\r' ??? */
686 case GDK_KP_F1: key_code = WXK_NUMPAD_F1; break;
687 case GDK_KP_F2: key_code = WXK_NUMPAD_F2; break;
688 case GDK_KP_F3: key_code = WXK_NUMPAD_F3; break;
689 case GDK_KP_F4: key_code = WXK_NUMPAD_F4; break;
690 case GDK_KP_Home: key_code = WXK_HOME; break;
691 case GDK_KP_Left: key_code = WXK_LEFT; break;
692 case GDK_KP_Up: key_code = WXK_UP; break;
693 case GDK_KP_Right: key_code = WXK_RIGHT; break;
694 case GDK_KP_Down: key_code = WXK_DOWN; break;
695 case GDK_KP_Prior: key_code = WXK_PRIOR; break;
696// case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
21884766 697 case GDK_KP_Next: key_code = WXK_NEXT; break;
c5b42c87
RR
698// case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
699 case GDK_KP_End: key_code = WXK_END; break;
700 case GDK_KP_Begin: key_code = WXK_HOME; break;
701 case GDK_KP_Insert: key_code = WXK_INSERT; break;
702 case GDK_KP_Delete: key_code = WXK_DELETE; break;
703 case GDK_KP_Equal: key_code = '='; break;
704 case GDK_KP_Multiply: key_code = '*'; break;
705 case GDK_KP_Add: key_code = '+'; break;
706 case GDK_KP_Separator: key_code = ','; break;
707 case GDK_KP_Subtract: key_code = '-'; break;
708 case GDK_KP_Decimal: key_code = '.'; break;
709 case GDK_KP_Divide: key_code = '/'; break;
c50f1fb9 710
c5b42c87
RR
711 case GDK_F1: key_code = WXK_F1; break;
712 case GDK_F2: key_code = WXK_F2; break;
713 case GDK_F3: key_code = WXK_F3; break;
714 case GDK_F4: key_code = WXK_F4; break;
715 case GDK_F5: key_code = WXK_F5; break;
716 case GDK_F6: key_code = WXK_F6; break;
717 case GDK_F7: key_code = WXK_F7; break;
718 case GDK_F8: key_code = WXK_F8; break;
719 case GDK_F9: key_code = WXK_F9; break;
720 case GDK_F10: key_code = WXK_F10; break;
721 case GDK_F11: key_code = WXK_F11; break;
722 case GDK_F12: key_code = WXK_F12; break;
723 default:
f17393f1
VZ
724 if (event->length == 1)
725 {
29d18d69
VZ
726 key_code = (unsigned char)*event->string;
727 }
728 else if ((keysym & 0xFF) == keysym)
729 {
730 key_code = (guint)keysym;
c5b42c87 731 }
c5b42c87
RR
732 }
733
f17393f1 734 return key_code;
c5b42c87
RR
735}
736
47c93b63
RR
737//-----------------------------------------------------------------------------
738// "size_request" of m_widget
739//-----------------------------------------------------------------------------
740
741static void gtk_window_size_request_callback( GtkWidget *widget, GtkRequisition *requisition, wxWindow *win )
742{
743 int w,h;
744 win->GetSize( &w, &h );
745 if (w < 2) w = 2;
746 if (h < 2) h = 2;
1e6feb95 747
47c93b63
RR
748 requisition->height = h;
749 requisition->width = w;
750}
751
c801d85f 752//-----------------------------------------------------------------------------
034be888 753// "expose_event" of m_wxwindow
c801d85f
KB
754//-----------------------------------------------------------------------------
755
1e6feb95
VZ
756static int gtk_window_expose_callback( GtkWidget *widget,
757 GdkEventExpose *gdk_event,
758 wxWindow *win )
47d67540 759{
3ac8d3bc
RR
760 DEBUG_MAIN_THREAD
761
b6fa52db
RR
762 if (g_isIdle)
763 wxapp_install_idle_handler();
1e6feb95 764
40c70187 765/*
8cb9f0d0 766 if (win->GetName() == wxT("panel"))
3d2d8da1
RR
767 {
768 wxPrintf( wxT("OnExpose from ") );
769 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
770 wxPrintf( win->GetClassInfo()->GetClassName() );
771 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
772 (int)gdk_event->area.y,
773 (int)gdk_event->area.width,
774 (int)gdk_event->area.height );
775 }
40c70187 776*/
1e6feb95 777
2bc6945a 778 GtkPizza *pizza = GTK_PIZZA (widget);
a2d93e73 779
a2d93e73
JS
780 if (win->GetThemeEnabled())
781 {
782 wxWindow *parent = win->GetParent();
783 while (parent && !parent->IsTopLevel())
784 parent = parent->GetParent();
785 if (!parent)
786 parent = win;
787
90350682
VZ
788 gtk_paint_flat_box (parent->m_widget->style,
789 pizza->bin_window,
790 GTK_STATE_NORMAL,
791 GTK_SHADOW_NONE,
792 &gdk_event->area,
793 parent->m_widget,
794 (char *)"base",
795 0, 0, -1, -1);
2bc6945a 796 }
1e6feb95 797
2bc6945a
RR
798 win->GetUpdateRegion().Union( gdk_event->area.x,
799 gdk_event->area.y,
800 gdk_event->area.width,
801 gdk_event->area.height );
0e09f76e 802
beab25bd
RR
803 // Actually send the various events based on the
804 // current update region.
9cc7121f 805 if (gdk_event->count == 0)
beab25bd 806 win->GtkSendPaintEvents();
f7a11f8c 807
b6fa52db
RR
808 return TRUE;
809}
810
811//-----------------------------------------------------------------------------
812// "event" of m_wxwindow
813//-----------------------------------------------------------------------------
814
beab25bd
RR
815// GTK thinks it is clever and filters out a certain amount of "unneeded"
816// expose events. We need them, of course, so we override the main event
817// procedure in GtkWidget by giving our own handler for all system events.
818// There, we look for expose events ourselves whereas all other events are
819// handled normally.
b6fa52db 820
1e6feb95
VZ
821gint gtk_window_event_event_callback( GtkWidget *widget,
822 GdkEventExpose *event,
823 wxWindow *win )
b6fa52db
RR
824{
825 if (event->type == GDK_EXPOSE)
826 {
827 gint ret = gtk_window_expose_callback( widget, event, win );
828 return ret;
829 }
830
b6fa52db 831 return FALSE;
362c6693 832}
c801d85f
KB
833
834//-----------------------------------------------------------------------------
034be888 835// "draw" of m_wxwindow
2f2aa628 836//-----------------------------------------------------------------------------
c801d85f 837
beab25bd
RR
838// This callback is a complete replacement of the gtk_pizza_draw() function,
839// which disabled.
b6fa52db 840
1e6feb95
VZ
841static void gtk_window_draw_callback( GtkWidget *widget,
842 GdkRectangle *rect,
843 wxWindow *win )
47d67540 844{
3ac8d3bc
RR
845 DEBUG_MAIN_THREAD
846
c50f1fb9 847 if (g_isIdle)
a2053b27 848 wxapp_install_idle_handler();
2d19ad25 849
beab25bd
RR
850 // The wxNO_FULL_REPAINT_ON_RESIZE flag only works if
851 // there are no child windows.
e22454be
RR
852 if ((win->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE)) &&
853 (win->GetChildren().GetCount() == 0))
854 {
855 return;
856 }
2d19ad25 857
40c70187 858/*
8cb9f0d0 859 if (win->GetName() == wxT("panel"))
3d2d8da1
RR
860 {
861 wxPrintf( wxT("OnDraw from ") );
862 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
863 wxPrintf( win->GetClassInfo()->GetClassName() );
864 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
865 (int)rect->y,
866 (int)rect->width,
867 (int)rect->height );
868 }
40c70187 869*/
1e6feb95 870
b420fb6a 871 GtkPizza *pizza = GTK_PIZZA (widget);
2bc6945a 872
9cc7121f 873 if (win->GetThemeEnabled())
789dbcd4 874 {
9cc7121f
RR
875 wxWindow *parent = win->GetParent();
876 while (parent && !parent->IsTopLevel())
789dbcd4 877 parent = parent->GetParent();
9cc7121f
RR
878 if (!parent)
879 parent = win;
880
90350682
VZ
881 gtk_paint_flat_box (parent->m_widget->style,
882 pizza->bin_window,
883 GTK_STATE_NORMAL,
884 GTK_SHADOW_NONE,
885 rect,
886 parent->m_widget,
887 (char *)"base",
888 0, 0, -1, -1);
789dbcd4 889 }
1e6feb95
VZ
890
891
9cc7121f
RR
892 if (!(GTK_WIDGET_APP_PAINTABLE (widget)) &&
893 (pizza->clear_on_draw))
894 {
895 gdk_window_clear_area( pizza->bin_window,
b420fb6a 896 rect->x, rect->y, rect->width, rect->height);
9cc7121f 897 }
1e6feb95 898
9cc7121f 899 win->GetUpdateRegion().Union( rect->x, rect->y, rect->width, rect->height );
148cd9b6 900
beab25bd
RR
901 // Actually send the various events based on the
902 // current update region.
903 win->GtkSendPaintEvents();
1e6feb95 904
beab25bd 905 // Redraw child widgets
e22454be
RR
906 GList *children = pizza->children;
907 while (children)
908 {
beab25bd
RR
909 GtkPizzaChild *child = (GtkPizzaChild*) children->data;
910 children = children->next;
b420fb6a 911
beab25bd
RR
912 GdkRectangle child_area;
913 if (gtk_widget_intersect (child->widget, rect, &child_area))
914 {
915 gtk_widget_draw (child->widget, &child_area /* (GdkRectangle*) NULL*/ );
916 }
e22454be 917 }
362c6693 918}
c801d85f
KB
919
920//-----------------------------------------------------------------------------
b292e2f5 921// "key_press_event" from any window
c801d85f 922//-----------------------------------------------------------------------------
c801d85f 923
f17393f1
VZ
924// turn on to see the key event codes on the console
925#undef DEBUG_KEY_EVENTS
926
1e6feb95
VZ
927static gint gtk_window_key_press_callback( GtkWidget *widget,
928 GdkEventKey *gdk_event,
929 wxWindow *win )
47d67540 930{
3ac8d3bc
RR
931 DEBUG_MAIN_THREAD
932
c50f1fb9 933 if (g_isIdle)
a2053b27
RR
934 wxapp_install_idle_handler();
935
936 if (!win->m_hasVMT) return FALSE;
f5e27805 937 if (g_blockEventsOnDrag) return FALSE;
c801d85f 938
3d6f7261 939
b0e813a0
RR
940 int x = 0;
941 int y = 0;
942 GdkModifierType state;
f17393f1
VZ
943 if (gdk_event->window)
944 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
47d67540 945
3017f78d 946 bool ret = FALSE;
148cd9b6 947
2d451165 948 long key_code = map_to_unmodified_wx_keysym( gdk_event );
f17393f1
VZ
949
950#ifdef DEBUG_KEY_EVENTS
951 wxPrintf(_T("Key press event: %d => %ld\n"), gdk_event->keyval, key_code);
952#endif // DEBUG_KEY_EVENTS
953
f0492f7d 954 /* sending unknown key events doesn't really make sense */
f17393f1
VZ
955 if (key_code == 0)
956 return FALSE;
f0492f7d 957
c50f1fb9 958 wxKeyEvent event( wxEVT_KEY_DOWN );
d1367c3d 959 event.SetTimestamp( gdk_event->time );
f5e27805
RR
960 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
961 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
962 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
963 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
964 event.m_keyCode = key_code;
b0e813a0
RR
965 event.m_scanCode = gdk_event->keyval;
966 event.m_x = x;
967 event.m_y = y;
f5e27805 968 event.SetEventObject( win );
c5b42c87 969 ret = win->GetEventHandler()->ProcessEvent( event );
c50f1fb9 970
88ac883a 971#if wxUSE_ACCEL
f5e27805 972 if (!ret)
47d67540 973 {
1e6feb95 974 wxWindowGTK *ancestor = win;
f5e27805
RR
975 while (ancestor)
976 {
977 int command = ancestor->GetAcceleratorTable()->GetCommand( event );
978 if (command != -1)
979 {
980 wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
981 ret = ancestor->GetEventHandler()->ProcessEvent( command_event );
982 break;
983 }
f6bcfd97 984 if (ancestor->IsTopLevel())
b02da6b1 985 break;
f5e27805
RR
986 ancestor = ancestor->GetParent();
987 }
bcf1fa6b 988 }
88ac883a 989#endif // wxUSE_ACCEL
3017f78d 990
d728dd40 991 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
3017f78d 992 will only be sent if it is not in an accelerator table. */
f17393f1 993 if ( !ret )
d728dd40 994 {
f17393f1
VZ
995 key_code = map_to_wx_keysym( gdk_event );
996
997 if ( key_code )
998 {
999#ifdef DEBUG_KEY_EVENTS
1000 wxPrintf(_T("Char event: %ld\n"), key_code);
1001#endif // DEBUG_KEY_EVENTS
1002
1003 // reuse the ame event object, just change its type and use the
1004 // translated keycode instead of the raw one
1005 event.SetEventType(wxEVT_CHAR);
1006 event.m_keyCode = key_code;
1007
1008 ret = win->GetEventHandler()->ProcessEvent( event );
1009 }
d728dd40
KB
1010 }
1011
053f9cc1 1012 /* win is a control: tab can be propagated up */
f17393f1 1013 if ( !ret &&
5664fc32 1014 ((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
f6bcfd97
BP
1015// VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1016// have this style, yet choose not to process this particular TAB in which
1017// case TAB must still work as a navigational character
1018#if 0
f17393f1 1019 !win->HasFlag(wxTE_PROCESS_TAB) &&
f6bcfd97 1020#endif // 0
f17393f1 1021 win->GetParent() && (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
b292e2f5
RR
1022 {
1023 wxNavigationKeyEvent new_event;
8253c7fd 1024 new_event.SetEventObject( win->GetParent() );
f03fc89f 1025 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
5664fc32 1026 new_event.SetDirection( (gdk_event->keyval == GDK_Tab) );
f03fc89f 1027 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
b98d804b 1028 new_event.SetWindowChange( (gdk_event->state & GDK_CONTROL_MASK) );
b292e2f5 1029 new_event.SetCurrentFocus( win );
8253c7fd 1030 ret = win->GetParent()->GetEventHandler()->ProcessEvent( new_event );
b292e2f5 1031 }
ff8bfdbb 1032
801aa178 1033 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
f17393f1 1034 if ( !ret &&
b98d804b
RR
1035 (gdk_event->keyval == GDK_Escape) )
1036 {
1037 wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
1038 new_event.SetEventObject( win );
1039 ret = win->GetEventHandler()->ProcessEvent( new_event );
1040 }
c50f1fb9 1041
da048e3d 1042 /* Doesn't work. */
f17393f1
VZ
1043#if 0 // (GTK_MINOR_VERSION > 0)
1044 /* Pressing F10 will activate the menu bar of the top frame. */
801aa178
RR
1045 if ( (!ret) &&
1046 (gdk_event->keyval == GDK_F10) )
1047 {
1e6feb95 1048 wxWindowGTK *ancestor = win;
801aa178
RR
1049 while (ancestor)
1050 {
1051 if (wxIsKindOf(ancestor,wxFrame))
c50f1fb9
VZ
1052 {
1053 wxFrame *frame = (wxFrame*) ancestor;
801aa178 1054 wxMenuBar *menubar = frame->GetMenuBar();
c50f1fb9
VZ
1055 if (menubar)
1056 {
801aa178 1057 wxNode *node = menubar->GetMenus().First();
c50f1fb9
VZ
1058 if (node)
1059 {
3017f78d
RR
1060 wxMenu *firstMenu = (wxMenu*) node->Data();
1061 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
1062 ret = TRUE;
c50f1fb9
VZ
1063 break;
1064 }
1065 }
1066 }
801aa178
RR
1067 ancestor = ancestor->GetParent();
1068 }
1069 }
f17393f1 1070#endif // 0
ca298c88 1071
f5e27805
RR
1072 if (ret)
1073 {
b292e2f5 1074 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
f03fc89f 1075 return TRUE;
f5e27805 1076 }
47d67540 1077
034be888 1078 return FALSE;
362c6693 1079}
c801d85f 1080
b666df2c
RR
1081//-----------------------------------------------------------------------------
1082// "key_release_event" from any window
1083//-----------------------------------------------------------------------------
1084
1e6feb95 1085static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindowGTK *win )
b666df2c 1086{
3ac8d3bc
RR
1087 DEBUG_MAIN_THREAD
1088
c50f1fb9 1089 if (g_isIdle)
a2053b27
RR
1090 wxapp_install_idle_handler();
1091
1092 if (!win->m_hasVMT) return FALSE;
b666df2c
RR
1093 if (g_blockEventsOnDrag) return FALSE;
1094
2d451165 1095 long key_code = map_to_unmodified_wx_keysym( gdk_event );
c50f1fb9 1096
f17393f1
VZ
1097#ifdef DEBUG_KEY_EVENTS
1098 wxPrintf(_T("Key release event: %d => %ld\n"), gdk_event->keyval, key_code);
1099#endif // DEBUG_KEY_EVENTS
1100
f0492f7d
RR
1101 /* sending unknown key events doesn't really make sense */
1102 if (key_code == 0) return FALSE;
b666df2c 1103
b0e813a0
RR
1104 int x = 0;
1105 int y = 0;
1106 GdkModifierType state;
f17393f1
VZ
1107 if (gdk_event->window)
1108 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
b666df2c
RR
1109
1110 wxKeyEvent event( wxEVT_KEY_UP );
d1367c3d 1111 event.SetTimestamp( gdk_event->time );
b666df2c
RR
1112 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1113 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1114 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1115 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1116 event.m_keyCode = key_code;
b0e813a0
RR
1117 event.m_scanCode = gdk_event->keyval;
1118 event.m_x = x;
1119 event.m_y = y;
b666df2c
RR
1120 event.SetEventObject( win );
1121
034be888 1122 if (win->GetEventHandler()->ProcessEvent( event ))
b666df2c 1123 {
b98d804b 1124 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_release_event" );
f03fc89f 1125 return TRUE;
b666df2c
RR
1126 }
1127
034be888 1128 return FALSE;
b666df2c
RR
1129}
1130
c5f9d156
VS
1131// ============================================================================
1132// the mouse events
1133// ============================================================================
1134
1135// init wxMouseEvent with the info from gdk_event
1136#define InitMouseEvent(win, event, gdk_event) \
1137 { \
1138 event.SetTimestamp( gdk_event->time ); \
1139 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1140 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1141 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1142 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1143 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1144 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1145 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1146\
1147 wxPoint pt = win->GetClientAreaOrigin(); \
1148 event.m_x = (wxCoord)gdk_event->x - pt.x; \
1149 event.m_y = (wxCoord)gdk_event->y - pt.y; \
1150 }
1151
2daa0ce9
VZ
1152// ----------------------------------------------------------------------------
1153// mouse event processing helper
1154// ----------------------------------------------------------------------------
1155
1156static void AdjustEventButtonState(wxMouseEvent& event)
1157{
1158 // GDK reports the old state of the button for a button press event, but
1159 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1160 // for a LEFT_DOWN event, not FALSE, so we will invert
1161 // left/right/middleDown for the corresponding click events
1e6feb95 1162
1a8caf94
RR
1163 if ((event.GetEventType() == wxEVT_LEFT_DOWN) ||
1164 (event.GetEventType() == wxEVT_LEFT_DCLICK) ||
1165 (event.GetEventType() == wxEVT_LEFT_UP))
1166 {
1167 event.m_leftDown = !event.m_leftDown;
1168 return;
1169 }
1170
1171 if ((event.GetEventType() == wxEVT_MIDDLE_DOWN) ||
1172 (event.GetEventType() == wxEVT_MIDDLE_DCLICK) ||
1173 (event.GetEventType() == wxEVT_MIDDLE_UP))
2daa0ce9 1174 {
1a8caf94
RR
1175 event.m_middleDown = !event.m_middleDown;
1176 return;
1177 }
1178
1179 if ((event.GetEventType() == wxEVT_RIGHT_DOWN) ||
1180 (event.GetEventType() == wxEVT_RIGHT_DCLICK) ||
1181 (event.GetEventType() == wxEVT_RIGHT_UP))
1182 {
1183 event.m_rightDown = !event.m_rightDown;
1184 return;
2daa0ce9
VZ
1185 }
1186}
1187
c801d85f 1188//-----------------------------------------------------------------------------
2f2aa628
RR
1189// "button_press_event"
1190//-----------------------------------------------------------------------------
c801d85f 1191
1e6feb95 1192static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindowGTK *win )
903f689b 1193{
3ac8d3bc
RR
1194 DEBUG_MAIN_THREAD
1195
c50f1fb9 1196 if (g_isIdle)
a2053b27
RR
1197 wxapp_install_idle_handler();
1198
1199/*
223d09f6 1200 wxPrintf( wxT("1) OnButtonPress from ") );
a2053b27
RR
1201 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1202 wxPrintf( win->GetClassInfo()->GetClassName() );
223d09f6 1203 wxPrintf( wxT(".\n") );
a2053b27 1204*/
a2053b27 1205 if (!win->m_hasVMT) return FALSE;
f5e27805 1206 if (g_blockEventsOnDrag) return TRUE;
76ed8f8d 1207 if (g_blockEventsOnScroll) return TRUE;
c801d85f 1208
034be888
RR
1209 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1210
a2053b27 1211 if (win->m_wxwindow)
c801d85f 1212 {
a2053b27 1213 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow) && !GTK_WIDGET_HAS_FOCUS (win->m_wxwindow) )
f5e27805 1214 {
a2053b27 1215 gtk_widget_grab_focus (win->m_wxwindow);
47d67540 1216
c801d85f 1217/*
223d09f6 1218 wxPrintf( wxT("GrabFocus from ") );
f5e27805 1219 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
a2053b27 1220 wxPrintf( win->GetClassInfo()->GetClassName() );
223d09f6 1221 wxPrintf( wxT(".\n") );
c801d85f 1222*/
47d67540 1223
f5e27805 1224 }
362c6693 1225 }
47d67540 1226
2daa0ce9 1227 wxEventType event_type = wxEVT_NULL;
47d67540 1228
f5e27805 1229 if (gdk_event->button == 1)
c801d85f 1230 {
f5e27805
RR
1231 switch (gdk_event->type)
1232 {
1233 case GDK_BUTTON_PRESS: event_type = wxEVT_LEFT_DOWN; break;
1234 case GDK_2BUTTON_PRESS: event_type = wxEVT_LEFT_DCLICK; break;
1235 default: break;
1236 }
362c6693 1237 }
f5e27805 1238 else if (gdk_event->button == 2)
c801d85f 1239 {
f5e27805
RR
1240 switch (gdk_event->type)
1241 {
1242 case GDK_BUTTON_PRESS: event_type = wxEVT_MIDDLE_DOWN; break;
1243 case GDK_2BUTTON_PRESS: event_type = wxEVT_MIDDLE_DCLICK; break;
1244 default: break;
1245 }
362c6693 1246 }
f5e27805 1247 else if (gdk_event->button == 3)
c801d85f 1248 {
f5e27805
RR
1249 switch (gdk_event->type)
1250 {
1251 case GDK_BUTTON_PRESS: event_type = wxEVT_RIGHT_DOWN; break;
1252 case GDK_2BUTTON_PRESS: event_type = wxEVT_RIGHT_DCLICK; break;
1253 default: break;
1254 }
362c6693 1255 }
47d67540 1256
2daa0ce9
VZ
1257 if ( event_type == wxEVT_NULL )
1258 {
1259 // unknown mouse button or click type
1260 return FALSE;
1261 }
1262
f5e27805 1263 wxMouseEvent event( event_type );
c5f9d156 1264 InitMouseEvent( win, event, gdk_event );
47d67540 1265
2daa0ce9 1266 AdjustEventButtonState(event);
94633ad9 1267
e2762ff0 1268 // wxListBox actually get mouse events from the item
94633ad9 1269
e2762ff0
RR
1270 if (win->m_isListBox)
1271 {
1272 event.m_x += widget->allocation.x;
1273 event.m_y += widget->allocation.y;
1274 }
2daa0ce9 1275
f5e27805
RR
1276 // Some control don't have their own X window and thus cannot get
1277 // any events.
47d67540 1278
72195a0f 1279 if (!g_captureWindow)
2f2aa628 1280 {
b02da6b1
VZ
1281 wxCoord x = event.m_x;
1282 wxCoord y = event.m_y;
2f073eb2
RR
1283 if (win->m_wxwindow)
1284 {
da048e3d 1285 GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
b02da6b1
VZ
1286 x += pizza->xoffset;
1287 y += pizza->yoffset;
2f073eb2
RR
1288 }
1289
db1b4961 1290 wxNode *node = win->GetChildren().First();
f5e27805
RR
1291 while (node)
1292 {
1e6feb95 1293 wxWindowGTK *child = (wxWindowGTK*)node->Data();
148cd9b6 1294
f96ac56a 1295 node = node->Next();
b02da6b1
VZ
1296 if (!child->IsShown())
1297 continue;
ff8bfdbb 1298
a2053b27 1299 if (child->m_isStaticBox)
ff8bfdbb
VZ
1300 {
1301 // wxStaticBox is transparent in the box itself
a2053b27
RR
1302 int xx1 = child->m_x;
1303 int yy1 = child->m_y;
1304 int xx2 = child->m_x + child->m_width;
1305 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1306
1307 // left
1308 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1309 // right
1310 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1311 // top
1312 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1313 // bottom
1314 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1315 {
1ecc4d80 1316 win = child;
a2053b27
RR
1317 event.m_x -= child->m_x;
1318 event.m_y -= child->m_y;
1ecc4d80 1319 break;
ff8bfdbb
VZ
1320 }
1321
1322 }
1323 else
1324 {
a2053b27 1325 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
2f073eb2
RR
1326 (child->m_x <= x) &&
1327 (child->m_y <= y) &&
1328 (child->m_x+child->m_width >= x) &&
1329 (child->m_y+child->m_height >= y))
1ecc4d80
RR
1330 {
1331 win = child;
a2053b27
RR
1332 event.m_x -= child->m_x;
1333 event.m_y -= child->m_y;
1ecc4d80 1334 break;
ff8bfdbb 1335 }
f5e27805 1336 }
f5e27805 1337 }
2f2aa628 1338 }
ff8bfdbb 1339
f5e27805 1340 event.SetEventObject( win );
47d67540 1341
f5e27805 1342 gs_timeLastClick = gdk_event->time;
47d67540 1343
2f073eb2
RR
1344/*
1345 wxPrintf( wxT("2) OnButtonPress from ") );
1346 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1347 wxPrintf( win->GetClassInfo()->GetClassName() );
1348 wxPrintf( wxT(".\n") );
1349*/
1350
f5e27805 1351 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1352 {
f5e27805 1353 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
f03fc89f 1354 return TRUE;
034be888 1355 }
47d67540 1356
034be888 1357 return FALSE;
362c6693 1358}
c801d85f
KB
1359
1360//-----------------------------------------------------------------------------
97b3455a 1361// "button_release_event"
2f2aa628 1362//-----------------------------------------------------------------------------
c801d85f 1363
1e6feb95 1364static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindowGTK *win )
47d67540 1365{
3ac8d3bc
RR
1366 DEBUG_MAIN_THREAD
1367
c50f1fb9 1368 if (g_isIdle)
a2053b27
RR
1369 wxapp_install_idle_handler();
1370
1371 if (!win->m_hasVMT) return FALSE;
034be888
RR
1372 if (g_blockEventsOnDrag) return FALSE;
1373 if (g_blockEventsOnScroll) return FALSE;
c801d85f 1374
034be888 1375 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
47d67540 1376
c801d85f 1377/*
f5e27805
RR
1378 printf( "OnButtonRelease from " );
1379 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1380 printf( win->GetClassInfo()->GetClassName() );
1381 printf( ".\n" );
c801d85f 1382*/
47d67540 1383
f5e27805 1384 wxEventType event_type = wxEVT_NULL;
47d67540 1385
f5e27805
RR
1386 switch (gdk_event->button)
1387 {
1388 case 1: event_type = wxEVT_LEFT_UP; break;
1389 case 2: event_type = wxEVT_MIDDLE_UP; break;
1390 case 3: event_type = wxEVT_RIGHT_UP; break;
2daa0ce9 1391 default: return FALSE;
f5e27805 1392 }
47d67540 1393
f5e27805 1394 wxMouseEvent event( event_type );
c5f9d156 1395 InitMouseEvent( win, event, gdk_event );
f5e27805 1396
2daa0ce9
VZ
1397 AdjustEventButtonState(event);
1398
e2762ff0 1399 // wxListBox actually get mouse events from the item
94633ad9 1400
e2762ff0
RR
1401 if (win->m_isListBox)
1402 {
1403 event.m_x += widget->allocation.x;
1404 event.m_y += widget->allocation.y;
1405 }
1406
f5e27805
RR
1407 // Some control don't have their own X window and thus cannot get
1408 // any events.
1409
72195a0f 1410 if (!g_captureWindow)
2f2aa628 1411 {
b02da6b1
VZ
1412 wxCoord x = event.m_x;
1413 wxCoord y = event.m_y;
2f073eb2
RR
1414 if (win->m_wxwindow)
1415 {
da048e3d 1416 GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
b02da6b1
VZ
1417 x += pizza->xoffset;
1418 y += pizza->yoffset;
2f073eb2
RR
1419 }
1420
db1b4961 1421 wxNode *node = win->GetChildren().First();
f5e27805
RR
1422 while (node)
1423 {
1e6feb95 1424 wxWindowGTK *child = (wxWindowGTK*)node->Data();
ff8bfdbb 1425
f96ac56a 1426 node = node->Next();
b02da6b1
VZ
1427 if (!child->IsShown())
1428 continue;
f96ac56a 1429
a2053b27 1430 if (child->m_isStaticBox)
ff8bfdbb
VZ
1431 {
1432 // wxStaticBox is transparent in the box itself
a2053b27
RR
1433 int xx1 = child->m_x;
1434 int yy1 = child->m_y;
1435 int xx2 = child->m_x + child->m_width;
1436 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1437
1438 // left
1439 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1440 // right
1441 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1442 // top
1443 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1444 // bottom
1445 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1446 {
1ecc4d80 1447 win = child;
a2053b27
RR
1448 event.m_x -= child->m_x;
1449 event.m_y -= child->m_y;
1ecc4d80 1450 break;
ff8bfdbb
VZ
1451 }
1452
1453 }
1454 else
1455 {
a2053b27 1456 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
2f073eb2
RR
1457 (child->m_x <= x) &&
1458 (child->m_y <= y) &&
1459 (child->m_x+child->m_width >= x) &&
1460 (child->m_y+child->m_height >= y))
1ecc4d80
RR
1461 {
1462 win = child;
a2053b27
RR
1463 event.m_x -= child->m_x;
1464 event.m_y -= child->m_y;
1ecc4d80 1465 break;
ff8bfdbb 1466 }
f5e27805 1467 }
f5e27805 1468 }
2f2aa628 1469 }
47d67540 1470
f5e27805 1471 event.SetEventObject( win );
47d67540 1472
f5e27805 1473 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1474 {
f5e27805 1475 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" );
f03fc89f 1476 return TRUE;
034be888 1477 }
47d67540 1478
034be888 1479 return FALSE;
362c6693 1480}
c801d85f
KB
1481
1482//-----------------------------------------------------------------------------
2f2aa628
RR
1483// "motion_notify_event"
1484//-----------------------------------------------------------------------------
c801d85f 1485
1e6feb95
VZ
1486static gint gtk_window_motion_notify_callback( GtkWidget *widget,
1487 GdkEventMotion *gdk_event,
1488 wxWindowGTK *win )
47d67540 1489{
3ac8d3bc
RR
1490 DEBUG_MAIN_THREAD
1491
c50f1fb9 1492 if (g_isIdle)
a2053b27
RR
1493 wxapp_install_idle_handler();
1494
1495 if (!win->m_hasVMT) return FALSE;
034be888
RR
1496 if (g_blockEventsOnDrag) return FALSE;
1497 if (g_blockEventsOnScroll) return FALSE;
148cd9b6 1498
034be888
RR
1499 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1500
ff8bfdbb 1501 if (gdk_event->is_hint)
aae24d21 1502 {
f7a11f8c
RR
1503 int x = 0;
1504 int y = 0;
1505 GdkModifierType state;
1506 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
1507 gdk_event->x = x;
1508 gdk_event->y = y;
aae24d21 1509 }
ff8bfdbb 1510
c801d85f 1511/*
e380f72b
RR
1512 printf( "OnMotion from " );
1513 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1514 printf( win->GetClassInfo()->GetClassName() );
1515 printf( ".\n" );
aae24d21 1516*/
47d67540 1517
e380f72b 1518 wxMouseEvent event( wxEVT_MOTION );
c5f9d156 1519 InitMouseEvent(win, event, gdk_event);
e380f72b 1520
1e6feb95 1521 if ( g_captureWindow )
2f2aa628 1522 {
1e6feb95
VZ
1523 // synthetize a mouse enter or leave event if needed
1524 GdkWindow *winUnderMouse = gdk_window_at_pointer(NULL, NULL);
1525 bool hasMouse = winUnderMouse == gdk_event->window;
1526 if ( hasMouse != g_captureWindowHasMouse )
1527 {
1528 // the mouse changed window
1529 g_captureWindowHasMouse = hasMouse;
1530
1531 wxMouseEvent event(g_captureWindowHasMouse ? wxEVT_ENTER_WINDOW
1532 : wxEVT_LEAVE_WINDOW);
c5f9d156 1533 InitMouseEvent(win, event, gdk_event);
1e6feb95
VZ
1534 event.SetEventObject(win);
1535 win->GetEventHandler()->ProcessEvent(event);
1536 }
1537 }
1538 else // no capture
1539 {
1540 // Some control don't have their own X window and thus cannot get
1541 // any events.
1542
b02da6b1
VZ
1543 wxCoord x = event.m_x;
1544 wxCoord y = event.m_y;
2f073eb2
RR
1545 if (win->m_wxwindow)
1546 {
da048e3d 1547 GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
b02da6b1
VZ
1548 x += pizza->xoffset;
1549 y += pizza->yoffset;
2f073eb2
RR
1550 }
1551
db1b4961 1552 wxNode *node = win->GetChildren().First();
e380f72b
RR
1553 while (node)
1554 {
1e6feb95 1555 wxWindowGTK *child = (wxWindowGTK*)node->Data();
ff8bfdbb 1556
f96ac56a 1557 node = node->Next();
b02da6b1
VZ
1558 if (!child->IsShown())
1559 continue;
f96ac56a 1560
a2053b27 1561 if (child->m_isStaticBox)
ff8bfdbb
VZ
1562 {
1563 // wxStaticBox is transparent in the box itself
a2053b27
RR
1564 int xx1 = child->m_x;
1565 int yy1 = child->m_y;
1566 int xx2 = child->m_x + child->m_width;
1567 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1568
1569 // left
1570 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1571 // right
1572 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1573 // top
1574 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1575 // bottom
1576 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1577 {
1ecc4d80 1578 win = child;
a2053b27
RR
1579 event.m_x -= child->m_x;
1580 event.m_y -= child->m_y;
1ecc4d80 1581 break;
ff8bfdbb
VZ
1582 }
1583
1584 }
1585 else
1586 {
a2053b27 1587 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
2f073eb2
RR
1588 (child->m_x <= x) &&
1589 (child->m_y <= y) &&
1590 (child->m_x+child->m_width >= x) &&
1591 (child->m_y+child->m_height >= y))
1ecc4d80
RR
1592 {
1593 win = child;
a2053b27
RR
1594 event.m_x -= child->m_x;
1595 event.m_y -= child->m_y;
1ecc4d80 1596 break;
ff8bfdbb 1597 }
e380f72b 1598 }
e380f72b 1599 }
2f2aa628 1600 }
47d67540 1601
e380f72b 1602 event.SetEventObject( win );
47d67540 1603
e380f72b 1604 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1605 {
e380f72b 1606 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
f03fc89f 1607 return TRUE;
034be888 1608 }
47d67540 1609
034be888 1610 return FALSE;
362c6693 1611}
c801d85f
KB
1612
1613//-----------------------------------------------------------------------------
2f2aa628
RR
1614// "focus_in_event"
1615//-----------------------------------------------------------------------------
c801d85f 1616
1e6feb95
VZ
1617static gint gtk_window_focus_in_callback( GtkWidget *widget,
1618 GdkEvent *WXUNUSED(event),
1619 wxWindow *win )
c801d85f 1620{
3ac8d3bc
RR
1621 DEBUG_MAIN_THREAD
1622
c50f1fb9 1623 if (g_isIdle)
a2053b27
RR
1624 wxapp_install_idle_handler();
1625
1626 if (!win->m_hasVMT) return FALSE;
034be888 1627 if (g_blockEventsOnDrag) return FALSE;
ff8bfdbb 1628
148cd9b6
VZ
1629 switch ( g_sendActivateEvent )
1630 {
1631 case -1:
76fcf0f2 1632 // we've got focus from outside, synthetize wxActivateEvent
148cd9b6
VZ
1633 g_sendActivateEvent = 1;
1634 break;
1635
1636 case 0:
1637 // another our window just lost focus, it was already ours before
1638 // - don't send any wxActivateEvent
1639 g_sendActivateEvent = -1;
1640 break;
1641 }
1642
1e6feb95 1643 g_focusWindowLast =
b292e2f5 1644 g_focusWindow = win;
ff8bfdbb 1645
76fcf0f2
RR
1646#if 0
1647 wxPrintf( "OnSetFocus from " );
e380f72b 1648 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
76fcf0f2
RR
1649 wxPrintf( win->GetClassInfo()->GetClassName() );
1650 wxPrintf( ".\n" );
1651#endif
47d67540 1652
456bc6d9
VZ
1653 // notify the parent keeping track of focus for the kbd navigation
1654 // purposes that we got it
5314ac16
VZ
1655 wxChildFocusEvent eventFocus(win);
1656 (void)win->GetEventHandler()->ProcessEvent(eventFocus);
148cd9b6 1657
b79395c5
RR
1658#ifdef HAVE_XIM
1659 if (win->m_ic)
1660 gdk_im_begin(win->m_ic, win->m_wxwindow->window);
1661#endif
1662
1e6feb95 1663#if wxUSE_CARET
f6bcfd97
BP
1664 // caret needs to be informed about focus change
1665 wxCaret *caret = win->GetCaret();
1666 if ( caret )
1667 {
1668 caret->OnSetFocus();
1669 }
1670#endif // wxUSE_CARET
1671
e8c12a53
VS
1672 wxWindowGTK *active = wxGetTopLevelParent(win);
1673 if ( active != g_activeFrame )
942bef71 1674 {
e8c12a53
VS
1675 if ( g_activeFrame )
1676 {
45eb5249 1677 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame);
e8c12a53
VS
1678 wxActivateEvent event(wxEVT_ACTIVATE, FALSE, g_activeFrame->GetId());
1679 event.SetEventObject(g_activeFrame);
1680 g_activeFrame->GetEventHandler()->ProcessEvent(event);
1681 }
47d67540 1682
45eb5249 1683 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active);
e8c12a53
VS
1684 g_activeFrame = active;
1685 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, g_activeFrame->GetId());
1686 event.SetEventObject(g_activeFrame);
1687 g_activeFrame->GetEventHandler()->ProcessEvent(event);
942bef71 1688 }
e8c12a53
VS
1689 g_activeFrameLostFocus = FALSE;
1690
942bef71 1691
5cd09f0b
RR
1692 wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
1693 event.SetEventObject( win );
1694
1695 if (win->GetEventHandler()->ProcessEvent( event ))
1696 {
1697 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
1698 return TRUE;
034be888 1699 }
ca298c88 1700
942bef71 1701
034be888 1702 return FALSE;
362c6693 1703}
c801d85f
KB
1704
1705//-----------------------------------------------------------------------------
2f2aa628
RR
1706// "focus_out_event"
1707//-----------------------------------------------------------------------------
c801d85f 1708
b231914f
VZ
1709static GtkWidget *gs_widgetLastFocus = NULL;
1710
1e6feb95 1711static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindowGTK *win )
c801d85f 1712{
3ac8d3bc
RR
1713 DEBUG_MAIN_THREAD
1714
c50f1fb9 1715 if (g_isIdle)
a2053b27
RR
1716 wxapp_install_idle_handler();
1717
1718 if (!win->m_hasVMT) return FALSE;
034be888 1719 if (g_blockEventsOnDrag) return FALSE;
ca298c88 1720
b231914f
VZ
1721 // VZ: this is really weird but GTK+ seems to call us from inside
1722 // gtk_widget_grab_focus(), i.e. it first sends "focus_out" signal to
1723 // this widget and then "focus_in". This is totally unexpected and
1724 // completely breaks wxUniv code so ignore this dummy event (we can't
1725 // be losing focus if we're about to acquire it!)
1726 if ( widget == gs_widgetLastFocus )
1727 {
1728 gs_widgetLastFocus = NULL;
1729
55fb2c6c 1730 return FALSE;
b231914f
VZ
1731 }
1732
45eb5249
VS
1733 if ( !g_activeFrameLostFocus && g_activeFrame )
1734 {
c0ad3d42
VZ
1735 // VZ: commenting this out because it does happen (although not easy
1736 // to reproduce, I only see it when using wxMiniFrame and not
1737 // always) and makes using Mahogany quite annoying
1738#if 0
1739 wxASSERT_MSG( wxGetTopLevelParent(win) == g_activeFrame,
1740 wxT("unfocusing window that hasn't gained focus properly") )
1741#endif // 0
1742
45eb5249
VS
1743 g_activeFrameLostFocus = TRUE;
1744 }
1745
148cd9b6
VZ
1746 // if the focus goes out of our app alltogether, OnIdle() will send
1747 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1748 // g_sendActivateEvent to -1
1749 g_sendActivateEvent = 0;
1750
3379ed37 1751 wxWindowGTK *winFocus = wxFindFocusedChild(win);
f6bcfd97
BP
1752 if ( winFocus )
1753 win = winFocus;
1754
1e6feb95 1755 g_focusWindow = (wxWindowGTK *)NULL;
148cd9b6 1756
76fcf0f2
RR
1757#if 0
1758 wxPrintf( "OnKillFocus from " );
e380f72b 1759 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
76fcf0f2
RR
1760 wxPrintf( win->GetClassInfo()->GetClassName() );
1761 wxPrintf( ".\n" );
1762#endif
47d67540 1763
b79395c5
RR
1764#ifdef HAVE_XIM
1765 if (win->m_ic)
1766 gdk_im_end();
1767#endif
1768
1e6feb95 1769#if wxUSE_CARET
f6bcfd97
BP
1770 // caret needs to be informed about focus change
1771 wxCaret *caret = win->GetCaret();
1772 if ( caret )
1773 {
1774 caret->OnKillFocus();
1775 }
1776#endif // wxUSE_CARET
1777
5cd09f0b
RR
1778 wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
1779 event.SetEventObject( win );
1780
1781 if (win->GetEventHandler()->ProcessEvent( event ))
1782 {
1783 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
1784 return TRUE;
034be888 1785 }
ca298c88 1786
034be888 1787 return FALSE;
362c6693 1788}
c801d85f 1789
b4071e91
RR
1790//-----------------------------------------------------------------------------
1791// "enter_notify_event"
1792//-----------------------------------------------------------------------------
1793
1e6feb95 1794static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindowGTK *win )
b4071e91 1795{
3ac8d3bc
RR
1796 DEBUG_MAIN_THREAD
1797
c50f1fb9 1798 if (g_isIdle)
a2053b27 1799 wxapp_install_idle_handler();
ca298c88 1800
a2053b27
RR
1801 if (!win->m_hasVMT) return FALSE;
1802 if (g_blockEventsOnDrag) return FALSE;
47d67540 1803
a2053b27 1804 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
b292e2f5 1805
e380f72b 1806 wxMouseEvent event( wxEVT_ENTER_WINDOW );
d1367c3d 1807 event.SetTimestamp( gdk_event->time );
e380f72b 1808 event.SetEventObject( win );
ff8bfdbb 1809
4a33eba6
RR
1810 int x = 0;
1811 int y = 0;
1812 GdkModifierType state = (GdkModifierType)0;
ff8bfdbb 1813
a2053b27 1814 gdk_window_get_pointer( widget->window, &x, &y, &state );
ff8bfdbb 1815
c5f9d156
VS
1816 InitMouseEvent(win, event, gdk_event);
1817 wxPoint pt = win->GetClientAreaOrigin();
1818 event.m_x = x + pt.x;
1819 event.m_y = y + pt.y;
ff8bfdbb 1820
e380f72b 1821 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1822 {
e380f72b 1823 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "enter_notify_event" );
034be888
RR
1824 return TRUE;
1825 }
ca298c88 1826
034be888 1827 return FALSE;
b4071e91 1828}
47d67540 1829
b4071e91
RR
1830//-----------------------------------------------------------------------------
1831// "leave_notify_event"
1832//-----------------------------------------------------------------------------
1833
1e6feb95 1834static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindowGTK *win )
b4071e91 1835{
3ac8d3bc
RR
1836 DEBUG_MAIN_THREAD
1837
c50f1fb9 1838 if (g_isIdle)
a2053b27 1839 wxapp_install_idle_handler();
acfd422a 1840
a2053b27
RR
1841 if (!win->m_hasVMT) return FALSE;
1842 if (g_blockEventsOnDrag) return FALSE;
b292e2f5 1843
a2053b27 1844 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
c50f1fb9 1845
e380f72b 1846 wxMouseEvent event( wxEVT_LEAVE_WINDOW );
d1367c3d 1847 event.SetTimestamp( gdk_event->time );
e380f72b 1848 event.SetEventObject( win );
47d67540 1849
4a33eba6
RR
1850 int x = 0;
1851 int y = 0;
1852 GdkModifierType state = (GdkModifierType)0;
ff8bfdbb 1853
4a33eba6 1854 gdk_window_get_pointer( widget->window, &x, &y, &state );
ff8bfdbb 1855
4a33eba6
RR
1856 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1857 event.m_controlDown = (state & GDK_CONTROL_MASK);
1858 event.m_altDown = (state & GDK_MOD1_MASK);
1859 event.m_metaDown = (state & GDK_MOD2_MASK);
1860 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1861 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1862 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1863
c5f9d156
VS
1864 wxPoint pt = win->GetClientAreaOrigin();
1865 event.m_x = x + pt.x;
1866 event.m_y = y + pt.y;
ff8bfdbb 1867
e380f72b 1868 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1869 {
e380f72b 1870 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "leave_notify_event" );
034be888
RR
1871 return TRUE;
1872 }
ca298c88 1873
034be888 1874 return FALSE;
b4071e91 1875}
47d67540 1876
c801d85f 1877//-----------------------------------------------------------------------------
2f2aa628
RR
1878// "value_changed" from m_vAdjust
1879//-----------------------------------------------------------------------------
c801d85f 1880
1e6feb95 1881static void gtk_window_vscroll_callback( GtkAdjustment *adjust, wxWindowGTK *win )
c801d85f 1882{
3ac8d3bc
RR
1883 DEBUG_MAIN_THREAD
1884
c50f1fb9 1885 if (g_isIdle)
a2053b27 1886 wxapp_install_idle_handler();
c801d85f 1887
a2053b27 1888 if (g_blockEventsOnDrag) return;
47d67540 1889
a2053b27 1890 if (!win->m_hasVMT) return;
148cd9b6 1891
5e014a0c 1892 float diff = adjust->value - win->m_oldVerticalPos;
e380f72b 1893 if (fabs(diff) < 0.2) return;
148cd9b6 1894
5e014a0c 1895 win->m_oldVerticalPos = adjust->value;
47d67540 1896
5e014a0c
RR
1897 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
1898 GtkRange *range = GTK_RANGE( scrolledWindow->vscrollbar );
148cd9b6 1899
5e014a0c
RR
1900 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
1901 if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP;
1902 else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN;
1903 else if (range->scroll_type == GTK_SCROLL_PAGE_BACKWARD) command = wxEVT_SCROLLWIN_PAGEUP;
1904 else if (range->scroll_type == GTK_SCROLL_PAGE_FORWARD) command = wxEVT_SCROLLWIN_PAGEDOWN;
148cd9b6 1905
5e014a0c 1906 int value = (int)(adjust->value+0.5);
c801d85f 1907
c5b42c87 1908 wxScrollWinEvent event( command, value, wxVERTICAL );
e380f72b
RR
1909 event.SetEventObject( win );
1910 win->GetEventHandler()->ProcessEvent( event );
362c6693 1911}
c801d85f
KB
1912
1913//-----------------------------------------------------------------------------
2f2aa628
RR
1914// "value_changed" from m_hAdjust
1915//-----------------------------------------------------------------------------
c801d85f 1916
1e6feb95 1917static void gtk_window_hscroll_callback( GtkAdjustment *adjust, wxWindowGTK *win )
47d67540 1918{
3ac8d3bc
RR
1919 DEBUG_MAIN_THREAD
1920
c50f1fb9 1921 if (g_isIdle)
a2053b27 1922 wxapp_install_idle_handler();
47d67540 1923
a2053b27
RR
1924 if (g_blockEventsOnDrag) return;
1925 if (!win->m_hasVMT) return;
47d67540 1926
5e014a0c 1927 float diff = adjust->value - win->m_oldHorizontalPos;
e380f72b 1928 if (fabs(diff) < 0.2) return;
148cd9b6 1929
5e014a0c 1930 win->m_oldHorizontalPos = adjust->value;
8bbe427f 1931
5e014a0c
RR
1932 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
1933 GtkRange *range = GTK_RANGE( scrolledWindow->hscrollbar );
148cd9b6 1934
5e014a0c
RR
1935 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
1936 if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP;
1937 else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN;
1938 else if (range->scroll_type == GTK_SCROLL_PAGE_BACKWARD) command = wxEVT_SCROLLWIN_PAGEUP;
1939 else if (range->scroll_type == GTK_SCROLL_PAGE_FORWARD) command = wxEVT_SCROLLWIN_PAGEDOWN;
148cd9b6 1940
5e014a0c 1941 int value = (int)(adjust->value+0.5);
47d67540 1942
c5b42c87 1943 wxScrollWinEvent event( command, value, wxHORIZONTAL );
e380f72b
RR
1944 event.SetEventObject( win );
1945 win->GetEventHandler()->ProcessEvent( event );
362c6693 1946}
c801d85f 1947
cb43b372
RR
1948//-----------------------------------------------------------------------------
1949// "button_press_event" from scrollbar
1950//-----------------------------------------------------------------------------
1951
2a23d363
RR
1952static gint gtk_scrollbar_button_press_callback( GtkRange *widget,
1953 GdkEventButton *gdk_event,
1e6feb95 1954 wxWindowGTK *win)
cb43b372 1955{
3ac8d3bc
RR
1956 DEBUG_MAIN_THREAD
1957
c50f1fb9 1958 if (g_isIdle)
a2053b27
RR
1959 wxapp_install_idle_handler();
1960
d6d26e04 1961
5b8a521e 1962 g_blockEventsOnScroll = TRUE;
2a23d363 1963 win->m_isScrolling = (gdk_event->window == widget->slider);
47d67540 1964
e380f72b 1965 return FALSE;
cb43b372
RR
1966}
1967
1968//-----------------------------------------------------------------------------
1969// "button_release_event" from scrollbar
1970//-----------------------------------------------------------------------------
1971
88413fec 1972static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
8bbe427f 1973 GdkEventButton *WXUNUSED(gdk_event),
1e6feb95 1974 wxWindowGTK *win)
cb43b372 1975{
3ac8d3bc
RR
1976 DEBUG_MAIN_THREAD
1977
1ecc4d80 1978// don't test here as we can release the mouse while being over
5e014a0c 1979// a different window than the slider
76ed8f8d
RR
1980//
1981// if (gdk_event->window != widget->slider) return FALSE;
cb43b372 1982
5b8a521e 1983 g_blockEventsOnScroll = FALSE;
47d67540 1984
2a23d363 1985 if (win->m_isScrolling)
88413fec 1986 {
d6d26e04 1987 wxEventType command = wxEVT_SCROLLWIN_THUMBRELEASE;
2a23d363
RR
1988 int value = -1;
1989 int dir = -1;
2daa0ce9 1990
2a23d363
RR
1991 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
1992 if (widget == GTK_RANGE(scrolledWindow->hscrollbar))
1993 {
1994 value = (int)(win->m_hAdjust->value+0.5);
1995 dir = wxHORIZONTAL;
1996 }
1997 if (widget == GTK_RANGE(scrolledWindow->vscrollbar))
1998 {
1999 value = (int)(win->m_vAdjust->value+0.5);
2000 dir = wxVERTICAL;
2001 }
2daa0ce9 2002
2a23d363 2003 wxScrollWinEvent event( command, value, dir );
2a23d363
RR
2004 event.SetEventObject( win );
2005 win->GetEventHandler()->ProcessEvent( event );
88413fec
RR
2006 }
2007
2a23d363 2008 win->m_isScrolling = FALSE;
2daa0ce9 2009
e380f72b 2010 return FALSE;
cb43b372
RR
2011}
2012
f03fc89f
VZ
2013// ----------------------------------------------------------------------------
2014// this wxWindowBase function is implemented here (in platform-specific file)
2015// because it is static and so couldn't be made virtual
2016// ----------------------------------------------------------------------------
2b07d713 2017
f03fc89f 2018wxWindow *wxWindowBase::FindFocus()
2b07d713 2019{
1e6feb95
VZ
2020 // the cast is necessary when we compile in wxUniversal mode
2021 return (wxWindow *)g_focusWindow;
2b07d713 2022}
ca298c88 2023
a2053b27
RR
2024//-----------------------------------------------------------------------------
2025// "realize" from m_widget
2026//-----------------------------------------------------------------------------
2027
b79395c5
RR
2028/* We cannot set colours and fonts before the widget has
2029 been realized, so we do this directly after realization. */
a2053b27
RR
2030
2031static gint
63081513 2032gtk_window_realized_callback( GtkWidget *WXUNUSED(m_widget), wxWindow *win )
a2053b27 2033{
3ac8d3bc
RR
2034 DEBUG_MAIN_THREAD
2035
c50f1fb9 2036 if (g_isIdle)
a2053b27
RR
2037 wxapp_install_idle_handler();
2038
739730ca
RR
2039 if (win->m_delayedBackgroundColour)
2040 win->SetBackgroundColour( win->GetBackgroundColour() );
a2053b27 2041
739730ca
RR
2042 if (win->m_delayedForegroundColour)
2043 win->SetForegroundColour( win->GetForegroundColour() );
a2053b27 2044
3c679789
RR
2045 wxWindowCreateEvent event( win );
2046 event.SetEventObject( win );
2047 win->GetEventHandler()->ProcessEvent( event );
1e6feb95 2048
a2053b27
RR
2049 return FALSE;
2050}
2051
b79395c5
RR
2052//-----------------------------------------------------------------------------
2053// "size_allocate"
2054//-----------------------------------------------------------------------------
2055
8f75cb6c 2056static
adc1999b
RR
2057void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
2058 GtkAllocation *WXUNUSED(alloc),
8f75cb6c
RR
2059 wxWindow *win )
2060{
2061 if (g_isIdle)
2062 wxapp_install_idle_handler();
2daa0ce9 2063
5b8a521e 2064 if (!win->m_hasScrolling) return;
2daa0ce9 2065
5b8a521e
RR
2066 int client_width = 0;
2067 int client_height = 0;
2068 win->GetClientSize( &client_width, &client_height );
2069 if ((client_width == win->m_oldClientWidth) && (client_height == win->m_oldClientHeight))
2070 return;
2daa0ce9 2071
5b8a521e
RR
2072 win->m_oldClientWidth = client_width;
2073 win->m_oldClientHeight = client_height;
2daa0ce9 2074
5b8a521e
RR
2075 if (!win->m_nativeSizeEvent)
2076 {
2077 wxSizeEvent event( win->GetSize(), win->GetId() );
2078 event.SetEventObject( win );
2079 win->GetEventHandler()->ProcessEvent( event );
2080 }
8f75cb6c
RR
2081}
2082
2083
3ed2e7ce
VZ
2084#ifdef HAVE_XIM
2085 #define WXUNUSED_UNLESS_XIM(param) param
2086#else
2087 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2088#endif
2089
b79395c5
RR
2090/* Resize XIM window */
2091
3ed2e7ce 2092static
8f75cb6c
RR
2093void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget),
2094 GtkAllocation* WXUNUSED_UNLESS_XIM(alloc),
1e6feb95 2095 wxWindowGTK* WXUNUSED_UNLESS_XIM(win) )
b79395c5
RR
2096{
2097 if (g_isIdle)
2098 wxapp_install_idle_handler();
2daa0ce9 2099
9a8c7620 2100#ifdef HAVE_XIM
b79395c5
RR
2101 if (!win->m_ic)
2102 return;
2103
b79395c5
RR
2104 if (gdk_ic_get_style (win->m_ic) & GDK_IM_PREEDIT_POSITION)
2105 {
2106 gint width, height;
2107
3ed2e7ce 2108 gdk_window_get_size (widget->window, &width, &height);
b79395c5
RR
2109 win->m_icattr->preedit_area.width = width;
2110 win->m_icattr->preedit_area.height = height;
2111 gdk_ic_set_attr (win->m_ic, win->m_icattr, GDK_IC_PREEDIT_AREA);
2112 }
9a8c7620 2113#endif // HAVE_XIM
b79395c5
RR
2114}
2115
63081513
RR
2116//-----------------------------------------------------------------------------
2117// "realize" from m_wxwindow
2118//-----------------------------------------------------------------------------
2119
2120/* Initialize XIM support */
2121
2122static gint
3ed2e7ce 2123gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
1e6feb95 2124 wxWindowGTK * WXUNUSED_UNLESS_XIM(win) )
63081513
RR
2125{
2126 if (g_isIdle)
2127 wxapp_install_idle_handler();
2128
d06800f1 2129#ifdef HAVE_XIM
63081513
RR
2130 if (win->m_ic) return FALSE;
2131 if (!widget) return FALSE;
2132 if (!gdk_im_ready()) return FALSE;
2133
2134 win->m_icattr = gdk_ic_attr_new();
2135 if (!win->m_icattr) return FALSE;
2daa0ce9 2136
63081513
RR
2137 gint width, height;
2138 GdkEventMask mask;
2139 GdkColormap *colormap;
2140 GdkICAttr *attr = win->m_icattr;
b58b1dfc 2141 unsigned attrmask = GDK_IC_ALL_REQ;
63081513 2142 GdkIMStyle style;
b79395c5
RR
2143 GdkIMStyle supported_style = (GdkIMStyle)
2144 (GDK_IM_PREEDIT_NONE |
1e6feb95
VZ
2145 GDK_IM_PREEDIT_NOTHING |
2146 GDK_IM_PREEDIT_POSITION |
2147 GDK_IM_STATUS_NONE |
2148 GDK_IM_STATUS_NOTHING);
63081513
RR
2149
2150 if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
1e6feb95 2151 supported_style = (GdkIMStyle)(supported_style & ~GDK_IM_PREEDIT_POSITION);
63081513
RR
2152
2153 attr->style = style = gdk_im_decide_style (supported_style);
2154 attr->client_window = widget->window;
2155
2156 if ((colormap = gtk_widget_get_colormap (widget)) !=
1e6feb95 2157 gtk_widget_get_default_colormap ())
63081513 2158 {
5cd09f0b
RR
2159 attrmask |= GDK_IC_PREEDIT_COLORMAP;
2160 attr->preedit_colormap = colormap;
63081513 2161 }
2daa0ce9 2162
63081513
RR
2163 attrmask |= GDK_IC_PREEDIT_FOREGROUND;
2164 attrmask |= GDK_IC_PREEDIT_BACKGROUND;
2165 attr->preedit_foreground = widget->style->fg[GTK_STATE_NORMAL];
2166 attr->preedit_background = widget->style->base[GTK_STATE_NORMAL];
2167
2168 switch (style & GDK_IM_PREEDIT_MASK)
2169 {
1e6feb95
VZ
2170 case GDK_IM_PREEDIT_POSITION:
2171 if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
2172 {
2173 g_warning ("over-the-spot style requires fontset");
2174 break;
2175 }
63081513 2176
1e6feb95 2177 gdk_window_get_size (widget->window, &width, &height);
63081513 2178
1e6feb95
VZ
2179 attrmask |= GDK_IC_PREEDIT_POSITION_REQ;
2180 attr->spot_location.x = 0;
2181 attr->spot_location.y = height;
2182 attr->preedit_area.x = 0;
2183 attr->preedit_area.y = 0;
2184 attr->preedit_area.width = width;
2185 attr->preedit_area.height = height;
2186 attr->preedit_fontset = widget->style->font;
63081513 2187
1e6feb95 2188 break;
b79395c5 2189 }
2daa0ce9 2190
b58b1dfc 2191 win->m_ic = gdk_ic_new (attr, (GdkICAttributesType)attrmask);
2daa0ce9 2192
63081513 2193 if (win->m_ic == NULL)
1e6feb95 2194 g_warning ("Can't create input context.");
63081513 2195 else
1e6feb95
VZ
2196 {
2197 mask = gdk_window_get_events (widget->window);
2198 mask = (GdkEventMask)(mask | gdk_ic_get_events (win->m_ic));
2199 gdk_window_set_events (widget->window, mask);
2200
2201 if (GTK_WIDGET_HAS_FOCUS(widget))
2202 gdk_im_begin (win->m_ic, widget->window);
2203 }
2204#endif // HAVE_XIM
63081513
RR
2205
2206 return FALSE;
2207}
2208
6ca41e57 2209//-----------------------------------------------------------------------------
1e6feb95 2210// InsertChild for wxWindowGTK.
6ca41e57
RR
2211//-----------------------------------------------------------------------------
2212
1e6feb95 2213/* Callback for wxWindowGTK. This very strange beast has to be used because
b1170810
RR
2214 * C++ has no virtual methods in a constructor. We have to emulate a
2215 * virtual function here as wxNotebook requires a different way to insert
2216 * a child in it. I had opted for creating a wxNotebookPage window class
2217 * which would have made this superfluous (such in the MDI window system),
2218 * but no-one was listening to me... */
6ca41e57 2219
1e6feb95 2220static void wxInsertChildInWindow( wxWindowGTK* parent, wxWindowGTK* child )
6ca41e57 2221{
bf0c00c6
RR
2222 /* the window might have been scrolled already, do we
2223 have to adapt the position */
da048e3d
RR
2224 GtkPizza *pizza = GTK_PIZZA(parent->m_wxwindow);
2225 child->m_x += pizza->xoffset;
2226 child->m_y += pizza->yoffset;
148cd9b6 2227
da048e3d 2228 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
a2053b27
RR
2229 GTK_WIDGET(child->m_widget),
2230 child->m_x,
2231 child->m_y,
2232 child->m_width,
2233 child->m_height );
6ca41e57
RR
2234}
2235
bbe0af5b
RR
2236//-----------------------------------------------------------------------------
2237// global functions
2238//-----------------------------------------------------------------------------
2239
1e6feb95 2240wxWindow *wxGetActiveWindow()
bbe0af5b 2241{
1e6feb95
VZ
2242 // the cast is necessary when we compile in wxUniversal mode
2243 return (wxWindow *)g_focusWindow;
bbe0af5b
RR
2244}
2245
c801d85f 2246//-----------------------------------------------------------------------------
1e6feb95 2247// wxWindowGTK
c801d85f
KB
2248//-----------------------------------------------------------------------------
2249
6522713c
VZ
2250// in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2251// method
1e6feb95 2252#ifdef __WXUNIVERSAL__
6522713c
VZ
2253 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK, wxWindowBase)
2254#else // __WXGTK__
1e6feb95 2255 IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
6522713c 2256#endif // __WXUNIVERSAL__/__WXGTK__
c801d85f 2257
1e6feb95 2258void wxWindowGTK::Init()
c801d85f 2259{
f03fc89f
VZ
2260 // common init
2261 InitBase();
68995f26 2262
f03fc89f 2263 // GTK specific
a2053b27 2264 m_widget = (GtkWidget *) NULL;
e380f72b 2265 m_wxwindow = (GtkWidget *) NULL;
76fcf0f2 2266 m_focusWidget = (GtkWidget *) NULL;
8bbe427f 2267
f03fc89f 2268 // position/size
a2053b27
RR
2269 m_x = 0;
2270 m_y = 0;
2271 m_width = 0;
e380f72b 2272 m_height = 0;
8bbe427f 2273
e380f72b
RR
2274 m_sizeSet = FALSE;
2275 m_hasVMT = FALSE;
2276 m_needParent = TRUE;
31c6b4fc 2277 m_isBeingDeleted = FALSE;
148cd9b6 2278
147bc491 2279 m_noExpose = FALSE;
30760ce7 2280 m_nativeSizeEvent = FALSE;
94633ad9 2281
a2053b27 2282 m_hasScrolling = FALSE;
846e1424 2283 m_isScrolling = FALSE;
f03fc89f 2284
a2053b27 2285 m_hAdjust = (GtkAdjustment*) NULL;
e380f72b 2286 m_vAdjust = (GtkAdjustment*) NULL;
a2053b27 2287 m_oldHorizontalPos = 0.0;
e380f72b 2288 m_oldVerticalPos = 0.0;
8bbe427f 2289
e380f72b 2290 m_resizing = FALSE;
e380f72b 2291 m_widgetStyle = (GtkStyle*) NULL;
8bbe427f 2292
ddb6bc71 2293 m_insertCallback = (wxInsertChildFunction) NULL;
8bbe427f 2294
1ecc4d80 2295 m_isStaticBox = FALSE;
953704c1 2296 m_isRadioButton = FALSE;
e2762ff0 2297 m_isListBox = FALSE;
54517652 2298 m_isFrame = FALSE;
b292e2f5 2299 m_acceptsFocus = FALSE;
148cd9b6 2300
b6fa52db 2301 m_clipPaintRegion = FALSE;
b6fa52db 2302
5e014a0c 2303 m_cursor = *wxSTANDARD_CURSOR;
2daa0ce9 2304
f6bcfd97
BP
2305 m_delayedForegroundColour = FALSE;
2306 m_delayedBackgroundColour = FALSE;
1e6feb95 2307
63081513
RR
2308#ifdef HAVE_XIM
2309 m_ic = (GdkIC*) NULL;
2310 m_icattr = (GdkICAttr*) NULL;
2311#endif
362c6693 2312}
c801d85f 2313
1e6feb95 2314wxWindowGTK::wxWindowGTK()
68995f26
VZ
2315{
2316 Init();
2317}
2318
1e6feb95
VZ
2319wxWindowGTK::wxWindowGTK( wxWindow *parent,
2320 wxWindowID id,
2321 const wxPoint &pos,
2322 const wxSize &size,
2323 long style,
2324 const wxString &name )
6ca41e57 2325{
68995f26
VZ
2326 Init();
2327
e380f72b 2328 Create( parent, id, pos, size, style, name );
6ca41e57 2329}
8bbe427f 2330
1e6feb95
VZ
2331bool wxWindowGTK::Create( wxWindow *parent,
2332 wxWindowID id,
2333 const wxPoint &pos,
2334 const wxSize &size,
2335 long style,
2336 const wxString &name )
c801d85f 2337{
4dcaf11a
RR
2338 if (!PreCreation( parent, pos, size ) ||
2339 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
2340 {
1e6feb95 2341 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
b02da6b1 2342 return FALSE;
4dcaf11a 2343 }
47d67540 2344
ddb6bc71 2345 m_insertCallback = wxInsertChildInWindow;
1e6feb95 2346
e380f72b 2347 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
38c7b3d3 2348 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
ff8bfdbb 2349
f03fc89f 2350 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
47d67540 2351
dd00f3f6 2352 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
e380f72b 2353 scroll_class->scrollbar_spacing = 0;
47d67540 2354
f03fc89f 2355 gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
47d67540 2356
f03fc89f
VZ
2357 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->hscrollbar) );
2358 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->vscrollbar) );
47d67540 2359
da048e3d 2360 m_wxwindow = gtk_pizza_new();
38c7b3d3 2361
034be888 2362 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
58dea4b0 2363
1e6feb95 2364#ifndef __WXUNIVERSAL__
034be888 2365#if (GTK_MINOR_VERSION > 0)
da048e3d 2366 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
b292e2f5 2367
f03fc89f 2368 if (HasFlag(wxRAISED_BORDER))
034be888 2369 {
da048e3d 2370 gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_OUT );
034be888 2371 }
f03fc89f 2372 else if (HasFlag(wxSUNKEN_BORDER))
034be888 2373 {
da048e3d 2374 gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_IN );
5e014a0c
RR
2375 }
2376 else if (HasFlag(wxSIMPLE_BORDER))
2377 {
da048e3d 2378 gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_THIN );
034be888
RR
2379 }
2380 else
2381 {
da048e3d 2382 gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_NONE );
034be888 2383 }
f03fc89f
VZ
2384#else // GTK_MINOR_VERSION == 0
2385 GtkViewport *viewport = GTK_VIEWPORT(scrolledWindow->viewport);
b292e2f5 2386
f03fc89f 2387 if (HasFlag(wxRAISED_BORDER))
e380f72b
RR
2388 {
2389 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
2390 }
f03fc89f 2391 else if (HasFlag(wxSUNKEN_BORDER))
e380f72b
RR
2392 {
2393 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
2394 }
2395 else
2396 {
2397 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
2398 }
f03fc89f 2399#endif // GTK_MINOR_VERSION
1e6feb95 2400#endif // __WXUNIVERSAL__
47d67540 2401
3da17724
RR
2402 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
2403 m_acceptsFocus = TRUE;
ca298c88 2404
034be888 2405#if (GTK_MINOR_VERSION == 0)
e380f72b
RR
2406 // shut the viewport up
2407 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2408 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
f03fc89f 2409#endif // GTK_MINOR_VERSION == 0
e380f72b
RR
2410
2411 // I _really_ don't want scrollbars in the beginning
a2053b27
RR
2412 m_vAdjust->lower = 0.0;
2413 m_vAdjust->upper = 1.0;
2414 m_vAdjust->value = 0.0;
2415 m_vAdjust->step_increment = 1.0;
2416 m_vAdjust->page_increment = 1.0;
2417 m_vAdjust->page_size = 5.0;
2418 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
2419 m_hAdjust->lower = 0.0;
2420 m_hAdjust->upper = 1.0;
2421 m_hAdjust->value = 0.0;
2422 m_hAdjust->step_increment = 1.0;
2423 m_hAdjust->page_increment = 1.0;
2424 m_hAdjust->page_size = 5.0;
2425 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
f03fc89f
VZ
2426
2427 // these handlers block mouse events to any window during scrolling such as
2428 // motion events and prevent GTK and wxWindows from fighting over where the
2429 // slider should be
2430
2431 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_press_event",
76ed8f8d
RR
2432 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
2433
f03fc89f 2434 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_press_event",
76ed8f8d
RR
2435 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
2436
f03fc89f 2437 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_release_event",
76ed8f8d
RR
2438 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
2439
f03fc89f 2440 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_release_event",
76ed8f8d 2441 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
8bbe427f 2442
034be888 2443 // these handlers get notified when screen updates are required either when
76ed8f8d
RR
2444 // scrolling or when the window size (and therefore scrollbar configuration)
2445 // has changed
2446
2447 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
2448 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
2449 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
2450 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
2451
f03fc89f 2452 gtk_widget_show( m_wxwindow );
47d67540 2453
f03fc89f
VZ
2454 if (m_parent)
2455 m_parent->DoAddChild( this );
94633ad9 2456
76fcf0f2 2457 m_focusWidget = m_wxwindow;
8bbe427f 2458
e380f72b 2459 PostCreation();
8bbe427f 2460
e380f72b 2461 Show( TRUE );
c801d85f 2462
e380f72b 2463 return TRUE;
362c6693 2464}
c801d85f 2465
1e6feb95 2466wxWindowGTK::~wxWindowGTK()
c801d85f 2467{
44cd54c2
JS
2468 if (g_focusWindow == this)
2469 g_focusWindow = NULL;
2470
e8c12a53
VS
2471 if (g_activeFrame == this)
2472 g_activeFrame = NULL;
2473
31c6b4fc 2474 m_isBeingDeleted = TRUE;
43a18898 2475 m_hasVMT = FALSE;
47d67540 2476
f03fc89f
VZ
2477 if (m_widget)
2478 Show( FALSE );
8bbe427f 2479
a2053b27
RR
2480 DestroyChildren();
2481
f03fc89f
VZ
2482 if (m_parent)
2483 m_parent->RemoveChild( this );
c801d85f 2484
63081513
RR
2485#ifdef HAVE_XIM
2486 if (m_ic)
2487 gdk_ic_destroy (m_ic);
2488 if (m_icattr)
2489 gdk_ic_attr_destroy (m_icattr);
2490#endif
2491
f03fc89f 2492 if (m_widgetStyle)
a2053b27 2493 {
a56fcaaf 2494#if DISABLE_STYLE_IF_BROKEN_THEME
bce1406b
RR
2495 // don't delete if it's a pixmap theme style
2496 if (!m_widgetStyle->engine_data)
2497 gtk_style_unref( m_widgetStyle );
1e6feb95 2498#endif
c50f1fb9 2499 m_widgetStyle = (GtkStyle*) NULL;
a2053b27 2500 }
c801d85f 2501
f03fc89f 2502 if (m_wxwindow)
a2053b27 2503 {
f03fc89f 2504 gtk_widget_destroy( m_wxwindow );
c50f1fb9 2505 m_wxwindow = (GtkWidget*) NULL;
a2053b27 2506 }
8bbe427f 2507
f03fc89f 2508 if (m_widget)
a2053b27 2509 {
f03fc89f 2510 gtk_widget_destroy( m_widget );
c50f1fb9 2511 m_widget = (GtkWidget*) NULL;
a2053b27 2512 }
362c6693 2513}
c801d85f 2514
1e6feb95 2515bool wxWindowGTK::PreCreation( wxWindowGTK *parent, const wxPoint &pos, const wxSize &size )
c801d85f 2516{
223d09f6 2517 wxCHECK_MSG( !m_needParent || parent, FALSE, wxT("Need complete parent.") );
8bbe427f 2518
4dcaf11a
RR
2519 /* this turns -1 into 20 so that a minimal window is
2520 visible even although -1,-1 has been given as the
2521 size of the window. the same trick is used in other
2522 ports and should make debugging easier */
f03fc89f
VZ
2523 m_width = WidthDefault(size.x);
2524 m_height = HeightDefault(size.y);
8bbe427f 2525
43a18898
RR
2526 m_x = (int)pos.x;
2527 m_y = (int)pos.y;
8bbe427f 2528
4dcaf11a 2529 /* some reasonable defaults */
148cd9b6 2530 if (!parent)
6ca41e57 2531 {
43a18898
RR
2532 if (m_x == -1)
2533 {
2534 m_x = (gdk_screen_width () - m_width) / 2;
2535 if (m_x < 10) m_x = 10;
2536 }
2537 if (m_y == -1)
2538 {
2539 m_y = (gdk_screen_height () - m_height) / 2;
2540 if (m_y < 10) m_y = 10;
2541 }
6ca41e57 2542 }
148cd9b6 2543
4dcaf11a 2544 return TRUE;
c801d85f
KB
2545}
2546
1e6feb95 2547void wxWindowGTK::PostCreation()
c801d85f 2548{
223d09f6 2549 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
94633ad9 2550
43a18898
RR
2551 if (m_wxwindow)
2552 {
147bc491 2553 if (!m_noExpose)
b02da6b1 2554 {
76fcf0f2 2555 // these get reported to wxWindows -> wxPaintEvent
1e6feb95 2556
b420fb6a
RR
2557 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow), TRUE );
2558
147bc491
RR
2559 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
2560 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
2561
2562 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
2563 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
e22454be
RR
2564
2565 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE))
2566 {
2567 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "event",
2568 GTK_SIGNAL_FUNC(gtk_window_event_event_callback), (gpointer)this );
2569 }
b02da6b1 2570 }
148cd9b6 2571
76fcf0f2 2572 // these are called when the "sunken" or "raised" borders are drawn */
034be888
RR
2573 gtk_signal_connect( GTK_OBJECT(m_widget), "expose_event",
2574 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback), (gpointer)this );
2575
2576 gtk_signal_connect( GTK_OBJECT(m_widget), "draw",
2577 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback), (gpointer)this );
43a18898 2578 }
47d67540 2579
76fcf0f2 2580 // focus handling
63081513 2581
76fcf0f2
RR
2582 if (m_focusWidget == NULL)
2583 m_focusWidget = m_widget;
2daa0ce9 2584
76fcf0f2
RR
2585#if 0
2586 if (GetClassInfo() && GetClassInfo()->GetClassName())
2587 wxPrintf( GetClassInfo()->GetClassName() );
2588 wxPrintf( ".\n" );
2589#endif
63081513 2590
76fcf0f2
RR
2591 gtk_signal_connect( GTK_OBJECT(m_focusWidget), "focus_in_event",
2592 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
2593
2594 gtk_signal_connect( GTK_OBJECT(m_focusWidget), "focus_out_event",
2595 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
2596
2597 // connect to the various key and mouse handlers
63081513 2598
a2053b27 2599 GtkWidget *connect_widget = GetConnectWidget();
f03fc89f 2600
a2053b27 2601 ConnectWidget( connect_widget );
47d67540 2602
63081513 2603 /* We cannot set colours, fonts and cursors before the widget has
a2053b27
RR
2604 been realized, so we do this directly after realization */
2605 gtk_signal_connect( GTK_OBJECT(connect_widget), "realize",
c50f1fb9 2606 GTK_SIGNAL_FUNC(gtk_window_realized_callback), (gpointer) this );
2daa0ce9 2607
63081513
RR
2608 if (m_wxwindow)
2609 {
47c93b63 2610 // Catch native resize events
8f75cb6c
RR
2611 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
2612 GTK_SIGNAL_FUNC(gtk_window_size_callback), (gpointer)this );
2daa0ce9 2613
47c93b63 2614 // Initialize XIM support
63081513
RR
2615 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
2616 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback), (gpointer) this );
8f75cb6c 2617
47c93b63 2618 // And resize XIM window
b79395c5
RR
2619 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
2620 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback), (gpointer)this );
63081513 2621 }
2daa0ce9 2622
47c93b63
RR
2623 if (!GTK_IS_COMBO(m_widget))
2624 {
2625 // This is needed if we want to add our windows into native
2626 // GTK control, such as the toolbar. With this callback, the
2627 // toolbar gets to know the correct size (the one set by the
2628 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2629 // when moving to GTK 2.0.
2630 gtk_signal_connect( GTK_OBJECT(m_widget), "size_request",
2631 GTK_SIGNAL_FUNC(gtk_window_size_request_callback), (gpointer) this );
2632 }
1e6feb95 2633
43a18898 2634 m_hasVMT = TRUE;
b4071e91
RR
2635}
2636
1e6feb95 2637void wxWindowGTK::ConnectWidget( GtkWidget *widget )
b4071e91 2638{
43a18898
RR
2639 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
2640 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
c801d85f 2641
b666df2c
RR
2642 gtk_signal_connect( GTK_OBJECT(widget), "key_release_event",
2643 GTK_SIGNAL_FUNC(gtk_window_key_release_callback), (gpointer)this );
2644
43a18898
RR
2645 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
2646 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
47d67540 2647
43a18898
RR
2648 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
2649 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
47d67540 2650
43a18898
RR
2651 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
2652 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
47d67540 2653
43a18898
RR
2654 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
2655 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
47d67540 2656
43a18898
RR
2657 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
2658 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
362c6693 2659}
c801d85f 2660
1e6feb95 2661bool wxWindowGTK::Destroy()
c801d85f 2662{
223d09f6 2663 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
47d67540 2664
43a18898 2665 m_hasVMT = FALSE;
c801d85f 2666
f03fc89f 2667 return wxWindowBase::Destroy();
362c6693 2668}
c801d85f 2669
1e6feb95 2670void wxWindowGTK::DoMoveWindow(int x, int y, int width, int height)
23efdd02
RR
2671{
2672 gtk_pizza_set_size( GTK_PIZZA(m_parent->m_wxwindow), m_widget, x, y, width, height );
2673}
2daa0ce9 2674
1e6feb95 2675void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
c801d85f 2676{
223d09f6 2677 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
1e6feb95 2678 wxASSERT_MSG( (m_parent != NULL), wxT("wxWindowGTK::SetSize requires parent.\n") );
8bbe427f 2679
33611ebb 2680/*
f94fca1b 2681 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
33611ebb
RR
2682*/
2683
e27ce4e9 2684 if (m_resizing) return; /* I don't like recursions */
fb1585ae 2685 m_resizing = TRUE;
1e6feb95 2686
b9f29261
VS
2687 int currentX, currentY;
2688 GetPosition(&currentX, &currentY);
2689 if (x == -1)
2690 x = currentX;
a200c35e 2691 if (y == -1)
b9f29261 2692 y = currentY;
a200c35e
VS
2693 AdjustForParentClientOrigin(x, y, sizeFlags);
2694
a2053b27 2695 if (m_parent->m_wxwindow == NULL) /* i.e. wxNotebook */
fb1585ae 2696 {
e27ce4e9 2697 /* don't set the size for children of wxNotebook, just take the values. */
fb1585ae
RR
2698 m_x = x;
2699 m_y = y;
2700 m_width = width;
ba4e3652 2701 m_height = height;
fb1585ae 2702 }
ba4e3652 2703 else
fb1585ae 2704 {
da048e3d 2705 GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
148cd9b6 2706
85ad5eb5 2707 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
ba4e3652 2708 {
da048e3d
RR
2709 if (x != -1) m_x = x + pizza->xoffset;
2710 if (y != -1) m_y = y + pizza->yoffset;
ba4e3652
RR
2711 if (width != -1) m_width = width;
2712 if (height != -1) m_height = height;
2713 }
2714 else
2715 {
da048e3d
RR
2716 m_x = x + pizza->xoffset;
2717 m_y = y + pizza->yoffset;
ba4e3652
RR
2718 m_width = width;
2719 m_height = height;
2720 }
47d67540 2721
ba4e3652
RR
2722 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
2723 {
2724 if (width == -1) m_width = 80;
2725 }
2726
2727 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
2728 {
2729 if (height == -1) m_height = 26;
2730 }
8bbe427f 2731
ba4e3652
RR
2732 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
2733 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
d3b4d113
RR
2734 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
2735 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
47d67540 2736
a2053b27 2737 int border = 0;
c50f1fb9 2738 int bottom_border = 0;
f03fc89f 2739
29f538ce 2740 if (GTK_WIDGET_CAN_DEFAULT(m_widget))
c50f1fb9
VZ
2741 {
2742 /* the default button has a border around it */
2743 border = 6;
2744 bottom_border = 5;
2745 }
2746
23efdd02
RR
2747 DoMoveWindow( m_x-border,
2748 m_y-border,
2749 m_width+2*border,
2750 m_height+border+bottom_border );
54517652 2751 }
148cd9b6 2752
5b8a521e
RR
2753 if (m_hasScrolling)
2754 {
1e6feb95 2755 /* Sometimes the client area changes size without the
b6fa52db
RR
2756 whole windows's size changing, but if the whole
2757 windows's size doesn't change, no wxSizeEvent will
2758 normally be sent. Here we add an extra test if
2759 the client test has been changed and this will
2760 be used then. */
5b8a521e
RR
2761 GetClientSize( &m_oldClientWidth, &m_oldClientHeight );
2762 }
2763
54517652 2764/*
6d693bb4
RR
2765 wxPrintf( "OnSize sent from " );
2766 if (GetClassInfo() && GetClassInfo()->GetClassName())
2767 wxPrintf( GetClassInfo()->GetClassName() );
2768 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2769*/
2770
30760ce7
RR
2771 if (!m_nativeSizeEvent)
2772 {
2773 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
2774 event.SetEventObject( this );
2775 GetEventHandler()->ProcessEvent( event );
2776 }
6d693bb4 2777
fb1585ae 2778 m_resizing = FALSE;
362c6693 2779}
c801d85f 2780
1e6feb95 2781void wxWindowGTK::OnInternalIdle()
9390a202 2782{
beab25bd
RR
2783 // Update invalidated regions.
2784 Update();
2785
2786 // Synthetize activate events.
148cd9b6
VZ
2787 if ( g_sendActivateEvent != -1 )
2788 {
2789 bool activate = g_sendActivateEvent != 0;
2790
2791 // do it only once
2792 g_sendActivateEvent = -1;
2793
1e6feb95 2794 wxTheApp->SetActive(activate, (wxWindow *)g_focusWindowLast);
148cd9b6
VZ
2795 }
2796
e8c12a53
VS
2797 if ( g_activeFrameLostFocus )
2798 {
2799 if ( g_activeFrame )
2800 {
45eb5249 2801 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame);
e8c12a53
VS
2802 wxActivateEvent event(wxEVT_ACTIVATE, FALSE, g_activeFrame->GetId());
2803 event.SetEventObject(g_activeFrame);
2804 g_activeFrame->GetEventHandler()->ProcessEvent(event);
2805 g_activeFrame = NULL;
2806 }
2807 g_activeFrameLostFocus = FALSE;
2808 }
2809
9146082c
RR
2810 wxCursor cursor = m_cursor;
2811 if (g_globalCursor.Ok()) cursor = g_globalCursor;
c50f1fb9 2812
f7a11f8c 2813 if (cursor.Ok())
9146082c 2814 {
3017f78d 2815 /* I now set the cursor anew in every OnInternalIdle call
b02da6b1
VZ
2816 as setting the cursor in a parent window also effects the
2817 windows above so that checking for the current cursor is
2818 not possible. */
148cd9b6 2819
9146082c 2820 if (m_wxwindow)
6a008b33 2821 {
da048e3d 2822 GdkWindow *window = GTK_PIZZA(m_wxwindow)->bin_window;
6a008b33 2823 if (window)
c50f1fb9 2824 gdk_window_set_cursor( window, cursor.GetCursor() );
6a008b33
VZ
2825
2826 if (!g_globalCursor.Ok())
2827 cursor = *wxSTANDARD_CURSOR;
2828
2829 window = m_widget->window;
5e014a0c 2830 if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
9146082c 2831 gdk_window_set_cursor( window, cursor.GetCursor() );
5e014a0c 2832
6a008b33
VZ
2833 }
2834 else
2835 {
5e014a0c 2836
9146082c 2837 GdkWindow *window = m_widget->window;
5e014a0c 2838 if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
9146082c 2839 gdk_window_set_cursor( window, cursor.GetCursor() );
5e014a0c 2840
6a008b33 2841 }
9146082c 2842 }
6a008b33 2843
9390a202
RR
2844 UpdateWindowUI();
2845}
2846
1e6feb95 2847void wxWindowGTK::DoGetSize( int *width, int *height ) const
c801d85f 2848{
223d09f6 2849 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2850
fb1585ae
RR
2851 if (width) (*width) = m_width;
2852 if (height) (*height) = m_height;
362c6693 2853}
c801d85f 2854
1e6feb95 2855void wxWindowGTK::DoSetClientSize( int width, int height )
c801d85f 2856{
223d09f6 2857 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2858
1ecc4d80 2859 if (!m_wxwindow)
c801d85f 2860 {
1ecc4d80 2861 SetSize( width, height );
c801d85f
KB
2862 }
2863 else
2864 {
1ecc4d80
RR
2865 int dw = 0;
2866 int dh = 0;
2867
1e6feb95 2868#ifndef __WXUNIVERSAL__
98d3fdbe
RR
2869 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2870 {
5e014a0c 2871 /* when using GTK 1.2 we set the shadow border size to 2 */
6a008b33 2872 dw += 2 * 2;
98d3fdbe
RR
2873 dh += 2 * 2;
2874 }
5e014a0c
RR
2875 if (HasFlag(wxSIMPLE_BORDER))
2876 {
2877 /* when using GTK 1.2 we set the simple border size to 1 */
2878 dw += 1 * 2;
2879 dh += 1 * 2;
2880 }
1e6feb95 2881#endif // __WXUNIVERSAL__
034be888 2882
5b8a521e 2883 if (m_hasScrolling)
98d3fdbe 2884 {
324dbfec 2885 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2daa0ce9 2886
9000c624
RR
2887 GtkRequisition vscroll_req;
2888 vscroll_req.width = 2;
2889 vscroll_req.height = 2;
dd00f3f6 2890 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
9000c624 2891 (scroll_window->vscrollbar, &vscroll_req );
2daa0ce9 2892
9000c624
RR
2893 GtkRequisition hscroll_req;
2894 hscroll_req.width = 2;
2895 hscroll_req.height = 2;
dd00f3f6 2896 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
9000c624
RR
2897 (scroll_window->hscrollbar, &hscroll_req );
2898
dd00f3f6 2899 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
324dbfec 2900
1ecc4d80
RR
2901 if (scroll_window->vscrollbar_visible)
2902 {
9000c624 2903 dw += vscroll_req.width;
1ecc4d80
RR
2904 dw += scroll_class->scrollbar_spacing;
2905 }
2906
2907 if (scroll_window->hscrollbar_visible)
2908 {
9000c624 2909 dh += hscroll_req.height;
63cc5d9d 2910 dh += scroll_class->scrollbar_spacing;
1ecc4d80 2911 }
9000c624 2912 }
1ecc4d80 2913
034be888 2914 SetSize( width+dw, height+dh );
1ecc4d80 2915 }
362c6693 2916}
c801d85f 2917
1e6feb95 2918void wxWindowGTK::DoGetClientSize( int *width, int *height ) const
c801d85f 2919{
223d09f6 2920 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2921
1ecc4d80
RR
2922 if (!m_wxwindow)
2923 {
2924 if (width) (*width) = m_width;
2925 if (height) (*height) = m_height;
c801d85f
KB
2926 }
2927 else
2928 {
1ecc4d80
RR
2929 int dw = 0;
2930 int dh = 0;
2931
1e6feb95 2932#ifndef __WXUNIVERSAL__
98d3fdbe
RR
2933 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2934 {
5e014a0c 2935 /* when using GTK 1.2 we set the shadow border size to 2 */
6a008b33 2936 dw += 2 * 2;
98d3fdbe
RR
2937 dh += 2 * 2;
2938 }
5e014a0c
RR
2939 if (HasFlag(wxSIMPLE_BORDER))
2940 {
2941 /* when using GTK 1.2 we set the simple border size to 1 */
2942 dw += 1 * 2;
2943 dh += 1 * 2;
2944 }
1e6feb95 2945#endif // __WXUNIVERSAL__
9000c624 2946
5b8a521e 2947 if (m_hasScrolling)
98d3fdbe 2948 {
6a008b33 2949 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2daa0ce9 2950
9000c624
RR
2951 GtkRequisition vscroll_req;
2952 vscroll_req.width = 2;
2953 vscroll_req.height = 2;
dd00f3f6 2954 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
9000c624 2955 (scroll_window->vscrollbar, &vscroll_req );
2daa0ce9 2956
9000c624
RR
2957 GtkRequisition hscroll_req;
2958 hscroll_req.width = 2;
2959 hscroll_req.height = 2;
dd00f3f6 2960 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
9000c624
RR
2961 (scroll_window->hscrollbar, &hscroll_req );
2962
dd00f3f6 2963 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
6a008b33 2964
1ecc4d80
RR
2965 if (scroll_window->vscrollbar_visible)
2966 {
9000c624 2967 dw += vscroll_req.width;
1ecc4d80
RR
2968 dw += scroll_class->scrollbar_spacing;
2969 }
2970
2971 if (scroll_window->hscrollbar_visible)
2972 {
9000c624 2973 dh += hscroll_req.height;
1ecc4d80
RR
2974 dh += scroll_class->scrollbar_spacing;
2975 }
6a008b33 2976 }
47d67540 2977
1ecc4d80
RR
2978 if (width) (*width) = m_width - dw;
2979 if (height) (*height) = m_height - dh;
2980 }
1e6feb95 2981
f94fca1b
RR
2982/*
2983 printf( "GetClientSize, name %s ", GetName().c_str() );
2984 if (width) printf( " width = %d", (*width) );
2985 if (height) printf( " height = %d", (*height) );
2986 printf( "\n" );
2987*/
362c6693 2988}
c801d85f 2989
1e6feb95 2990void wxWindowGTK::DoGetPosition( int *x, int *y ) const
c801d85f 2991{
223d09f6 2992 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2993
bf0c00c6
RR
2994 int dx = 0;
2995 int dy = 0;
2996 if (m_parent && m_parent->m_wxwindow)
2997 {
da048e3d 2998 GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
b02da6b1
VZ
2999 dx = pizza->xoffset;
3000 dy = pizza->yoffset;
bf0c00c6 3001 }
94633ad9 3002
496beb3f
VS
3003 if (x) (*x) = m_x - dx;
3004 if (y) (*y) = m_y - dy;
362c6693 3005}
c801d85f 3006
1e6feb95 3007void wxWindowGTK::DoClientToScreen( int *x, int *y ) const
c801d85f 3008{
223d09f6 3009 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 3010
a2053b27
RR
3011 if (!m_widget->window) return;
3012
43a18898
RR
3013 GdkWindow *source = (GdkWindow *) NULL;
3014 if (m_wxwindow)
da048e3d 3015 source = GTK_PIZZA(m_wxwindow)->bin_window;
43a18898
RR
3016 else
3017 source = m_widget->window;
47d67540 3018
43a18898
RR
3019 int org_x = 0;
3020 int org_y = 0;
3021 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 3022
43a18898 3023 if (!m_wxwindow)
c801d85f 3024 {
43a18898
RR
3025 if (GTK_WIDGET_NO_WINDOW (m_widget))
3026 {
3027 org_x += m_widget->allocation.x;
3028 org_y += m_widget->allocation.y;
3029 }
362c6693 3030 }
47d67540 3031
43a18898
RR
3032 if (x) *x += org_x;
3033 if (y) *y += org_y;
362c6693 3034}
c801d85f 3035
1e6feb95 3036void wxWindowGTK::DoScreenToClient( int *x, int *y ) const
c801d85f 3037{
223d09f6 3038 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 3039
a2053b27
RR
3040 if (!m_widget->window) return;
3041
1ecc4d80
RR
3042 GdkWindow *source = (GdkWindow *) NULL;
3043 if (m_wxwindow)
da048e3d 3044 source = GTK_PIZZA(m_wxwindow)->bin_window;
1ecc4d80
RR
3045 else
3046 source = m_widget->window;
47d67540 3047
1ecc4d80
RR
3048 int org_x = 0;
3049 int org_y = 0;
3050 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 3051
1ecc4d80 3052 if (!m_wxwindow)
c801d85f 3053 {
1ecc4d80
RR
3054 if (GTK_WIDGET_NO_WINDOW (m_widget))
3055 {
3056 org_x += m_widget->allocation.x;
3057 org_y += m_widget->allocation.y;
3058 }
362c6693 3059 }
47d67540 3060
1ecc4d80
RR
3061 if (x) *x -= org_x;
3062 if (y) *y -= org_y;
362c6693 3063}
c801d85f 3064
1e6feb95 3065bool wxWindowGTK::Show( bool show )
c801d85f 3066{
223d09f6 3067 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
47d67540 3068
739730ca
RR
3069 if (!wxWindowBase::Show(show))
3070 {
3071 // nothing to do
f03fc89f 3072 return FALSE;
739730ca 3073 }
8bbe427f 3074
f03fc89f
VZ
3075 if (show)
3076 gtk_widget_show( m_widget );
1ecc4d80 3077 else
f03fc89f 3078 gtk_widget_hide( m_widget );
8bbe427f 3079
f03fc89f 3080 return TRUE;
362c6693 3081}
c801d85f 3082
3379ed37 3083static void wxWindowNotifyEnable(wxWindowGTK* win, bool enable)
fdca68a6
JS
3084{
3085 win->OnParentEnable(enable);
3086
3087 // Recurse, so that children have the opportunity to Do The Right Thing
3088 // and reset colours that have been messed up by a parent's (really ancestor's)
3089 // Enable call
3090 for ( wxWindowList::Node *node = win->GetChildren().GetFirst();
3091 node;
3092 node = node->GetNext() )
3093 {
3094 wxWindow *child = node->GetData();
3095 if (!child->IsKindOf(CLASSINFO(wxDialog)) && !child->IsKindOf(CLASSINFO(wxFrame)))
3096 wxWindowNotifyEnable(child, enable);
3097 }
3098}
3099
3379ed37 3100bool wxWindowGTK::Enable( bool enable )
c801d85f 3101{
223d09f6 3102 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
5e0aa05a 3103
739730ca
RR
3104 if (!wxWindowBase::Enable(enable))
3105 {
3106 // nothing to do
f03fc89f 3107 return FALSE;
739730ca 3108 }
1ecc4d80 3109
f03fc89f
VZ
3110 gtk_widget_set_sensitive( m_widget, enable );
3111 if ( m_wxwindow )
3112 gtk_widget_set_sensitive( m_wxwindow, enable );
ff8bfdbb 3113
fdca68a6 3114 wxWindowNotifyEnable(this, enable);
513903c4 3115
f03fc89f 3116 return TRUE;
362c6693 3117}
c801d85f 3118
1e6feb95 3119int wxWindowGTK::GetCharHeight() const
2f2aa628 3120{
223d09f6 3121 wxCHECK_MSG( (m_widget != NULL), 12, wxT("invalid window") );
47d67540 3122
223d09f6 3123 wxCHECK_MSG( m_font.Ok(), 12, wxT("invalid font") );
2f2aa628 3124
f03fc89f
VZ
3125 GdkFont *font = m_font.GetInternalFont( 1.0 );
3126
3127 return font->ascent + font->descent;
362c6693 3128}
c801d85f 3129
1e6feb95 3130int wxWindowGTK::GetCharWidth() const
c33c4050 3131{
223d09f6 3132 wxCHECK_MSG( (m_widget != NULL), 8, wxT("invalid window") );
47d67540 3133
223d09f6 3134 wxCHECK_MSG( m_font.Ok(), 8, wxT("invalid font") );
47d67540 3135
463c1fa1 3136 GdkFont *font = m_font.GetInternalFont( 1.0 );
ff8bfdbb 3137
463c1fa1 3138 return gdk_string_width( font, "H" );
c33c4050
RR
3139}
3140
1e6feb95 3141void wxWindowGTK::GetTextExtent( const wxString& string,
f03fc89f
VZ
3142 int *x,
3143 int *y,
3144 int *descent,
3145 int *externalLeading,
3146 const wxFont *theFont ) const
c33c4050 3147{
463c1fa1
RR
3148 wxFont fontToUse = m_font;
3149 if (theFont) fontToUse = *theFont;
47d67540 3150
223d09f6 3151 wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
47d67540 3152
463c1fa1 3153 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
05939a81 3154 if (x) (*x) = gdk_string_width( font, string.mbc_str() );
463c1fa1
RR
3155 if (y) (*y) = font->ascent + font->descent;
3156 if (descent) (*descent) = font->descent;
3157 if (externalLeading) (*externalLeading) = 0; // ??
c33c4050
RR
3158}
3159
1e6feb95 3160void wxWindowGTK::SetFocus()
c801d85f 3161{
223d09f6 3162 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2daa0ce9 3163
780bb874
RR
3164#if 0
3165 wxPrintf( "SetFocus from " );
3166 if (GetClassInfo() && GetClassInfo()->GetClassName())
3167 wxPrintf( GetClassInfo()->GetClassName() );
3168 wxPrintf( ".\n" );
3169#endif
3170
354aa1e3
RR
3171 if (m_wxwindow)
3172 {
173348db 3173 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow))
b231914f
VZ
3174 {
3175 // see comment in gtk_window_focus_out_callback()
3176 gs_widgetLastFocus = m_wxwindow;
173348db 3177 gtk_widget_grab_focus (m_wxwindow);
b231914f 3178 }
354aa1e3 3179 }
b231914f 3180 else if (m_widget)
c801d85f 3181 {
173348db 3182 if (GTK_WIDGET_CAN_FOCUS(m_widget) && !GTK_WIDGET_HAS_FOCUS (m_widget) )
463c1fa1 3183 {
354aa1e3 3184 gtk_widget_grab_focus (m_widget);
463c1fa1 3185 }
354aa1e3 3186 else if (GTK_IS_CONTAINER(m_widget))
ff8bfdbb 3187 {
354aa1e3 3188 gtk_container_focus( GTK_CONTAINER(m_widget), GTK_DIR_TAB_FORWARD );
ff8bfdbb
VZ
3189 }
3190 else
3191 {
b02da6b1 3192 // ?
ff8bfdbb 3193 }
362c6693 3194 }
94633ad9 3195
780bb874
RR
3196#if 0
3197 wxPrintf( "SetFocus finished in " );
3198 if (GetClassInfo() && GetClassInfo()->GetClassName())
3199 wxPrintf( GetClassInfo()->GetClassName() );
3200 wxPrintf( ".\n" );
3201#endif
3202
362c6693 3203}
c801d85f 3204
1e6feb95 3205bool wxWindowGTK::AcceptsFocus() const
b292e2f5 3206{
f03fc89f 3207 return m_acceptsFocus && wxWindowBase::AcceptsFocus();
b292e2f5
RR
3208}
3209
1e6feb95 3210bool wxWindowGTK::Reparent( wxWindowBase *newParentBase )
463c1fa1 3211{
223d09f6 3212 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
c50f1fb9 3213
1e6feb95
VZ
3214 wxWindowGTK *oldParent = m_parent,
3215 *newParent = (wxWindowGTK *)newParentBase;
a2053b27 3216
5fd11f09
RR
3217 wxASSERT( GTK_IS_WIDGET(m_widget) );
3218
f03fc89f
VZ
3219 if ( !wxWindowBase::Reparent(newParent) )
3220 return FALSE;
8bbe427f 3221
5fd11f09
RR
3222 wxASSERT( GTK_IS_WIDGET(m_widget) );
3223
3224 /* prevent GTK from deleting the widget arbitrarily */
3225 gtk_widget_ref( m_widget );
3226
8ce63e9d
RR
3227 if (oldParent)
3228 {
3017f78d 3229 gtk_container_remove( GTK_CONTAINER(m_widget->parent), m_widget );
8ce63e9d 3230 }
c50f1fb9 3231
5fd11f09
RR
3232 wxASSERT( GTK_IS_WIDGET(m_widget) );
3233
8ce63e9d
RR
3234 if (newParent)
3235 {
3236 /* insert GTK representation */
3237 (*(newParent->m_insertCallback))(newParent, this);
3238 }
c50f1fb9 3239
5fd11f09
RR
3240 /* reverse: prevent GTK from deleting the widget arbitrarily */
3241 gtk_widget_unref( m_widget );
148cd9b6 3242
f03fc89f 3243 return TRUE;
362c6693 3244}
c801d85f 3245
1e6feb95 3246void wxWindowGTK::DoAddChild(wxWindowGTK *child)
ddb6bc71 3247{
223d09f6 3248 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
ddb6bc71 3249
223d09f6 3250 wxASSERT_MSG( (child != NULL), wxT("invalid child window") );
ddb6bc71 3251
223d09f6 3252 wxASSERT_MSG( (m_insertCallback != NULL), wxT("invalid child insertion function") );
c50f1fb9 3253
ddb6bc71
RR
3254 /* add to list */
3255 AddChild( child );
c50f1fb9 3256
ddb6bc71
RR
3257 /* insert GTK representation */
3258 (*m_insertCallback)(this, child);
3259}
3260
1e6feb95 3261void wxWindowGTK::Raise()
362c6693 3262{
223d09f6 3263 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 3264
a2053b27
RR
3265 if (!m_widget->window) return;
3266
f03fc89f 3267 gdk_window_raise( m_widget->window );
362c6693
RR
3268}
3269
1e6feb95 3270void wxWindowGTK::Lower()
362c6693 3271{
223d09f6 3272 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 3273
a2053b27
RR
3274 if (!m_widget->window) return;
3275
f03fc89f 3276 gdk_window_lower( m_widget->window );
362c6693 3277}
c801d85f 3278
1e6feb95 3279bool wxWindowGTK::SetCursor( const wxCursor &cursor )
86b29a61 3280{
223d09f6 3281 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
86b29a61 3282
f6bcfd97
BP
3283 if (cursor == m_cursor)
3284 return FALSE;
3285
3286 if (g_isIdle)
3287 wxapp_install_idle_handler();
1e6feb95 3288
f6bcfd97
BP
3289 if (cursor == wxNullCursor)
3290 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR );
3291 else
3292 return wxWindowBase::SetCursor( cursor );
362c6693 3293}
c801d85f 3294
1e6feb95 3295void wxWindowGTK::WarpPointer( int x, int y )
4f22cf8d 3296{
223d09f6 3297 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
85eb36c2 3298
3bcc8d15
RR
3299 // We provide this function ourselves as it is
3300 // missing in GDK (top of this file).
148cd9b6 3301
ed673c6a
RR
3302 GdkWindow *window = (GdkWindow*) NULL;
3303 if (m_wxwindow)
da048e3d 3304 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3305 else
3306 window = GetConnectWidget()->window;
148cd9b6 3307
ed673c6a
RR
3308 if (window)
3309 gdk_window_warp_pointer( window, x, y );
4f22cf8d
RR
3310}
3311
1e6feb95 3312void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
c801d85f 3313{
f2593d0d 3314 if (!m_widget) return;
a2053b27
RR
3315 if (!m_widget->window) return;
3316
1e6feb95
VZ
3317 // temporarily hide the caret to avoid nasty interactions between caret
3318 // drawing and the window contents redraw
3319#if 0 // def wxUSE_CARET -- doesn't seem to help :-(
3320 wxCaretSuspend cs((wxWindow *)this);
3321#endif // wxUSE_CARET
3322
139adb6a 3323 if (eraseBackground && m_wxwindow && m_wxwindow->window)
c801d85f 3324 {
139adb6a
RR
3325 if (rect)
3326 {
3bcc8d15
RR
3327 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3328 m_clearRegion.Union( rect->x, rect->y, rect->width, rect->height );
139adb6a
RR
3329 }
3330 else
3331 {
3bcc8d15
RR
3332 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3333 m_clearRegion.Clear();
3334 m_clearRegion.Union( 0, 0, m_wxwindow->allocation.width, m_wxwindow->allocation.height );
139adb6a
RR
3335 }
3336 }
ff8bfdbb 3337
3bcc8d15 3338 if (rect)
139adb6a
RR
3339 {
3340 if (m_wxwindow)
b02da6b1 3341 {
23716407 3342 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3bcc8d15 3343 m_updateRegion.Union( rect->x, rect->y, rect->width, rect->height );
b02da6b1 3344 }
ff8bfdbb 3345 else
b6fa52db 3346 {
3bcc8d15
RR
3347 GdkRectangle gdk_rect;
3348 gdk_rect.x = rect->x;
3349 gdk_rect.y = rect->y;
3350 gdk_rect.width = rect->width;
3351 gdk_rect.height = rect->height;
3352 gtk_widget_draw( m_widget, &gdk_rect );
b6fa52db 3353 }
362c6693 3354 }
c801d85f 3355 else
139adb6a 3356 {
139adb6a 3357 if (m_wxwindow)
b02da6b1 3358 {
23716407 3359 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3bcc8d15
RR
3360 m_updateRegion.Clear();
3361 m_updateRegion.Union( 0, 0, m_wxwindow->allocation.width, m_wxwindow->allocation.height );
b02da6b1 3362 }
139adb6a 3363 else
b6fa52db 3364 {
3bcc8d15 3365 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
b6fa52db 3366 }
139adb6a 3367 }
362c6693 3368}
c801d85f 3369
beab25bd
RR
3370void wxWindowGTK::Update()
3371{
3372 if (!m_updateRegion.IsEmpty())
3373 {
23716407 3374 GtkSendPaintEvents();
beab25bd
RR
3375 }
3376}
3377
3378void wxWindowGTK::GtkSendPaintEvents()
3379{
3bcc8d15
RR
3380 if (!m_wxwindow)
3381 {
3382 m_clearRegion.Clear();
3383 m_updateRegion.Clear();
3384 return;
3385 }
beab25bd 3386
3bcc8d15 3387 m_clipPaintRegion = TRUE;
beab25bd 3388
3bcc8d15 3389 if (!m_clearRegion.IsEmpty())
beab25bd 3390 {
3bcc8d15
RR
3391 wxWindowDC dc( (wxWindow*)this );
3392 dc.SetClippingRegion( m_clearRegion );
3393
3394 wxEraseEvent erase_event( GetId(), &dc );
3395 erase_event.SetEventObject( this );
3396
beab25bd
RR
3397 if (!GetEventHandler()->ProcessEvent(erase_event))
3398 {
3bcc8d15 3399 wxRegionIterator upd( m_clearRegion );
beab25bd
RR
3400 while (upd)
3401 {
3bcc8d15
RR
3402 gdk_window_clear_area( GTK_PIZZA(m_wxwindow)->bin_window,
3403 upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() );
beab25bd
RR
3404 upd ++;
3405 }
3406 }
3bcc8d15 3407 m_clearRegion.Clear();
beab25bd 3408 }
beab25bd
RR
3409
3410 wxNcPaintEvent nc_paint_event( GetId() );
3411 nc_paint_event.SetEventObject( this );
3412 GetEventHandler()->ProcessEvent( nc_paint_event );
3413
3414 wxPaintEvent paint_event( GetId() );
3415 paint_event.SetEventObject( this );
3416 GetEventHandler()->ProcessEvent( paint_event );
3417
beab25bd 3418 m_clipPaintRegion = FALSE;
c89f5c02
RR
3419
3420 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3421 if (g_list_length(pizza->children) > 0)
3422 {
3423 // The following code will result in all window-less widgets
3424 // being redrawn because the wxWindows class is allowed to
3425 // paint over the window-less widgets.
3426 GList *children = pizza->children;
3427 while (children)
3428 {
3429 GtkPizzaChild *child = (GtkPizzaChild*) children->data;
3430 children = children->next;
3431
3432 if (GTK_WIDGET_NO_WINDOW (child->widget) &&
3433 GTK_WIDGET_DRAWABLE (child->widget))
3434 {
3435 // Get intersection of widget area and update region
3436 wxRegion region( m_updateRegion );
3437 region.Intersect( child->widget->allocation.x,
3438 child->widget->allocation.y,
3439 child->widget->allocation.width,
3440 child->widget->allocation.height );
3441
3442 // Redraw the whole widget anyway
3443 if (!region.IsEmpty())
3444 gtk_widget_draw( child->widget, NULL );
3445 }
3446 }
3447 }
3448
3449 m_updateRegion.Clear();
beab25bd
RR
3450}
3451
1e6feb95 3452void wxWindowGTK::Clear()
c801d85f 3453{
223d09f6 3454 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3455
a2053b27
RR
3456 if (!m_widget->window) return;
3457
f234c60c
RR
3458 if (m_wxwindow && m_wxwindow->window)
3459 {
c916e13b 3460// gdk_window_clear( m_wxwindow->window );
f234c60c 3461 }
362c6693 3462}
c801d85f 3463
ff8bfdbb 3464#if wxUSE_TOOLTIPS
1e6feb95 3465void wxWindowGTK::DoSetToolTip( wxToolTip *tip )
b1170810 3466{
f03fc89f 3467 wxWindowBase::DoSetToolTip(tip);
ff8bfdbb 3468
f03fc89f 3469 if (m_tooltip)
3379ed37 3470 m_tooltip->Apply( (wxWindow *)this );
b1170810
RR
3471}
3472
1e6feb95 3473void wxWindowGTK::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
b1170810 3474{
dcf924a3 3475 gtk_tooltips_set_tip( tips, GetConnectWidget(), wxConvCurrent->cWX2MB(tip), (gchar*) NULL );
301cd871 3476}
ff8bfdbb 3477#endif // wxUSE_TOOLTIPS
b1170810 3478
1e6feb95 3479bool wxWindowGTK::SetBackgroundColour( const wxColour &colour )
c801d85f 3480{
223d09f6 3481 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
8bbe427f 3482
739730ca
RR
3483 if (!wxWindowBase::SetBackgroundColour(colour))
3484 {
3485 // don't leave if the GTK widget has just
3486 // been realized
3487 if (!m_delayedBackgroundColour) return FALSE;
3488 }
c50f1fb9 3489
ed673c6a
RR
3490 GdkWindow *window = (GdkWindow*) NULL;
3491 if (m_wxwindow)
da048e3d 3492 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3493 else
3494 window = GetConnectWidget()->window;
148cd9b6 3495
ed673c6a 3496 if (!window)
739730ca
RR
3497 {
3498 // indicate that a new style has been set
c50f1fb9
VZ
3499 // but it couldn't get applied as the
3500 // widget hasn't been realized yet.
3501 m_delayedBackgroundColour = TRUE;
739730ca 3502 }
ca298c88 3503
0f2f4986 3504 if ((m_wxwindow) &&
103aab26 3505 (m_wxwindow->window) &&
a756f210 3506 (m_backgroundColour != wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)))
3bc755fc 3507 {
a2053b27
RR
3508 /* wxMSW doesn't clear the window here. I don't do that either to
3509 provide compatibility. call Clear() to do the job. */
ca298c88 3510
ed673c6a
RR
3511 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
3512 gdk_window_set_background( window, m_backgroundColour.GetColor() );
3bc755fc 3513 }
8bbe427f 3514
0f2f4986 3515 ApplyWidgetStyle();
c801d85f 3516
f03fc89f 3517 return TRUE;
6de97a3b
RR
3518}
3519
1e6feb95 3520bool wxWindowGTK::SetForegroundColour( const wxColour &colour )
6de97a3b 3521{
223d09f6 3522 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
8bbe427f 3523
739730ca
RR
3524 if (!wxWindowBase::SetForegroundColour(colour))
3525 {
3526 // don't leave if the GTK widget has just
3527 // been realized
3528 if (!m_delayedForegroundColour) return FALSE;
3529 }
c50f1fb9 3530
ed673c6a
RR
3531 GdkWindow *window = (GdkWindow*) NULL;
3532 if (m_wxwindow)
da048e3d 3533 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3534 else
3535 window = GetConnectWidget()->window;
148cd9b6 3536
ed673c6a 3537 if (!window)
739730ca
RR
3538 {
3539 // indicate that a new style has been set
c50f1fb9
VZ
3540 // but it couldn't get applied as the
3541 // widget hasn't been realized yet.
3542 m_delayedForegroundColour = TRUE;
739730ca 3543 }
2b07d713 3544
0f2f4986 3545 ApplyWidgetStyle();
f03fc89f
VZ
3546
3547 return TRUE;
58614078
RR
3548}
3549
1e6feb95 3550GtkStyle *wxWindowGTK::GetWidgetStyle()
58614078 3551{
103aab26
RR
3552 if (m_widgetStyle)
3553 {
3554 GtkStyle *remake = gtk_style_copy( m_widgetStyle );
dd00f3f6
OK
3555#ifdef __WXGTK20__
3556 /* FIXME: is this necessary? */
3557 _G_TYPE_IGC(remake, GtkObjectClass) = _G_TYPE_IGC(m_widgetStyle, GtkObjectClass);
3558#else
103aab26 3559 remake->klass = m_widgetStyle->klass;
dd00f3f6 3560#endif
2daa0ce9 3561
103aab26
RR
3562 gtk_style_unref( m_widgetStyle );
3563 m_widgetStyle = remake;
3564 }
3565 else
3566 {
3567 GtkStyle *def = gtk_rc_get_style( m_widget );
e6527f9d 3568
103aab26
RR
3569 if (!def)
3570 def = gtk_widget_get_default_style();
e6527f9d 3571
103aab26 3572 m_widgetStyle = gtk_style_copy( def );
dd00f3f6
OK
3573#ifdef __WXGTK20__
3574 /* FIXME: is this necessary? */
3575 _G_TYPE_IGC(m_widgetStyle, GtkObjectClass) = _G_TYPE_IGC(def, GtkObjectClass);
3576#else
103aab26 3577 m_widgetStyle->klass = def->klass;
dd00f3f6 3578#endif
103aab26 3579 }
8bbe427f 3580
1ecc4d80 3581 return m_widgetStyle;
58614078
RR
3582}
3583
1e6feb95 3584void wxWindowGTK::SetWidgetStyle()
58614078 3585{
a56fcaaf 3586#if DISABLE_STYLE_IF_BROKEN_THEM
fb65642c
RR
3587 if (m_widget->style->engine_data)
3588 {
3589 static bool s_warningPrinted = FALSE;
3590 if (!s_warningPrinted)
3591 {
3592 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3593 s_warningPrinted = TRUE;
3594 }
3595 m_widgetStyle = m_widget->style;
3596 return;
3597 }
a56fcaaf 3598#endif
fb65642c 3599
1ecc4d80
RR
3600 GtkStyle *style = GetWidgetStyle();
3601
a756f210 3602 if (m_font != wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ))
db434467
RR
3603 {
3604 gdk_font_unref( style->font );
3605 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
3606 }
1ecc4d80
RR
3607
3608 if (m_foregroundColour.Ok())
3609 {
454e2a22 3610 m_foregroundColour.CalcPixel( gtk_widget_get_colormap( m_widget ) );
a756f210 3611 if (m_foregroundColour != wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT))
db434467
RR
3612 {
3613 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
3614 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
3615 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
3616 }
1e6feb95 3617 else
f6bcfd97
BP
3618 {
3619 // Try to restore the gtk default style. This is still a little
3620 // oversimplified for what is probably really needed here for controls
3621 // other than buttons, but is better than not being able to (re)set a
3622 // control's foreground colour to *wxBLACK -- RL
3623 GtkStyle *def = gtk_rc_get_style( m_widget );
3624
3625 if (!def)
3626 def = gtk_widget_get_default_style();
3627
3628 style->fg[GTK_STATE_NORMAL] = def->fg[GTK_STATE_NORMAL];
3629 style->fg[GTK_STATE_PRELIGHT] = def->fg[GTK_STATE_PRELIGHT];
3630 style->fg[GTK_STATE_ACTIVE] = def->fg[GTK_STATE_ACTIVE];
3631 }
1ecc4d80
RR
3632 }
3633
3634 if (m_backgroundColour.Ok())
3635 {
454e2a22 3636 m_backgroundColour.CalcPixel( gtk_widget_get_colormap( m_widget ) );
a756f210 3637 if (m_backgroundColour != wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE))
db434467
RR
3638 {
3639 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
3640 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
3641 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
3642 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
3643 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
3644 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
3645 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
3646 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
f6bcfd97
BP
3647 }
3648 else
3649 {
3650 // Try to restore the gtk default style. This is still a little
3651 // oversimplified for what is probably really needed here for controls
3652 // other than buttons, but is better than not being able to (re)set a
3653 // control's background colour to default grey and means resetting a
1e6feb95 3654 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
f6bcfd97
BP
3655 // behavior -- RL
3656 GtkStyle *def = gtk_rc_get_style( m_widget );
3657
3658 if (!def)
3659 def = gtk_widget_get_default_style();
3660
3661 style->bg[GTK_STATE_NORMAL] = def->bg[GTK_STATE_NORMAL];
3662 style->base[GTK_STATE_NORMAL] = def->base[GTK_STATE_NORMAL];
3663 style->bg[GTK_STATE_PRELIGHT] = def->bg[GTK_STATE_PRELIGHT];
3664 style->base[GTK_STATE_PRELIGHT] = def->base[GTK_STATE_PRELIGHT];
3665 style->bg[GTK_STATE_ACTIVE] = def->bg[GTK_STATE_ACTIVE];
3666 style->base[GTK_STATE_ACTIVE] = def->base[GTK_STATE_ACTIVE];
3667 style->bg[GTK_STATE_INSENSITIVE] = def->bg[GTK_STATE_INSENSITIVE];
3668 style->base[GTK_STATE_INSENSITIVE] = def->base[GTK_STATE_INSENSITIVE];
3669 }
1ecc4d80 3670 }
a81258be
RR
3671}
3672
1e6feb95 3673void wxWindowGTK::ApplyWidgetStyle()
a81258be 3674{
6de97a3b
RR
3675}
3676
2259e007
RR
3677//-----------------------------------------------------------------------------
3678// Pop-up menu stuff
3679//-----------------------------------------------------------------------------
3680
6522713c 3681#if wxUSE_MENUS_NATIVE
1e6feb95 3682
90350682
VZ
3683extern "C"
3684void gtk_pop_hide_callback( GtkWidget *WXUNUSED(widget), bool* is_waiting )
2259e007
RR
3685{
3686 *is_waiting = FALSE;
3687}
3688
1e6feb95 3689static void SetInvokingWindow( wxMenu *menu, wxWindowGTK *win )
30dea054 3690{
1ecc4d80 3691 menu->SetInvokingWindow( win );
1987af7e 3692 wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
1ecc4d80
RR
3693 while (node)
3694 {
1987af7e 3695 wxMenuItem *menuitem = node->GetData();
1ecc4d80
RR
3696 if (menuitem->IsSubMenu())
3697 {
ff8bfdbb
VZ
3698 SetInvokingWindow( menuitem->GetSubMenu(), win );
3699 }
1987af7e
VZ
3700
3701 node = node->GetNext();
1ecc4d80 3702 }
362c6693 3703}
30dea054 3704
e3473203
VZ
3705// used to pass the coordinates from wxWindowGTK::DoPopupMenu() to
3706// wxPopupMenuPositionCallback()
3707//
3708// should be safe even in the MT case as the user can hardly popup 2 menus
3709// simultaneously, can he?
0c77152e
RR
3710static gint gs_pop_x = 0;
3711static gint gs_pop_y = 0;
3712
295272bd
VZ
3713extern "C" void wxPopupMenuPositionCallback( GtkMenu *menu,
3714 gint *x, gint *y,
3715 gpointer WXUNUSED(user_data) )
0c77152e 3716{
e3473203
VZ
3717 // ensure that the menu appears entirely on screen
3718 GtkRequisition req;
3719 gtk_widget_get_child_requisition(GTK_WIDGET(menu), &req);
3720
3721 wxSize sizeScreen = wxGetDisplaySize();
3722
3723 gint xmax = sizeScreen.x - req.width,
3724 ymax = sizeScreen.y - req.height;
3725
3726 *x = gs_pop_x < xmax ? gs_pop_x : xmax;
3727 *y = gs_pop_y < ymax ? gs_pop_y : ymax;
0c77152e
RR
3728}
3729
1e6feb95 3730bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y )
30dea054 3731{
223d09f6 3732 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
47d67540 3733
223d09f6 3734 wxCHECK_MSG( menu != NULL, FALSE, wxT("invalid popup-menu") );
8bbe427f 3735
1ecc4d80 3736 SetInvokingWindow( menu, this );
ff8bfdbb 3737
631f1bfe
JS
3738 menu->UpdateUI();
3739
0c77152e
RR
3740 gs_pop_x = x;
3741 gs_pop_y = y;
e3473203 3742 ClientToScreen( &gs_pop_x, &gs_pop_y );
ff8bfdbb 3743
2259e007 3744 bool is_waiting = TRUE;
148cd9b6 3745
90350682
VZ
3746 gtk_signal_connect( GTK_OBJECT(menu->m_menu),
3747 "hide",
3748 GTK_SIGNAL_FUNC(gtk_pop_hide_callback),
3749 (gpointer)&is_waiting );
2259e007 3750
1ecc4d80 3751 gtk_menu_popup(
47d67540 3752 GTK_MENU(menu->m_menu),
e3473203
VZ
3753 (GtkWidget *) NULL, // parent menu shell
3754 (GtkWidget *) NULL, // parent menu item
3755 wxPopupMenuPositionCallback, // function to position it
3756 NULL, // client data
3757 0, // button used to activate it
3758 gs_timeLastClick // the time of activation
47d67540 3759 );
148cd9b6 3760
956dbab1
RR
3761 while (is_waiting)
3762 {
3763 while (gtk_events_pending())
3764 gtk_main_iteration();
3765 }
2259e007 3766
1ecc4d80 3767 return TRUE;
30dea054
RR
3768}
3769
6522713c 3770#endif // wxUSE_MENUS_NATIVE
1e6feb95 3771
06cfab17 3772#if wxUSE_DRAG_AND_DROP
ac57418f 3773
1e6feb95 3774void wxWindowGTK::SetDropTarget( wxDropTarget *dropTarget )
c801d85f 3775{
223d09f6 3776 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3777
1ecc4d80 3778 GtkWidget *dnd_widget = GetConnectWidget();
47d67540 3779
1ecc4d80 3780 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
47d67540 3781
1ecc4d80
RR
3782 if (m_dropTarget) delete m_dropTarget;
3783 m_dropTarget = dropTarget;
47d67540 3784
1ecc4d80 3785 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
362c6693 3786}
c801d85f 3787
f03fc89f 3788#endif // wxUSE_DRAG_AND_DROP
ac57418f 3789
1e6feb95 3790GtkWidget* wxWindowGTK::GetConnectWidget()
e3e65dac 3791{
1ecc4d80
RR
3792 GtkWidget *connect_widget = m_widget;
3793 if (m_wxwindow) connect_widget = m_wxwindow;
47d67540 3794
1ecc4d80 3795 return connect_widget;
e3e65dac 3796}
47d67540 3797
1e6feb95 3798bool wxWindowGTK::IsOwnGtkWindow( GdkWindow *window )
903f689b 3799{
148cd9b6 3800 if (m_wxwindow)
da048e3d 3801 return (window == GTK_PIZZA(m_wxwindow)->bin_window);
148cd9b6 3802
1ecc4d80 3803 return (window == m_widget->window);
903f689b
RR
3804}
3805
1e6feb95 3806bool wxWindowGTK::SetFont( const wxFont &font )
c801d85f 3807{
223d09f6 3808 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
c801d85f 3809
739730ca
RR
3810 if (!wxWindowBase::SetFont(font))
3811 {
454e2a22 3812 return FALSE;
739730ca 3813 }
9c288e4d 3814
a756f210 3815 wxColour sysbg = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE );
f03fc89f 3816 if ( sysbg == m_backgroundColour )
ae0bdb01
RR
3817 {
3818 m_backgroundColour = wxNullColour;
3819 ApplyWidgetStyle();
ff8bfdbb
VZ
3820 m_backgroundColour = sysbg;
3821 }
ae0bdb01
RR
3822 else
3823 {
3824 ApplyWidgetStyle();
3825 }
c801d85f 3826
f03fc89f 3827 return TRUE;
362c6693 3828}
c801d85f 3829
94633ad9 3830void wxWindowGTK::DoCaptureMouse()
c801d85f 3831{
b231914f
VZ
3832 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
3833
ed673c6a 3834 GdkWindow *window = (GdkWindow*) NULL;
b231914f
VZ
3835 if (m_wxwindow)
3836 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a 3837 else
b231914f 3838 window = GetConnectWidget()->window;
148cd9b6 3839
e4606ed9 3840 wxCHECK_RET( window, _T("CaptureMouse() failed") );
c50f1fb9 3841
b231914f 3842 wxCursor* cursor = & m_cursor;
cca602ac
JS
3843 if (!cursor->Ok())
3844 cursor = wxSTANDARD_CURSOR;
3845
ed673c6a 3846 gdk_pointer_grab( window, FALSE,
1ecc4d80
RR
3847 (GdkEventMask)
3848 (GDK_BUTTON_PRESS_MASK |
3849 GDK_BUTTON_RELEASE_MASK |
148cd9b6 3850 GDK_POINTER_MOTION_HINT_MASK |
1ecc4d80 3851 GDK_POINTER_MOTION_MASK),
ff8bfdbb 3852 (GdkWindow *) NULL,
cca602ac 3853 cursor->GetCursor(),
b02da6b1 3854 (guint32)GDK_CURRENT_TIME );
b231914f 3855 g_captureWindow = this;
1e6feb95 3856 g_captureWindowHasMouse = TRUE;
362c6693 3857}
c801d85f 3858
94633ad9 3859void wxWindowGTK::DoReleaseMouse()
c801d85f 3860{
b231914f
VZ
3861 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
3862
e4606ed9 3863 wxCHECK_RET( g_captureWindow, wxT("can't release mouse - not captured") );
47d67540 3864
c43430bb
VS
3865 g_captureWindow = (wxWindowGTK*) NULL;
3866
ed673c6a 3867 GdkWindow *window = (GdkWindow*) NULL;
b231914f
VZ
3868 if (m_wxwindow)
3869 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a 3870 else
b231914f 3871 window = GetConnectWidget()->window;
148cd9b6 3872
b02da6b1
VZ
3873 if (!window)
3874 return;
c50f1fb9 3875
b02da6b1 3876 gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME );
362c6693 3877}
c801d85f 3878
1e6feb95
VZ
3879/* static */
3880wxWindow *wxWindowBase::GetCapture()
3881{
3882 return (wxWindow *)g_captureWindow;
3883}
3884
3885bool wxWindowGTK::IsRetained() const
c801d85f 3886{
1ecc4d80 3887 return FALSE;
362c6693 3888}
c801d85f 3889
1e6feb95 3890void wxWindowGTK::SetScrollbar( int orient, int pos, int thumbVisible,
cb43b372 3891 int range, bool refresh )
c801d85f 3892{
223d09f6 3893 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
8bbe427f 3894
223d09f6 3895 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
c801d85f 3896
1ecc4d80 3897 m_hasScrolling = TRUE;
47d67540 3898
1ecc4d80 3899 if (orient == wxHORIZONTAL)
cb43b372 3900 {
1ecc4d80
RR
3901 float fpos = (float)pos;
3902 float frange = (float)range;
3903 float fthumb = (float)thumbVisible;
3904 if (fpos > frange-fthumb) fpos = frange-fthumb;
3905 if (fpos < 0.0) fpos = 0.0;
3906
3907 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
3908 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
3909 {
3910 SetScrollPos( orient, pos, refresh );
3911 return;
3912 }
47d67540 3913
1ecc4d80 3914 m_oldHorizontalPos = fpos;
47d67540 3915
1ecc4d80
RR
3916 m_hAdjust->lower = 0.0;
3917 m_hAdjust->upper = frange;
3918 m_hAdjust->value = fpos;
3919 m_hAdjust->step_increment = 1.0;
3920 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
3921 m_hAdjust->page_size = fthumb;
cb43b372 3922 }
1ecc4d80
RR
3923 else
3924 {
3925 float fpos = (float)pos;
3926 float frange = (float)range;
3927 float fthumb = (float)thumbVisible;
3928 if (fpos > frange-fthumb) fpos = frange-fthumb;
3929 if (fpos < 0.0) fpos = 0.0;
3930
3931 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
3932 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
3933 {
3934 SetScrollPos( orient, pos, refresh );
3935 return;
3936 }
47d67540 3937
1ecc4d80 3938 m_oldVerticalPos = fpos;
47d67540 3939
1ecc4d80
RR
3940 m_vAdjust->lower = 0.0;
3941 m_vAdjust->upper = frange;
3942 m_vAdjust->value = fpos;
3943 m_vAdjust->step_increment = 1.0;
3944 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
3945 m_vAdjust->page_size = fthumb;
3946 }
47d67540 3947
eb082a08
RR
3948 if (orient == wxHORIZONTAL)
3949 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
3950 else
3951 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
362c6693 3952}
c801d85f 3953
1e6feb95 3954void wxWindowGTK::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
c801d85f 3955{
223d09f6 3956 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
1ecc4d80 3957
223d09f6 3958 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
1ecc4d80
RR
3959
3960 if (orient == wxHORIZONTAL)
3961 {
3962 float fpos = (float)pos;
3963 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
3964 if (fpos < 0.0) fpos = 0.0;
3965 m_oldHorizontalPos = fpos;
3966
3967 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
3968 m_hAdjust->value = fpos;
3969 }
3970 else
3971 {
3972 float fpos = (float)pos;
3973 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
3974 if (fpos < 0.0) fpos = 0.0;
3975 m_oldVerticalPos = fpos;
ff8bfdbb 3976
1ecc4d80
RR
3977 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
3978 m_vAdjust->value = fpos;
3979 }
47d67540 3980
5b8a521e 3981 if (m_wxwindow->window)
47d67540 3982 {
5b8a521e 3983 if (orient == wxHORIZONTAL)
473d087e
RR
3984 {
3985 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust),
3986 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
2daa0ce9 3987
5b8a521e 3988 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2daa0ce9 3989
473d087e
RR
3990 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
3991 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
3992 }
5b8a521e 3993 else
473d087e
RR
3994 {
3995 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust),
3996 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
2daa0ce9 3997
5b8a521e 3998 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
473d087e
RR
3999
4000 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
4001 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
4002 }
cb43b372 4003 }
362c6693 4004}
c801d85f 4005
1e6feb95 4006int wxWindowGTK::GetScrollThumb( int orient ) const
c801d85f 4007{
223d09f6 4008 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 4009
223d09f6 4010 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
47d67540 4011
1ecc4d80
RR
4012 if (orient == wxHORIZONTAL)
4013 return (int)(m_hAdjust->page_size+0.5);
4014 else
4015 return (int)(m_vAdjust->page_size+0.5);
362c6693 4016}
c801d85f 4017
1e6feb95 4018int wxWindowGTK::GetScrollPos( int orient ) const
c801d85f 4019{
223d09f6 4020 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 4021
223d09f6 4022 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
c801d85f 4023
1ecc4d80
RR
4024 if (orient == wxHORIZONTAL)
4025 return (int)(m_hAdjust->value+0.5);
4026 else
4027 return (int)(m_vAdjust->value+0.5);
362c6693 4028}
c801d85f 4029
1e6feb95 4030int wxWindowGTK::GetScrollRange( int orient ) const
c801d85f 4031{
223d09f6 4032 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 4033
223d09f6 4034 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
c801d85f 4035
1ecc4d80
RR
4036 if (orient == wxHORIZONTAL)
4037 return (int)(m_hAdjust->upper+0.5);
4038 else
4039 return (int)(m_vAdjust->upper+0.5);
362c6693 4040}
c801d85f 4041
1e6feb95 4042void wxWindowGTK::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
c801d85f 4043{
223d09f6 4044 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 4045
223d09f6 4046 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
1e6feb95 4047
f47ae6e7 4048 // No scrolling requested.
8e217128 4049 if ((dx == 0) && (dy == 0)) return;
f47ae6e7 4050
35917d22
RR
4051 if (!m_updateRegion.IsEmpty())
4052 {
4053 m_updateRegion.Offset( dx, dy );
4054
4055 int cw = 0;
4056 int ch = 0;
4057 GetClientSize( &cw, &ch );
4058 m_updateRegion.Intersect( 0, 0, cw, ch );
4059 }
4060
3bcc8d15
RR
4061 if (!m_clearRegion.IsEmpty())
4062 {
4063 m_clearRegion.Offset( dx, dy );
4064
4065 int cw = 0;
4066 int ch = 0;
4067 GetClientSize( &cw, &ch );
4068 m_clearRegion.Intersect( 0, 0, cw, ch );
4069 }
4070
f47ae6e7 4071#if 1
c801d85f 4072
b6fa52db 4073 m_clipPaintRegion = TRUE;
f47ae6e7 4074
da048e3d 4075 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
f47ae6e7 4076
b6fa52db 4077 m_clipPaintRegion = FALSE;
1e6feb95 4078
f47ae6e7
RR
4079#else
4080
8e217128
RR
4081 if (m_children.GetCount() > 0)
4082 {
4083 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
4084 }
4085 else
4086 {
4087 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
1e6feb95 4088
8e217128
RR
4089 pizza->xoffset -= dx;
4090 pizza->yoffset -= dy;
1e6feb95 4091
8e217128
RR
4092 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
4093 gdk_gc_set_exposures( m_scrollGC, TRUE );
4094
4095 int cw = 0;
4096 int ch = 0;
4097 GetClientSize( &cw, &ch );
4098 int w = cw - abs(dx);
4099 int h = ch - abs(dy);
4100
4101 if ((h < 0) || (w < 0))
4102 {
4103 Refresh();
1e6feb95 4104 }
8e217128
RR
4105 else
4106 {
4107 int s_x = 0;
4108 int s_y = 0;
4109 if (dx < 0) s_x = -dx;
4110 if (dy < 0) s_y = -dy;
4111 int d_x = 0;
4112 int d_y = 0;
4113 if (dx > 0) d_x = dx;
4114 if (dy > 0) d_y = dy;
4115
4116 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
4117 pizza->bin_window, s_x, s_y, w, h );
4118
4119 wxRect rect;
4120 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
4121 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
4122 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
4123 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
4124
4125 Refresh( TRUE, &rect );
4126 }
1e6feb95 4127
8e217128
RR
4128 gdk_gc_unref( m_scrollGC );
4129 }
f47ae6e7 4130#endif
c801d85f 4131}
3723b7b1 4132
3723b7b1
JS
4133// Find the wxWindow at the current mouse position, also returning the mouse
4134// position.
4135wxWindow* wxFindWindowAtPointer(wxPoint& pt)
4136{
59a12e90
JS
4137 pt = wxGetMousePosition();
4138 wxWindow* found = wxFindWindowAtPoint(pt);
4139 return found;
3723b7b1
JS
4140}
4141
4142// Get the current mouse position.
4143wxPoint wxGetMousePosition()
4144{
59a12e90
JS
4145 /* This crashes when used within wxHelpContext,
4146 so we have to use the X-specific implementation below.
4147 gint x, y;
4148 GdkModifierType *mask;
4149 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4150
4151 return wxPoint(x, y);
4152 */
4153
3723b7b1
JS
4154 int x, y;
4155 GdkWindow* windowAtPtr = gdk_window_at_pointer(& x, & y);
57591e0e
JS
4156 if (!windowAtPtr)
4157 return wxPoint(-999, -999);
59a12e90
JS
4158
4159 Display *display = GDK_WINDOW_XDISPLAY(windowAtPtr);
4160 Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
4161 Window rootReturn, childReturn;
4162 int rootX, rootY, winX, winY;
4163 unsigned int maskReturn;
4164
4165 XQueryPointer (display,
5cd09f0b
RR
4166 rootWindow,
4167 &rootReturn,
59a12e90
JS
4168 &childReturn,
4169 &rootX, &rootY, &winX, &winY, &maskReturn);
4170 return wxPoint(rootX, rootY);
4171
3723b7b1
JS
4172}
4173