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