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