]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/window.cpp
fixed an over-optimisation
[wxWidgets.git] / src / gtk1 / window.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: window.cpp
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
15#include "wx/defs.h"
16#include "wx/window.h"
17#include "wx/dc.h"
18#include "wx/frame.h"
19#include "wx/app.h"
20#include "wx/layout.h"
21#include "wx/utils.h"
22#include "wx/dialog.h"
23#include "wx/msgdlg.h"
bfc6fde4 24
06cfab17 25#if wxUSE_DRAG_AND_DROP
bfc6fde4 26 #include "wx/dnd.h"
ac57418f 27#endif
bfc6fde4 28
cad880f5 29#if wxUSE_TOOLTIPS
bfc6fde4 30 #include "wx/tooltip.h"
cad880f5 31#endif
bfc6fde4 32
30dea054 33#include "wx/menu.h"
d4c99d6f 34#include "wx/statusbr.h"
b4071e91 35#include "wx/intl.h"
3bc755fc 36#include "wx/settings.h"
3069ac4e 37#include "wx/log.h"
b4071e91
RR
38
39#include <math.h>
c801d85f 40
83624f79
RR
41#include "gdk/gdk.h"
42#include "gtk/gtk.h"
43#include "gdk/gdkprivate.h"
44#include "gdk/gdkkeysyms.h"
c5b42c87 45#include "gdk/gdkx.h"
83624f79
RR
46#include "wx/gtk/win_gtk.h"
47
868a2826
RR
48//-----------------------------------------------------------------------------
49// documentation on internals
50//-----------------------------------------------------------------------------
51
52/*
53 I have been asked several times about writing some documentation about
54 the GTK port of wxWindows, especially its internal structures. Obviously,
55 you cannot understand wxGTK without knowing a little about the GTK, but
47d67540 56 some more information about what the wxWindow, which is the base class
868a2826 57 for all other window classes, does seems required as well.
47d67540 58
868a2826 59 What does wxWindow do? It contains the common interface for the following
e380f72b 60 jobs of its descendants:
47d67540 61
868a2826 62 1) Define the rudimentary behaviour common to all window classes, such as
e380f72b
RR
63 resizing, intercepting user input (so as to make it possible to use these
64 events for special purposes in a derived class), window names etc.
868a2826
RR
65
66 2) Provide the possibility to contain and manage children, if the derived
67 class is allowed to contain children, which holds true for those window
e380f72b 68 classes which do not display a native GTK widget. To name them, these
868a2826 69 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
47d67540 70 work classes are a special case and are handled a bit differently from
e380f72b 71 the rest. The same holds true for the wxNotebook class.
47d67540 72
868a2826
RR
73 3) Provide the possibility to draw into a client area of a window. This,
74 too, only holds true for classes that do not display a native GTK widget
75 as above.
47d67540 76
e380f72b
RR
77 4) Provide the entire mechanism for scrolling widgets. This actual inter-
78 face for this is usually in wxScrolledWindow, but the GTK implementation
868a2826 79 is in this class.
47d67540 80
868a2826
RR
81 5) A multitude of helper or extra methods for special purposes, such as
82 Drag'n'Drop, managing validators etc.
47d67540 83
e380f72b
RR
84 Normally one might expect, that one wxWindows window would always correspond
85 to one GTK widget. Under GTK, there is no such allround widget that has all
868a2826
RR
86 the functionality. Moreover, the GTK defines a client area as a different
87 widget from the actual widget you are handling. Last but not least some
88 special classes (e.g. wxFrame) handle different categories of widgets and
89 still have the possibility to draw something in the client area.
90 It was therefore required to write a special purpose GTK widget, that would
91 represent a client area in the sense of wxWindows capable to do the jobs
92 2), 3) and 4). I have written this class and it resides in win_gtk.c of
93 this directory.
47d67540 94
868a2826 95 All windows must have a widget, with which they interact with other under-
e380f72b 96 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
868a2826 97 thw wxWindow class has a member variable called m_widget which holds a
e380f72b
RR
98 pointer to this widget. When the window class represents a GTK native widget,
99 this is (in most cases) the only GTK widget the class manages. E.g. the
100 wxStatitText class handles only a GtkLabel widget a pointer to which you
101 can find in m_widget (defined in wxWindow)
8bbe427f 102
e380f72b 103 When the class has a client area for drawing into and for containing children
8bbe427f
VZ
104 it has to handle the client area widget (of the type GtkMyFixed, defined in
105 win_gtk.c), but there could be any number of widgets, handled by a class
106 The common rule for all windows is only, that the widget that interacts with
107 the rest of GTK must be referenced in m_widget and all other widgets must be
108 children of this widget on the GTK level. The top-most widget, which also
109 represents the client area, must be in the m_wxwindow field and must be of
e380f72b 110 the type GtkMyFixed.
47d67540 111
868a2826
RR
112 As I said, the window classes that display a GTK native widget only have
113 one widget, so in the case of e.g. the wxButton class m_widget holds a
114 pointer to a GtkButton widget. But windows with client areas (for drawing
115 and children) have a m_widget field that is a pointer to a GtkScrolled-
116 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
117 one is (in the GTK sense) a child of the GtkScrolledWindow.
47d67540 118
868a2826
RR
119 If the m_wxwindow field is set, then all input to this widget is inter-
120 cepted and sent to the wxWindows class. If not, all input to the widget
121 that gets pointed to by m_widget gets intercepted and sent to the class.
122
123*/
124
f03fc89f
VZ
125//-----------------------------------------------------------------------------
126// data
127//-----------------------------------------------------------------------------
128
129extern wxList wxPendingDelete;
130extern bool g_blockEventsOnDrag;
131extern bool g_blockEventsOnScroll;
132static bool g_capturing = FALSE;
133static wxWindow *g_focusWindow = (wxWindow*) NULL;
134
135/* hack: we need something to pass to gtk_menu_popup, so we store the time of
136 the last click here */
137static guint32 gs_timeLastClick = 0;
138
2e563988
RR
139//-----------------------------------------------------------------------------
140// debug
141//-----------------------------------------------------------------------------
142
143#ifdef __WXDEBUG__
144
145static gint gtk_debug_focus_in_callback( GtkWidget *WXUNUSED(widget),
146 GdkEvent *WXUNUSED(event),
147 const wxChar *name )
148{
053dcf1a 149/*
167e3718
VZ
150 static bool s_done = FALSE;
151 if ( !s_done )
152 {
153 wxLog::AddTraceMask("focus");
154 s_done = TRUE;
155 }
167e3718 156 wxLogTrace(_T("FOCUS NOW AT: %s"), name);
053dcf1a 157*/
2e563988
RR
158
159 return FALSE;
160}
161
162void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window )
163{
164 wxString tmp = name;
165 tmp += _T(" FROM ");
166 tmp += window;
167
168 wxChar *s = new wxChar[tmp.Length()+1];
169
170 wxStrcpy( s, tmp );
171
172 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
173 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback), (gpointer)s );
174}
175
f03fc89f 176#endif // Debug
ff8bfdbb 177
acfd422a 178//-----------------------------------------------------------------------------
a2053b27 179// idle system
acfd422a
RR
180//-----------------------------------------------------------------------------
181
a2053b27
RR
182extern void wxapp_install_idle_handler();
183extern bool g_isIdle;
184
c5b42c87
RR
185//-----------------------------------------------------------------------------
186// key event conversion routines
187//-----------------------------------------------------------------------------
188
189static long map_to_unmodified_wx_keysym( KeySym keysym )
190{
191 guint key_code = 0;
192
193 switch (keysym)
194 {
195 case GDK_Shift_L:
196 case GDK_Shift_R: key_code = WXK_SHIFT; break;
197 case GDK_Control_L:
198 case GDK_Control_R: key_code = WXK_CONTROL; break;
199 case GDK_Menu: key_code = WXK_MENU; break;
200 case GDK_Help: key_code = WXK_HELP; break;
201 case GDK_BackSpace: key_code = WXK_BACK; break;
202 case GDK_ISO_Left_Tab:
203 case GDK_Tab: key_code = WXK_TAB; break;
204 case GDK_Linefeed: key_code = WXK_RETURN; break;
205 case GDK_Clear: key_code = WXK_CLEAR; break;
206 case GDK_Return: key_code = WXK_RETURN; break;
207 case GDK_Pause: key_code = WXK_PAUSE; break;
208 case GDK_Scroll_Lock: key_code = WXK_SCROLL; break;
209 case GDK_Escape: key_code = WXK_ESCAPE; break;
210 case GDK_Delete: key_code = WXK_DELETE; break;
211 case GDK_Home: key_code = WXK_HOME; break;
212 case GDK_Left: key_code = WXK_LEFT; break;
213 case GDK_Up: key_code = WXK_UP; break;
214 case GDK_Right: key_code = WXK_RIGHT; break;
215 case GDK_Down: key_code = WXK_DOWN; break;
216 case GDK_Prior: key_code = WXK_PRIOR; break;
217// case GDK_Page_Up: key_code = WXK_PAGEUP; break;
218 case GDK_Next: key_code = WXK_NEXT; break;
219// case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
220 case GDK_End: key_code = WXK_END; break;
221 case GDK_Begin: key_code = WXK_HOME; break;
222 case GDK_Select: key_code = WXK_SELECT; break;
223 case GDK_Print: key_code = WXK_PRINT; break;
224 case GDK_Execute: key_code = WXK_EXECUTE; break;
225 case GDK_Insert: key_code = WXK_INSERT; break;
226 case GDK_Num_Lock: key_code = WXK_NUMLOCK; break;
227
228 case GDK_KP_0: key_code = WXK_NUMPAD0; break;
229 case GDK_KP_1: key_code = WXK_NUMPAD1; break;
230 case GDK_KP_2: key_code = WXK_NUMPAD2; break;
231 case GDK_KP_3: key_code = WXK_NUMPAD3; break;
232 case GDK_KP_4: key_code = WXK_NUMPAD4; break;
233 case GDK_KP_5: key_code = WXK_NUMPAD5; break;
234 case GDK_KP_6: key_code = WXK_NUMPAD6; break;
235 case GDK_KP_7: key_code = WXK_NUMPAD7; break;
236 case GDK_KP_8: key_code = WXK_NUMPAD8; break;
237 case GDK_KP_9: key_code = WXK_NUMPAD9; break;
238 case GDK_KP_Space: key_code = WXK_NUMPAD_SPACE; break;
239 case GDK_KP_Tab: key_code = WXK_NUMPAD_TAB; break;
240 case GDK_KP_Enter: key_code = WXK_NUMPAD_ENTER; break;
241 case GDK_KP_F1: key_code = WXK_NUMPAD_F1; break;
242 case GDK_KP_F2: key_code = WXK_NUMPAD_F2; break;
243 case GDK_KP_F3: key_code = WXK_NUMPAD_F3; break;
244 case GDK_KP_F4: key_code = WXK_NUMPAD_F4; break;
245 case GDK_KP_Home: key_code = WXK_NUMPAD_HOME; break;
246 case GDK_KP_Left: key_code = WXK_NUMPAD_LEFT; break;
247 case GDK_KP_Up: key_code = WXK_NUMPAD_UP; break;
248 case GDK_KP_Right: key_code = WXK_NUMPAD_RIGHT; break;
249 case GDK_KP_Down: key_code = WXK_NUMPAD_DOWN; break;
250 case GDK_KP_Prior: key_code = WXK_NUMPAD_PRIOR; break;
251// case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
252 case GDK_KP_Next: key_code = WXK_NUMPAD_PRIOR; break;
253// case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
254 case GDK_KP_End: key_code = WXK_NUMPAD_END; break;
255 case GDK_KP_Begin: key_code = WXK_NUMPAD_BEGIN; break;
256 case GDK_KP_Insert: key_code = WXK_NUMPAD_INSERT; break;
257 case GDK_KP_Delete: key_code = WXK_NUMPAD_DELETE; break;
258 case GDK_KP_Equal: key_code = WXK_NUMPAD_EQUAL; break;
259 case GDK_KP_Multiply: key_code = WXK_NUMPAD_MULTIPLY; break;
260 case GDK_KP_Add: key_code = WXK_NUMPAD_ADD; break;
261 case GDK_KP_Separator: key_code = WXK_NUMPAD_SEPARATOR; break;
262 case GDK_KP_Subtract: key_code = WXK_NUMPAD_SUBTRACT; break;
263 case GDK_KP_Decimal: key_code = WXK_NUMPAD_DECIMAL; break;
264 case GDK_KP_Divide: key_code = WXK_NUMPAD_DIVIDE; break;
265
266 case GDK_F1: key_code = WXK_F1; break;
267 case GDK_F2: key_code = WXK_F2; break;
268 case GDK_F3: key_code = WXK_F3; break;
269 case GDK_F4: key_code = WXK_F4; break;
270 case GDK_F5: key_code = WXK_F5; break;
271 case GDK_F6: key_code = WXK_F6; break;
272 case GDK_F7: key_code = WXK_F7; break;
273 case GDK_F8: key_code = WXK_F8; break;
274 case GDK_F9: key_code = WXK_F9; break;
275 case GDK_F10: key_code = WXK_F10; break;
276 case GDK_F11: key_code = WXK_F11; break;
277 case GDK_F12: key_code = WXK_F12; break;
278 default:
279 {
280 if (keysym <= 0xFF)
281 {
282 guint upper = gdk_keyval_to_upper( keysym );
283 keysym = (upper != 0 ? upper : keysym ); /* to be MSW compatible */
284 key_code = keysym;
285 }
286 }
287 }
288
289 return (key_code);
290}
291
292static long map_to_wx_keysym( KeySym keysym )
293{
294 guint key_code = 0;
295
296 switch (keysym)
297 {
298 case GDK_Shift_L:
299 case GDK_Shift_R: key_code = WXK_SHIFT; break;
300 case GDK_Control_L:
301 case GDK_Control_R: key_code = WXK_CONTROL; break;
302 case GDK_Menu: key_code = WXK_MENU; break;
303 case GDK_Help: key_code = WXK_HELP; break;
304 case GDK_BackSpace: key_code = WXK_BACK; break;
305 case GDK_ISO_Left_Tab:
306 case GDK_Tab: key_code = WXK_TAB; break;
307 case GDK_Linefeed: key_code = WXK_RETURN; break;
308 case GDK_Clear: key_code = WXK_CLEAR; break;
309 case GDK_Return: key_code = WXK_RETURN; break;
310 case GDK_Pause: key_code = WXK_PAUSE; break;
311 case GDK_Scroll_Lock: key_code = WXK_SCROLL; break;
312 case GDK_Escape: key_code = WXK_ESCAPE; break;
313 case GDK_Delete: key_code = WXK_DELETE; break;
314 case GDK_Home: key_code = WXK_HOME; break;
315 case GDK_Left: key_code = WXK_LEFT; break;
316 case GDK_Up: key_code = WXK_UP; break;
317 case GDK_Right: key_code = WXK_RIGHT; break;
318 case GDK_Down: key_code = WXK_DOWN; break;
319 case GDK_Prior: key_code = WXK_PRIOR; break;
320// case GDK_Page_Up: key_code = WXK_PAGEUP; break;
321 case GDK_Next: key_code = WXK_NEXT; break;
322// case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
323 case GDK_End: key_code = WXK_END; break;
324 case GDK_Begin: key_code = WXK_HOME; break;
325 case GDK_Select: key_code = WXK_SELECT; break;
326 case GDK_Print: key_code = WXK_PRINT; break;
327 case GDK_Execute: key_code = WXK_EXECUTE; break;
328 case GDK_Insert: key_code = WXK_INSERT; break;
329 case GDK_Num_Lock: key_code = WXK_NUMLOCK; break;
330
331 case GDK_KP_0: key_code = '0'; break;
332 case GDK_KP_1: key_code = '1'; break;
333 case GDK_KP_2: key_code = '2'; break;
334 case GDK_KP_3: key_code = '3'; break;
335 case GDK_KP_4: key_code = '4'; break;
336 case GDK_KP_5: key_code = '5'; break;
337 case GDK_KP_6: key_code = '6'; break;
338 case GDK_KP_7: key_code = '7'; break;
339 case GDK_KP_8: key_code = '8'; break;
340 case GDK_KP_9: key_code = '9'; break;
341 case GDK_KP_Space: key_code = ' '; break;
342 case GDK_KP_Tab: key_code = WXK_TAB; break; /* or '\t' ??? */
343 case GDK_KP_Enter: key_code = WXK_RETURN; break; /* or '\r' ??? */
344 case GDK_KP_F1: key_code = WXK_NUMPAD_F1; break;
345 case GDK_KP_F2: key_code = WXK_NUMPAD_F2; break;
346 case GDK_KP_F3: key_code = WXK_NUMPAD_F3; break;
347 case GDK_KP_F4: key_code = WXK_NUMPAD_F4; break;
348 case GDK_KP_Home: key_code = WXK_HOME; break;
349 case GDK_KP_Left: key_code = WXK_LEFT; break;
350 case GDK_KP_Up: key_code = WXK_UP; break;
351 case GDK_KP_Right: key_code = WXK_RIGHT; break;
352 case GDK_KP_Down: key_code = WXK_DOWN; break;
353 case GDK_KP_Prior: key_code = WXK_PRIOR; break;
354// case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
355 case GDK_KP_Next: key_code = WXK_PRIOR; break;
356// case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
357 case GDK_KP_End: key_code = WXK_END; break;
358 case GDK_KP_Begin: key_code = WXK_HOME; break;
359 case GDK_KP_Insert: key_code = WXK_INSERT; break;
360 case GDK_KP_Delete: key_code = WXK_DELETE; break;
361 case GDK_KP_Equal: key_code = '='; break;
362 case GDK_KP_Multiply: key_code = '*'; break;
363 case GDK_KP_Add: key_code = '+'; break;
364 case GDK_KP_Separator: key_code = ','; break;
365 case GDK_KP_Subtract: key_code = '-'; break;
366 case GDK_KP_Decimal: key_code = '.'; break;
367 case GDK_KP_Divide: key_code = '/'; break;
368
369 case GDK_F1: key_code = WXK_F1; break;
370 case GDK_F2: key_code = WXK_F2; break;
371 case GDK_F3: key_code = WXK_F3; break;
372 case GDK_F4: key_code = WXK_F4; break;
373 case GDK_F5: key_code = WXK_F5; break;
374 case GDK_F6: key_code = WXK_F6; break;
375 case GDK_F7: key_code = WXK_F7; break;
376 case GDK_F8: key_code = WXK_F8; break;
377 case GDK_F9: key_code = WXK_F9; break;
378 case GDK_F10: key_code = WXK_F10; break;
379 case GDK_F11: key_code = WXK_F11; break;
380 case GDK_F12: key_code = WXK_F12; break;
381 default:
382 {
383 if (keysym <= 0xFF)
384 {
385 key_code = keysym;
386 }
387 }
388 }
389
390 return (key_code);
391}
392
393static long get_unmodified_wx_keysym( GdkEventKey *event )
394{
395 KeyCode keycode = XKeysymToKeycode( GDK_DISPLAY(), event->keyval );
396 KeySym keysym = XKeycodeToKeysym( GDK_DISPLAY(), keycode, 0 );
397
398 return (map_to_unmodified_wx_keysym( keysym ));
399}
400
a2053b27
RR
401//-----------------------------------------------------------------------------
402// local code (see below)
403//-----------------------------------------------------------------------------
acfd422a 404
ef47f9b3
RR
405#if (GTK_MINOR_VERSION > 0)
406
034be888 407static void draw_frame( GtkWidget *widget, wxWindow *win )
b292e2f5 408{
a2053b27 409 if (!win->m_hasVMT)
f03fc89f 410 return;
b292e2f5 411
034be888
RR
412 int dw = 0;
413 int dh = 0;
ca298c88 414
f03fc89f 415 if (win->HasScrolling())
034be888
RR
416 {
417 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(widget);
418 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget)->klass );
ff8bfdbb 419
034be888
RR
420/*
421 GtkWidget *hscrollbar = scroll_window->hscrollbar;
422 GtkWidget *vscrollbar = scroll_window->vscrollbar;
ca298c88 423
f03fc89f 424 we use this instead: range.slider_width = 11 + 2*2pts edge
034be888 425*/
ff8bfdbb 426
034be888
RR
427 if (scroll_window->vscrollbar_visible)
428 {
429 dw += 15; /* dw += vscrollbar->allocation.width; */
430 dw += scroll_class->scrollbar_spacing;
431 }
b292e2f5 432
034be888
RR
433 if (scroll_window->hscrollbar_visible)
434 {
435 dh += 15; /* dh += hscrollbar->allocation.height; */
436 dw += scroll_class->scrollbar_spacing;
437 }
438 }
ca298c88 439
034be888
RR
440 int dx = 0;
441 int dy = 0;
442 if (GTK_WIDGET_NO_WINDOW (widget))
443 {
444 dx += widget->allocation.x;
445 dy += widget->allocation.y;
446 }
ca298c88 447
f03fc89f 448 if (win->HasFlag(wxRAISED_BORDER))
034be888 449 {
ca298c88 450 gtk_draw_shadow( widget->style,
034be888 451 widget->window,
f03fc89f
VZ
452 GTK_STATE_NORMAL,
453 GTK_SHADOW_OUT,
454 dx, dy,
a2053b27 455 win->m_width-dw, win->m_height-dh );
f03fc89f 456 return;
ca298c88
RD
457 }
458
f03fc89f 459 if (win->HasFlag(wxSUNKEN_BORDER))
034be888 460 {
ca298c88 461 gtk_draw_shadow( widget->style,
034be888 462 widget->window,
f03fc89f
VZ
463 GTK_STATE_NORMAL,
464 GTK_SHADOW_IN,
465 dx, dy,
a2053b27 466 win->m_width-dw, win->m_height-dh );
f03fc89f 467 return;
034be888 468 }
b292e2f5
RR
469}
470
c801d85f 471//-----------------------------------------------------------------------------
034be888 472// "expose_event" of m_widget
c801d85f
KB
473//-----------------------------------------------------------------------------
474
034be888
RR
475static void gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win )
476{
477 if (gdk_event->count > 0) return;
478 draw_frame( widget, win );
479}
47d67540 480
034be888
RR
481//-----------------------------------------------------------------------------
482// "draw" of m_wxwindow
483//-----------------------------------------------------------------------------
484
485static void gtk_window_own_draw_callback( GtkWidget *widget, GdkRectangle *WXUNUSED(rect), wxWindow *win )
486{
487 draw_frame( widget, win );
488}
c801d85f 489
f03fc89f 490#endif // GTK_MINOR_VERSION > 0
ef47f9b3 491
c801d85f 492//-----------------------------------------------------------------------------
034be888 493// "expose_event" of m_wxwindow
c801d85f
KB
494//-----------------------------------------------------------------------------
495
2f2aa628 496static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxWindow *win )
47d67540 497{
a2053b27 498 if ( !win->m_hasVMT )
f03fc89f 499 return;
47d67540 500
f03fc89f
VZ
501 win->GetUpdateRegion().Union( gdk_event->area.x,
502 gdk_event->area.y,
503 gdk_event->area.width,
504 gdk_event->area.height );
47d67540 505
f03fc89f
VZ
506 if ( gdk_event->count > 0 )
507 return;
c801d85f 508
d8c83875 509/*
f5e27805
RR
510 printf( "OnExpose from " );
511 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
512 printf( win->GetClassInfo()->GetClassName() );
513 printf( ".\n" );
d8c83875
RR
514*/
515
f5e27805
RR
516 wxPaintEvent event( win->GetId() );
517 event.SetEventObject( win );
518 win->GetEventHandler()->ProcessEvent( event );
47d67540 519
f03fc89f 520 win->GetUpdateRegion().Clear();
362c6693 521}
c801d85f
KB
522
523//-----------------------------------------------------------------------------
034be888 524// "draw" of m_wxwindow
2f2aa628 525//-----------------------------------------------------------------------------
c801d85f 526
2f2aa628 527static void gtk_window_draw_callback( GtkWidget *WXUNUSED(widget), GdkRectangle *rect, wxWindow *win )
47d67540 528{
a2053b27
RR
529 if (g_isIdle)
530 wxapp_install_idle_handler();
531
532 if (!win->m_hasVMT)
f03fc89f 533 return;
47d67540 534
f03fc89f
VZ
535 win->GetUpdateRegion().Union( rect->x, rect->y,
536 rect->width, rect->height );
47d67540 537
f5e27805
RR
538 wxPaintEvent event( win->GetId() );
539 event.SetEventObject( win );
540 win->GetEventHandler()->ProcessEvent( event );
47d67540 541
f03fc89f 542 win->GetUpdateRegion().Clear();
362c6693 543}
c801d85f
KB
544
545//-----------------------------------------------------------------------------
b292e2f5 546// "key_press_event" from any window
c801d85f 547//-----------------------------------------------------------------------------
c801d85f 548
2f2aa628 549static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
47d67540 550{
a2053b27
RR
551 if (g_isIdle)
552 wxapp_install_idle_handler();
553
554 if (!win->m_hasVMT) return FALSE;
f5e27805 555 if (g_blockEventsOnDrag) return FALSE;
c801d85f 556
7be4c594 557/*
d1367c3d
RR
558 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
559 if (gdk_event->state & GDK_SHIFT_MASK)
560 printf( "ShiftDown.\n" );
561 else
562 printf( "ShiftUp.\n" );
563 if (gdk_event->state & GDK_CONTROL_MASK)
564 printf( "ControlDown.\n" );
565 else
566 printf( "ControlUp.\n" );
567 printf( "\n" );
7be4c594 568*/
ca298c88 569
c5b42c87
RR
570 bool ret = FALSE;
571
b0e813a0
RR
572 int x = 0;
573 int y = 0;
574 GdkModifierType state;
575 if (gdk_event->window) gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
47d67540 576
c5b42c87
RR
577 long key_code = get_unmodified_wx_keysym( gdk_event );
578
579 wxKeyEvent event( wxEVT_KEY_DOWN );
d1367c3d 580 event.SetTimestamp( gdk_event->time );
f5e27805
RR
581 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
582 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
583 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
584 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
585 event.m_keyCode = key_code;
b0e813a0
RR
586 event.m_scanCode = gdk_event->keyval;
587 event.m_x = x;
588 event.m_y = y;
f5e27805 589 event.SetEventObject( win );
c5b42c87
RR
590 ret = win->GetEventHandler()->ProcessEvent( event );
591
592 key_code = map_to_wx_keysym( gdk_event->keyval );
47d67540 593
c5b42c87
RR
594 /* wxMSW doesn't send char events with Alt pressed */
595 if (((gdk_event->state & GDK_MOD1_MASK) == 0) &&
596 ((gdk_event->state & GDK_MOD1_MASK) == 0))
597 {
598 wxKeyEvent event2( wxEVT_CHAR );
599 event2.SetTimestamp( gdk_event->time );
600 event2.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
601 event2.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
602// event2.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
603// event2.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
604 event2.m_keyCode = key_code;
605 event2.m_scanCode = gdk_event->keyval;
606 event2.m_x = x;
607 event2.m_y = y;
608 event2.SetEventObject( win );
609 ret = (ret || win->GetEventHandler()->ProcessEvent( event2 ));
610 }
47d67540 611
f5e27805 612 if (!ret)
47d67540 613 {
f5e27805
RR
614 wxWindow *ancestor = win;
615 while (ancestor)
616 {
617 int command = ancestor->GetAcceleratorTable()->GetCommand( event );
618 if (command != -1)
619 {
620 wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
621 ret = ancestor->GetEventHandler()->ProcessEvent( command_event );
622 break;
623 }
624 ancestor = ancestor->GetParent();
625 }
bcf1fa6b 626 }
ff8bfdbb 627
b292e2f5 628 // win is a control: tab can be propagated up
ca298c88 629 if ( (!ret) &&
5664fc32 630 ((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
f03fc89f 631 (win->HasFlag(wxTE_PROCESS_TAB) == 0))
b292e2f5
RR
632 {
633 wxNavigationKeyEvent new_event;
f03fc89f 634 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
5664fc32 635 new_event.SetDirection( (gdk_event->keyval == GDK_Tab) );
f03fc89f 636 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
b98d804b 637 new_event.SetWindowChange( (gdk_event->state & GDK_CONTROL_MASK) );
b292e2f5 638 new_event.SetCurrentFocus( win );
ff8bfdbb 639 ret = win->GetEventHandler()->ProcessEvent( new_event );
b292e2f5 640 }
ff8bfdbb 641
ca298c88 642 if ( (!ret) &&
b98d804b
RR
643 (gdk_event->keyval == GDK_Escape) )
644 {
645 wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
646 new_event.SetEventObject( win );
647 ret = win->GetEventHandler()->ProcessEvent( new_event );
648 }
ca298c88 649
b292e2f5 650/*
b98d804b
RR
651 Damn, I forgot why this didn't work, but it didn't work.
652
b292e2f5 653 // win is a panel: up can be propagated to the panel
a2053b27 654 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
b292e2f5
RR
655 (gdk_event->keyval == GDK_Up))
656 {
657 win->m_parent->SetFocus();
ff8bfdbb 658 ret = TRUE;
b292e2f5 659 }
ff8bfdbb 660
b292e2f5 661 // win is a panel: left/right can be propagated to the panel
a2053b27 662 if ((!ret) && (win->m_wxwindow) &&
ff8bfdbb 663 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
b292e2f5
RR
664 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
665 {
666 wxNavigationKeyEvent new_event;
667 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
668 new_event.SetCurrentFocus( win );
ff8bfdbb 669 ret = win->GetEventHandler()->ProcessEvent( new_event );
b292e2f5
RR
670 }
671*/
ff8bfdbb 672
f5e27805
RR
673 if (ret)
674 {
b292e2f5 675 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
f03fc89f 676 return TRUE;
f5e27805 677 }
47d67540 678
034be888 679 return FALSE;
362c6693 680}
c801d85f 681
b666df2c
RR
682//-----------------------------------------------------------------------------
683// "key_release_event" from any window
684//-----------------------------------------------------------------------------
685
686static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
687{
a2053b27
RR
688 if (g_isIdle)
689 wxapp_install_idle_handler();
690
691 if (!win->m_hasVMT) return FALSE;
b666df2c
RR
692 if (g_blockEventsOnDrag) return FALSE;
693
694/*
d1367c3d
RR
695 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
696 if (gdk_event->state & GDK_SHIFT_MASK)
697 printf( "ShiftDown.\n" );
698 else
699 printf( "ShiftUp.\n" );
700 if (gdk_event->state & GDK_CONTROL_MASK)
701 printf( "ControlDown.\n" );
702 else
703 printf( "ControlUp.\n" );
704 printf( "\n" );
b666df2c
RR
705*/
706
c5b42c87 707 long key_code = get_unmodified_wx_keysym( gdk_event );
b666df2c 708
b0e813a0
RR
709 int x = 0;
710 int y = 0;
711 GdkModifierType state;
712 if (gdk_event->window) gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
b666df2c
RR
713
714 wxKeyEvent event( wxEVT_KEY_UP );
d1367c3d 715 event.SetTimestamp( gdk_event->time );
b666df2c
RR
716 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
717 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
718 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
719 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
720 event.m_keyCode = key_code;
b0e813a0
RR
721 event.m_scanCode = gdk_event->keyval;
722 event.m_x = x;
723 event.m_y = y;
b666df2c
RR
724 event.SetEventObject( win );
725
034be888 726 if (win->GetEventHandler()->ProcessEvent( event ))
b666df2c 727 {
b98d804b 728 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_release_event" );
f03fc89f 729 return TRUE;
b666df2c
RR
730 }
731
034be888 732 return FALSE;
b666df2c
RR
733}
734
c801d85f 735//-----------------------------------------------------------------------------
2f2aa628
RR
736// "button_press_event"
737//-----------------------------------------------------------------------------
c801d85f 738
2f2aa628 739static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
903f689b 740{
a2053b27
RR
741 if (g_isIdle)
742 wxapp_install_idle_handler();
743
744/*
745 wxPrintf( _T("1) OnButtonPress from ") );
746 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
747 wxPrintf( win->GetClassInfo()->GetClassName() );
748 wxPrintf( _T(".\n") );
749*/
a2053b27 750 if (!win->m_hasVMT) return FALSE;
f5e27805 751 if (g_blockEventsOnDrag) return TRUE;
76ed8f8d 752 if (g_blockEventsOnScroll) return TRUE;
c801d85f 753
034be888
RR
754 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
755
a2053b27 756 if (win->m_wxwindow)
c801d85f 757 {
a2053b27 758 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow) && !GTK_WIDGET_HAS_FOCUS (win->m_wxwindow) )
f5e27805 759 {
a2053b27 760 gtk_widget_grab_focus (win->m_wxwindow);
47d67540 761
c801d85f 762/*
a2053b27 763 wxPrintf( _T("GrabFocus from ") );
f5e27805 764 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
a2053b27
RR
765 wxPrintf( win->GetClassInfo()->GetClassName() );
766 wxPrintf( _T(".\n") );
c801d85f 767*/
47d67540 768
f5e27805 769 }
362c6693 770 }
47d67540 771
8429bec1 772/*
a2053b27 773 wxPrintf( _T("2) OnButtonPress from ") );
f5e27805 774 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
a2053b27
RR
775 wxPrintf( win->GetClassInfo()->GetClassName() );
776 wxPrintf( _T(".\n") );
8429bec1 777*/
30dea054 778
f5e27805 779 wxEventType event_type = wxEVT_LEFT_DOWN;
47d67540 780
f5e27805 781 if (gdk_event->button == 1)
c801d85f 782 {
f5e27805
RR
783 switch (gdk_event->type)
784 {
785 case GDK_BUTTON_PRESS: event_type = wxEVT_LEFT_DOWN; break;
786 case GDK_2BUTTON_PRESS: event_type = wxEVT_LEFT_DCLICK; break;
787 default: break;
788 }
362c6693 789 }
f5e27805 790 else if (gdk_event->button == 2)
c801d85f 791 {
f5e27805
RR
792 switch (gdk_event->type)
793 {
794 case GDK_BUTTON_PRESS: event_type = wxEVT_MIDDLE_DOWN; break;
795 case GDK_2BUTTON_PRESS: event_type = wxEVT_MIDDLE_DCLICK; break;
796 default: break;
797 }
362c6693 798 }
f5e27805 799 else if (gdk_event->button == 3)
c801d85f 800 {
f5e27805
RR
801 switch (gdk_event->type)
802 {
803 case GDK_BUTTON_PRESS: event_type = wxEVT_RIGHT_DOWN; break;
804 case GDK_2BUTTON_PRESS: event_type = wxEVT_RIGHT_DCLICK; break;
805 default: break;
806 }
362c6693 807 }
47d67540 808
f5e27805 809 wxMouseEvent event( event_type );
d1367c3d 810 event.SetTimestamp( gdk_event->time );
f5e27805
RR
811 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
812 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
813 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
814 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
815 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
816 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
817 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
47d67540 818
f5e27805
RR
819 event.m_x = (long)gdk_event->x;
820 event.m_y = (long)gdk_event->y;
47d67540 821
f5e27805
RR
822 // Some control don't have their own X window and thus cannot get
823 // any events.
47d67540 824
f5e27805 825 if (!g_capturing)
2f2aa628 826 {
db1b4961 827 wxNode *node = win->GetChildren().First();
f5e27805
RR
828 while (node)
829 {
830 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb 831
a2053b27 832 if (child->m_isStaticBox)
ff8bfdbb
VZ
833 {
834 // wxStaticBox is transparent in the box itself
a2053b27
RR
835 int x = event.m_x;
836 int y = event.m_y;
837 int xx1 = child->m_x;
838 int yy1 = child->m_y;
839 int xx2 = child->m_x + child->m_width;
840 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
841
842 // left
843 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
844 // right
845 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
846 // top
847 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
848 // bottom
849 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
850 {
1ecc4d80 851 win = child;
a2053b27
RR
852 event.m_x -= child->m_x;
853 event.m_y -= child->m_y;
1ecc4d80 854 break;
ff8bfdbb
VZ
855 }
856
857 }
858 else
859 {
a2053b27
RR
860 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
861 (child->m_x <= event.m_x) &&
862 (child->m_y <= event.m_y) &&
863 (child->m_x+child->m_width >= event.m_x) &&
864 (child->m_y+child->m_height >= event.m_y))
1ecc4d80
RR
865 {
866 win = child;
a2053b27
RR
867 event.m_x -= child->m_x;
868 event.m_y -= child->m_y;
1ecc4d80 869 break;
ff8bfdbb 870 }
f5e27805
RR
871 }
872 node = node->Next();
873 }
2f2aa628 874 }
ff8bfdbb 875
f5e27805 876 event.SetEventObject( win );
47d67540 877
f5e27805 878 gs_timeLastClick = gdk_event->time;
47d67540 879
f5e27805 880 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 881 {
f5e27805 882 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
f03fc89f 883 return TRUE;
034be888 884 }
47d67540 885
034be888 886 return FALSE;
362c6693 887}
c801d85f
KB
888
889//-----------------------------------------------------------------------------
97b3455a 890// "button_release_event"
2f2aa628 891//-----------------------------------------------------------------------------
c801d85f 892
2f2aa628 893static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
47d67540 894{
a2053b27
RR
895 if (g_isIdle)
896 wxapp_install_idle_handler();
897
898 if (!win->m_hasVMT) return FALSE;
034be888
RR
899 if (g_blockEventsOnDrag) return FALSE;
900 if (g_blockEventsOnScroll) return FALSE;
c801d85f 901
034be888 902 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
47d67540 903
c801d85f 904/*
f5e27805
RR
905 printf( "OnButtonRelease from " );
906 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
907 printf( win->GetClassInfo()->GetClassName() );
908 printf( ".\n" );
c801d85f 909*/
47d67540 910
f5e27805 911 wxEventType event_type = wxEVT_NULL;
47d67540 912
f5e27805
RR
913 switch (gdk_event->button)
914 {
915 case 1: event_type = wxEVT_LEFT_UP; break;
916 case 2: event_type = wxEVT_MIDDLE_UP; break;
917 case 3: event_type = wxEVT_RIGHT_UP; break;
918 }
47d67540 919
f5e27805 920 wxMouseEvent event( event_type );
d1367c3d 921 event.SetTimestamp( gdk_event->time );
f5e27805
RR
922 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
923 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
924 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
925 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
926 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
927 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
928 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
929 event.m_x = (long)gdk_event->x;
930 event.m_y = (long)gdk_event->y;
931
932 // Some control don't have their own X window and thus cannot get
933 // any events.
934
935 if (!g_capturing)
2f2aa628 936 {
db1b4961 937 wxNode *node = win->GetChildren().First();
f5e27805
RR
938 while (node)
939 {
940 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb 941
a2053b27 942 if (child->m_isStaticBox)
ff8bfdbb
VZ
943 {
944 // wxStaticBox is transparent in the box itself
945 int x = event.m_x;
946 int y = event.m_y;
a2053b27
RR
947 int xx1 = child->m_x;
948 int yy1 = child->m_y;
949 int xx2 = child->m_x + child->m_width;
950 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
951
952 // left
953 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
954 // right
955 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
956 // top
957 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
958 // bottom
959 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
960 {
1ecc4d80 961 win = child;
a2053b27
RR
962 event.m_x -= child->m_x;
963 event.m_y -= child->m_y;
1ecc4d80 964 break;
ff8bfdbb
VZ
965 }
966
967 }
968 else
969 {
a2053b27
RR
970 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
971 (child->m_x <= event.m_x) &&
972 (child->m_y <= event.m_y) &&
973 (child->m_x+child->m_width >= event.m_x) &&
974 (child->m_y+child->m_height >= event.m_y))
1ecc4d80
RR
975 {
976 win = child;
a2053b27
RR
977 event.m_x -= child->m_x;
978 event.m_y -= child->m_y;
1ecc4d80 979 break;
ff8bfdbb 980 }
f5e27805
RR
981 }
982 node = node->Next();
983 }
2f2aa628 984 }
47d67540 985
f5e27805 986 event.SetEventObject( win );
47d67540 987
f5e27805 988 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 989 {
f5e27805 990 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" );
f03fc89f 991 return TRUE;
034be888 992 }
47d67540 993
034be888 994 return FALSE;
362c6693 995}
c801d85f
KB
996
997//-----------------------------------------------------------------------------
2f2aa628
RR
998// "motion_notify_event"
999//-----------------------------------------------------------------------------
c801d85f 1000
2f2aa628 1001static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
47d67540 1002{
a2053b27
RR
1003 if (g_isIdle)
1004 wxapp_install_idle_handler();
1005
1006 if (!win->m_hasVMT) return FALSE;
034be888
RR
1007 if (g_blockEventsOnDrag) return FALSE;
1008 if (g_blockEventsOnScroll) return FALSE;
1009
1010 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1011
ff8bfdbb 1012 if (gdk_event->is_hint)
aae24d21
RR
1013 {
1014 int x = 0;
1015 int y = 0;
1016 GdkModifierType state;
1017 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
1018 gdk_event->x = x;
1019 gdk_event->y = y;
1020 gdk_event->state = state;
1021 }
ff8bfdbb 1022
c801d85f 1023/*
e380f72b
RR
1024 printf( "OnMotion from " );
1025 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1026 printf( win->GetClassInfo()->GetClassName() );
1027 printf( ".\n" );
aae24d21 1028*/
47d67540 1029
e380f72b 1030 wxMouseEvent event( wxEVT_MOTION );
d1367c3d 1031 event.SetTimestamp( gdk_event->time );
e380f72b
RR
1032 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1033 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1034 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1035 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1036 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1037 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1038 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
1039
1040 event.m_x = (long)gdk_event->x;
1041 event.m_y = (long)gdk_event->y;
1042
1043 // Some control don't have their own X window and thus cannot get
1044 // any events.
1045
1046 if (!g_capturing)
2f2aa628 1047 {
db1b4961 1048 wxNode *node = win->GetChildren().First();
e380f72b
RR
1049 while (node)
1050 {
1051 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb 1052
a2053b27 1053 if (child->m_isStaticBox)
ff8bfdbb
VZ
1054 {
1055 // wxStaticBox is transparent in the box itself
1056 int x = event.m_x;
1057 int y = event.m_y;
a2053b27
RR
1058 int xx1 = child->m_x;
1059 int yy1 = child->m_y;
1060 int xx2 = child->m_x + child->m_width;
1061 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1062
1063 // left
1064 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1065 // right
1066 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1067 // top
1068 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1069 // bottom
1070 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1071 {
1ecc4d80 1072 win = child;
a2053b27
RR
1073 event.m_x -= child->m_x;
1074 event.m_y -= child->m_y;
1ecc4d80 1075 break;
ff8bfdbb
VZ
1076 }
1077
1078 }
1079 else
1080 {
a2053b27
RR
1081 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
1082 (child->m_x <= event.m_x) &&
1083 (child->m_y <= event.m_y) &&
1084 (child->m_x+child->m_width >= event.m_x) &&
1085 (child->m_y+child->m_height >= event.m_y))
1ecc4d80
RR
1086 {
1087 win = child;
a2053b27
RR
1088 event.m_x -= child->m_x;
1089 event.m_y -= child->m_y;
1ecc4d80 1090 break;
ff8bfdbb 1091 }
e380f72b
RR
1092 }
1093 node = node->Next();
1094 }
2f2aa628 1095 }
47d67540 1096
e380f72b 1097 event.SetEventObject( win );
47d67540 1098
e380f72b 1099 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1100 {
e380f72b 1101 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
f03fc89f 1102 return TRUE;
034be888 1103 }
47d67540 1104
034be888 1105 return FALSE;
362c6693 1106}
c801d85f
KB
1107
1108//-----------------------------------------------------------------------------
2f2aa628
RR
1109// "focus_in_event"
1110//-----------------------------------------------------------------------------
c801d85f 1111
2f2aa628 1112static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
c801d85f 1113{
a2053b27
RR
1114 if (g_isIdle)
1115 wxapp_install_idle_handler();
1116
1117 if (!win->m_hasVMT) return FALSE;
034be888 1118 if (g_blockEventsOnDrag) return FALSE;
ff8bfdbb 1119
b292e2f5 1120 g_focusWindow = win;
ff8bfdbb 1121
a2053b27 1122 if (win->m_wxwindow)
c801d85f 1123 {
a2053b27 1124 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
e380f72b 1125 {
a2053b27 1126 GTK_WIDGET_SET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
47d67540 1127/*
e380f72b
RR
1128 printf( "SetFocus flag from " );
1129 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1130 printf( win->GetClassInfo()->GetClassName() );
1131 printf( ".\n" );
c801d85f 1132*/
e380f72b 1133 }
362c6693 1134 }
47d67540 1135
47d67540 1136
c801d85f 1137/*
f03fc89f 1138 printf( "OnSetFocus from " );
e380f72b 1139 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
f03fc89f
VZ
1140 printf( win->GetClassInfo()->GetClassName() );
1141 printf( " " );
1142 printf( WXSTRINGCAST win->GetLabel() );
1143 printf( ".\n" );
c801d85f 1144*/
47d67540 1145
e380f72b
RR
1146 wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
1147 event.SetEventObject( win );
47d67540 1148
e380f72b 1149 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1150 {
e380f72b 1151 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
034be888
RR
1152 return TRUE;
1153 }
ca298c88 1154
034be888 1155 return FALSE;
362c6693 1156}
c801d85f
KB
1157
1158//-----------------------------------------------------------------------------
2f2aa628
RR
1159// "focus_out_event"
1160//-----------------------------------------------------------------------------
c801d85f 1161
2f2aa628 1162static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
c801d85f 1163{
a2053b27
RR
1164 if (g_isIdle)
1165 wxapp_install_idle_handler();
1166
1167 if (!win->m_hasVMT) return FALSE;
034be888 1168 if (g_blockEventsOnDrag) return FALSE;
ca298c88 1169
a2053b27 1170 if (win->m_wxwindow)
e380f72b 1171 {
a2053b27
RR
1172 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
1173 GTK_WIDGET_UNSET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
e380f72b 1174 }
47d67540 1175
c801d85f 1176/*
f03fc89f 1177 printf( "OnKillFocus from " );
e380f72b 1178 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
f03fc89f
VZ
1179 printf( win->GetClassInfo()->GetClassName() );
1180 printf( ".\n" );
c801d85f 1181*/
47d67540 1182
e380f72b
RR
1183 wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
1184 event.SetEventObject( win );
47d67540 1185
e380f72b 1186 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1187 {
e380f72b 1188 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
034be888
RR
1189 return TRUE;
1190 }
ca298c88 1191
034be888 1192 return FALSE;
362c6693 1193}
c801d85f 1194
b4071e91
RR
1195//-----------------------------------------------------------------------------
1196// "enter_notify_event"
1197//-----------------------------------------------------------------------------
1198
1199static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1200{
a2053b27
RR
1201 if (g_isIdle)
1202 wxapp_install_idle_handler();
ca298c88 1203
a2053b27
RR
1204 if (!win->m_hasVMT) return FALSE;
1205 if (g_blockEventsOnDrag) return FALSE;
47d67540 1206
a2053b27 1207 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
b292e2f5 1208
a2053b27
RR
1209 if (widget->window && win->GetCursor().Ok() )
1210 gdk_window_set_cursor( widget->window, win->GetCursor().GetCursor() );
47d67540 1211
e380f72b 1212 wxMouseEvent event( wxEVT_ENTER_WINDOW );
d1367c3d 1213 event.SetTimestamp( gdk_event->time );
e380f72b 1214 event.SetEventObject( win );
ff8bfdbb 1215
4a33eba6
RR
1216 int x = 0;
1217 int y = 0;
1218 GdkModifierType state = (GdkModifierType)0;
ff8bfdbb 1219
a2053b27 1220 gdk_window_get_pointer( widget->window, &x, &y, &state );
ff8bfdbb 1221
4a33eba6
RR
1222 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1223 event.m_controlDown = (state & GDK_CONTROL_MASK);
1224 event.m_altDown = (state & GDK_MOD1_MASK);
1225 event.m_metaDown = (state & GDK_MOD2_MASK);
1226 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1227 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1228 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1229
1230 event.m_x = (long)x;
1231 event.m_y = (long)y;
ff8bfdbb 1232
e380f72b 1233 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1234 {
e380f72b 1235 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "enter_notify_event" );
034be888
RR
1236 return TRUE;
1237 }
ca298c88 1238
034be888 1239 return FALSE;
b4071e91 1240}
47d67540 1241
b4071e91
RR
1242//-----------------------------------------------------------------------------
1243// "leave_notify_event"
1244//-----------------------------------------------------------------------------
1245
1246static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1247{
a2053b27
RR
1248 if (g_isIdle)
1249 wxapp_install_idle_handler();
acfd422a 1250
a2053b27
RR
1251 if (!win->m_hasVMT) return FALSE;
1252 if (g_blockEventsOnDrag) return FALSE;
b292e2f5 1253
a2053b27
RR
1254 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1255
1256 if (widget->window && win->GetCursor().Ok() )
1257 gdk_window_set_cursor( widget->window, wxSTANDARD_CURSOR->GetCursor() );
47d67540 1258
e380f72b 1259 wxMouseEvent event( wxEVT_LEAVE_WINDOW );
d1367c3d 1260 event.SetTimestamp( gdk_event->time );
e380f72b 1261 event.SetEventObject( win );
47d67540 1262
4a33eba6
RR
1263 int x = 0;
1264 int y = 0;
1265 GdkModifierType state = (GdkModifierType)0;
ff8bfdbb 1266
4a33eba6 1267 gdk_window_get_pointer( widget->window, &x, &y, &state );
ff8bfdbb 1268
4a33eba6
RR
1269 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1270 event.m_controlDown = (state & GDK_CONTROL_MASK);
1271 event.m_altDown = (state & GDK_MOD1_MASK);
1272 event.m_metaDown = (state & GDK_MOD2_MASK);
1273 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1274 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1275 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1276
1277 event.m_x = (long)x;
1278 event.m_y = (long)y;
ff8bfdbb 1279
e380f72b 1280 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1281 {
e380f72b 1282 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "leave_notify_event" );
034be888
RR
1283 return TRUE;
1284 }
ca298c88 1285
034be888 1286 return FALSE;
b4071e91 1287}
47d67540 1288
c801d85f 1289//-----------------------------------------------------------------------------
2f2aa628
RR
1290// "value_changed" from m_vAdjust
1291//-----------------------------------------------------------------------------
c801d85f 1292
2f2aa628 1293static void gtk_window_vscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
c801d85f 1294{
a2053b27
RR
1295 if (g_isIdle)
1296 wxapp_install_idle_handler();
c801d85f 1297
a2053b27 1298 if (g_blockEventsOnDrag) return;
47d67540 1299
a2053b27 1300 if (!win->m_hasVMT) return;
47d67540 1301
a2053b27 1302 float diff = win->m_vAdjust->value - win->m_oldVerticalPos;
e380f72b 1303 if (fabs(diff) < 0.2) return;
a2053b27 1304 win->m_oldVerticalPos = win->m_vAdjust->value;
47d67540 1305
e380f72b 1306 wxEventType command = wxEVT_NULL;
47d67540 1307
a2053b27
RR
1308 float line_step = win->m_vAdjust->step_increment;
1309 float page_step = win->m_vAdjust->page_increment;
47d67540 1310
f03fc89f 1311 if (win->IsScrolling())
76ed8f8d 1312 {
c5b42c87 1313 command = wxEVT_SCROLLWIN_THUMBTRACK;
76ed8f8d
RR
1314 }
1315 else
1316 {
c5b42c87
RR
1317 if (fabs(win->m_vAdjust->value-win->m_vAdjust->lower) < 0.2) command = wxEVT_SCROLLWIN_BOTTOM;
1318 else if (fabs(win->m_vAdjust->value-win->m_vAdjust->upper) < 0.2) command = wxEVT_SCROLLWIN_TOP;
1319 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLLWIN_LINEDOWN;
1320 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLLWIN_LINEUP;
1321 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLLWIN_PAGEDOWN;
1322 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLLWIN_PAGEUP;
1323 else command = wxEVT_SCROLLWIN_THUMBTRACK;
76ed8f8d 1324 }
47d67540 1325
a2053b27 1326 int value = (int)(win->m_vAdjust->value+0.5);
c801d85f 1327
c5b42c87 1328 wxScrollWinEvent event( command, value, wxVERTICAL );
e380f72b
RR
1329 event.SetEventObject( win );
1330 win->GetEventHandler()->ProcessEvent( event );
362c6693 1331}
c801d85f
KB
1332
1333//-----------------------------------------------------------------------------
2f2aa628
RR
1334// "value_changed" from m_hAdjust
1335//-----------------------------------------------------------------------------
c801d85f 1336
2f2aa628 1337static void gtk_window_hscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
47d67540 1338{
a2053b27
RR
1339 if (g_isIdle)
1340 wxapp_install_idle_handler();
47d67540 1341
a2053b27
RR
1342 if (g_blockEventsOnDrag) return;
1343 if (!win->m_hasVMT) return;
47d67540 1344
a2053b27 1345 float diff = win->m_hAdjust->value - win->m_oldHorizontalPos;
e380f72b 1346 if (fabs(diff) < 0.2) return;
a2053b27 1347 win->m_oldHorizontalPos = win->m_hAdjust->value;
47d67540 1348
e380f72b 1349 wxEventType command = wxEVT_NULL;
47d67540 1350
a2053b27
RR
1351 float line_step = win->m_hAdjust->step_increment;
1352 float page_step = win->m_hAdjust->page_increment;
8bbe427f 1353
f03fc89f 1354 if (win->IsScrolling())
76ed8f8d 1355 {
c5b42c87 1356 command = wxEVT_SCROLLWIN_THUMBTRACK;
76ed8f8d
RR
1357 }
1358 else
1359 {
c5b42c87
RR
1360 if (fabs(win->m_hAdjust->value-win->m_hAdjust->lower) < 0.2) command = wxEVT_SCROLLWIN_BOTTOM;
1361 else if (fabs(win->m_hAdjust->value-win->m_hAdjust->upper) < 0.2) command = wxEVT_SCROLLWIN_TOP;
1362 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLLWIN_LINEDOWN;
1363 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLLWIN_LINEUP;
1364 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLLWIN_PAGEDOWN;
1365 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLLWIN_PAGEUP;
1366 else command = wxEVT_SCROLLWIN_THUMBTRACK;
76ed8f8d 1367 }
c801d85f 1368
a2053b27 1369 int value = (int)(win->m_hAdjust->value+0.5);
47d67540 1370
c5b42c87 1371 wxScrollWinEvent event( command, value, wxHORIZONTAL );
e380f72b
RR
1372 event.SetEventObject( win );
1373 win->GetEventHandler()->ProcessEvent( event );
362c6693 1374}
c801d85f
KB
1375
1376//-----------------------------------------------------------------------------
2f2aa628
RR
1377// "changed" from m_vAdjust
1378//-----------------------------------------------------------------------------
c801d85f 1379
2f2aa628 1380static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
c801d85f 1381{
a2053b27
RR
1382 if (g_isIdle)
1383 wxapp_install_idle_handler();
c801d85f 1384
a2053b27
RR
1385 if (g_blockEventsOnDrag) return;
1386 if (!win->m_hasVMT) return;
47d67540 1387
c5b42c87 1388 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
a2053b27 1389 int value = (int)(win->m_vAdjust->value+0.5);
c801d85f 1390
c5b42c87 1391 wxScrollWinEvent event( command, value, wxVERTICAL );
e380f72b
RR
1392 event.SetEventObject( win );
1393 win->GetEventHandler()->ProcessEvent( event );
362c6693 1394}
c801d85f
KB
1395
1396//-----------------------------------------------------------------------------
2f2aa628
RR
1397// "changed" from m_hAdjust
1398//-----------------------------------------------------------------------------
c801d85f 1399
2f2aa628 1400static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
47d67540 1401{
a2053b27
RR
1402 if (g_isIdle)
1403 wxapp_install_idle_handler();
47d67540 1404
a2053b27
RR
1405 if (g_blockEventsOnDrag) return;
1406 if (!win->m_hasVMT) return;
47d67540 1407
c5b42c87 1408 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
a2053b27 1409 int value = (int)(win->m_hAdjust->value+0.5);
47d67540 1410
c5b42c87 1411 wxScrollWinEvent event( command, value, wxHORIZONTAL );
e380f72b
RR
1412 event.SetEventObject( win );
1413 win->GetEventHandler()->ProcessEvent( event );
362c6693 1414}
c801d85f 1415
cb43b372
RR
1416//-----------------------------------------------------------------------------
1417// "button_press_event" from scrollbar
1418//-----------------------------------------------------------------------------
1419
8bbe427f
VZ
1420static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
1421 GdkEventButton *WXUNUSED(gdk_event),
ff8bfdbb 1422 wxWindow *win )
cb43b372 1423{
a2053b27
RR
1424 if (g_isIdle)
1425 wxapp_install_idle_handler();
1426
1ecc4d80
RR
1427// don't test here as we can release the mouse while being over
1428// a different window then the slider
1429//
76ed8f8d 1430// if (gdk_event->window != widget->slider) return FALSE;
8bbe427f 1431
f03fc89f 1432 win->SetScrolling( TRUE );
47d67540 1433
e380f72b 1434 return FALSE;
cb43b372
RR
1435}
1436
1437//-----------------------------------------------------------------------------
1438// "button_release_event" from scrollbar
1439//-----------------------------------------------------------------------------
1440
8bbe427f
VZ
1441static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
1442 GdkEventButton *WXUNUSED(gdk_event),
ff8bfdbb 1443 wxWindow *win )
cb43b372 1444{
76ed8f8d 1445
1ecc4d80 1446// don't test here as we can release the mouse while being over
76ed8f8d
RR
1447// a different window then the slider
1448//
1449// if (gdk_event->window != widget->slider) return FALSE;
cb43b372 1450
a2053b27 1451 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
47d67540 1452
f03fc89f 1453 if (widget == GTK_RANGE(scrolledWindow->vscrollbar))
a2053b27 1454 gtk_signal_emit_by_name( GTK_OBJECT(win->m_hAdjust), "value_changed" );
e380f72b 1455 else
a2053b27 1456 gtk_signal_emit_by_name( GTK_OBJECT(win->m_vAdjust), "value_changed" );
47d67540 1457
f03fc89f 1458 win->SetScrolling( FALSE );
47d67540 1459
e380f72b 1460 return FALSE;
cb43b372
RR
1461}
1462
f03fc89f
VZ
1463// ----------------------------------------------------------------------------
1464// this wxWindowBase function is implemented here (in platform-specific file)
1465// because it is static and so couldn't be made virtual
1466// ----------------------------------------------------------------------------
2b07d713 1467
f03fc89f 1468wxWindow *wxWindowBase::FindFocus()
2b07d713 1469{
f03fc89f 1470 return g_focusWindow;
2b07d713 1471}
ca298c88 1472
a2053b27
RR
1473//-----------------------------------------------------------------------------
1474// "realize" from m_widget
1475//-----------------------------------------------------------------------------
1476
1477/* we cannot set colours, fonts and cursors before the widget has
1478 been realized, so we do this directly after realization */
1479
1480static gint
a234a61a 1481gtk_window_realized_callback( GtkWidget * WXUNUSED(widget), wxWindow *win )
a2053b27
RR
1482{
1483 if (g_isIdle)
1484 wxapp_install_idle_handler();
1485
739730ca
RR
1486 if (win->m_delayedFont)
1487 win->SetFont( win->GetFont() );
a2053b27 1488
739730ca
RR
1489 if (win->m_delayedBackgroundColour)
1490 win->SetBackgroundColour( win->GetBackgroundColour() );
a2053b27 1491
739730ca
RR
1492 if (win->m_delayedForegroundColour)
1493 win->SetForegroundColour( win->GetForegroundColour() );
a2053b27 1494
739730ca 1495 win->SetCursor( win->GetCursor() );
a2053b27
RR
1496
1497 return FALSE;
1498}
1499
6ca41e57
RR
1500//-----------------------------------------------------------------------------
1501// InsertChild for wxWindow.
1502//-----------------------------------------------------------------------------
1503
b1170810
RR
1504/* Callback for wxWindow. This very strange beast has to be used because
1505 * C++ has no virtual methods in a constructor. We have to emulate a
1506 * virtual function here as wxNotebook requires a different way to insert
1507 * a child in it. I had opted for creating a wxNotebookPage window class
1508 * which would have made this superfluous (such in the MDI window system),
1509 * but no-one was listening to me... */
6ca41e57
RR
1510
1511static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
1512{
a2053b27
RR
1513 gtk_myfixed_put( GTK_MYFIXED(parent->m_wxwindow),
1514 GTK_WIDGET(child->m_widget),
1515 child->m_x,
1516 child->m_y,
1517 child->m_width,
1518 child->m_height );
f03fc89f
VZ
1519
1520 if (parent->HasFlag(wxTAB_TRAVERSAL))
3e61c765
RR
1521 {
1522 /* we now allow a window to get the focus as long as it
ff8bfdbb 1523 doesn't have any children. */
a2053b27 1524 GTK_WIDGET_UNSET_FLAGS( parent->m_wxwindow, GTK_CAN_FOCUS );
3e61c765 1525 }
6ca41e57
RR
1526}
1527
bbe0af5b
RR
1528//-----------------------------------------------------------------------------
1529// global functions
1530//-----------------------------------------------------------------------------
1531
1532wxWindow* wxGetActiveWindow()
1533{
f03fc89f 1534 return g_focusWindow;
bbe0af5b
RR
1535}
1536
c801d85f 1537//-----------------------------------------------------------------------------
2f2aa628 1538// wxWindow
c801d85f
KB
1539//-----------------------------------------------------------------------------
1540
f03fc89f 1541IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
c801d85f 1542
68995f26 1543void wxWindow::Init()
c801d85f 1544{
f03fc89f
VZ
1545 // common init
1546 InitBase();
68995f26 1547
f03fc89f 1548 // GTK specific
a2053b27 1549 m_widget = (GtkWidget *) NULL;
e380f72b 1550 m_wxwindow = (GtkWidget *) NULL;
8bbe427f 1551
f03fc89f 1552 // position/size
a2053b27
RR
1553 m_x = 0;
1554 m_y = 0;
1555 m_width = 0;
e380f72b 1556 m_height = 0;
8bbe427f 1557
e380f72b
RR
1558 m_sizeSet = FALSE;
1559 m_hasVMT = FALSE;
1560 m_needParent = TRUE;
31c6b4fc 1561 m_isBeingDeleted = FALSE;
8bbe427f 1562
a2053b27 1563 m_hasScrolling = FALSE;
e380f72b 1564 m_isScrolling = FALSE;
f03fc89f 1565
a2053b27 1566 m_hAdjust = (GtkAdjustment*) NULL;
e380f72b 1567 m_vAdjust = (GtkAdjustment*) NULL;
a2053b27 1568 m_oldHorizontalPos = 0.0;
e380f72b 1569 m_oldVerticalPos = 0.0;
8bbe427f 1570
e380f72b
RR
1571 m_resizing = FALSE;
1572 m_scrollGC = (GdkGC*) NULL;
1573 m_widgetStyle = (GtkStyle*) NULL;
8bbe427f 1574
e380f72b 1575 m_insertCallback = wxInsertChildInWindow;
8bbe427f 1576
1ecc4d80 1577 m_isStaticBox = FALSE;
b292e2f5 1578 m_acceptsFocus = FALSE;
362c6693 1579}
c801d85f 1580
68995f26
VZ
1581wxWindow::wxWindow()
1582{
1583 Init();
1584}
1585
6ca41e57 1586wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
e380f72b
RR
1587 const wxPoint &pos, const wxSize &size,
1588 long style, const wxString &name )
6ca41e57 1589{
68995f26
VZ
1590 Init();
1591
e380f72b 1592 Create( parent, id, pos, size, style, name );
6ca41e57 1593}
8bbe427f 1594
debe6624 1595bool wxWindow::Create( wxWindow *parent, wxWindowID id,
e380f72b
RR
1596 const wxPoint &pos, const wxSize &size,
1597 long style, const wxString &name )
c801d85f 1598{
e380f72b 1599 PreCreation( parent, id, pos, size, style, name );
47d67540 1600
e380f72b 1601 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
38c7b3d3 1602 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
ff8bfdbb 1603
2e563988
RR
1604#ifdef __WXDEBUG__
1605 debug_focus_in( m_widget, _T("wxWindow::m_widget"), name );
1606#endif
1607
f03fc89f 1608 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
47d67540 1609
2e563988 1610#ifdef __WXDEBUG__
f03fc89f
VZ
1611 debug_focus_in( scrolledWindow->hscrollbar, _T("wxWindow::hsrcollbar"), name );
1612 debug_focus_in( scrolledWindow->vscrollbar, _T("wxWindow::vsrcollbar"), name );
2e563988
RR
1613#endif
1614
e380f72b
RR
1615 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1616 scroll_class->scrollbar_spacing = 0;
47d67540 1617
f03fc89f 1618 gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
47d67540 1619
f03fc89f
VZ
1620 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->hscrollbar) );
1621 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->vscrollbar) );
47d67540 1622
38c7b3d3
RR
1623 m_wxwindow = gtk_myfixed_new();
1624
2e563988
RR
1625#ifdef __WXDEBUG__
1626 debug_focus_in( m_wxwindow, _T("wxWindow::m_wxwindow"), name );
1627#endif
1628
034be888 1629 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
58dea4b0 1630
034be888
RR
1631#if (GTK_MINOR_VERSION > 0)
1632 GtkMyFixed *myfixed = GTK_MYFIXED(m_wxwindow);
b292e2f5 1633
f03fc89f 1634 if (HasFlag(wxRAISED_BORDER))
034be888
RR
1635 {
1636 gtk_myfixed_set_shadow_type( myfixed, GTK_SHADOW_OUT );
1637 }
f03fc89f 1638 else if (HasFlag(wxSUNKEN_BORDER))
034be888
RR
1639 {
1640 gtk_myfixed_set_shadow_type( myfixed, GTK_SHADOW_IN );
1641 }
1642 else
1643 {
1644 gtk_myfixed_set_shadow_type( myfixed, GTK_SHADOW_NONE );
1645 }
f03fc89f
VZ
1646#else // GTK_MINOR_VERSION == 0
1647 GtkViewport *viewport = GTK_VIEWPORT(scrolledWindow->viewport);
b292e2f5 1648
f03fc89f 1649 if (HasFlag(wxRAISED_BORDER))
e380f72b
RR
1650 {
1651 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
1652 }
f03fc89f 1653 else if (HasFlag(wxSUNKEN_BORDER))
e380f72b
RR
1654 {
1655 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
1656 }
1657 else
1658 {
1659 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
1660 }
f03fc89f 1661#endif // GTK_MINOR_VERSION
47d67540 1662
f03fc89f 1663 if (HasFlag(wxTAB_TRAVERSAL))
b292e2f5 1664 {
f03fc89f
VZ
1665 /* we now allow a window to get the focus as long as it
1666 doesn't have any children. */
ff8bfdbb 1667 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
b292e2f5
RR
1668 m_acceptsFocus = FALSE;
1669 }
e380f72b 1670 else
b292e2f5 1671 {
e380f72b 1672 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
b292e2f5
RR
1673 m_acceptsFocus = TRUE;
1674 }
ca298c88 1675
034be888 1676#if (GTK_MINOR_VERSION == 0)
e380f72b
RR
1677 // shut the viewport up
1678 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1679 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
f03fc89f 1680#endif // GTK_MINOR_VERSION == 0
e380f72b
RR
1681
1682 // I _really_ don't want scrollbars in the beginning
a2053b27
RR
1683 m_vAdjust->lower = 0.0;
1684 m_vAdjust->upper = 1.0;
1685 m_vAdjust->value = 0.0;
1686 m_vAdjust->step_increment = 1.0;
1687 m_vAdjust->page_increment = 1.0;
1688 m_vAdjust->page_size = 5.0;
1689 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1690 m_hAdjust->lower = 0.0;
1691 m_hAdjust->upper = 1.0;
1692 m_hAdjust->value = 0.0;
1693 m_hAdjust->step_increment = 1.0;
1694 m_hAdjust->page_increment = 1.0;
1695 m_hAdjust->page_size = 5.0;
1696 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
f03fc89f
VZ
1697
1698 // these handlers block mouse events to any window during scrolling such as
1699 // motion events and prevent GTK and wxWindows from fighting over where the
1700 // slider should be
1701
1702 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_press_event",
76ed8f8d
RR
1703 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1704
f03fc89f 1705 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_press_event",
76ed8f8d
RR
1706 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1707
f03fc89f 1708 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_release_event",
76ed8f8d
RR
1709 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1710
f03fc89f 1711 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_release_event",
76ed8f8d 1712 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
8bbe427f 1713
034be888 1714 // these handlers get notified when screen updates are required either when
76ed8f8d
RR
1715 // scrolling or when the window size (and therefore scrollbar configuration)
1716 // has changed
1717
1718 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
1719 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
1720 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
1721 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
1722
1723 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
1724 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
1725 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
1726 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
1727
f03fc89f 1728 gtk_widget_show( m_wxwindow );
47d67540 1729
f03fc89f
VZ
1730 if (m_parent)
1731 m_parent->DoAddChild( this );
8bbe427f 1732
e380f72b 1733 PostCreation();
8bbe427f 1734
e380f72b 1735 Show( TRUE );
c801d85f 1736
e380f72b 1737 return TRUE;
362c6693 1738}
c801d85f 1739
68dda785 1740wxWindow::~wxWindow()
c801d85f 1741{
31c6b4fc 1742 m_isBeingDeleted = TRUE;
43a18898 1743 m_hasVMT = FALSE;
47d67540 1744
f03fc89f
VZ
1745 if (m_widget)
1746 Show( FALSE );
8bbe427f 1747
a2053b27
RR
1748 DestroyChildren();
1749
f03fc89f
VZ
1750 if (m_parent)
1751 m_parent->RemoveChild( this );
c801d85f 1752
f03fc89f 1753 if (m_widgetStyle)
a2053b27 1754 {
f03fc89f 1755 gtk_style_unref( m_widgetStyle );
a2053b27
RR
1756 m_widgetStyle = (GtkStyle*) NULL;
1757 }
c801d85f 1758
f03fc89f 1759 if (m_scrollGC)
a2053b27 1760 {
f03fc89f 1761 gdk_gc_unref( m_scrollGC );
a2053b27
RR
1762 m_scrollGC = (GdkGC*) NULL;
1763 }
47d67540 1764
f03fc89f 1765 if (m_wxwindow)
a2053b27 1766 {
f03fc89f 1767 gtk_widget_destroy( m_wxwindow );
a2053b27
RR
1768 m_wxwindow = (GtkWidget*) NULL;
1769 }
8bbe427f 1770
f03fc89f 1771 if (m_widget)
a2053b27 1772 {
f03fc89f 1773 gtk_widget_destroy( m_widget );
a2053b27
RR
1774 m_widget = (GtkWidget*) NULL;
1775 }
362c6693 1776}
c801d85f 1777
f03fc89f
VZ
1778void wxWindow::PreCreation( wxWindow *parent,
1779 wxWindowID id,
1780 const wxPoint &pos,
1781 const wxSize &size,
1782 long style,
1783 const wxString &name )
c801d85f 1784{
f03fc89f 1785 wxASSERT_MSG( !m_needParent || parent, _T("Need complete parent.") );
8bbe427f 1786
f03fc89f
VZ
1787 if ( !CreateBase(parent, id, pos, size, style, name) )
1788 {
1789 wxFAIL_MSG(_T("window creation failed"));
1790 }
8bbe427f 1791
f03fc89f
VZ
1792 m_width = WidthDefault(size.x);
1793 m_height = HeightDefault(size.y);
8bbe427f 1794
43a18898
RR
1795 m_x = (int)pos.x;
1796 m_y = (int)pos.y;
8bbe427f 1797
f03fc89f 1798 if (!parent) /* some reasonable defaults */
6ca41e57 1799 {
43a18898
RR
1800 if (m_x == -1)
1801 {
1802 m_x = (gdk_screen_width () - m_width) / 2;
1803 if (m_x < 10) m_x = 10;
1804 }
1805 if (m_y == -1)
1806 {
1807 m_y = (gdk_screen_height () - m_height) / 2;
1808 if (m_y < 10) m_y = 10;
1809 }
6ca41e57 1810 }
c801d85f
KB
1811}
1812
68dda785 1813void wxWindow::PostCreation()
c801d85f 1814{
05939a81 1815 wxASSERT_MSG( (m_widget != NULL), _T("invalid window") );
ca298c88 1816
43a18898
RR
1817 if (m_wxwindow)
1818 {
034be888 1819 /* these get reported to wxWindows -> wxPaintEvent */
20239453
RR
1820 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
1821 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
47d67540 1822
20239453
RR
1823 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
1824 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
ca298c88 1825
ef47f9b3 1826#if (GTK_MINOR_VERSION > 0)
f03fc89f 1827 /* these are called when the "sunken" or "raised" borders are drawn */
034be888
RR
1828 gtk_signal_connect( GTK_OBJECT(m_widget), "expose_event",
1829 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback), (gpointer)this );
1830
1831 gtk_signal_connect( GTK_OBJECT(m_widget), "draw",
1832 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback), (gpointer)this );
ef47f9b3 1833#endif
43a18898 1834 }
47d67540 1835
a2053b27 1836 GtkWidget *connect_widget = GetConnectWidget();
f03fc89f 1837
a2053b27 1838 ConnectWidget( connect_widget );
47d67540 1839
a2053b27
RR
1840 /* we cannot set colours, fonts and cursors before the widget has
1841 been realized, so we do this directly after realization */
1842 gtk_signal_connect( GTK_OBJECT(connect_widget), "realize",
1843 GTK_SIGNAL_FUNC(gtk_window_realized_callback), (gpointer) this );
ca298c88 1844
43a18898 1845 m_hasVMT = TRUE;
b4071e91
RR
1846}
1847
1848void wxWindow::ConnectWidget( GtkWidget *widget )
1849{
43a18898
RR
1850 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
1851 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
c801d85f 1852
b666df2c
RR
1853 gtk_signal_connect( GTK_OBJECT(widget), "key_release_event",
1854 GTK_SIGNAL_FUNC(gtk_window_key_release_callback), (gpointer)this );
1855
43a18898
RR
1856 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
1857 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
47d67540 1858
43a18898
RR
1859 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
1860 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
47d67540 1861
43a18898
RR
1862 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
1863 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
47d67540 1864
43a18898
RR
1865 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
1866 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
c801d85f 1867
43a18898
RR
1868 gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
1869 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
c801d85f 1870
43a18898
RR
1871 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
1872 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
47d67540 1873
43a18898
RR
1874 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
1875 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
362c6693 1876}
c801d85f 1877
68dda785 1878bool wxWindow::Destroy()
c801d85f 1879{
05939a81 1880 wxASSERT_MSG( (m_widget != NULL), _T("invalid window") );
47d67540 1881
43a18898 1882 m_hasVMT = FALSE;
c801d85f 1883
f03fc89f 1884 return wxWindowBase::Destroy();
362c6693 1885}
c801d85f 1886
bfc6fde4 1887void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
c801d85f 1888{
05939a81
OK
1889 wxASSERT_MSG( (m_widget != NULL), _T("invalid window") );
1890 wxASSERT_MSG( (m_parent != NULL), _T("wxWindow::SetSize requires parent.\n") );
8bbe427f 1891
e27ce4e9 1892 if (m_resizing) return; /* I don't like recursions */
fb1585ae 1893 m_resizing = TRUE;
47d67540 1894
a2053b27 1895 if (m_parent->m_wxwindow == NULL) /* i.e. wxNotebook */
fb1585ae 1896 {
e27ce4e9 1897 /* don't set the size for children of wxNotebook, just take the values. */
fb1585ae
RR
1898 m_x = x;
1899 m_y = y;
1900 m_width = width;
ba4e3652 1901 m_height = height;
fb1585ae 1902 }
ba4e3652 1903 else
fb1585ae 1904 {
ba4e3652
RR
1905 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
1906 {
1907 if (x != -1) m_x = x;
1908 if (y != -1) m_y = y;
1909 if (width != -1) m_width = width;
1910 if (height != -1) m_height = height;
1911 }
1912 else
1913 {
1914 m_x = x;
1915 m_y = y;
1916 m_width = width;
1917 m_height = height;
1918 }
47d67540 1919
ba4e3652
RR
1920 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
1921 {
1922 if (width == -1) m_width = 80;
1923 }
1924
1925 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
1926 {
1927 if (height == -1) m_height = 26;
1928 }
8bbe427f 1929
ba4e3652
RR
1930 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
1931 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
d3b4d113
RR
1932 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
1933 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
47d67540 1934
a2053b27 1935 int border = 0;
f03fc89f 1936
a2053b27
RR
1937 if (GTK_WIDGET_HAS_DEFAULT(m_widget))
1938 {
1939 /* the default button has a border around it */
1940 border = 5;
1941 }
1942
1943 /* this is the result of hours of debugging: the following code
1944 means that if we have a m_wxwindow and we set the size of
1945 m_widget, m_widget (which is a GtkScrolledWindow) does NOT
1946 automatically propagate its size down to its m_wxwindow,
1947 which is its client area. therefore, we have to tell the
1948 client area directly that it has to resize itself.
1949 this will lead to that m_widget (GtkScrolledWindow) will
1950 calculate how much size it needs for scrollbars etc and
1951 it will then call XXX_size_allocate of its child, which
1952 is m_wxwindow. m_wxwindow in turn will do the same with its
1953 children and so on. problems can arise if this happens
1954 before all the children have been realized as some widgets
1955 stupidy need to be realized during XXX_size_allocate (e.g.
1956 GtkNotebook) and they will segv if called otherwise. this
1957 emergency is tested in gtk_myfixed_size_allocate. Normally
1958 this shouldn't be needed and only gtk_widget_queue_resize()
1959 should be enough to provoke a resize at the next appropriate
1960 moment, but this seems to fail, e.g. when a wxNotebook contains
1961 a wxSplitterWindow: the splitter window's children won't
1962 show up properly resized then. */
1963
1964 gtk_myfixed_set_size( GTK_MYFIXED(m_parent->m_wxwindow),
1965 m_widget,
1966 m_x-border,
1967 m_y-border,
1968 m_width+2*border,
1969 m_height+2*border );
ba4e3652 1970 }
8bbe427f 1971
fb1585ae 1972 m_sizeSet = TRUE;
47d67540 1973
fb1585ae
RR
1974 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
1975 event.SetEventObject( this );
ba4e3652 1976 GetEventHandler()->ProcessEvent( event );
47d67540 1977
fb1585ae 1978 m_resizing = FALSE;
362c6693 1979}
c801d85f 1980
9390a202
RR
1981void wxWindow::OnInternalIdle()
1982{
1983 UpdateWindowUI();
1984}
1985
f03fc89f 1986void wxWindow::DoGetSize( int *width, int *height ) const
c801d85f 1987{
05939a81 1988 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 1989
fb1585ae
RR
1990 if (width) (*width) = m_width;
1991 if (height) (*height) = m_height;
362c6693 1992}
c801d85f 1993
bfc6fde4 1994void wxWindow::DoSetClientSize( int width, int height )
c801d85f 1995{
05939a81 1996 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 1997
1ecc4d80 1998 if (!m_wxwindow)
c801d85f 1999 {
1ecc4d80 2000 SetSize( width, height );
c801d85f
KB
2001 }
2002 else
2003 {
1ecc4d80
RR
2004 int dw = 0;
2005 int dh = 0;
2006
2007 if (!m_hasScrolling)
2008 {
2009 GtkStyleClass *window_class = m_wxwindow->style->klass;
2010
f03fc89f 2011 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
1ecc4d80
RR
2012 {
2013 dw += 2 * window_class->xthickness;
2014 dh += 2 * window_class->ythickness;
2015 }
2016 }
2017 else
2018 {
2019 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2020 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
47d67540 2021
034be888 2022#if (GTK_MINOR_VERSION == 0)
1ecc4d80 2023 GtkWidget *viewport = scroll_window->viewport;
1ecc4d80
RR
2024 GtkStyleClass *viewport_class = viewport->style->klass;
2025
f03fc89f 2026 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
1ecc4d80
RR
2027 {
2028 dw += 2 * viewport_class->xthickness;
2029 dh += 2 * viewport_class->ythickness;
2030 }
034be888
RR
2031#endif
2032
2033/*
2034 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2035 GtkWidget *vscrollbar = scroll_window->vscrollbar;
ca298c88 2036
f03fc89f 2037 we use this instead: range.slider_width = 11 + 2*2pts edge
034be888 2038*/
47d67540 2039
1ecc4d80
RR
2040 if (scroll_window->vscrollbar_visible)
2041 {
034be888 2042 dw += 15; /* dw += vscrollbar->allocation.width; */
1ecc4d80
RR
2043 dw += scroll_class->scrollbar_spacing;
2044 }
2045
2046 if (scroll_window->hscrollbar_visible)
2047 {
034be888 2048 dh += 15; /* dh += hscrollbar->allocation.height; */
1ecc4d80
RR
2049 dw += scroll_class->scrollbar_spacing;
2050 }
2051 }
2052
034be888 2053 SetSize( width+dw, height+dh );
1ecc4d80 2054 }
362c6693 2055}
c801d85f 2056
f03fc89f 2057void wxWindow::DoGetClientSize( int *width, int *height ) const
c801d85f 2058{
05939a81 2059 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2060
1ecc4d80
RR
2061 if (!m_wxwindow)
2062 {
2063 if (width) (*width) = m_width;
2064 if (height) (*height) = m_height;
c801d85f
KB
2065 }
2066 else
2067 {
1ecc4d80
RR
2068 int dw = 0;
2069 int dh = 0;
2070
2071 if (!m_hasScrolling)
2072 {
2073 GtkStyleClass *window_class = m_wxwindow->style->klass;
2074
f03fc89f 2075 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
1ecc4d80
RR
2076 {
2077 dw += 2 * window_class->xthickness;
2078 dh += 2 * window_class->ythickness;
2079 }
2080 }
2081 else
2082 {
2083 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2084 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
47d67540 2085
034be888 2086#if (GTK_MINOR_VERSION == 0)
1ecc4d80 2087 GtkWidget *viewport = scroll_window->viewport;
1ecc4d80
RR
2088 GtkStyleClass *viewport_class = viewport->style->klass;
2089
f03fc89f 2090 if ( HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER) )
1ecc4d80
RR
2091 {
2092 dw += 2 * viewport_class->xthickness;
2093 dh += 2 * viewport_class->ythickness;
2094 }
034be888
RR
2095#endif
2096/*
2097 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2098 GtkWidget *vscrollbar = scroll_window->vscrollbar;
ca298c88 2099
f03fc89f 2100 we use this instead: range.slider_width = 11 + 2*2pts edge
034be888 2101*/
1ecc4d80
RR
2102
2103 if (scroll_window->vscrollbar_visible)
2104 {
034be888 2105 dw += 15; /* dw += vscrollbar->allocation.width; */
1ecc4d80
RR
2106 dw += scroll_class->scrollbar_spacing;
2107 }
2108
2109 if (scroll_window->hscrollbar_visible)
2110 {
034be888 2111 dh += 15; /* dh += hscrollbar->allocation.height; */
1ecc4d80
RR
2112 dh += scroll_class->scrollbar_spacing;
2113 }
2114 }
47d67540 2115
1ecc4d80
RR
2116 if (width) (*width) = m_width - dw;
2117 if (height) (*height) = m_height - dh;
2118 }
362c6693 2119}
c801d85f 2120
f03fc89f 2121void wxWindow::DoGetPosition( int *x, int *y ) const
c801d85f 2122{
05939a81 2123 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2124
43a18898
RR
2125 if (x) (*x) = m_x;
2126 if (y) (*y) = m_y;
362c6693 2127}
c801d85f 2128
f03fc89f 2129void wxWindow::ClientToScreen( int *x, int *y ) const
c801d85f 2130{
05939a81 2131 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2132
a2053b27
RR
2133 if (!m_widget->window) return;
2134
43a18898
RR
2135 GdkWindow *source = (GdkWindow *) NULL;
2136 if (m_wxwindow)
2137 source = m_wxwindow->window;
2138 else
2139 source = m_widget->window;
47d67540 2140
43a18898
RR
2141 int org_x = 0;
2142 int org_y = 0;
2143 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2144
43a18898 2145 if (!m_wxwindow)
c801d85f 2146 {
43a18898
RR
2147 if (GTK_WIDGET_NO_WINDOW (m_widget))
2148 {
2149 org_x += m_widget->allocation.x;
2150 org_y += m_widget->allocation.y;
2151 }
362c6693 2152 }
47d67540 2153
43a18898
RR
2154 if (x) *x += org_x;
2155 if (y) *y += org_y;
362c6693 2156}
c801d85f 2157
f03fc89f 2158void wxWindow::ScreenToClient( int *x, int *y ) const
c801d85f 2159{
05939a81 2160 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2161
a2053b27
RR
2162 if (!m_widget->window) return;
2163
1ecc4d80
RR
2164 GdkWindow *source = (GdkWindow *) NULL;
2165 if (m_wxwindow)
2166 source = m_wxwindow->window;
2167 else
2168 source = m_widget->window;
47d67540 2169
1ecc4d80
RR
2170 int org_x = 0;
2171 int org_y = 0;
2172 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2173
1ecc4d80 2174 if (!m_wxwindow)
c801d85f 2175 {
1ecc4d80
RR
2176 if (GTK_WIDGET_NO_WINDOW (m_widget))
2177 {
2178 org_x += m_widget->allocation.x;
2179 org_y += m_widget->allocation.y;
2180 }
362c6693 2181 }
47d67540 2182
1ecc4d80
RR
2183 if (x) *x -= org_x;
2184 if (y) *y -= org_y;
362c6693 2185}
c801d85f 2186
f03fc89f 2187bool wxWindow::Show( bool show )
c801d85f 2188{
f03fc89f 2189 wxCHECK_MSG( (m_widget != NULL), FALSE, _T("invalid window") );
47d67540 2190
739730ca
RR
2191 if (!wxWindowBase::Show(show))
2192 {
2193 // nothing to do
f03fc89f 2194 return FALSE;
739730ca 2195 }
8bbe427f 2196
f03fc89f
VZ
2197 if (show)
2198 gtk_widget_show( m_widget );
1ecc4d80 2199 else
f03fc89f 2200 gtk_widget_hide( m_widget );
8bbe427f 2201
f03fc89f 2202 return TRUE;
362c6693 2203}
c801d85f 2204
f03fc89f 2205bool wxWindow::Enable( bool enable )
c801d85f 2206{
f03fc89f 2207 wxCHECK_MSG( (m_widget != NULL), FALSE, _T("invalid window") );
5e0aa05a 2208
739730ca
RR
2209 if (!wxWindowBase::Enable(enable))
2210 {
2211 // nothing to do
f03fc89f 2212 return FALSE;
739730ca 2213 }
1ecc4d80 2214
f03fc89f
VZ
2215 gtk_widget_set_sensitive( m_widget, enable );
2216 if ( m_wxwindow )
2217 gtk_widget_set_sensitive( m_wxwindow, enable );
ff8bfdbb 2218
f03fc89f 2219 return TRUE;
362c6693 2220}
c801d85f 2221
f03fc89f 2222int wxWindow::GetCharHeight() const
2f2aa628 2223{
f03fc89f 2224 wxCHECK_MSG( (m_widget != NULL), 12, _T("invalid window") );
47d67540 2225
f03fc89f 2226 wxCHECK_MSG( m_font.Ok(), 12, _T("invalid font") );
2f2aa628 2227
f03fc89f
VZ
2228 GdkFont *font = m_font.GetInternalFont( 1.0 );
2229
2230 return font->ascent + font->descent;
362c6693 2231}
c801d85f 2232
f03fc89f 2233int wxWindow::GetCharWidth() const
c33c4050 2234{
05939a81 2235 wxCHECK_MSG( (m_widget != NULL), 8, _T("invalid window") );
47d67540 2236
05939a81 2237 wxCHECK_MSG( m_font.Ok(), 8, _T("invalid font") );
47d67540 2238
463c1fa1 2239 GdkFont *font = m_font.GetInternalFont( 1.0 );
ff8bfdbb 2240
463c1fa1 2241 return gdk_string_width( font, "H" );
c33c4050
RR
2242}
2243
f03fc89f
VZ
2244void wxWindow::GetTextExtent( const wxString& string,
2245 int *x,
2246 int *y,
2247 int *descent,
2248 int *externalLeading,
2249 const wxFont *theFont ) const
c33c4050 2250{
463c1fa1
RR
2251 wxFont fontToUse = m_font;
2252 if (theFont) fontToUse = *theFont;
47d67540 2253
05939a81 2254 wxCHECK_RET( fontToUse.Ok(), _T("invalid font") );
47d67540 2255
463c1fa1 2256 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
05939a81 2257 if (x) (*x) = gdk_string_width( font, string.mbc_str() );
463c1fa1
RR
2258 if (y) (*y) = font->ascent + font->descent;
2259 if (descent) (*descent) = font->descent;
2260 if (externalLeading) (*externalLeading) = 0; // ??
c33c4050
RR
2261}
2262
68dda785 2263void wxWindow::SetFocus()
c801d85f 2264{
05939a81 2265 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
ff8bfdbb 2266
463c1fa1
RR
2267 GtkWidget *connect_widget = GetConnectWidget();
2268 if (connect_widget)
c801d85f 2269 {
b292e2f5 2270 if (GTK_WIDGET_CAN_FOCUS(connect_widget) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
463c1fa1
RR
2271 {
2272 gtk_widget_grab_focus (connect_widget);
2273 }
ff8bfdbb
VZ
2274 else if (GTK_IS_CONTAINER(connect_widget))
2275 {
2276 gtk_container_focus( GTK_CONTAINER(connect_widget), GTK_DIR_TAB_FORWARD );
2277 }
2278 else
2279 {
2280 }
362c6693 2281 }
362c6693 2282}
c801d85f 2283
b292e2f5
RR
2284bool wxWindow::AcceptsFocus() const
2285{
f03fc89f 2286 return m_acceptsFocus && wxWindowBase::AcceptsFocus();
b292e2f5
RR
2287}
2288
f03fc89f 2289bool wxWindow::Reparent( wxWindow *newParent )
463c1fa1 2290{
05939a81 2291 wxCHECK_MSG( (m_widget != NULL), (wxWindow*) NULL, _T("invalid window") );
ff8bfdbb 2292
a2053b27
RR
2293 gtk_widget_unparent( m_widget );
2294
f03fc89f
VZ
2295 if ( !wxWindowBase::Reparent(newParent) )
2296 return FALSE;
8bbe427f 2297
f03fc89f 2298 return TRUE;
362c6693 2299}
c801d85f 2300
68dda785 2301void wxWindow::Raise()
362c6693 2302{
05939a81 2303 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2304
a2053b27
RR
2305 if (!m_widget->window) return;
2306
f03fc89f 2307 gdk_window_raise( m_widget->window );
362c6693
RR
2308}
2309
68dda785 2310void wxWindow::Lower()
362c6693 2311{
05939a81 2312 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2313
a2053b27
RR
2314 if (!m_widget->window) return;
2315
f03fc89f 2316 gdk_window_lower( m_widget->window );
362c6693 2317}
c801d85f 2318
f03fc89f 2319bool wxWindow::SetCursor( const wxCursor &cursor )
86b29a61 2320{
f03fc89f 2321 wxCHECK_MSG( (m_widget != NULL), FALSE, _T("invalid window") );
86b29a61 2322
739730ca 2323 if (!wxWindowBase::SetCursor(cursor))
e55ad60e 2324 {
739730ca
RR
2325 // don't leave if the GTK widget has just
2326 // been realized
2327 if (!m_delayedCursor) return FALSE;
2328 }
2329
2330 GtkWidget *connect_widget = GetConnectWidget();
2331 if (!connect_widget->window)
2332 {
2333 // indicate that a new style has been set
2334 // but it couldn't get applied as the
2335 // widget hasn't been realized yet.
2336 m_delayedCursor = TRUE;
2337
2338 // pretend we have done something
2339 return TRUE;
2340 }
a2053b27 2341
f03fc89f
VZ
2342 if ((m_widget) && (m_widget->window))
2343 gdk_window_set_cursor( m_widget->window, GetCursor().GetCursor() );
fd0eed64 2344
f03fc89f
VZ
2345 if ((m_wxwindow) && (m_wxwindow->window))
2346 gdk_window_set_cursor( m_wxwindow->window, GetCursor().GetCursor() );
fd0eed64 2347
739730ca
RR
2348 // cursor was set
2349 return TRUE;
362c6693 2350}
c801d85f 2351
4f22cf8d
RR
2352void wxWindow::WarpPointer( int WXUNUSED(x), int WXUNUSED(y) )
2353{
f03fc89f 2354 // TODO
4f22cf8d
RR
2355}
2356
debe6624 2357void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
c801d85f 2358{
05939a81 2359 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2360
a2053b27
RR
2361 if (!m_widget->window) return;
2362
139adb6a 2363 if (eraseBackground && m_wxwindow && m_wxwindow->window)
c801d85f 2364 {
139adb6a
RR
2365 if (rect)
2366 {
2367 gdk_window_clear_area( m_wxwindow->window,
2368 rect->x, rect->y,
f234c60c 2369 rect->width, rect->height );
139adb6a
RR
2370 }
2371 else
2372 {
f234c60c 2373 gdk_window_clear( m_wxwindow->window );
139adb6a
RR
2374 }
2375 }
ff8bfdbb 2376
139adb6a
RR
2377 if (!rect)
2378 {
2379 if (m_wxwindow)
2380 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
ff8bfdbb 2381 else
139adb6a 2382 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
362c6693 2383 }
c801d85f 2384 else
139adb6a
RR
2385 {
2386 GdkRectangle gdk_rect;
2387 gdk_rect.x = rect->x;
2388 gdk_rect.y = rect->y;
2389 gdk_rect.width = rect->width;
2390 gdk_rect.height = rect->height;
2391
2392 if (m_wxwindow)
2393 gtk_widget_draw( m_wxwindow, &gdk_rect );
2394 else
2395 gtk_widget_draw( m_widget, &gdk_rect );
2396 }
362c6693 2397}
c801d85f 2398
68dda785 2399void wxWindow::Clear()
c801d85f 2400{
05939a81 2401 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
47d67540 2402
a2053b27
RR
2403 if (!m_widget->window) return;
2404
f234c60c
RR
2405 if (m_wxwindow && m_wxwindow->window)
2406 {
2407 gdk_window_clear( m_wxwindow->window );
2408 }
362c6693 2409}
c801d85f 2410
ff8bfdbb 2411#if wxUSE_TOOLTIPS
f03fc89f 2412void wxWindow::DoSetToolTip( wxToolTip *tip )
b1170810 2413{
f03fc89f 2414 wxWindowBase::DoSetToolTip(tip);
ff8bfdbb 2415
f03fc89f
VZ
2416 if (m_tooltip)
2417 m_tooltip->Apply( this );
b1170810
RR
2418}
2419
05939a81 2420void wxWindow::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
b1170810 2421{
05939a81 2422 gtk_tooltips_set_tip( tips, GetConnectWidget(), wxConv_current->cWX2MB(tip), (gchar*) NULL );
301cd871 2423}
ff8bfdbb 2424#endif // wxUSE_TOOLTIPS
b1170810 2425
f03fc89f 2426bool wxWindow::SetBackgroundColour( const wxColour &colour )
c801d85f 2427{
f03fc89f 2428 wxCHECK_MSG( m_widget != NULL, FALSE, _T("invalid window") );
8bbe427f 2429
739730ca
RR
2430 if (!wxWindowBase::SetBackgroundColour(colour))
2431 {
2432 // don't leave if the GTK widget has just
2433 // been realized
2434 if (!m_delayedBackgroundColour) return FALSE;
2435 }
2436
a2053b27 2437 GtkWidget *connect_widget = GetConnectWidget();
739730ca
RR
2438 if (!connect_widget->window)
2439 {
2440 // indicate that a new style has been set
2441 // but it couldn't get applied as the
2442 // widget hasn't been realized yet.
2443 m_delayedBackgroundColour = TRUE;
2444
2445 // pretend we have done something
2446 return TRUE;
2447 }
ca298c88 2448
f234c60c 2449 if (m_wxwindow && m_wxwindow->window)
3bc755fc 2450 {
a2053b27
RR
2451 /* wxMSW doesn't clear the window here. I don't do that either to
2452 provide compatibility. call Clear() to do the job. */
ca298c88 2453
f234c60c
RR
2454 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_wxwindow->window ) );
2455 gdk_window_set_background( m_wxwindow->window, m_backgroundColour.GetColor() );
3bc755fc 2456 }
8bbe427f 2457
ae0bdb01 2458 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
ca298c88 2459
121a3581 2460 if (sysbg == m_backgroundColour)
ae0bdb01
RR
2461 {
2462 m_backgroundColour = wxNullColour;
2463 ApplyWidgetStyle();
ff8bfdbb
VZ
2464 m_backgroundColour = sysbg;
2465 }
ae0bdb01
RR
2466 else
2467 {
2468 ApplyWidgetStyle();
2469 }
c801d85f 2470
f03fc89f 2471 return TRUE;
6de97a3b
RR
2472}
2473
f03fc89f 2474bool wxWindow::SetForegroundColour( const wxColour &colour )
6de97a3b 2475{
f03fc89f 2476 wxCHECK_MSG( m_widget != NULL, FALSE, _T("invalid window") );
8bbe427f 2477
739730ca
RR
2478 if (!wxWindowBase::SetForegroundColour(colour))
2479 {
2480 // don't leave if the GTK widget has just
2481 // been realized
2482 if (!m_delayedForegroundColour) return FALSE;
2483 }
2484
a2053b27 2485 GtkWidget *connect_widget = GetConnectWidget();
739730ca
RR
2486 if (!connect_widget->window)
2487 {
2488 // indicate that a new style has been set
2489 // but it couldn't get applied as the
2490 // widget hasn't been realized yet.
2491 m_delayedForegroundColour = TRUE;
2492
2493 // pretend we have done something
2494 return TRUE;
2495 }
2b07d713 2496
ae0bdb01 2497 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
121a3581 2498 if (sysbg == m_foregroundColour)
ae0bdb01
RR
2499 {
2500 m_backgroundColour = wxNullColour;
2501 ApplyWidgetStyle();
ff8bfdbb
VZ
2502 m_backgroundColour = sysbg;
2503 }
ae0bdb01
RR
2504 else
2505 {
2506 ApplyWidgetStyle();
2507 }
f03fc89f
VZ
2508
2509 return TRUE;
58614078
RR
2510}
2511
2512GtkStyle *wxWindow::GetWidgetStyle()
2513{
1ecc4d80 2514 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
8bbe427f 2515
f03fc89f 2516 m_widgetStyle = gtk_style_copy( gtk_widget_get_style( m_widget ) );
8bbe427f 2517
1ecc4d80 2518 return m_widgetStyle;
58614078
RR
2519}
2520
2521void wxWindow::SetWidgetStyle()
2522{
1ecc4d80
RR
2523 GtkStyle *style = GetWidgetStyle();
2524
2525 gdk_font_unref( style->font );
2526 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2527
2528 if (m_foregroundColour.Ok())
2529 {
2530 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2531 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2532 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2533 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2534 }
2535
2536 if (m_backgroundColour.Ok())
2537 {
2538 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2539 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2540 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2541 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2542 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2543 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2544 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2545 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2546 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2547 }
a81258be
RR
2548}
2549
58614078 2550void wxWindow::ApplyWidgetStyle()
a81258be 2551{
6de97a3b
RR
2552}
2553
30dea054
RR
2554static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2555{
1ecc4d80 2556 menu->SetInvokingWindow( win );
c626a8b7 2557 wxNode *node = menu->GetItems().First();
1ecc4d80
RR
2558 while (node)
2559 {
2560 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2561 if (menuitem->IsSubMenu())
2562 {
ff8bfdbb
VZ
2563 SetInvokingWindow( menuitem->GetSubMenu(), win );
2564 }
1ecc4d80
RR
2565 node = node->Next();
2566 }
362c6693 2567}
30dea054 2568
0c77152e
RR
2569static gint gs_pop_x = 0;
2570static gint gs_pop_y = 0;
2571
a234a61a
VZ
2572static void pop_pos_callback( GtkMenu * WXUNUSED(menu),
2573 gint *x, gint *y,
2574 wxWindow *win )
0c77152e
RR
2575{
2576 win->ClientToScreen( &gs_pop_x, &gs_pop_y );
2577 *x = gs_pop_x;
2578 *y = gs_pop_y;
2579}
2580
2581bool wxWindow::PopupMenu( wxMenu *menu, int x, int y )
30dea054 2582{
05939a81 2583 wxCHECK_MSG( m_widget != NULL, FALSE, _T("invalid window") );
47d67540 2584
05939a81 2585 wxCHECK_MSG( menu != NULL, FALSE, _T("invalid popup-menu") );
8bbe427f 2586
1ecc4d80 2587 SetInvokingWindow( menu, this );
ff8bfdbb 2588
631f1bfe
JS
2589 menu->UpdateUI();
2590
0c77152e
RR
2591 gs_pop_x = x;
2592 gs_pop_y = y;
ff8bfdbb 2593
1ecc4d80 2594 gtk_menu_popup(
47d67540 2595 GTK_MENU(menu->m_menu),
0c77152e
RR
2596 (GtkWidget *) NULL, // parent menu shell
2597 (GtkWidget *) NULL, // parent menu item
2598 (GtkMenuPositionFunc) pop_pos_callback,
2599 (gpointer) this, // client data
2600 0, // button used to activate it
2601 0 //gs_timeLastClick // the time of activation
47d67540 2602 );
1ecc4d80 2603 return TRUE;
30dea054
RR
2604}
2605
06cfab17 2606#if wxUSE_DRAG_AND_DROP
ac57418f 2607
c801d85f
KB
2608void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2609{
05939a81 2610 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
47d67540 2611
1ecc4d80 2612 GtkWidget *dnd_widget = GetConnectWidget();
47d67540 2613
1ecc4d80 2614 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
47d67540 2615
1ecc4d80
RR
2616 if (m_dropTarget) delete m_dropTarget;
2617 m_dropTarget = dropTarget;
47d67540 2618
1ecc4d80 2619 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
362c6693 2620}
c801d85f 2621
f03fc89f 2622#endif // wxUSE_DRAG_AND_DROP
ac57418f 2623
68dda785 2624GtkWidget* wxWindow::GetConnectWidget()
e3e65dac 2625{
1ecc4d80
RR
2626 GtkWidget *connect_widget = m_widget;
2627 if (m_wxwindow) connect_widget = m_wxwindow;
47d67540 2628
1ecc4d80 2629 return connect_widget;
e3e65dac 2630}
47d67540 2631
903f689b
RR
2632bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2633{
1ecc4d80
RR
2634 if (m_wxwindow) return (window == m_wxwindow->window);
2635 return (window == m_widget->window);
903f689b
RR
2636}
2637
f03fc89f 2638bool wxWindow::SetFont( const wxFont &font )
c801d85f 2639{
a2053b27 2640 wxCHECK_MSG( m_widget != NULL, FALSE, _T( "invalid window") );
c801d85f 2641
739730ca
RR
2642 if (!wxWindowBase::SetFont(font))
2643 {
2644 // don't leave if the GTK widget has just
2645 // been realized
2646 if (!m_delayedFont) return FALSE;
2647 }
121a3581 2648
a2053b27 2649 GtkWidget *connect_widget = GetConnectWidget();
739730ca
RR
2650 if (!connect_widget->window)
2651 {
2652 // indicate that a new style has been set
2653 // but it couldn't get applied as the
2654 // widget hasn't been realized yet.
2655 m_delayedFont = TRUE;
2656
2657 // pretend we have done something
2658 return TRUE;
2659 }
9c288e4d 2660
ae0bdb01 2661 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
f03fc89f 2662 if ( sysbg == m_backgroundColour )
ae0bdb01
RR
2663 {
2664 m_backgroundColour = wxNullColour;
2665 ApplyWidgetStyle();
ff8bfdbb
VZ
2666 m_backgroundColour = sysbg;
2667 }
ae0bdb01
RR
2668 else
2669 {
2670 ApplyWidgetStyle();
2671 }
c801d85f 2672
f03fc89f 2673 return TRUE;
362c6693 2674}
c801d85f 2675
68dda785 2676void wxWindow::CaptureMouse()
c801d85f 2677{
05939a81 2678 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
47d67540 2679
05939a81 2680 wxCHECK_RET( g_capturing == FALSE, _T("CaptureMouse called twice") );
47d67540 2681
1ecc4d80 2682 GtkWidget *connect_widget = GetConnectWidget();
a2053b27
RR
2683 if (!connect_widget->window) return;
2684
1ecc4d80
RR
2685 gtk_grab_add( connect_widget );
2686 gdk_pointer_grab( connect_widget->window, FALSE,
2687 (GdkEventMask)
2688 (GDK_BUTTON_PRESS_MASK |
2689 GDK_BUTTON_RELEASE_MASK |
2690 GDK_POINTER_MOTION_MASK),
ff8bfdbb
VZ
2691 (GdkWindow *) NULL,
2692 (GdkCursor *) NULL,
2693 GDK_CURRENT_TIME );
1ecc4d80 2694 g_capturing = TRUE;
362c6693 2695}
c801d85f 2696
68dda785 2697void wxWindow::ReleaseMouse()
c801d85f 2698{
05939a81 2699 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
47d67540 2700
05939a81 2701 wxCHECK_RET( g_capturing == TRUE, _T("ReleaseMouse called twice") );
47d67540 2702
1ecc4d80 2703 GtkWidget *connect_widget = GetConnectWidget();
a2053b27
RR
2704 if (!connect_widget->window) return;
2705
1ecc4d80
RR
2706 gtk_grab_remove( connect_widget );
2707 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
2708 g_capturing = FALSE;
362c6693 2709}
c801d85f 2710
f03fc89f 2711bool wxWindow::IsRetained() const
c801d85f 2712{
1ecc4d80 2713 return FALSE;
362c6693 2714}
c801d85f 2715
debe6624 2716void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
cb43b372 2717 int range, bool refresh )
c801d85f 2718{
05939a81 2719 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
8bbe427f 2720
05939a81 2721 wxCHECK_RET( m_wxwindow != NULL, _T("window needs client area for scrolling") );
c801d85f 2722
1ecc4d80 2723 m_hasScrolling = TRUE;
47d67540 2724
1ecc4d80 2725 if (orient == wxHORIZONTAL)
cb43b372 2726 {
1ecc4d80
RR
2727 float fpos = (float)pos;
2728 float frange = (float)range;
2729 float fthumb = (float)thumbVisible;
2730 if (fpos > frange-fthumb) fpos = frange-fthumb;
2731 if (fpos < 0.0) fpos = 0.0;
2732
2733 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
2734 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
2735 {
2736 SetScrollPos( orient, pos, refresh );
2737 return;
2738 }
47d67540 2739
1ecc4d80 2740 m_oldHorizontalPos = fpos;
47d67540 2741
1ecc4d80
RR
2742 m_hAdjust->lower = 0.0;
2743 m_hAdjust->upper = frange;
2744 m_hAdjust->value = fpos;
2745 m_hAdjust->step_increment = 1.0;
2746 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
2747 m_hAdjust->page_size = fthumb;
cb43b372 2748 }
1ecc4d80
RR
2749 else
2750 {
2751 float fpos = (float)pos;
2752 float frange = (float)range;
2753 float fthumb = (float)thumbVisible;
2754 if (fpos > frange-fthumb) fpos = frange-fthumb;
2755 if (fpos < 0.0) fpos = 0.0;
2756
2757 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
2758 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
2759 {
2760 SetScrollPos( orient, pos, refresh );
2761 return;
2762 }
47d67540 2763
1ecc4d80 2764 m_oldVerticalPos = fpos;
47d67540 2765
1ecc4d80
RR
2766 m_vAdjust->lower = 0.0;
2767 m_vAdjust->upper = frange;
2768 m_vAdjust->value = fpos;
2769 m_vAdjust->step_increment = 1.0;
2770 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
2771 m_vAdjust->page_size = fthumb;
2772 }
47d67540 2773
eb082a08
RR
2774 if (orient == wxHORIZONTAL)
2775 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
2776 else
2777 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
362c6693 2778}
c801d85f 2779
debe6624 2780void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
c801d85f 2781{
05939a81 2782 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
1ecc4d80 2783
05939a81 2784 wxCHECK_RET( m_wxwindow != NULL, _T("window needs client area for scrolling") );
1ecc4d80
RR
2785
2786 if (orient == wxHORIZONTAL)
2787 {
2788 float fpos = (float)pos;
2789 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
2790 if (fpos < 0.0) fpos = 0.0;
2791 m_oldHorizontalPos = fpos;
2792
2793 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
2794 m_hAdjust->value = fpos;
2795 }
2796 else
2797 {
2798 float fpos = (float)pos;
2799 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
2800 if (fpos < 0.0) fpos = 0.0;
2801 m_oldVerticalPos = fpos;
ff8bfdbb 2802
1ecc4d80
RR
2803 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
2804 m_vAdjust->value = fpos;
2805 }
47d67540 2806
eb082a08 2807 if (!m_isScrolling) /* prevent recursion */
47d67540 2808 {
1ecc4d80
RR
2809 if (m_wxwindow->window)
2810 {
2811 if (orient == wxHORIZONTAL)
2812 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2813 else
2814 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
2815 }
cb43b372 2816 }
362c6693 2817}
c801d85f 2818
debe6624 2819int wxWindow::GetScrollThumb( int orient ) const
c801d85f 2820{
05939a81 2821 wxCHECK_MSG( m_widget != NULL, 0, _T("invalid window") );
47d67540 2822
05939a81 2823 wxCHECK_MSG( m_wxwindow != NULL, 0, _T("window needs client area for scrolling") );
47d67540 2824
1ecc4d80
RR
2825 if (orient == wxHORIZONTAL)
2826 return (int)(m_hAdjust->page_size+0.5);
2827 else
2828 return (int)(m_vAdjust->page_size+0.5);
362c6693 2829}
c801d85f 2830
debe6624 2831int wxWindow::GetScrollPos( int orient ) const
c801d85f 2832{
05939a81 2833 wxCHECK_MSG( m_widget != NULL, 0, _T("invalid window") );
47d67540 2834
05939a81 2835 wxCHECK_MSG( m_wxwindow != NULL, 0, _T("window needs client area for scrolling") );
c801d85f 2836
1ecc4d80
RR
2837 if (orient == wxHORIZONTAL)
2838 return (int)(m_hAdjust->value+0.5);
2839 else
2840 return (int)(m_vAdjust->value+0.5);
362c6693 2841}
c801d85f 2842
debe6624 2843int wxWindow::GetScrollRange( int orient ) const
c801d85f 2844{
05939a81 2845 wxCHECK_MSG( m_widget != NULL, 0, _T("invalid window") );
47d67540 2846
05939a81 2847 wxCHECK_MSG( m_wxwindow != NULL, 0, _T("window needs client area for scrolling") );
c801d85f 2848
1ecc4d80
RR
2849 if (orient == wxHORIZONTAL)
2850 return (int)(m_hAdjust->upper+0.5);
2851 else
2852 return (int)(m_vAdjust->upper+0.5);
362c6693 2853}
c801d85f 2854
debe6624 2855void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
c801d85f 2856{
05939a81 2857 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
47d67540 2858
05939a81 2859 wxCHECK_RET( m_wxwindow != NULL, _T("window needs client area for scrolling") );
c801d85f 2860
a2053b27 2861 if (!m_scrollGC)
96d5ab4d 2862 {
a2053b27
RR
2863 m_scrollGC = gdk_gc_new( m_wxwindow->window );
2864 gdk_gc_set_exposures( m_scrollGC, TRUE );
96d5ab4d
RR
2865 }
2866
c801d85f
KB
2867 int cw = 0;
2868 int ch = 0;
2869 GetClientSize( &cw, &ch );
c801d85f
KB
2870 int w = cw - abs(dx);
2871 int h = ch - abs(dy);
a2053b27 2872
c801d85f
KB
2873 if ((h < 0) || (w < 0))
2874 {
1ecc4d80 2875 Refresh();
362c6693 2876 }
a2053b27 2877 else
c801d85f 2878 {
a2053b27
RR
2879 int s_x = 0;
2880 int s_y = 0;
2881 if (dx < 0) s_x = -dx;
2882 if (dy < 0) s_y = -dy;
2883 int d_x = 0;
2884 int d_y = 0;
2885 if (dx > 0) d_x = dx;
2886 if (dy > 0) d_y = dy;
c801d85f 2887
a2053b27
RR
2888 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
2889 m_wxwindow->window, s_x, s_y, w, h );
c801d85f 2890
a2053b27
RR
2891 wxRect rect;
2892 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
2893 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
2894 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
2895 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
c801d85f 2896
a2053b27
RR
2897 Refresh( TRUE, &rect );
2898 }
2899
2900 wxNode *node = m_children.First();
2901 while (node)
2902 {
2903 wxWindow *child = (wxWindow*) node->Data();
2904 child->Move( child->m_x + dx, child->m_y + dy );
2905 node = node->Next();
2906 }
c801d85f
KB
2907}
2908
f03fc89f 2909void wxWindow::SetScrolling(bool scroll)
c801d85f 2910{
f03fc89f 2911 m_isScrolling = g_blockEventsOnScroll = scroll;
c801d85f 2912}