]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/window.cpp
...fixing up a previous Unicode fix.
[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;
72195a0f 134static wxWindow *g_captureWindow = (wxWindow*) NULL;
f03fc89f
VZ
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
88ac883a 653#if wxUSE_ACCEL
f5e27805 654 if (!ret)
47d67540 655 {
f5e27805
RR
656 wxWindow *ancestor = win;
657 while (ancestor)
658 {
659 int command = ancestor->GetAcceleratorTable()->GetCommand( event );
660 if (command != -1)
661 {
662 wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
663 ret = ancestor->GetEventHandler()->ProcessEvent( command_event );
664 break;
665 }
666 ancestor = ancestor->GetParent();
667 }
bcf1fa6b 668 }
88ac883a 669#endif // wxUSE_ACCEL
ff8bfdbb 670
053f9cc1 671 /* win is a control: tab can be propagated up */
ca298c88 672 if ( (!ret) &&
5664fc32 673 ((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
f03fc89f 674 (win->HasFlag(wxTE_PROCESS_TAB) == 0))
b292e2f5
RR
675 {
676 wxNavigationKeyEvent new_event;
f03fc89f 677 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
5664fc32 678 new_event.SetDirection( (gdk_event->keyval == GDK_Tab) );
f03fc89f 679 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
b98d804b 680 new_event.SetWindowChange( (gdk_event->state & GDK_CONTROL_MASK) );
b292e2f5 681 new_event.SetCurrentFocus( win );
ff8bfdbb 682 ret = win->GetEventHandler()->ProcessEvent( new_event );
b292e2f5 683 }
ff8bfdbb 684
801aa178 685 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
ca298c88 686 if ( (!ret) &&
b98d804b
RR
687 (gdk_event->keyval == GDK_Escape) )
688 {
689 wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
690 new_event.SetEventObject( win );
691 ret = win->GetEventHandler()->ProcessEvent( new_event );
692 }
801aa178 693
6bc8a1c8 694#if (GTK_MINOR_VERSION > 0)
801aa178
RR
695 /* pressing F10 will activate the menu bar of the top frame */
696 if ( (!ret) &&
697 (gdk_event->keyval == GDK_F10) )
698 {
699 wxWindow *ancestor = win;
700 while (ancestor)
701 {
702 if (wxIsKindOf(ancestor,wxFrame))
703 {
704 wxFrame *frame = (wxFrame*) ancestor;
705 wxMenuBar *menubar = frame->GetMenuBar();
706 if (menubar)
707 {
708 wxNode *node = menubar->GetMenus().First();
709 if (node)
710 {
93b7364e 711 // doesn't work correctly
88ac883a 712 // wxMenu *firstMenu = (wxMenu*) node->Data();
93b7364e
RR
713 // gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
714 // ret = TRUE;
801aa178
RR
715 break;
716 }
717 }
718 }
719 ancestor = ancestor->GetParent();
720 }
721 }
6bc8a1c8 722#endif
ca298c88 723
b292e2f5 724/*
b98d804b
RR
725 Damn, I forgot why this didn't work, but it didn't work.
726
b292e2f5 727 // win is a panel: up can be propagated to the panel
a2053b27 728 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
b292e2f5
RR
729 (gdk_event->keyval == GDK_Up))
730 {
731 win->m_parent->SetFocus();
ff8bfdbb 732 ret = TRUE;
b292e2f5 733 }
ff8bfdbb 734
b292e2f5 735 // win is a panel: left/right can be propagated to the panel
a2053b27 736 if ((!ret) && (win->m_wxwindow) &&
ff8bfdbb 737 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
b292e2f5
RR
738 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
739 {
740 wxNavigationKeyEvent new_event;
741 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
742 new_event.SetCurrentFocus( win );
ff8bfdbb 743 ret = win->GetEventHandler()->ProcessEvent( new_event );
b292e2f5
RR
744 }
745*/
ff8bfdbb 746
f5e27805
RR
747 if (ret)
748 {
b292e2f5 749 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
f03fc89f 750 return TRUE;
f5e27805 751 }
47d67540 752
034be888 753 return FALSE;
362c6693 754}
c801d85f 755
b666df2c
RR
756//-----------------------------------------------------------------------------
757// "key_release_event" from any window
758//-----------------------------------------------------------------------------
759
760static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
761{
a2053b27
RR
762 if (g_isIdle)
763 wxapp_install_idle_handler();
764
765 if (!win->m_hasVMT) return FALSE;
b666df2c
RR
766 if (g_blockEventsOnDrag) return FALSE;
767
768/*
d1367c3d
RR
769 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
770 if (gdk_event->state & GDK_SHIFT_MASK)
771 printf( "ShiftDown.\n" );
772 else
773 printf( "ShiftUp.\n" );
774 if (gdk_event->state & GDK_CONTROL_MASK)
775 printf( "ControlDown.\n" );
776 else
777 printf( "ControlUp.\n" );
778 printf( "\n" );
b666df2c
RR
779*/
780
74505862 781 long key_code = map_to_unmodified_wx_keysym( gdk_event->keyval );
f0492f7d
RR
782
783 /* sending unknown key events doesn't really make sense */
784 if (key_code == 0) return FALSE;
b666df2c 785
b0e813a0
RR
786 int x = 0;
787 int y = 0;
788 GdkModifierType state;
789 if (gdk_event->window) gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
b666df2c
RR
790
791 wxKeyEvent event( wxEVT_KEY_UP );
d1367c3d 792 event.SetTimestamp( gdk_event->time );
b666df2c
RR
793 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
794 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
795 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
796 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
797 event.m_keyCode = key_code;
b0e813a0
RR
798 event.m_scanCode = gdk_event->keyval;
799 event.m_x = x;
800 event.m_y = y;
b666df2c
RR
801 event.SetEventObject( win );
802
034be888 803 if (win->GetEventHandler()->ProcessEvent( event ))
b666df2c 804 {
b98d804b 805 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_release_event" );
f03fc89f 806 return TRUE;
b666df2c
RR
807 }
808
034be888 809 return FALSE;
b666df2c
RR
810}
811
c801d85f 812//-----------------------------------------------------------------------------
2f2aa628
RR
813// "button_press_event"
814//-----------------------------------------------------------------------------
c801d85f 815
2f2aa628 816static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
903f689b 817{
a2053b27
RR
818 if (g_isIdle)
819 wxapp_install_idle_handler();
820
821/*
822 wxPrintf( _T("1) OnButtonPress from ") );
823 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
824 wxPrintf( win->GetClassInfo()->GetClassName() );
825 wxPrintf( _T(".\n") );
826*/
a2053b27 827 if (!win->m_hasVMT) return FALSE;
f5e27805 828 if (g_blockEventsOnDrag) return TRUE;
76ed8f8d 829 if (g_blockEventsOnScroll) return TRUE;
c801d85f 830
034be888
RR
831 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
832
a2053b27 833 if (win->m_wxwindow)
c801d85f 834 {
a2053b27 835 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow) && !GTK_WIDGET_HAS_FOCUS (win->m_wxwindow) )
f5e27805 836 {
a2053b27 837 gtk_widget_grab_focus (win->m_wxwindow);
47d67540 838
c801d85f 839/*
a2053b27 840 wxPrintf( _T("GrabFocus from ") );
f5e27805 841 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
a2053b27
RR
842 wxPrintf( win->GetClassInfo()->GetClassName() );
843 wxPrintf( _T(".\n") );
c801d85f 844*/
47d67540 845
f5e27805 846 }
362c6693 847 }
47d67540 848
8429bec1 849/*
a2053b27 850 wxPrintf( _T("2) OnButtonPress from ") );
f5e27805 851 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
a2053b27
RR
852 wxPrintf( win->GetClassInfo()->GetClassName() );
853 wxPrintf( _T(".\n") );
8429bec1 854*/
30dea054 855
f5e27805 856 wxEventType event_type = wxEVT_LEFT_DOWN;
47d67540 857
f5e27805 858 if (gdk_event->button == 1)
c801d85f 859 {
f5e27805
RR
860 switch (gdk_event->type)
861 {
862 case GDK_BUTTON_PRESS: event_type = wxEVT_LEFT_DOWN; break;
863 case GDK_2BUTTON_PRESS: event_type = wxEVT_LEFT_DCLICK; break;
864 default: break;
865 }
362c6693 866 }
f5e27805 867 else if (gdk_event->button == 2)
c801d85f 868 {
f5e27805
RR
869 switch (gdk_event->type)
870 {
871 case GDK_BUTTON_PRESS: event_type = wxEVT_MIDDLE_DOWN; break;
872 case GDK_2BUTTON_PRESS: event_type = wxEVT_MIDDLE_DCLICK; break;
873 default: break;
874 }
362c6693 875 }
f5e27805 876 else if (gdk_event->button == 3)
c801d85f 877 {
f5e27805
RR
878 switch (gdk_event->type)
879 {
880 case GDK_BUTTON_PRESS: event_type = wxEVT_RIGHT_DOWN; break;
881 case GDK_2BUTTON_PRESS: event_type = wxEVT_RIGHT_DCLICK; break;
882 default: break;
883 }
362c6693 884 }
47d67540 885
f5e27805 886 wxMouseEvent event( event_type );
d1367c3d 887 event.SetTimestamp( gdk_event->time );
f5e27805
RR
888 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
889 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
890 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
891 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
892 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
893 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
894 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
47d67540 895
f5e27805
RR
896 event.m_x = (long)gdk_event->x;
897 event.m_y = (long)gdk_event->y;
47d67540 898
f5e27805
RR
899 // Some control don't have their own X window and thus cannot get
900 // any events.
47d67540 901
72195a0f 902 if (!g_captureWindow)
2f2aa628 903 {
db1b4961 904 wxNode *node = win->GetChildren().First();
f5e27805
RR
905 while (node)
906 {
907 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb 908
a2053b27 909 if (child->m_isStaticBox)
ff8bfdbb
VZ
910 {
911 // wxStaticBox is transparent in the box itself
a2053b27
RR
912 int x = event.m_x;
913 int y = event.m_y;
914 int xx1 = child->m_x;
915 int yy1 = child->m_y;
916 int xx2 = child->m_x + child->m_width;
917 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
918
919 // left
920 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
921 // right
922 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
923 // top
924 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
925 // bottom
926 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
927 {
1ecc4d80 928 win = child;
a2053b27
RR
929 event.m_x -= child->m_x;
930 event.m_y -= child->m_y;
1ecc4d80 931 break;
ff8bfdbb
VZ
932 }
933
934 }
935 else
936 {
a2053b27
RR
937 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
938 (child->m_x <= event.m_x) &&
939 (child->m_y <= event.m_y) &&
940 (child->m_x+child->m_width >= event.m_x) &&
941 (child->m_y+child->m_height >= event.m_y))
1ecc4d80
RR
942 {
943 win = child;
a2053b27
RR
944 event.m_x -= child->m_x;
945 event.m_y -= child->m_y;
1ecc4d80 946 break;
ff8bfdbb 947 }
f5e27805
RR
948 }
949 node = node->Next();
950 }
2f2aa628 951 }
ff8bfdbb 952
f5e27805 953 event.SetEventObject( win );
47d67540 954
f5e27805 955 gs_timeLastClick = gdk_event->time;
47d67540 956
f5e27805 957 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 958 {
f5e27805 959 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
f03fc89f 960 return TRUE;
034be888 961 }
47d67540 962
034be888 963 return FALSE;
362c6693 964}
c801d85f
KB
965
966//-----------------------------------------------------------------------------
97b3455a 967// "button_release_event"
2f2aa628 968//-----------------------------------------------------------------------------
c801d85f 969
2f2aa628 970static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
47d67540 971{
a2053b27
RR
972 if (g_isIdle)
973 wxapp_install_idle_handler();
974
975 if (!win->m_hasVMT) return FALSE;
034be888
RR
976 if (g_blockEventsOnDrag) return FALSE;
977 if (g_blockEventsOnScroll) return FALSE;
c801d85f 978
034be888 979 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
47d67540 980
c801d85f 981/*
f5e27805
RR
982 printf( "OnButtonRelease from " );
983 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
984 printf( win->GetClassInfo()->GetClassName() );
985 printf( ".\n" );
c801d85f 986*/
47d67540 987
f5e27805 988 wxEventType event_type = wxEVT_NULL;
47d67540 989
f5e27805
RR
990 switch (gdk_event->button)
991 {
992 case 1: event_type = wxEVT_LEFT_UP; break;
993 case 2: event_type = wxEVT_MIDDLE_UP; break;
994 case 3: event_type = wxEVT_RIGHT_UP; break;
995 }
47d67540 996
f5e27805 997 wxMouseEvent event( event_type );
d1367c3d 998 event.SetTimestamp( gdk_event->time );
f5e27805
RR
999 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1000 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1001 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1002 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1003 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1004 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1005 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
1006 event.m_x = (long)gdk_event->x;
1007 event.m_y = (long)gdk_event->y;
1008
1009 // Some control don't have their own X window and thus cannot get
1010 // any events.
1011
72195a0f 1012 if (!g_captureWindow)
2f2aa628 1013 {
db1b4961 1014 wxNode *node = win->GetChildren().First();
f5e27805
RR
1015 while (node)
1016 {
1017 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb 1018
a2053b27 1019 if (child->m_isStaticBox)
ff8bfdbb
VZ
1020 {
1021 // wxStaticBox is transparent in the box itself
1022 int x = event.m_x;
1023 int y = event.m_y;
a2053b27
RR
1024 int xx1 = child->m_x;
1025 int yy1 = child->m_y;
1026 int xx2 = child->m_x + child->m_width;
1027 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1028
1029 // left
1030 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1031 // right
1032 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1033 // top
1034 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1035 // bottom
1036 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1037 {
1ecc4d80 1038 win = child;
a2053b27
RR
1039 event.m_x -= child->m_x;
1040 event.m_y -= child->m_y;
1ecc4d80 1041 break;
ff8bfdbb
VZ
1042 }
1043
1044 }
1045 else
1046 {
a2053b27
RR
1047 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
1048 (child->m_x <= event.m_x) &&
1049 (child->m_y <= event.m_y) &&
1050 (child->m_x+child->m_width >= event.m_x) &&
1051 (child->m_y+child->m_height >= event.m_y))
1ecc4d80
RR
1052 {
1053 win = child;
a2053b27
RR
1054 event.m_x -= child->m_x;
1055 event.m_y -= child->m_y;
1ecc4d80 1056 break;
ff8bfdbb 1057 }
f5e27805
RR
1058 }
1059 node = node->Next();
1060 }
2f2aa628 1061 }
47d67540 1062
f5e27805 1063 event.SetEventObject( win );
47d67540 1064
f5e27805 1065 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1066 {
f5e27805 1067 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" );
f03fc89f 1068 return TRUE;
034be888 1069 }
47d67540 1070
034be888 1071 return FALSE;
362c6693 1072}
c801d85f
KB
1073
1074//-----------------------------------------------------------------------------
2f2aa628
RR
1075// "motion_notify_event"
1076//-----------------------------------------------------------------------------
c801d85f 1077
2f2aa628 1078static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
47d67540 1079{
a2053b27
RR
1080 if (g_isIdle)
1081 wxapp_install_idle_handler();
1082
1083 if (!win->m_hasVMT) return FALSE;
034be888
RR
1084 if (g_blockEventsOnDrag) return FALSE;
1085 if (g_blockEventsOnScroll) return FALSE;
1086
1087 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1088
ff8bfdbb 1089 if (gdk_event->is_hint)
aae24d21
RR
1090 {
1091 int x = 0;
1092 int y = 0;
1093 GdkModifierType state;
1094 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
1095 gdk_event->x = x;
1096 gdk_event->y = y;
1097 gdk_event->state = state;
1098 }
ff8bfdbb 1099
c801d85f 1100/*
e380f72b
RR
1101 printf( "OnMotion from " );
1102 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1103 printf( win->GetClassInfo()->GetClassName() );
1104 printf( ".\n" );
aae24d21 1105*/
47d67540 1106
e380f72b 1107 wxMouseEvent event( wxEVT_MOTION );
d1367c3d 1108 event.SetTimestamp( gdk_event->time );
e380f72b
RR
1109 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1110 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1111 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1112 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1113 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1114 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1115 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
1116
1117 event.m_x = (long)gdk_event->x;
1118 event.m_y = (long)gdk_event->y;
1119
1120 // Some control don't have their own X window and thus cannot get
1121 // any events.
1122
72195a0f 1123 if (!g_captureWindow)
2f2aa628 1124 {
db1b4961 1125 wxNode *node = win->GetChildren().First();
e380f72b
RR
1126 while (node)
1127 {
1128 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb 1129
a2053b27 1130 if (child->m_isStaticBox)
ff8bfdbb
VZ
1131 {
1132 // wxStaticBox is transparent in the box itself
1133 int x = event.m_x;
1134 int y = event.m_y;
a2053b27
RR
1135 int xx1 = child->m_x;
1136 int yy1 = child->m_y;
1137 int xx2 = child->m_x + child->m_width;
1138 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1139
1140 // left
1141 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1142 // right
1143 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1144 // top
1145 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1146 // bottom
1147 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1148 {
1ecc4d80 1149 win = child;
a2053b27
RR
1150 event.m_x -= child->m_x;
1151 event.m_y -= child->m_y;
1ecc4d80 1152 break;
ff8bfdbb
VZ
1153 }
1154
1155 }
1156 else
1157 {
a2053b27
RR
1158 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
1159 (child->m_x <= event.m_x) &&
1160 (child->m_y <= event.m_y) &&
1161 (child->m_x+child->m_width >= event.m_x) &&
1162 (child->m_y+child->m_height >= event.m_y))
1ecc4d80
RR
1163 {
1164 win = child;
a2053b27
RR
1165 event.m_x -= child->m_x;
1166 event.m_y -= child->m_y;
1ecc4d80 1167 break;
ff8bfdbb 1168 }
e380f72b
RR
1169 }
1170 node = node->Next();
1171 }
2f2aa628 1172 }
47d67540 1173
e380f72b 1174 event.SetEventObject( win );
47d67540 1175
e380f72b 1176 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1177 {
e380f72b 1178 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
f03fc89f 1179 return TRUE;
034be888 1180 }
47d67540 1181
034be888 1182 return FALSE;
362c6693 1183}
c801d85f
KB
1184
1185//-----------------------------------------------------------------------------
2f2aa628
RR
1186// "focus_in_event"
1187//-----------------------------------------------------------------------------
c801d85f 1188
2f2aa628 1189static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
c801d85f 1190{
a2053b27
RR
1191 if (g_isIdle)
1192 wxapp_install_idle_handler();
1193
1194 if (!win->m_hasVMT) return FALSE;
034be888 1195 if (g_blockEventsOnDrag) return FALSE;
ff8bfdbb 1196
b292e2f5 1197 g_focusWindow = win;
ff8bfdbb 1198
a2053b27 1199 if (win->m_wxwindow)
c801d85f 1200 {
a2053b27 1201 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
e380f72b 1202 {
a2053b27 1203 GTK_WIDGET_SET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
47d67540 1204/*
e380f72b
RR
1205 printf( "SetFocus flag from " );
1206 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1207 printf( win->GetClassInfo()->GetClassName() );
1208 printf( ".\n" );
c801d85f 1209*/
e380f72b 1210 }
362c6693 1211 }
47d67540 1212
47d67540 1213
c801d85f 1214/*
f03fc89f 1215 printf( "OnSetFocus from " );
e380f72b 1216 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
f03fc89f
VZ
1217 printf( win->GetClassInfo()->GetClassName() );
1218 printf( " " );
1219 printf( WXSTRINGCAST win->GetLabel() );
1220 printf( ".\n" );
c801d85f 1221*/
47d67540 1222
e380f72b
RR
1223 wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
1224 event.SetEventObject( win );
47d67540 1225
e380f72b 1226 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1227 {
e380f72b 1228 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
034be888
RR
1229 return TRUE;
1230 }
ca298c88 1231
034be888 1232 return FALSE;
362c6693 1233}
c801d85f
KB
1234
1235//-----------------------------------------------------------------------------
2f2aa628
RR
1236// "focus_out_event"
1237//-----------------------------------------------------------------------------
c801d85f 1238
2f2aa628 1239static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
c801d85f 1240{
a2053b27
RR
1241 if (g_isIdle)
1242 wxapp_install_idle_handler();
1243
1244 if (!win->m_hasVMT) return FALSE;
034be888 1245 if (g_blockEventsOnDrag) return FALSE;
ca298c88 1246
a2053b27 1247 if (win->m_wxwindow)
e380f72b 1248 {
a2053b27
RR
1249 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
1250 GTK_WIDGET_UNSET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
e380f72b 1251 }
47d67540 1252
c801d85f 1253/*
f03fc89f 1254 printf( "OnKillFocus from " );
e380f72b 1255 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
f03fc89f
VZ
1256 printf( win->GetClassInfo()->GetClassName() );
1257 printf( ".\n" );
c801d85f 1258*/
47d67540 1259
e380f72b
RR
1260 wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
1261 event.SetEventObject( win );
47d67540 1262
e380f72b 1263 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1264 {
e380f72b 1265 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
034be888
RR
1266 return TRUE;
1267 }
ca298c88 1268
034be888 1269 return FALSE;
362c6693 1270}
c801d85f 1271
b4071e91
RR
1272//-----------------------------------------------------------------------------
1273// "enter_notify_event"
1274//-----------------------------------------------------------------------------
1275
1276static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1277{
a2053b27
RR
1278 if (g_isIdle)
1279 wxapp_install_idle_handler();
ca298c88 1280
a2053b27
RR
1281 if (!win->m_hasVMT) return FALSE;
1282 if (g_blockEventsOnDrag) return FALSE;
47d67540 1283
a2053b27 1284 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
b292e2f5 1285
e380f72b 1286 wxMouseEvent event( wxEVT_ENTER_WINDOW );
6bc8a1c8 1287#if (GTK_MINOR_VERSION > 0)
d1367c3d 1288 event.SetTimestamp( gdk_event->time );
6bc8a1c8 1289#endif
e380f72b 1290 event.SetEventObject( win );
ff8bfdbb 1291
4a33eba6
RR
1292 int x = 0;
1293 int y = 0;
1294 GdkModifierType state = (GdkModifierType)0;
ff8bfdbb 1295
a2053b27 1296 gdk_window_get_pointer( widget->window, &x, &y, &state );
ff8bfdbb 1297
4a33eba6
RR
1298 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1299 event.m_controlDown = (state & GDK_CONTROL_MASK);
1300 event.m_altDown = (state & GDK_MOD1_MASK);
1301 event.m_metaDown = (state & GDK_MOD2_MASK);
1302 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1303 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1304 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1305
1306 event.m_x = (long)x;
1307 event.m_y = (long)y;
ff8bfdbb 1308
e380f72b 1309 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1310 {
e380f72b 1311 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "enter_notify_event" );
034be888
RR
1312 return TRUE;
1313 }
ca298c88 1314
034be888 1315 return FALSE;
b4071e91 1316}
47d67540 1317
b4071e91
RR
1318//-----------------------------------------------------------------------------
1319// "leave_notify_event"
1320//-----------------------------------------------------------------------------
1321
1322static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1323{
a2053b27
RR
1324 if (g_isIdle)
1325 wxapp_install_idle_handler();
acfd422a 1326
a2053b27
RR
1327 if (!win->m_hasVMT) return FALSE;
1328 if (g_blockEventsOnDrag) return FALSE;
b292e2f5 1329
a2053b27
RR
1330 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1331
e380f72b 1332 wxMouseEvent event( wxEVT_LEAVE_WINDOW );
6bc8a1c8 1333#if (GTK_MINOR_VERSION > 0)
d1367c3d 1334 event.SetTimestamp( gdk_event->time );
6bc8a1c8 1335#endif
e380f72b 1336 event.SetEventObject( win );
47d67540 1337
4a33eba6
RR
1338 int x = 0;
1339 int y = 0;
1340 GdkModifierType state = (GdkModifierType)0;
ff8bfdbb 1341
4a33eba6 1342 gdk_window_get_pointer( widget->window, &x, &y, &state );
ff8bfdbb 1343
4a33eba6
RR
1344 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1345 event.m_controlDown = (state & GDK_CONTROL_MASK);
1346 event.m_altDown = (state & GDK_MOD1_MASK);
1347 event.m_metaDown = (state & GDK_MOD2_MASK);
1348 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1349 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1350 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1351
1352 event.m_x = (long)x;
1353 event.m_y = (long)y;
ff8bfdbb 1354
e380f72b 1355 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1356 {
e380f72b 1357 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "leave_notify_event" );
034be888
RR
1358 return TRUE;
1359 }
ca298c88 1360
034be888 1361 return FALSE;
b4071e91 1362}
47d67540 1363
c801d85f 1364//-----------------------------------------------------------------------------
2f2aa628
RR
1365// "value_changed" from m_vAdjust
1366//-----------------------------------------------------------------------------
c801d85f 1367
2f2aa628 1368static void gtk_window_vscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
c801d85f 1369{
a2053b27
RR
1370 if (g_isIdle)
1371 wxapp_install_idle_handler();
c801d85f 1372
a2053b27 1373 if (g_blockEventsOnDrag) return;
47d67540 1374
a2053b27 1375 if (!win->m_hasVMT) return;
47d67540 1376
a2053b27 1377 float diff = win->m_vAdjust->value - win->m_oldVerticalPos;
e380f72b 1378 if (fabs(diff) < 0.2) return;
a2053b27 1379 win->m_oldVerticalPos = win->m_vAdjust->value;
47d67540 1380
e380f72b 1381 wxEventType command = wxEVT_NULL;
47d67540 1382
a2053b27
RR
1383 float line_step = win->m_vAdjust->step_increment;
1384 float page_step = win->m_vAdjust->page_increment;
47d67540 1385
f03fc89f 1386 if (win->IsScrolling())
76ed8f8d 1387 {
c5b42c87 1388 command = wxEVT_SCROLLWIN_THUMBTRACK;
76ed8f8d
RR
1389 }
1390 else
1391 {
c5b42c87
RR
1392 if (fabs(win->m_vAdjust->value-win->m_vAdjust->lower) < 0.2) command = wxEVT_SCROLLWIN_BOTTOM;
1393 else if (fabs(win->m_vAdjust->value-win->m_vAdjust->upper) < 0.2) command = wxEVT_SCROLLWIN_TOP;
1394 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLLWIN_LINEDOWN;
1395 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLLWIN_LINEUP;
1396 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLLWIN_PAGEDOWN;
1397 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLLWIN_PAGEUP;
1398 else command = wxEVT_SCROLLWIN_THUMBTRACK;
76ed8f8d 1399 }
47d67540 1400
a2053b27 1401 int value = (int)(win->m_vAdjust->value+0.5);
c801d85f 1402
c5b42c87 1403 wxScrollWinEvent event( command, value, wxVERTICAL );
e380f72b
RR
1404 event.SetEventObject( win );
1405 win->GetEventHandler()->ProcessEvent( event );
362c6693 1406}
c801d85f
KB
1407
1408//-----------------------------------------------------------------------------
2f2aa628
RR
1409// "value_changed" from m_hAdjust
1410//-----------------------------------------------------------------------------
c801d85f 1411
2f2aa628 1412static void gtk_window_hscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
47d67540 1413{
a2053b27
RR
1414 if (g_isIdle)
1415 wxapp_install_idle_handler();
47d67540 1416
a2053b27
RR
1417 if (g_blockEventsOnDrag) return;
1418 if (!win->m_hasVMT) return;
47d67540 1419
a2053b27 1420 float diff = win->m_hAdjust->value - win->m_oldHorizontalPos;
e380f72b 1421 if (fabs(diff) < 0.2) return;
a2053b27 1422 win->m_oldHorizontalPos = win->m_hAdjust->value;
47d67540 1423
e380f72b 1424 wxEventType command = wxEVT_NULL;
47d67540 1425
a2053b27
RR
1426 float line_step = win->m_hAdjust->step_increment;
1427 float page_step = win->m_hAdjust->page_increment;
8bbe427f 1428
f03fc89f 1429 if (win->IsScrolling())
76ed8f8d 1430 {
c5b42c87 1431 command = wxEVT_SCROLLWIN_THUMBTRACK;
76ed8f8d
RR
1432 }
1433 else
1434 {
c5b42c87
RR
1435 if (fabs(win->m_hAdjust->value-win->m_hAdjust->lower) < 0.2) command = wxEVT_SCROLLWIN_BOTTOM;
1436 else if (fabs(win->m_hAdjust->value-win->m_hAdjust->upper) < 0.2) command = wxEVT_SCROLLWIN_TOP;
1437 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLLWIN_LINEDOWN;
1438 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLLWIN_LINEUP;
1439 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLLWIN_PAGEDOWN;
1440 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLLWIN_PAGEUP;
1441 else command = wxEVT_SCROLLWIN_THUMBTRACK;
76ed8f8d 1442 }
c801d85f 1443
a2053b27 1444 int value = (int)(win->m_hAdjust->value+0.5);
47d67540 1445
c5b42c87 1446 wxScrollWinEvent event( command, value, wxHORIZONTAL );
e380f72b
RR
1447 event.SetEventObject( win );
1448 win->GetEventHandler()->ProcessEvent( event );
362c6693 1449}
c801d85f
KB
1450
1451//-----------------------------------------------------------------------------
2f2aa628
RR
1452// "changed" from m_vAdjust
1453//-----------------------------------------------------------------------------
c801d85f 1454
2f2aa628 1455static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
c801d85f 1456{
a2053b27
RR
1457 if (g_isIdle)
1458 wxapp_install_idle_handler();
c801d85f 1459
a2053b27
RR
1460 if (g_blockEventsOnDrag) return;
1461 if (!win->m_hasVMT) return;
47d67540 1462
c5b42c87 1463 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
a2053b27 1464 int value = (int)(win->m_vAdjust->value+0.5);
c801d85f 1465
c5b42c87 1466 wxScrollWinEvent event( command, value, wxVERTICAL );
e380f72b
RR
1467 event.SetEventObject( win );
1468 win->GetEventHandler()->ProcessEvent( event );
362c6693 1469}
c801d85f
KB
1470
1471//-----------------------------------------------------------------------------
2f2aa628
RR
1472// "changed" from m_hAdjust
1473//-----------------------------------------------------------------------------
c801d85f 1474
2f2aa628 1475static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
47d67540 1476{
a2053b27
RR
1477 if (g_isIdle)
1478 wxapp_install_idle_handler();
47d67540 1479
a2053b27
RR
1480 if (g_blockEventsOnDrag) return;
1481 if (!win->m_hasVMT) return;
47d67540 1482
c5b42c87 1483 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
a2053b27 1484 int value = (int)(win->m_hAdjust->value+0.5);
47d67540 1485
c5b42c87 1486 wxScrollWinEvent event( command, value, wxHORIZONTAL );
e380f72b
RR
1487 event.SetEventObject( win );
1488 win->GetEventHandler()->ProcessEvent( event );
362c6693 1489}
c801d85f 1490
cb43b372
RR
1491//-----------------------------------------------------------------------------
1492// "button_press_event" from scrollbar
1493//-----------------------------------------------------------------------------
1494
8bbe427f
VZ
1495static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
1496 GdkEventButton *WXUNUSED(gdk_event),
ff8bfdbb 1497 wxWindow *win )
cb43b372 1498{
a2053b27
RR
1499 if (g_isIdle)
1500 wxapp_install_idle_handler();
1501
1ecc4d80
RR
1502// don't test here as we can release the mouse while being over
1503// a different window then the slider
1504//
76ed8f8d 1505// if (gdk_event->window != widget->slider) return FALSE;
8bbe427f 1506
f03fc89f 1507 win->SetScrolling( TRUE );
47d67540 1508
e380f72b 1509 return FALSE;
cb43b372
RR
1510}
1511
1512//-----------------------------------------------------------------------------
1513// "button_release_event" from scrollbar
1514//-----------------------------------------------------------------------------
1515
8bbe427f
VZ
1516static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
1517 GdkEventButton *WXUNUSED(gdk_event),
ff8bfdbb 1518 wxWindow *win )
cb43b372 1519{
76ed8f8d 1520
1ecc4d80 1521// don't test here as we can release the mouse while being over
76ed8f8d
RR
1522// a different window then the slider
1523//
1524// if (gdk_event->window != widget->slider) return FALSE;
cb43b372 1525
a2053b27 1526 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
47d67540 1527
f03fc89f 1528 if (widget == GTK_RANGE(scrolledWindow->vscrollbar))
a2053b27 1529 gtk_signal_emit_by_name( GTK_OBJECT(win->m_hAdjust), "value_changed" );
e380f72b 1530 else
a2053b27 1531 gtk_signal_emit_by_name( GTK_OBJECT(win->m_vAdjust), "value_changed" );
47d67540 1532
f03fc89f 1533 win->SetScrolling( FALSE );
47d67540 1534
e380f72b 1535 return FALSE;
cb43b372
RR
1536}
1537
f03fc89f
VZ
1538// ----------------------------------------------------------------------------
1539// this wxWindowBase function is implemented here (in platform-specific file)
1540// because it is static and so couldn't be made virtual
1541// ----------------------------------------------------------------------------
2b07d713 1542
f03fc89f 1543wxWindow *wxWindowBase::FindFocus()
2b07d713 1544{
f03fc89f 1545 return g_focusWindow;
2b07d713 1546}
ca298c88 1547
a2053b27
RR
1548//-----------------------------------------------------------------------------
1549// "realize" from m_widget
1550//-----------------------------------------------------------------------------
1551
1552/* we cannot set colours, fonts and cursors before the widget has
1553 been realized, so we do this directly after realization */
1554
1555static gint
a234a61a 1556gtk_window_realized_callback( GtkWidget * WXUNUSED(widget), wxWindow *win )
a2053b27
RR
1557{
1558 if (g_isIdle)
1559 wxapp_install_idle_handler();
1560
739730ca
RR
1561 if (win->m_delayedFont)
1562 win->SetFont( win->GetFont() );
a2053b27 1563
739730ca
RR
1564 if (win->m_delayedBackgroundColour)
1565 win->SetBackgroundColour( win->GetBackgroundColour() );
a2053b27 1566
739730ca
RR
1567 if (win->m_delayedForegroundColour)
1568 win->SetForegroundColour( win->GetForegroundColour() );
a2053b27 1569
739730ca 1570 win->SetCursor( win->GetCursor() );
3c679789
RR
1571
1572 wxWindowCreateEvent event( win );
1573 event.SetEventObject( win );
1574 win->GetEventHandler()->ProcessEvent( event );
a2053b27
RR
1575
1576 return FALSE;
1577}
1578
6ca41e57
RR
1579//-----------------------------------------------------------------------------
1580// InsertChild for wxWindow.
1581//-----------------------------------------------------------------------------
1582
b1170810
RR
1583/* Callback for wxWindow. This very strange beast has to be used because
1584 * C++ has no virtual methods in a constructor. We have to emulate a
1585 * virtual function here as wxNotebook requires a different way to insert
1586 * a child in it. I had opted for creating a wxNotebookPage window class
1587 * which would have made this superfluous (such in the MDI window system),
1588 * but no-one was listening to me... */
6ca41e57
RR
1589
1590static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
1591{
a2053b27
RR
1592 gtk_myfixed_put( GTK_MYFIXED(parent->m_wxwindow),
1593 GTK_WIDGET(child->m_widget),
1594 child->m_x,
1595 child->m_y,
1596 child->m_width,
1597 child->m_height );
f03fc89f
VZ
1598
1599 if (parent->HasFlag(wxTAB_TRAVERSAL))
3e61c765
RR
1600 {
1601 /* we now allow a window to get the focus as long as it
ff8bfdbb 1602 doesn't have any children. */
a2053b27 1603 GTK_WIDGET_UNSET_FLAGS( parent->m_wxwindow, GTK_CAN_FOCUS );
3e61c765 1604 }
6ca41e57
RR
1605}
1606
bbe0af5b
RR
1607//-----------------------------------------------------------------------------
1608// global functions
1609//-----------------------------------------------------------------------------
1610
1611wxWindow* wxGetActiveWindow()
1612{
f03fc89f 1613 return g_focusWindow;
bbe0af5b
RR
1614}
1615
c801d85f 1616//-----------------------------------------------------------------------------
2f2aa628 1617// wxWindow
c801d85f
KB
1618//-----------------------------------------------------------------------------
1619
f03fc89f 1620IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
c801d85f 1621
68995f26 1622void wxWindow::Init()
c801d85f 1623{
f03fc89f
VZ
1624 // common init
1625 InitBase();
68995f26 1626
f03fc89f 1627 // GTK specific
a2053b27 1628 m_widget = (GtkWidget *) NULL;
e380f72b 1629 m_wxwindow = (GtkWidget *) NULL;
8bbe427f 1630
f03fc89f 1631 // position/size
a2053b27
RR
1632 m_x = 0;
1633 m_y = 0;
1634 m_width = 0;
e380f72b 1635 m_height = 0;
8bbe427f 1636
e380f72b
RR
1637 m_sizeSet = FALSE;
1638 m_hasVMT = FALSE;
1639 m_needParent = TRUE;
31c6b4fc 1640 m_isBeingDeleted = FALSE;
8bbe427f 1641
a2053b27 1642 m_hasScrolling = FALSE;
e380f72b 1643 m_isScrolling = FALSE;
f03fc89f 1644
a2053b27 1645 m_hAdjust = (GtkAdjustment*) NULL;
e380f72b 1646 m_vAdjust = (GtkAdjustment*) NULL;
a2053b27 1647 m_oldHorizontalPos = 0.0;
e380f72b 1648 m_oldVerticalPos = 0.0;
8bbe427f 1649
e380f72b
RR
1650 m_resizing = FALSE;
1651 m_scrollGC = (GdkGC*) NULL;
1652 m_widgetStyle = (GtkStyle*) NULL;
8bbe427f 1653
ddb6bc71 1654 m_insertCallback = (wxInsertChildFunction) NULL;
8bbe427f 1655
1ecc4d80 1656 m_isStaticBox = FALSE;
b292e2f5 1657 m_acceptsFocus = FALSE;
362c6693 1658}
c801d85f 1659
68995f26
VZ
1660wxWindow::wxWindow()
1661{
1662 Init();
1663}
1664
6ca41e57 1665wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
e380f72b
RR
1666 const wxPoint &pos, const wxSize &size,
1667 long style, const wxString &name )
6ca41e57 1668{
68995f26
VZ
1669 Init();
1670
e380f72b 1671 Create( parent, id, pos, size, style, name );
6ca41e57 1672}
8bbe427f 1673
debe6624 1674bool wxWindow::Create( wxWindow *parent, wxWindowID id,
e380f72b
RR
1675 const wxPoint &pos, const wxSize &size,
1676 long style, const wxString &name )
c801d85f 1677{
e380f72b 1678 PreCreation( parent, id, pos, size, style, name );
47d67540 1679
ddb6bc71
RR
1680 m_insertCallback = wxInsertChildInWindow;
1681
e380f72b 1682 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
38c7b3d3 1683 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
ff8bfdbb 1684
2e563988
RR
1685#ifdef __WXDEBUG__
1686 debug_focus_in( m_widget, _T("wxWindow::m_widget"), name );
1687#endif
1688
f03fc89f 1689 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
47d67540 1690
2e563988 1691#ifdef __WXDEBUG__
f03fc89f
VZ
1692 debug_focus_in( scrolledWindow->hscrollbar, _T("wxWindow::hsrcollbar"), name );
1693 debug_focus_in( scrolledWindow->vscrollbar, _T("wxWindow::vsrcollbar"), name );
2e563988
RR
1694#endif
1695
e380f72b
RR
1696 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1697 scroll_class->scrollbar_spacing = 0;
47d67540 1698
f03fc89f 1699 gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
47d67540 1700
f03fc89f
VZ
1701 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->hscrollbar) );
1702 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->vscrollbar) );
47d67540 1703
38c7b3d3
RR
1704 m_wxwindow = gtk_myfixed_new();
1705
2e563988
RR
1706#ifdef __WXDEBUG__
1707 debug_focus_in( m_wxwindow, _T("wxWindow::m_wxwindow"), name );
1708#endif
1709
034be888 1710 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
58dea4b0 1711
034be888
RR
1712#if (GTK_MINOR_VERSION > 0)
1713 GtkMyFixed *myfixed = GTK_MYFIXED(m_wxwindow);
b292e2f5 1714
f03fc89f 1715 if (HasFlag(wxRAISED_BORDER))
034be888
RR
1716 {
1717 gtk_myfixed_set_shadow_type( myfixed, GTK_SHADOW_OUT );
1718 }
f03fc89f 1719 else if (HasFlag(wxSUNKEN_BORDER))
034be888
RR
1720 {
1721 gtk_myfixed_set_shadow_type( myfixed, GTK_SHADOW_IN );
1722 }
1723 else
1724 {
1725 gtk_myfixed_set_shadow_type( myfixed, GTK_SHADOW_NONE );
1726 }
f03fc89f
VZ
1727#else // GTK_MINOR_VERSION == 0
1728 GtkViewport *viewport = GTK_VIEWPORT(scrolledWindow->viewport);
b292e2f5 1729
f03fc89f 1730 if (HasFlag(wxRAISED_BORDER))
e380f72b
RR
1731 {
1732 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
1733 }
f03fc89f 1734 else if (HasFlag(wxSUNKEN_BORDER))
e380f72b
RR
1735 {
1736 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
1737 }
1738 else
1739 {
1740 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
1741 }
f03fc89f 1742#endif // GTK_MINOR_VERSION
47d67540 1743
f03fc89f 1744 if (HasFlag(wxTAB_TRAVERSAL))
b292e2f5 1745 {
f03fc89f
VZ
1746 /* we now allow a window to get the focus as long as it
1747 doesn't have any children. */
ff8bfdbb 1748 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
b292e2f5
RR
1749 m_acceptsFocus = FALSE;
1750 }
e380f72b 1751 else
b292e2f5 1752 {
e380f72b 1753 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
b292e2f5
RR
1754 m_acceptsFocus = TRUE;
1755 }
ca298c88 1756
034be888 1757#if (GTK_MINOR_VERSION == 0)
e380f72b
RR
1758 // shut the viewport up
1759 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1760 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
f03fc89f 1761#endif // GTK_MINOR_VERSION == 0
e380f72b
RR
1762
1763 // I _really_ don't want scrollbars in the beginning
a2053b27
RR
1764 m_vAdjust->lower = 0.0;
1765 m_vAdjust->upper = 1.0;
1766 m_vAdjust->value = 0.0;
1767 m_vAdjust->step_increment = 1.0;
1768 m_vAdjust->page_increment = 1.0;
1769 m_vAdjust->page_size = 5.0;
1770 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1771 m_hAdjust->lower = 0.0;
1772 m_hAdjust->upper = 1.0;
1773 m_hAdjust->value = 0.0;
1774 m_hAdjust->step_increment = 1.0;
1775 m_hAdjust->page_increment = 1.0;
1776 m_hAdjust->page_size = 5.0;
1777 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
f03fc89f
VZ
1778
1779 // these handlers block mouse events to any window during scrolling such as
1780 // motion events and prevent GTK and wxWindows from fighting over where the
1781 // slider should be
1782
1783 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_press_event",
76ed8f8d
RR
1784 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1785
f03fc89f 1786 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_press_event",
76ed8f8d
RR
1787 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1788
f03fc89f 1789 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_release_event",
76ed8f8d
RR
1790 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1791
f03fc89f 1792 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_release_event",
76ed8f8d 1793 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
8bbe427f 1794
034be888 1795 // these handlers get notified when screen updates are required either when
76ed8f8d
RR
1796 // scrolling or when the window size (and therefore scrollbar configuration)
1797 // has changed
1798
1799 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
1800 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
1801 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
1802 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
1803
1804 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
1805 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
1806 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
1807 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
1808
f03fc89f 1809 gtk_widget_show( m_wxwindow );
47d67540 1810
f03fc89f
VZ
1811 if (m_parent)
1812 m_parent->DoAddChild( this );
8bbe427f 1813
e380f72b 1814 PostCreation();
8bbe427f 1815
e380f72b 1816 Show( TRUE );
c801d85f 1817
e380f72b 1818 return TRUE;
362c6693 1819}
c801d85f 1820
68dda785 1821wxWindow::~wxWindow()
c801d85f 1822{
31c6b4fc 1823 m_isBeingDeleted = TRUE;
43a18898 1824 m_hasVMT = FALSE;
47d67540 1825
f03fc89f
VZ
1826 if (m_widget)
1827 Show( FALSE );
8bbe427f 1828
a2053b27
RR
1829 DestroyChildren();
1830
f03fc89f
VZ
1831 if (m_parent)
1832 m_parent->RemoveChild( this );
c801d85f 1833
f03fc89f 1834 if (m_widgetStyle)
a2053b27 1835 {
f03fc89f 1836 gtk_style_unref( m_widgetStyle );
a2053b27
RR
1837 m_widgetStyle = (GtkStyle*) NULL;
1838 }
c801d85f 1839
f03fc89f 1840 if (m_scrollGC)
a2053b27 1841 {
f03fc89f 1842 gdk_gc_unref( m_scrollGC );
a2053b27
RR
1843 m_scrollGC = (GdkGC*) NULL;
1844 }
47d67540 1845
f03fc89f 1846 if (m_wxwindow)
a2053b27 1847 {
f03fc89f 1848 gtk_widget_destroy( m_wxwindow );
a2053b27
RR
1849 m_wxwindow = (GtkWidget*) NULL;
1850 }
8bbe427f 1851
f03fc89f 1852 if (m_widget)
a2053b27 1853 {
f03fc89f 1854 gtk_widget_destroy( m_widget );
a2053b27
RR
1855 m_widget = (GtkWidget*) NULL;
1856 }
362c6693 1857}
c801d85f 1858
f03fc89f
VZ
1859void wxWindow::PreCreation( wxWindow *parent,
1860 wxWindowID id,
1861 const wxPoint &pos,
1862 const wxSize &size,
1863 long style,
1864 const wxString &name )
c801d85f 1865{
f03fc89f 1866 wxASSERT_MSG( !m_needParent || parent, _T("Need complete parent.") );
8bbe427f 1867
f03fc89f
VZ
1868 if ( !CreateBase(parent, id, pos, size, style, name) )
1869 {
1870 wxFAIL_MSG(_T("window creation failed"));
1871 }
8bbe427f 1872
f03fc89f
VZ
1873 m_width = WidthDefault(size.x);
1874 m_height = HeightDefault(size.y);
8bbe427f 1875
43a18898
RR
1876 m_x = (int)pos.x;
1877 m_y = (int)pos.y;
8bbe427f 1878
f03fc89f 1879 if (!parent) /* some reasonable defaults */
6ca41e57 1880 {
43a18898
RR
1881 if (m_x == -1)
1882 {
1883 m_x = (gdk_screen_width () - m_width) / 2;
1884 if (m_x < 10) m_x = 10;
1885 }
1886 if (m_y == -1)
1887 {
1888 m_y = (gdk_screen_height () - m_height) / 2;
1889 if (m_y < 10) m_y = 10;
1890 }
6ca41e57 1891 }
c801d85f
KB
1892}
1893
68dda785 1894void wxWindow::PostCreation()
c801d85f 1895{
05939a81 1896 wxASSERT_MSG( (m_widget != NULL), _T("invalid window") );
ca298c88 1897
43a18898
RR
1898 if (m_wxwindow)
1899 {
034be888 1900 /* these get reported to wxWindows -> wxPaintEvent */
20239453
RR
1901 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
1902 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
47d67540 1903
20239453
RR
1904 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
1905 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
ca298c88 1906
ef47f9b3 1907#if (GTK_MINOR_VERSION > 0)
f03fc89f 1908 /* these are called when the "sunken" or "raised" borders are drawn */
034be888
RR
1909 gtk_signal_connect( GTK_OBJECT(m_widget), "expose_event",
1910 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback), (gpointer)this );
1911
1912 gtk_signal_connect( GTK_OBJECT(m_widget), "draw",
1913 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback), (gpointer)this );
ef47f9b3 1914#endif
43a18898 1915 }
47d67540 1916
a2053b27 1917 GtkWidget *connect_widget = GetConnectWidget();
f03fc89f 1918
a2053b27 1919 ConnectWidget( connect_widget );
47d67540 1920
a2053b27
RR
1921 /* we cannot set colours, fonts and cursors before the widget has
1922 been realized, so we do this directly after realization */
1923 gtk_signal_connect( GTK_OBJECT(connect_widget), "realize",
1924 GTK_SIGNAL_FUNC(gtk_window_realized_callback), (gpointer) this );
ca298c88 1925
43a18898 1926 m_hasVMT = TRUE;
b4071e91
RR
1927}
1928
1929void wxWindow::ConnectWidget( GtkWidget *widget )
1930{
43a18898
RR
1931 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
1932 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
c801d85f 1933
b666df2c
RR
1934 gtk_signal_connect( GTK_OBJECT(widget), "key_release_event",
1935 GTK_SIGNAL_FUNC(gtk_window_key_release_callback), (gpointer)this );
1936
43a18898
RR
1937 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
1938 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
47d67540 1939
43a18898
RR
1940 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
1941 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
47d67540 1942
43a18898
RR
1943 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
1944 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
47d67540 1945
43a18898
RR
1946 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
1947 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
c801d85f 1948
43a18898
RR
1949 gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
1950 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
c801d85f 1951
43a18898
RR
1952 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
1953 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
47d67540 1954
43a18898
RR
1955 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
1956 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
362c6693 1957}
c801d85f 1958
68dda785 1959bool wxWindow::Destroy()
c801d85f 1960{
05939a81 1961 wxASSERT_MSG( (m_widget != NULL), _T("invalid window") );
47d67540 1962
43a18898 1963 m_hasVMT = FALSE;
c801d85f 1964
f03fc89f 1965 return wxWindowBase::Destroy();
362c6693 1966}
c801d85f 1967
bfc6fde4 1968void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
c801d85f 1969{
05939a81
OK
1970 wxASSERT_MSG( (m_widget != NULL), _T("invalid window") );
1971 wxASSERT_MSG( (m_parent != NULL), _T("wxWindow::SetSize requires parent.\n") );
8bbe427f 1972
e27ce4e9 1973 if (m_resizing) return; /* I don't like recursions */
fb1585ae 1974 m_resizing = TRUE;
47d67540 1975
a2053b27 1976 if (m_parent->m_wxwindow == NULL) /* i.e. wxNotebook */
fb1585ae 1977 {
e27ce4e9 1978 /* don't set the size for children of wxNotebook, just take the values. */
fb1585ae
RR
1979 m_x = x;
1980 m_y = y;
1981 m_width = width;
ba4e3652 1982 m_height = height;
fb1585ae 1983 }
ba4e3652 1984 else
fb1585ae 1985 {
85ad5eb5 1986 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
ba4e3652
RR
1987 {
1988 if (x != -1) m_x = x;
1989 if (y != -1) m_y = y;
1990 if (width != -1) m_width = width;
1991 if (height != -1) m_height = height;
1992 }
1993 else
1994 {
1995 m_x = x;
1996 m_y = y;
1997 m_width = width;
1998 m_height = height;
1999 }
47d67540 2000
ba4e3652
RR
2001 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
2002 {
2003 if (width == -1) m_width = 80;
2004 }
2005
2006 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
2007 {
2008 if (height == -1) m_height = 26;
2009 }
8bbe427f 2010
ba4e3652
RR
2011 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
2012 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
d3b4d113
RR
2013 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
2014 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
47d67540 2015
a2053b27 2016 int border = 0;
012a03e0 2017 int bottom_border = 0;
f03fc89f 2018
29f538ce 2019 if (GTK_WIDGET_CAN_DEFAULT(m_widget))
a2053b27
RR
2020 {
2021 /* the default button has a border around it */
012a03e0
RR
2022 border = 6;
2023 bottom_border = 5;
a2053b27
RR
2024 }
2025
2026 /* this is the result of hours of debugging: the following code
2027 means that if we have a m_wxwindow and we set the size of
2028 m_widget, m_widget (which is a GtkScrolledWindow) does NOT
2029 automatically propagate its size down to its m_wxwindow,
2030 which is its client area. therefore, we have to tell the
2031 client area directly that it has to resize itself.
2032 this will lead to that m_widget (GtkScrolledWindow) will
2033 calculate how much size it needs for scrollbars etc and
2034 it will then call XXX_size_allocate of its child, which
2035 is m_wxwindow. m_wxwindow in turn will do the same with its
2036 children and so on. problems can arise if this happens
2037 before all the children have been realized as some widgets
2038 stupidy need to be realized during XXX_size_allocate (e.g.
2039 GtkNotebook) and they will segv if called otherwise. this
2040 emergency is tested in gtk_myfixed_size_allocate. Normally
2041 this shouldn't be needed and only gtk_widget_queue_resize()
2042 should be enough to provoke a resize at the next appropriate
2043 moment, but this seems to fail, e.g. when a wxNotebook contains
2044 a wxSplitterWindow: the splitter window's children won't
2045 show up properly resized then. */
2046
2047 gtk_myfixed_set_size( GTK_MYFIXED(m_parent->m_wxwindow),
2048 m_widget,
2049 m_x-border,
2050 m_y-border,
2051 m_width+2*border,
012a03e0 2052 m_height+border+bottom_border );
ba4e3652 2053 }
8bbe427f 2054
fb1585ae 2055 m_sizeSet = TRUE;
47d67540 2056
fb1585ae
RR
2057 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
2058 event.SetEventObject( this );
ba4e3652 2059 GetEventHandler()->ProcessEvent( event );
47d67540 2060
fb1585ae 2061 m_resizing = FALSE;
362c6693 2062}
c801d85f 2063
9390a202
RR
2064void wxWindow::OnInternalIdle()
2065{
72195a0f
RR
2066 GdkWindow *window = GetConnectWidget()->window;
2067 if (window)
2068 {
2069 wxCursor cursor = m_cursor;
2070 if (g_globalCursor.Ok()) cursor = g_globalCursor;
082b2798 2071
076d2575 2072 if (cursor.Ok() && m_currentGdkCursor != cursor)
72195a0f
RR
2073 {
2074 gdk_window_set_cursor( window, cursor.GetCursor() );
2075 m_currentGdkCursor = cursor;
2076 }
082b2798 2077 }
238d735d 2078
9390a202
RR
2079 UpdateWindowUI();
2080}
2081
f03fc89f 2082void wxWindow::DoGetSize( int *width, int *height ) const
c801d85f 2083{
05939a81 2084 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2085
fb1585ae
RR
2086 if (width) (*width) = m_width;
2087 if (height) (*height) = m_height;
362c6693 2088}
c801d85f 2089
bfc6fde4 2090void wxWindow::DoSetClientSize( int width, int height )
c801d85f 2091{
05939a81 2092 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2093
1ecc4d80 2094 if (!m_wxwindow)
c801d85f 2095 {
1ecc4d80 2096 SetSize( width, height );
c801d85f
KB
2097 }
2098 else
2099 {
1ecc4d80
RR
2100 int dw = 0;
2101 int dh = 0;
2102
2103 if (!m_hasScrolling)
2104 {
2105 GtkStyleClass *window_class = m_wxwindow->style->klass;
2106
f03fc89f 2107 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
1ecc4d80
RR
2108 {
2109 dw += 2 * window_class->xthickness;
2110 dh += 2 * window_class->ythickness;
2111 }
2112 }
2113 else
2114 {
2115 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2116 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
47d67540 2117
034be888 2118#if (GTK_MINOR_VERSION == 0)
1ecc4d80 2119 GtkWidget *viewport = scroll_window->viewport;
1ecc4d80
RR
2120 GtkStyleClass *viewport_class = viewport->style->klass;
2121
f03fc89f 2122 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
1ecc4d80
RR
2123 {
2124 dw += 2 * viewport_class->xthickness;
2125 dh += 2 * viewport_class->ythickness;
2126 }
034be888
RR
2127#endif
2128
2129/*
2130 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2131 GtkWidget *vscrollbar = scroll_window->vscrollbar;
ca298c88 2132
f03fc89f 2133 we use this instead: range.slider_width = 11 + 2*2pts edge
034be888 2134*/
47d67540 2135
1ecc4d80
RR
2136 if (scroll_window->vscrollbar_visible)
2137 {
034be888 2138 dw += 15; /* dw += vscrollbar->allocation.width; */
1ecc4d80
RR
2139 dw += scroll_class->scrollbar_spacing;
2140 }
2141
2142 if (scroll_window->hscrollbar_visible)
2143 {
034be888 2144 dh += 15; /* dh += hscrollbar->allocation.height; */
63cc5d9d 2145 dh += scroll_class->scrollbar_spacing;
1ecc4d80
RR
2146 }
2147 }
2148
034be888 2149 SetSize( width+dw, height+dh );
1ecc4d80 2150 }
362c6693 2151}
c801d85f 2152
f03fc89f 2153void wxWindow::DoGetClientSize( int *width, int *height ) const
c801d85f 2154{
05939a81 2155 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2156
1ecc4d80
RR
2157 if (!m_wxwindow)
2158 {
2159 if (width) (*width) = m_width;
2160 if (height) (*height) = m_height;
c801d85f
KB
2161 }
2162 else
2163 {
1ecc4d80
RR
2164 int dw = 0;
2165 int dh = 0;
2166
2167 if (!m_hasScrolling)
2168 {
2169 GtkStyleClass *window_class = m_wxwindow->style->klass;
2170
f03fc89f 2171 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
1ecc4d80
RR
2172 {
2173 dw += 2 * window_class->xthickness;
2174 dh += 2 * window_class->ythickness;
2175 }
2176 }
2177 else
2178 {
2179 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2180 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
47d67540 2181
034be888 2182#if (GTK_MINOR_VERSION == 0)
1ecc4d80 2183 GtkWidget *viewport = scroll_window->viewport;
1ecc4d80
RR
2184 GtkStyleClass *viewport_class = viewport->style->klass;
2185
f03fc89f 2186 if ( HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER) )
1ecc4d80
RR
2187 {
2188 dw += 2 * viewport_class->xthickness;
2189 dh += 2 * viewport_class->ythickness;
2190 }
034be888
RR
2191#endif
2192/*
2193 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2194 GtkWidget *vscrollbar = scroll_window->vscrollbar;
ca298c88 2195
f03fc89f 2196 we use this instead: range.slider_width = 11 + 2*2pts edge
034be888 2197*/
1ecc4d80
RR
2198
2199 if (scroll_window->vscrollbar_visible)
2200 {
034be888 2201 dw += 15; /* dw += vscrollbar->allocation.width; */
1ecc4d80
RR
2202 dw += scroll_class->scrollbar_spacing;
2203 }
2204
2205 if (scroll_window->hscrollbar_visible)
2206 {
034be888 2207 dh += 15; /* dh += hscrollbar->allocation.height; */
1ecc4d80
RR
2208 dh += scroll_class->scrollbar_spacing;
2209 }
2210 }
47d67540 2211
1ecc4d80
RR
2212 if (width) (*width) = m_width - dw;
2213 if (height) (*height) = m_height - dh;
2214 }
362c6693 2215}
c801d85f 2216
f03fc89f 2217void wxWindow::DoGetPosition( int *x, int *y ) const
c801d85f 2218{
05939a81 2219 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2220
43a18898
RR
2221 if (x) (*x) = m_x;
2222 if (y) (*y) = m_y;
362c6693 2223}
c801d85f 2224
dabc0cd5 2225void wxWindow::DoClientToScreen( int *x, int *y ) const
c801d85f 2226{
05939a81 2227 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2228
a2053b27
RR
2229 if (!m_widget->window) return;
2230
43a18898
RR
2231 GdkWindow *source = (GdkWindow *) NULL;
2232 if (m_wxwindow)
2233 source = m_wxwindow->window;
2234 else
2235 source = m_widget->window;
47d67540 2236
43a18898
RR
2237 int org_x = 0;
2238 int org_y = 0;
2239 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2240
43a18898 2241 if (!m_wxwindow)
c801d85f 2242 {
43a18898
RR
2243 if (GTK_WIDGET_NO_WINDOW (m_widget))
2244 {
2245 org_x += m_widget->allocation.x;
2246 org_y += m_widget->allocation.y;
2247 }
362c6693 2248 }
47d67540 2249
43a18898
RR
2250 if (x) *x += org_x;
2251 if (y) *y += org_y;
362c6693 2252}
c801d85f 2253
dabc0cd5 2254void wxWindow::DoScreenToClient( int *x, int *y ) const
c801d85f 2255{
05939a81 2256 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2257
a2053b27
RR
2258 if (!m_widget->window) return;
2259
1ecc4d80
RR
2260 GdkWindow *source = (GdkWindow *) NULL;
2261 if (m_wxwindow)
2262 source = m_wxwindow->window;
2263 else
2264 source = m_widget->window;
47d67540 2265
1ecc4d80
RR
2266 int org_x = 0;
2267 int org_y = 0;
2268 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2269
1ecc4d80 2270 if (!m_wxwindow)
c801d85f 2271 {
1ecc4d80
RR
2272 if (GTK_WIDGET_NO_WINDOW (m_widget))
2273 {
2274 org_x += m_widget->allocation.x;
2275 org_y += m_widget->allocation.y;
2276 }
362c6693 2277 }
47d67540 2278
1ecc4d80
RR
2279 if (x) *x -= org_x;
2280 if (y) *y -= org_y;
362c6693 2281}
c801d85f 2282
f03fc89f 2283bool wxWindow::Show( bool show )
c801d85f 2284{
f03fc89f 2285 wxCHECK_MSG( (m_widget != NULL), FALSE, _T("invalid window") );
47d67540 2286
739730ca
RR
2287 if (!wxWindowBase::Show(show))
2288 {
2289 // nothing to do
f03fc89f 2290 return FALSE;
739730ca 2291 }
8bbe427f 2292
f03fc89f
VZ
2293 if (show)
2294 gtk_widget_show( m_widget );
1ecc4d80 2295 else
f03fc89f 2296 gtk_widget_hide( m_widget );
8bbe427f 2297
f03fc89f 2298 return TRUE;
362c6693 2299}
c801d85f 2300
f03fc89f 2301bool wxWindow::Enable( bool enable )
c801d85f 2302{
f03fc89f 2303 wxCHECK_MSG( (m_widget != NULL), FALSE, _T("invalid window") );
5e0aa05a 2304
739730ca
RR
2305 if (!wxWindowBase::Enable(enable))
2306 {
2307 // nothing to do
f03fc89f 2308 return FALSE;
739730ca 2309 }
1ecc4d80 2310
f03fc89f
VZ
2311 gtk_widget_set_sensitive( m_widget, enable );
2312 if ( m_wxwindow )
2313 gtk_widget_set_sensitive( m_wxwindow, enable );
ff8bfdbb 2314
f03fc89f 2315 return TRUE;
362c6693 2316}
c801d85f 2317
f03fc89f 2318int wxWindow::GetCharHeight() const
2f2aa628 2319{
f03fc89f 2320 wxCHECK_MSG( (m_widget != NULL), 12, _T("invalid window") );
47d67540 2321
f03fc89f 2322 wxCHECK_MSG( m_font.Ok(), 12, _T("invalid font") );
2f2aa628 2323
f03fc89f
VZ
2324 GdkFont *font = m_font.GetInternalFont( 1.0 );
2325
2326 return font->ascent + font->descent;
362c6693 2327}
c801d85f 2328
f03fc89f 2329int wxWindow::GetCharWidth() const
c33c4050 2330{
05939a81 2331 wxCHECK_MSG( (m_widget != NULL), 8, _T("invalid window") );
47d67540 2332
05939a81 2333 wxCHECK_MSG( m_font.Ok(), 8, _T("invalid font") );
47d67540 2334
463c1fa1 2335 GdkFont *font = m_font.GetInternalFont( 1.0 );
ff8bfdbb 2336
463c1fa1 2337 return gdk_string_width( font, "H" );
c33c4050
RR
2338}
2339
f03fc89f
VZ
2340void wxWindow::GetTextExtent( const wxString& string,
2341 int *x,
2342 int *y,
2343 int *descent,
2344 int *externalLeading,
2345 const wxFont *theFont ) const
c33c4050 2346{
463c1fa1
RR
2347 wxFont fontToUse = m_font;
2348 if (theFont) fontToUse = *theFont;
47d67540 2349
05939a81 2350 wxCHECK_RET( fontToUse.Ok(), _T("invalid font") );
47d67540 2351
463c1fa1 2352 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
05939a81 2353 if (x) (*x) = gdk_string_width( font, string.mbc_str() );
463c1fa1
RR
2354 if (y) (*y) = font->ascent + font->descent;
2355 if (descent) (*descent) = font->descent;
2356 if (externalLeading) (*externalLeading) = 0; // ??
c33c4050
RR
2357}
2358
68dda785 2359void wxWindow::SetFocus()
c801d85f 2360{
05939a81 2361 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
ff8bfdbb 2362
463c1fa1
RR
2363 GtkWidget *connect_widget = GetConnectWidget();
2364 if (connect_widget)
c801d85f 2365 {
b292e2f5 2366 if (GTK_WIDGET_CAN_FOCUS(connect_widget) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
463c1fa1
RR
2367 {
2368 gtk_widget_grab_focus (connect_widget);
2369 }
ff8bfdbb
VZ
2370 else if (GTK_IS_CONTAINER(connect_widget))
2371 {
2372 gtk_container_focus( GTK_CONTAINER(connect_widget), GTK_DIR_TAB_FORWARD );
2373 }
2374 else
2375 {
2376 }
362c6693 2377 }
362c6693 2378}
c801d85f 2379
b292e2f5
RR
2380bool wxWindow::AcceptsFocus() const
2381{
f03fc89f 2382 return m_acceptsFocus && wxWindowBase::AcceptsFocus();
b292e2f5
RR
2383}
2384
f03fc89f 2385bool wxWindow::Reparent( wxWindow *newParent )
463c1fa1 2386{
05939a81 2387 wxCHECK_MSG( (m_widget != NULL), (wxWindow*) NULL, _T("invalid window") );
8ce63e9d
RR
2388
2389 wxWindow *oldParent = m_parent;
a2053b27 2390
f03fc89f
VZ
2391 if ( !wxWindowBase::Reparent(newParent) )
2392 return FALSE;
8bbe427f 2393
8ce63e9d
RR
2394 if (oldParent)
2395 {
2396 gtk_container_remove( GTK_CONTAINER(oldParent->m_wxwindow), m_widget );
2397 }
2398
2399 if (newParent)
2400 {
2401 /* insert GTK representation */
2402 (*(newParent->m_insertCallback))(newParent, this);
2403 }
2404
f03fc89f 2405 return TRUE;
362c6693 2406}
c801d85f 2407
ddb6bc71
RR
2408void wxWindow::DoAddChild(wxWindow *child)
2409{
2410 wxASSERT_MSG( (m_widget != NULL), _T("invalid window") );
2411
2412 wxASSERT_MSG( (child != NULL), _T("invalid child window") );
2413
2414 wxASSERT_MSG( (m_insertCallback != NULL), _T("invalid child insertion function") );
2415
2416 /* add to list */
2417 AddChild( child );
2418
2419 /* insert GTK representation */
2420 (*m_insertCallback)(this, child);
2421}
2422
68dda785 2423void wxWindow::Raise()
362c6693 2424{
05939a81 2425 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2426
a2053b27
RR
2427 if (!m_widget->window) return;
2428
f03fc89f 2429 gdk_window_raise( m_widget->window );
362c6693
RR
2430}
2431
68dda785 2432void wxWindow::Lower()
362c6693 2433{
05939a81 2434 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2435
a2053b27
RR
2436 if (!m_widget->window) return;
2437
f03fc89f 2438 gdk_window_lower( m_widget->window );
362c6693 2439}
c801d85f 2440
f03fc89f 2441bool wxWindow::SetCursor( const wxCursor &cursor )
86b29a61 2442{
f03fc89f 2443 wxCHECK_MSG( (m_widget != NULL), FALSE, _T("invalid window") );
86b29a61 2444
739730ca 2445 if (!wxWindowBase::SetCursor(cursor))
e55ad60e 2446 {
739730ca
RR
2447 // don't leave if the GTK widget has just
2448 // been realized
2449 if (!m_delayedCursor) return FALSE;
2450 }
2451
2452 GtkWidget *connect_widget = GetConnectWidget();
2453 if (!connect_widget->window)
2454 {
2455 // indicate that a new style has been set
2456 // but it couldn't get applied as the
2457 // widget hasn't been realized yet.
2458 m_delayedCursor = TRUE;
2459
2460 // pretend we have done something
2461 return TRUE;
2462 }
a2053b27 2463
238d735d 2464// gdk_window_set_cursor( connect_widget->window, GetCursor().GetCursor() );
fd0eed64 2465
739730ca
RR
2466 // cursor was set
2467 return TRUE;
362c6693 2468}
c801d85f 2469
85eb36c2 2470void wxWindow::WarpPointer( int x, int y )
4f22cf8d 2471{
85eb36c2
RR
2472 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
2473
2474 GtkWidget *connect_widget = GetConnectWidget();
2475 if (connect_widget->window)
2476 {
2477 /* we provide this function ourselves as it is
2478 missing in GDK */
2479 gdk_window_warp_pointer( connect_widget->window, x, y );
2480 }
4f22cf8d
RR
2481}
2482
debe6624 2483void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
c801d85f 2484{
05939a81 2485 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2486
a2053b27
RR
2487 if (!m_widget->window) return;
2488
139adb6a 2489 if (eraseBackground && m_wxwindow && m_wxwindow->window)
c801d85f 2490 {
139adb6a
RR
2491 if (rect)
2492 {
2493 gdk_window_clear_area( m_wxwindow->window,
2494 rect->x, rect->y,
f234c60c 2495 rect->width, rect->height );
139adb6a
RR
2496 }
2497 else
2498 {
f234c60c 2499 gdk_window_clear( m_wxwindow->window );
139adb6a
RR
2500 }
2501 }
ff8bfdbb 2502
139adb6a
RR
2503 if (!rect)
2504 {
2505 if (m_wxwindow)
2506 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
ff8bfdbb 2507 else
139adb6a 2508 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
362c6693 2509 }
c801d85f 2510 else
139adb6a
RR
2511 {
2512 GdkRectangle gdk_rect;
2513 gdk_rect.x = rect->x;
2514 gdk_rect.y = rect->y;
2515 gdk_rect.width = rect->width;
2516 gdk_rect.height = rect->height;
2517
2518 if (m_wxwindow)
2519 gtk_widget_draw( m_wxwindow, &gdk_rect );
2520 else
2521 gtk_widget_draw( m_widget, &gdk_rect );
2522 }
362c6693 2523}
c801d85f 2524
68dda785 2525void wxWindow::Clear()
c801d85f 2526{
05939a81 2527 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
47d67540 2528
a2053b27
RR
2529 if (!m_widget->window) return;
2530
f234c60c
RR
2531 if (m_wxwindow && m_wxwindow->window)
2532 {
2533 gdk_window_clear( m_wxwindow->window );
2534 }
362c6693 2535}
c801d85f 2536
ff8bfdbb 2537#if wxUSE_TOOLTIPS
f03fc89f 2538void wxWindow::DoSetToolTip( wxToolTip *tip )
b1170810 2539{
f03fc89f 2540 wxWindowBase::DoSetToolTip(tip);
ff8bfdbb 2541
f03fc89f
VZ
2542 if (m_tooltip)
2543 m_tooltip->Apply( this );
b1170810
RR
2544}
2545
05939a81 2546void wxWindow::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
b1170810 2547{
dcf924a3 2548 gtk_tooltips_set_tip( tips, GetConnectWidget(), wxConvCurrent->cWX2MB(tip), (gchar*) NULL );
301cd871 2549}
ff8bfdbb 2550#endif // wxUSE_TOOLTIPS
b1170810 2551
f03fc89f 2552bool wxWindow::SetBackgroundColour( const wxColour &colour )
c801d85f 2553{
f03fc89f 2554 wxCHECK_MSG( m_widget != NULL, FALSE, _T("invalid window") );
8bbe427f 2555
739730ca
RR
2556 if (!wxWindowBase::SetBackgroundColour(colour))
2557 {
2558 // don't leave if the GTK widget has just
2559 // been realized
2560 if (!m_delayedBackgroundColour) return FALSE;
2561 }
2562
a2053b27 2563 GtkWidget *connect_widget = GetConnectWidget();
739730ca
RR
2564 if (!connect_widget->window)
2565 {
2566 // indicate that a new style has been set
2567 // but it couldn't get applied as the
2568 // widget hasn't been realized yet.
2569 m_delayedBackgroundColour = TRUE;
2570
2571 // pretend we have done something
2572 return TRUE;
2573 }
ca298c88 2574
f234c60c 2575 if (m_wxwindow && m_wxwindow->window)
3bc755fc 2576 {
a2053b27
RR
2577 /* wxMSW doesn't clear the window here. I don't do that either to
2578 provide compatibility. call Clear() to do the job. */
ca298c88 2579
f234c60c
RR
2580 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_wxwindow->window ) );
2581 gdk_window_set_background( m_wxwindow->window, m_backgroundColour.GetColor() );
3bc755fc 2582 }
8bbe427f 2583
ae0bdb01 2584 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
121a3581 2585 if (sysbg == m_backgroundColour)
ae0bdb01
RR
2586 {
2587 m_backgroundColour = wxNullColour;
2588 ApplyWidgetStyle();
ff8bfdbb
VZ
2589 m_backgroundColour = sysbg;
2590 }
ae0bdb01
RR
2591 else
2592 {
2593 ApplyWidgetStyle();
2594 }
c801d85f 2595
f03fc89f 2596 return TRUE;
6de97a3b
RR
2597}
2598
f03fc89f 2599bool wxWindow::SetForegroundColour( const wxColour &colour )
6de97a3b 2600{
f03fc89f 2601 wxCHECK_MSG( m_widget != NULL, FALSE, _T("invalid window") );
8bbe427f 2602
739730ca
RR
2603 if (!wxWindowBase::SetForegroundColour(colour))
2604 {
2605 // don't leave if the GTK widget has just
2606 // been realized
2607 if (!m_delayedForegroundColour) return FALSE;
2608 }
2609
a2053b27 2610 GtkWidget *connect_widget = GetConnectWidget();
739730ca
RR
2611 if (!connect_widget->window)
2612 {
2613 // indicate that a new style has been set
2614 // but it couldn't get applied as the
2615 // widget hasn't been realized yet.
2616 m_delayedForegroundColour = TRUE;
2617
2618 // pretend we have done something
2619 return TRUE;
2620 }
2b07d713 2621
ae0bdb01 2622 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2b62ab35 2623 if ( sysbg == m_backgroundColour )
ae0bdb01
RR
2624 {
2625 m_backgroundColour = wxNullColour;
2626 ApplyWidgetStyle();
ff8bfdbb
VZ
2627 m_backgroundColour = sysbg;
2628 }
ae0bdb01
RR
2629 else
2630 {
2631 ApplyWidgetStyle();
2632 }
f03fc89f
VZ
2633
2634 return TRUE;
58614078
RR
2635}
2636
2637GtkStyle *wxWindow::GetWidgetStyle()
2638{
1ecc4d80 2639 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
8bbe427f 2640
f03fc89f 2641 m_widgetStyle = gtk_style_copy( gtk_widget_get_style( m_widget ) );
8bbe427f 2642
1ecc4d80 2643 return m_widgetStyle;
58614078
RR
2644}
2645
2646void wxWindow::SetWidgetStyle()
2647{
1ecc4d80
RR
2648 GtkStyle *style = GetWidgetStyle();
2649
2650 gdk_font_unref( style->font );
2651 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2652
2653 if (m_foregroundColour.Ok())
2654 {
2655 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2656 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2657 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2658 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2659 }
2660
2661 if (m_backgroundColour.Ok())
2662 {
2663 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2664 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2665 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2666 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2667 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2668 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2669 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2670 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2671 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2672 }
a81258be
RR
2673}
2674
58614078 2675void wxWindow::ApplyWidgetStyle()
a81258be 2676{
6de97a3b
RR
2677}
2678
30dea054
RR
2679static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2680{
1ecc4d80 2681 menu->SetInvokingWindow( win );
c626a8b7 2682 wxNode *node = menu->GetItems().First();
1ecc4d80
RR
2683 while (node)
2684 {
2685 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2686 if (menuitem->IsSubMenu())
2687 {
ff8bfdbb
VZ
2688 SetInvokingWindow( menuitem->GetSubMenu(), win );
2689 }
1ecc4d80
RR
2690 node = node->Next();
2691 }
362c6693 2692}
30dea054 2693
0c77152e
RR
2694static gint gs_pop_x = 0;
2695static gint gs_pop_y = 0;
2696
a234a61a
VZ
2697static void pop_pos_callback( GtkMenu * WXUNUSED(menu),
2698 gint *x, gint *y,
2699 wxWindow *win )
0c77152e
RR
2700{
2701 win->ClientToScreen( &gs_pop_x, &gs_pop_y );
2702 *x = gs_pop_x;
2703 *y = gs_pop_y;
2704}
2705
2706bool wxWindow::PopupMenu( wxMenu *menu, int x, int y )
30dea054 2707{
05939a81 2708 wxCHECK_MSG( m_widget != NULL, FALSE, _T("invalid window") );
47d67540 2709
05939a81 2710 wxCHECK_MSG( menu != NULL, FALSE, _T("invalid popup-menu") );
8bbe427f 2711
1ecc4d80 2712 SetInvokingWindow( menu, this );
ff8bfdbb 2713
631f1bfe
JS
2714 menu->UpdateUI();
2715
0c77152e
RR
2716 gs_pop_x = x;
2717 gs_pop_y = y;
ff8bfdbb 2718
1ecc4d80 2719 gtk_menu_popup(
47d67540 2720 GTK_MENU(menu->m_menu),
0c77152e
RR
2721 (GtkWidget *) NULL, // parent menu shell
2722 (GtkWidget *) NULL, // parent menu item
2723 (GtkMenuPositionFunc) pop_pos_callback,
2724 (gpointer) this, // client data
2725 0, // button used to activate it
2726 0 //gs_timeLastClick // the time of activation
47d67540 2727 );
1ecc4d80 2728 return TRUE;
30dea054
RR
2729}
2730
06cfab17 2731#if wxUSE_DRAG_AND_DROP
ac57418f 2732
c801d85f
KB
2733void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2734{
05939a81 2735 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
47d67540 2736
1ecc4d80 2737 GtkWidget *dnd_widget = GetConnectWidget();
47d67540 2738
1ecc4d80 2739 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
47d67540 2740
1ecc4d80
RR
2741 if (m_dropTarget) delete m_dropTarget;
2742 m_dropTarget = dropTarget;
47d67540 2743
1ecc4d80 2744 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
362c6693 2745}
c801d85f 2746
f03fc89f 2747#endif // wxUSE_DRAG_AND_DROP
ac57418f 2748
68dda785 2749GtkWidget* wxWindow::GetConnectWidget()
e3e65dac 2750{
1ecc4d80
RR
2751 GtkWidget *connect_widget = m_widget;
2752 if (m_wxwindow) connect_widget = m_wxwindow;
47d67540 2753
1ecc4d80 2754 return connect_widget;
e3e65dac 2755}
47d67540 2756
903f689b
RR
2757bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2758{
1ecc4d80
RR
2759 if (m_wxwindow) return (window == m_wxwindow->window);
2760 return (window == m_widget->window);
903f689b
RR
2761}
2762
f03fc89f 2763bool wxWindow::SetFont( const wxFont &font )
c801d85f 2764{
a2053b27 2765 wxCHECK_MSG( m_widget != NULL, FALSE, _T( "invalid window") );
c801d85f 2766
739730ca
RR
2767 if (!wxWindowBase::SetFont(font))
2768 {
2769 // don't leave if the GTK widget has just
2770 // been realized
2771 if (!m_delayedFont) return FALSE;
2772 }
121a3581 2773
a2053b27 2774 GtkWidget *connect_widget = GetConnectWidget();
739730ca
RR
2775 if (!connect_widget->window)
2776 {
2777 // indicate that a new style has been set
2778 // but it couldn't get applied as the
2779 // widget hasn't been realized yet.
2780 m_delayedFont = TRUE;
2781
2782 // pretend we have done something
2783 return TRUE;
2784 }
9c288e4d 2785
ae0bdb01 2786 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
f03fc89f 2787 if ( sysbg == m_backgroundColour )
ae0bdb01
RR
2788 {
2789 m_backgroundColour = wxNullColour;
2790 ApplyWidgetStyle();
ff8bfdbb
VZ
2791 m_backgroundColour = sysbg;
2792 }
ae0bdb01
RR
2793 else
2794 {
2795 ApplyWidgetStyle();
2796 }
c801d85f 2797
f03fc89f 2798 return TRUE;
362c6693 2799}
c801d85f 2800
68dda785 2801void wxWindow::CaptureMouse()
c801d85f 2802{
05939a81 2803 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
47d67540 2804
72195a0f 2805 wxCHECK_RET( g_captureWindow == NULL, _T("CaptureMouse called twice") );
47d67540 2806
1ecc4d80 2807 GtkWidget *connect_widget = GetConnectWidget();
a2053b27
RR
2808 if (!connect_widget->window) return;
2809
1ecc4d80
RR
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 2815 (GdkWindow *) NULL,
72195a0f 2816 m_cursor.GetCursor(),
ff8bfdbb 2817 GDK_CURRENT_TIME );
72195a0f 2818 g_captureWindow = this;
362c6693 2819}
c801d85f 2820
68dda785 2821void wxWindow::ReleaseMouse()
c801d85f 2822{
05939a81 2823 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
47d67540 2824
72195a0f 2825 wxCHECK_RET( g_captureWindow, _T("ReleaseMouse called twice") );
47d67540 2826
1ecc4d80 2827 GtkWidget *connect_widget = GetConnectWidget();
a2053b27
RR
2828 if (!connect_widget->window) return;
2829
1ecc4d80 2830 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
72195a0f 2831 g_captureWindow = (wxWindow*) NULL;
362c6693 2832}
c801d85f 2833
f03fc89f 2834bool wxWindow::IsRetained() const
c801d85f 2835{
1ecc4d80 2836 return FALSE;
362c6693 2837}
c801d85f 2838
debe6624 2839void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
cb43b372 2840 int range, bool refresh )
c801d85f 2841{
05939a81 2842 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
8bbe427f 2843
05939a81 2844 wxCHECK_RET( m_wxwindow != NULL, _T("window needs client area for scrolling") );
c801d85f 2845
1ecc4d80 2846 m_hasScrolling = TRUE;
47d67540 2847
1ecc4d80 2848 if (orient == wxHORIZONTAL)
cb43b372 2849 {
1ecc4d80
RR
2850 float fpos = (float)pos;
2851 float frange = (float)range;
2852 float fthumb = (float)thumbVisible;
2853 if (fpos > frange-fthumb) fpos = frange-fthumb;
2854 if (fpos < 0.0) fpos = 0.0;
2855
2856 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
2857 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
2858 {
2859 SetScrollPos( orient, pos, refresh );
2860 return;
2861 }
47d67540 2862
1ecc4d80 2863 m_oldHorizontalPos = fpos;
47d67540 2864
1ecc4d80
RR
2865 m_hAdjust->lower = 0.0;
2866 m_hAdjust->upper = frange;
2867 m_hAdjust->value = fpos;
2868 m_hAdjust->step_increment = 1.0;
2869 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
2870 m_hAdjust->page_size = fthumb;
cb43b372 2871 }
1ecc4d80
RR
2872 else
2873 {
2874 float fpos = (float)pos;
2875 float frange = (float)range;
2876 float fthumb = (float)thumbVisible;
2877 if (fpos > frange-fthumb) fpos = frange-fthumb;
2878 if (fpos < 0.0) fpos = 0.0;
2879
2880 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
2881 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
2882 {
2883 SetScrollPos( orient, pos, refresh );
2884 return;
2885 }
47d67540 2886
1ecc4d80 2887 m_oldVerticalPos = fpos;
47d67540 2888
1ecc4d80
RR
2889 m_vAdjust->lower = 0.0;
2890 m_vAdjust->upper = frange;
2891 m_vAdjust->value = fpos;
2892 m_vAdjust->step_increment = 1.0;
2893 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
2894 m_vAdjust->page_size = fthumb;
2895 }
47d67540 2896
eb082a08
RR
2897 if (orient == wxHORIZONTAL)
2898 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
2899 else
2900 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
362c6693 2901}
c801d85f 2902
debe6624 2903void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
c801d85f 2904{
05939a81 2905 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
1ecc4d80 2906
05939a81 2907 wxCHECK_RET( m_wxwindow != NULL, _T("window needs client area for scrolling") );
1ecc4d80
RR
2908
2909 if (orient == wxHORIZONTAL)
2910 {
2911 float fpos = (float)pos;
2912 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
2913 if (fpos < 0.0) fpos = 0.0;
2914 m_oldHorizontalPos = fpos;
2915
2916 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
2917 m_hAdjust->value = fpos;
2918 }
2919 else
2920 {
2921 float fpos = (float)pos;
2922 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
2923 if (fpos < 0.0) fpos = 0.0;
2924 m_oldVerticalPos = fpos;
ff8bfdbb 2925
1ecc4d80
RR
2926 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
2927 m_vAdjust->value = fpos;
2928 }
47d67540 2929
eb082a08 2930 if (!m_isScrolling) /* prevent recursion */
47d67540 2931 {
1ecc4d80
RR
2932 if (m_wxwindow->window)
2933 {
2934 if (orient == wxHORIZONTAL)
2935 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2936 else
2937 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
2938 }
cb43b372 2939 }
362c6693 2940}
c801d85f 2941
debe6624 2942int wxWindow::GetScrollThumb( int orient ) const
c801d85f 2943{
05939a81 2944 wxCHECK_MSG( m_widget != NULL, 0, _T("invalid window") );
47d67540 2945
05939a81 2946 wxCHECK_MSG( m_wxwindow != NULL, 0, _T("window needs client area for scrolling") );
47d67540 2947
1ecc4d80
RR
2948 if (orient == wxHORIZONTAL)
2949 return (int)(m_hAdjust->page_size+0.5);
2950 else
2951 return (int)(m_vAdjust->page_size+0.5);
362c6693 2952}
c801d85f 2953
debe6624 2954int wxWindow::GetScrollPos( int orient ) const
c801d85f 2955{
05939a81 2956 wxCHECK_MSG( m_widget != NULL, 0, _T("invalid window") );
47d67540 2957
05939a81 2958 wxCHECK_MSG( m_wxwindow != NULL, 0, _T("window needs client area for scrolling") );
c801d85f 2959
1ecc4d80
RR
2960 if (orient == wxHORIZONTAL)
2961 return (int)(m_hAdjust->value+0.5);
2962 else
2963 return (int)(m_vAdjust->value+0.5);
362c6693 2964}
c801d85f 2965
debe6624 2966int wxWindow::GetScrollRange( int orient ) const
c801d85f 2967{
05939a81 2968 wxCHECK_MSG( m_widget != NULL, 0, _T("invalid window") );
47d67540 2969
05939a81 2970 wxCHECK_MSG( m_wxwindow != NULL, 0, _T("window needs client area for scrolling") );
c801d85f 2971
1ecc4d80
RR
2972 if (orient == wxHORIZONTAL)
2973 return (int)(m_hAdjust->upper+0.5);
2974 else
2975 return (int)(m_vAdjust->upper+0.5);
362c6693 2976}
c801d85f 2977
debe6624 2978void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
c801d85f 2979{
05939a81 2980 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
47d67540 2981
05939a81 2982 wxCHECK_RET( m_wxwindow != NULL, _T("window needs client area for scrolling") );
c801d85f 2983
a2053b27 2984 if (!m_scrollGC)
96d5ab4d 2985 {
a2053b27
RR
2986 m_scrollGC = gdk_gc_new( m_wxwindow->window );
2987 gdk_gc_set_exposures( m_scrollGC, TRUE );
96d5ab4d 2988 }
ea5c6ca7
RR
2989
2990 wxNode *node = m_children.First();
2991 while (node)
2992 {
2993 wxWindow *child = (wxWindow*) node->Data();
85ad5eb5
RR
2994 int sx = 0;
2995 int sy = 0;
2996 child->GetSize( &sx, &sy );
2997 child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
ea5c6ca7
RR
2998 node = node->Next();
2999 }
96d5ab4d 3000
c801d85f
KB
3001 int cw = 0;
3002 int ch = 0;
3003 GetClientSize( &cw, &ch );
c801d85f
KB
3004 int w = cw - abs(dx);
3005 int h = ch - abs(dy);
a2053b27 3006
c801d85f
KB
3007 if ((h < 0) || (w < 0))
3008 {
1ecc4d80 3009 Refresh();
362c6693 3010 }
a2053b27 3011 else
c801d85f 3012 {
a2053b27
RR
3013 int s_x = 0;
3014 int s_y = 0;
3015 if (dx < 0) s_x = -dx;
3016 if (dy < 0) s_y = -dy;
3017 int d_x = 0;
3018 int d_y = 0;
3019 if (dx > 0) d_x = dx;
3020 if (dy > 0) d_y = dy;
c801d85f 3021
a2053b27
RR
3022 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3023 m_wxwindow->window, s_x, s_y, w, h );
c801d85f 3024
a2053b27
RR
3025 wxRect rect;
3026 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3027 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3028 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3029 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
c801d85f 3030
a2053b27
RR
3031 Refresh( TRUE, &rect );
3032 }
c801d85f
KB
3033}
3034
f03fc89f 3035void wxWindow::SetScrolling(bool scroll)
c801d85f 3036{
f03fc89f 3037 m_isScrolling = g_blockEventsOnScroll = scroll;
c801d85f 3038}