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