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