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