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