]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/window.cpp
Minor Reparent() and SetToolBar() fix for wxFrame.
[wxWidgets.git] / src / gtk / window.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: window.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10
11 #ifdef __GNUG__
12 #pragma implementation "window.h"
13 #endif
14
15 #include "wx/defs.h"
16 #include "wx/window.h"
17 #include "wx/dc.h"
18 #include "wx/frame.h"
19 #include "wx/app.h"
20 #include "wx/layout.h"
21 #include "wx/utils.h"
22 #include "wx/dialog.h"
23 #include "wx/msgdlg.h"
24
25 #if wxUSE_DRAG_AND_DROP
26 #include "wx/dnd.h"
27 #endif
28
29 #if wxUSE_TOOLTIPS
30 #include "wx/tooltip.h"
31 #endif
32
33 #include "wx/menu.h"
34 #include "wx/statusbr.h"
35 #include "wx/intl.h"
36 #include "wx/settings.h"
37 #include "wx/log.h"
38
39 #include <math.h>
40
41 #include "gdk/gdk.h"
42 #include "gtk/gtk.h"
43 #include "gdk/gdkprivate.h"
44 #include "gdk/gdkkeysyms.h"
45 #include "wx/gtk/win_gtk.h"
46
47 #include "gdk/gdkx.h"
48
49 //-----------------------------------------------------------------------------
50 // documentation on internals
51 //-----------------------------------------------------------------------------
52
53 /*
54 I have been asked several times about writing some documentation about
55 the GTK port of wxWindows, especially its internal structures. Obviously,
56 you cannot understand wxGTK without knowing a little about the GTK, but
57 some more information about what the wxWindow, which is the base class
58 for all other window classes, does seems required as well.
59
60 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 /*
1065 wxPrintf( wxT("2) OnButtonPress from ") );
1066 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1067 wxPrintf( win->GetClassInfo()->GetClassName() );
1068 wxPrintf( wxT(".\n") );
1069 */
1070
1071 wxEventType event_type = wxEVT_LEFT_DOWN;
1072
1073 if (gdk_event->button == 1)
1074 {
1075 switch (gdk_event->type)
1076 {
1077 case GDK_BUTTON_PRESS: event_type = wxEVT_LEFT_DOWN; break;
1078 case GDK_2BUTTON_PRESS: event_type = wxEVT_LEFT_DCLICK; break;
1079 default: break;
1080 }
1081 }
1082 else if (gdk_event->button == 2)
1083 {
1084 switch (gdk_event->type)
1085 {
1086 case GDK_BUTTON_PRESS: event_type = wxEVT_MIDDLE_DOWN; break;
1087 case GDK_2BUTTON_PRESS: event_type = wxEVT_MIDDLE_DCLICK; break;
1088 default: break;
1089 }
1090 }
1091 else if (gdk_event->button == 3)
1092 {
1093 switch (gdk_event->type)
1094 {
1095 case GDK_BUTTON_PRESS: event_type = wxEVT_RIGHT_DOWN; break;
1096 case GDK_2BUTTON_PRESS: event_type = wxEVT_RIGHT_DCLICK; break;
1097 default: break;
1098 }
1099 }
1100
1101 wxMouseEvent event( event_type );
1102 event.SetTimestamp( gdk_event->time );
1103 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1104 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1105 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1106 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1107 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1108 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1109 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
1110
1111 event.m_x = (long)gdk_event->x;
1112 event.m_y = (long)gdk_event->y;
1113
1114 // Some control don't have their own X window and thus cannot get
1115 // any events.
1116
1117 if (!g_captureWindow)
1118 {
1119 wxNode *node = win->GetChildren().First();
1120 while (node)
1121 {
1122 wxWindow *child = (wxWindow*)node->Data();
1123
1124 if (child->m_isStaticBox)
1125 {
1126 // wxStaticBox is transparent in the box itself
1127 int x = event.m_x;
1128 int y = event.m_y;
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 <= event.m_x) &&
1154 (child->m_y <= event.m_y) &&
1155 (child->m_x+child->m_width >= event.m_x) &&
1156 (child->m_y+child->m_height >= event.m_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 if (win->GetEventHandler()->ProcessEvent( event ))
1173 {
1174 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
1175 return TRUE;
1176 }
1177
1178 return FALSE;
1179 }
1180
1181 //-----------------------------------------------------------------------------
1182 // "button_release_event"
1183 //-----------------------------------------------------------------------------
1184
1185 static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
1186 {
1187 if (g_isIdle)
1188 wxapp_install_idle_handler();
1189
1190 if (!win->m_hasVMT) return FALSE;
1191 if (g_blockEventsOnDrag) return FALSE;
1192 if (g_blockEventsOnScroll) return FALSE;
1193
1194 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1195
1196 /*
1197 printf( "OnButtonRelease from " );
1198 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1199 printf( win->GetClassInfo()->GetClassName() );
1200 printf( ".\n" );
1201 */
1202
1203 wxEventType event_type = wxEVT_NULL;
1204
1205 switch (gdk_event->button)
1206 {
1207 case 1: event_type = wxEVT_LEFT_UP; break;
1208 case 2: event_type = wxEVT_MIDDLE_UP; break;
1209 case 3: event_type = wxEVT_RIGHT_UP; break;
1210 }
1211
1212 wxMouseEvent event( event_type );
1213 event.SetTimestamp( gdk_event->time );
1214 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1215 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1216 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1217 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1218 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1219 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1220 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
1221 event.m_x = (long)gdk_event->x;
1222 event.m_y = (long)gdk_event->y;
1223
1224 // Some control don't have their own X window and thus cannot get
1225 // any events.
1226
1227 if (!g_captureWindow)
1228 {
1229 wxNode *node = win->GetChildren().First();
1230 while (node)
1231 {
1232 wxWindow *child = (wxWindow*)node->Data();
1233
1234 if (child->m_isStaticBox)
1235 {
1236 // wxStaticBox is transparent in the box itself
1237 int x = event.m_x;
1238 int y = event.m_y;
1239 int xx1 = child->m_x;
1240 int yy1 = child->m_y;
1241 int xx2 = child->m_x + child->m_width;
1242 int yy2 = child->m_x + child->m_height;
1243
1244 // left
1245 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1246 // right
1247 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1248 // top
1249 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1250 // bottom
1251 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1252 {
1253 win = child;
1254 event.m_x -= child->m_x;
1255 event.m_y -= child->m_y;
1256 break;
1257 }
1258
1259 }
1260 else
1261 {
1262 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
1263 (child->m_x <= event.m_x) &&
1264 (child->m_y <= event.m_y) &&
1265 (child->m_x+child->m_width >= event.m_x) &&
1266 (child->m_y+child->m_height >= event.m_y))
1267 {
1268 win = child;
1269 event.m_x -= child->m_x;
1270 event.m_y -= child->m_y;
1271 break;
1272 }
1273 }
1274 node = node->Next();
1275 }
1276 }
1277
1278 event.SetEventObject( win );
1279
1280 if (win->GetEventHandler()->ProcessEvent( event ))
1281 {
1282 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" );
1283 return TRUE;
1284 }
1285
1286 return FALSE;
1287 }
1288
1289 //-----------------------------------------------------------------------------
1290 // "motion_notify_event"
1291 //-----------------------------------------------------------------------------
1292
1293 static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
1294 {
1295 if (g_isIdle)
1296 wxapp_install_idle_handler();
1297
1298 if (!win->m_hasVMT) return FALSE;
1299 if (g_blockEventsOnDrag) return FALSE;
1300 if (g_blockEventsOnScroll) return FALSE;
1301
1302 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1303
1304 if (gdk_event->is_hint)
1305 {
1306 int x = 0;
1307 int y = 0;
1308 GdkModifierType state;
1309 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
1310 gdk_event->x = x;
1311 gdk_event->y = y;
1312 }
1313
1314 /*
1315 printf( "OnMotion from " );
1316 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1317 printf( win->GetClassInfo()->GetClassName() );
1318 printf( ".\n" );
1319 */
1320
1321 wxMouseEvent event( wxEVT_MOTION );
1322 event.SetTimestamp( gdk_event->time );
1323 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1324 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1325 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1326 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1327 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1328 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1329 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
1330
1331 event.m_x = (long)gdk_event->x;
1332 event.m_y = (long)gdk_event->y;
1333
1334 // Some control don't have their own X window and thus cannot get
1335 // any events.
1336
1337 if (!g_captureWindow)
1338 {
1339 wxNode *node = win->GetChildren().First();
1340 while (node)
1341 {
1342 wxWindow *child = (wxWindow*)node->Data();
1343
1344 if (child->m_isStaticBox)
1345 {
1346 // wxStaticBox is transparent in the box itself
1347 int x = event.m_x;
1348 int y = event.m_y;
1349 int xx1 = child->m_x;
1350 int yy1 = child->m_y;
1351 int xx2 = child->m_x + child->m_width;
1352 int yy2 = child->m_x + child->m_height;
1353
1354 // left
1355 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1356 // right
1357 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1358 // top
1359 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1360 // bottom
1361 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1362 {
1363 win = child;
1364 event.m_x -= child->m_x;
1365 event.m_y -= child->m_y;
1366 break;
1367 }
1368
1369 }
1370 else
1371 {
1372 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
1373 (child->m_x <= event.m_x) &&
1374 (child->m_y <= event.m_y) &&
1375 (child->m_x+child->m_width >= event.m_x) &&
1376 (child->m_y+child->m_height >= event.m_y))
1377 {
1378 win = child;
1379 event.m_x -= child->m_x;
1380 event.m_y -= child->m_y;
1381 break;
1382 }
1383 }
1384 node = node->Next();
1385 }
1386 }
1387
1388 event.SetEventObject( win );
1389
1390 if (win->GetEventHandler()->ProcessEvent( event ))
1391 {
1392 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
1393 return TRUE;
1394 }
1395
1396 return FALSE;
1397 }
1398
1399 //-----------------------------------------------------------------------------
1400 // "focus_in_event"
1401 //-----------------------------------------------------------------------------
1402
1403 static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
1404 {
1405 if (g_isIdle)
1406 wxapp_install_idle_handler();
1407
1408 if (!win->m_hasVMT) return FALSE;
1409 if (g_blockEventsOnDrag) return FALSE;
1410
1411 g_focusWindow = win;
1412
1413 if (win->m_wxwindow)
1414 {
1415 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
1416 {
1417 GTK_WIDGET_SET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
1418 /*
1419 printf( "SetFocus flag from " );
1420 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1421 printf( win->GetClassInfo()->GetClassName() );
1422 printf( ".\n" );
1423 */
1424 }
1425 }
1426
1427
1428 /*
1429 printf( "OnSetFocus from " );
1430 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1431 printf( win->GetClassInfo()->GetClassName() );
1432 printf( " " );
1433 printf( WXSTRINGCAST win->GetLabel() );
1434 printf( ".\n" );
1435 */
1436
1437 wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
1438 event.SetEventObject( win );
1439
1440 if (win->GetEventHandler()->ProcessEvent( event ))
1441 {
1442 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
1443 return TRUE;
1444 }
1445
1446 return FALSE;
1447 }
1448
1449 //-----------------------------------------------------------------------------
1450 // "focus_out_event"
1451 //-----------------------------------------------------------------------------
1452
1453 static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
1454 {
1455 if (g_isIdle)
1456 wxapp_install_idle_handler();
1457
1458 if (!win->m_hasVMT) return FALSE;
1459 if (g_blockEventsOnDrag) return FALSE;
1460
1461 if (win->m_wxwindow)
1462 {
1463 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
1464 GTK_WIDGET_UNSET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
1465 }
1466
1467 /*
1468 printf( "OnKillFocus from " );
1469 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1470 printf( win->GetClassInfo()->GetClassName() );
1471 printf( ".\n" );
1472 */
1473
1474 wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
1475 event.SetEventObject( win );
1476
1477 if (win->GetEventHandler()->ProcessEvent( event ))
1478 {
1479 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
1480 return TRUE;
1481 }
1482
1483 return FALSE;
1484 }
1485
1486 //-----------------------------------------------------------------------------
1487 // "enter_notify_event"
1488 //-----------------------------------------------------------------------------
1489
1490 static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1491 {
1492 if (g_isIdle)
1493 wxapp_install_idle_handler();
1494
1495 if (!win->m_hasVMT) return FALSE;
1496 if (g_blockEventsOnDrag) return FALSE;
1497
1498 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1499
1500 wxMouseEvent event( wxEVT_ENTER_WINDOW );
1501 #if (GTK_MINOR_VERSION > 0)
1502 event.SetTimestamp( gdk_event->time );
1503 #endif
1504 event.SetEventObject( win );
1505
1506 int x = 0;
1507 int y = 0;
1508 GdkModifierType state = (GdkModifierType)0;
1509
1510 gdk_window_get_pointer( widget->window, &x, &y, &state );
1511
1512 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1513 event.m_controlDown = (state & GDK_CONTROL_MASK);
1514 event.m_altDown = (state & GDK_MOD1_MASK);
1515 event.m_metaDown = (state & GDK_MOD2_MASK);
1516 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1517 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1518 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1519
1520 event.m_x = (long)x;
1521 event.m_y = (long)y;
1522
1523 if (win->GetEventHandler()->ProcessEvent( event ))
1524 {
1525 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "enter_notify_event" );
1526 return TRUE;
1527 }
1528
1529 return FALSE;
1530 }
1531
1532 //-----------------------------------------------------------------------------
1533 // "leave_notify_event"
1534 //-----------------------------------------------------------------------------
1535
1536 static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1537 {
1538 if (g_isIdle)
1539 wxapp_install_idle_handler();
1540
1541 if (!win->m_hasVMT) return FALSE;
1542 if (g_blockEventsOnDrag) return FALSE;
1543
1544 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1545
1546 wxMouseEvent event( wxEVT_LEAVE_WINDOW );
1547 #if (GTK_MINOR_VERSION > 0)
1548 event.SetTimestamp( gdk_event->time );
1549 #endif
1550 event.SetEventObject( win );
1551
1552 int x = 0;
1553 int y = 0;
1554 GdkModifierType state = (GdkModifierType)0;
1555
1556 gdk_window_get_pointer( widget->window, &x, &y, &state );
1557
1558 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1559 event.m_controlDown = (state & GDK_CONTROL_MASK);
1560 event.m_altDown = (state & GDK_MOD1_MASK);
1561 event.m_metaDown = (state & GDK_MOD2_MASK);
1562 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1563 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1564 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1565
1566 event.m_x = (long)x;
1567 event.m_y = (long)y;
1568
1569 if (win->GetEventHandler()->ProcessEvent( event ))
1570 {
1571 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "leave_notify_event" );
1572 return TRUE;
1573 }
1574
1575 return FALSE;
1576 }
1577
1578 //-----------------------------------------------------------------------------
1579 // "value_changed" from m_vAdjust
1580 //-----------------------------------------------------------------------------
1581
1582 static void gtk_window_vscroll_callback( GtkAdjustment *adjust, wxWindow *win )
1583 {
1584 if (g_isIdle)
1585 wxapp_install_idle_handler();
1586
1587 if (g_blockEventsOnDrag) return;
1588
1589 if (!win->m_hasVMT) return;
1590
1591 float diff = adjust->value - win->m_oldVerticalPos;
1592 if (fabs(diff) < 0.2) return;
1593
1594 win->m_oldVerticalPos = adjust->value;
1595
1596 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
1597 GtkRange *range = GTK_RANGE( scrolledWindow->vscrollbar );
1598
1599 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
1600 if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP;
1601 else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN;
1602 else if (range->scroll_type == GTK_SCROLL_PAGE_BACKWARD) command = wxEVT_SCROLLWIN_PAGEUP;
1603 else if (range->scroll_type == GTK_SCROLL_PAGE_FORWARD) command = wxEVT_SCROLLWIN_PAGEDOWN;
1604
1605 int value = (int)(adjust->value+0.5);
1606
1607 wxScrollWinEvent event( command, value, wxVERTICAL );
1608 event.SetEventObject( win );
1609 win->GetEventHandler()->ProcessEvent( event );
1610 }
1611
1612 //-----------------------------------------------------------------------------
1613 // "value_changed" from m_hAdjust
1614 //-----------------------------------------------------------------------------
1615
1616 static void gtk_window_hscroll_callback( GtkAdjustment *adjust, wxWindow *win )
1617 {
1618 if (g_isIdle)
1619 wxapp_install_idle_handler();
1620
1621 if (g_blockEventsOnDrag) return;
1622 if (!win->m_hasVMT) return;
1623
1624 float diff = adjust->value - win->m_oldHorizontalPos;
1625 if (fabs(diff) < 0.2) return;
1626
1627 win->m_oldHorizontalPos = adjust->value;
1628
1629 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
1630 GtkRange *range = GTK_RANGE( scrolledWindow->hscrollbar );
1631
1632 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
1633 if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP;
1634 else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN;
1635 else if (range->scroll_type == GTK_SCROLL_PAGE_BACKWARD) command = wxEVT_SCROLLWIN_PAGEUP;
1636 else if (range->scroll_type == GTK_SCROLL_PAGE_FORWARD) command = wxEVT_SCROLLWIN_PAGEDOWN;
1637
1638 int value = (int)(adjust->value+0.5);
1639
1640 wxScrollWinEvent event( command, value, wxHORIZONTAL );
1641 event.SetEventObject( win );
1642 win->GetEventHandler()->ProcessEvent( event );
1643 }
1644
1645 //-----------------------------------------------------------------------------
1646 // "changed" from m_vAdjust
1647 //-----------------------------------------------------------------------------
1648
1649 static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
1650 {
1651 if (g_isIdle)
1652 wxapp_install_idle_handler();
1653
1654 if (g_blockEventsOnDrag) return;
1655 if (!win->m_hasVMT) return;
1656
1657 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
1658 int value = (int)(win->m_vAdjust->value+0.5);
1659
1660 wxScrollWinEvent event( command, value, wxVERTICAL );
1661 event.SetEventObject( win );
1662 win->GetEventHandler()->ProcessEvent( event );
1663 }
1664
1665 //-----------------------------------------------------------------------------
1666 // "changed" from m_hAdjust
1667 //-----------------------------------------------------------------------------
1668
1669 static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
1670 {
1671 if (g_isIdle)
1672 wxapp_install_idle_handler();
1673
1674 if (g_blockEventsOnDrag) return;
1675 if (!win->m_hasVMT) return;
1676
1677 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
1678 int value = (int)(win->m_hAdjust->value+0.5);
1679
1680 wxScrollWinEvent event( command, value, wxHORIZONTAL );
1681 event.SetEventObject( win );
1682 win->GetEventHandler()->ProcessEvent( event );
1683 }
1684
1685 //-----------------------------------------------------------------------------
1686 // "button_press_event" from scrollbar
1687 //-----------------------------------------------------------------------------
1688
1689 static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
1690 GdkEventButton *WXUNUSED(gdk_event),
1691 wxWindow *win )
1692 {
1693 if (g_isIdle)
1694 wxapp_install_idle_handler();
1695
1696 // don't test here as we can release the mouse while being over
1697 // a different window than the slider
1698 //
1699 // if (gdk_event->window != widget->slider) return FALSE;
1700
1701 win->SetScrolling( TRUE );
1702
1703 return FALSE;
1704 }
1705
1706 //-----------------------------------------------------------------------------
1707 // "button_release_event" from scrollbar
1708 //-----------------------------------------------------------------------------
1709
1710 static gint gtk_scrollbar_button_release_callback( GtkRange *WXUNUSED(widget),
1711 GdkEventButton *WXUNUSED(gdk_event),
1712 wxWindow *win )
1713 {
1714
1715 // don't test here as we can release the mouse while being over
1716 // a different window than the slider
1717 //
1718 // if (gdk_event->window != widget->slider) return FALSE;
1719
1720 win->SetScrolling( FALSE );
1721
1722 return FALSE;
1723 }
1724
1725 // ----------------------------------------------------------------------------
1726 // this wxWindowBase function is implemented here (in platform-specific file)
1727 // because it is static and so couldn't be made virtual
1728 // ----------------------------------------------------------------------------
1729
1730 wxWindow *wxWindowBase::FindFocus()
1731 {
1732 return g_focusWindow;
1733 }
1734
1735 //-----------------------------------------------------------------------------
1736 // "realize" from m_widget
1737 //-----------------------------------------------------------------------------
1738
1739 /* we cannot set colours and fonts before the widget has
1740 been realized, so we do this directly after realization */
1741
1742 static gint
1743 gtk_window_realized_callback( GtkWidget * WXUNUSED(widget), wxWindow *win )
1744 {
1745 if (g_isIdle)
1746 wxapp_install_idle_handler();
1747
1748 if (win->m_delayedFont)
1749 win->SetFont( win->GetFont() );
1750
1751 if (win->m_delayedBackgroundColour)
1752 win->SetBackgroundColour( win->GetBackgroundColour() );
1753
1754 if (win->m_delayedForegroundColour)
1755 win->SetForegroundColour( win->GetForegroundColour() );
1756
1757 wxWindowCreateEvent event( win );
1758 event.SetEventObject( win );
1759 win->GetEventHandler()->ProcessEvent( event );
1760
1761 return FALSE;
1762 }
1763
1764 //-----------------------------------------------------------------------------
1765 // InsertChild for wxWindow.
1766 //-----------------------------------------------------------------------------
1767
1768 /* Callback for wxWindow. This very strange beast has to be used because
1769 * C++ has no virtual methods in a constructor. We have to emulate a
1770 * virtual function here as wxNotebook requires a different way to insert
1771 * a child in it. I had opted for creating a wxNotebookPage window class
1772 * which would have made this superfluous (such in the MDI window system),
1773 * but no-one was listening to me... */
1774
1775 static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
1776 {
1777 /* the window might have been scrolled already, do we
1778 have to adapt the position */
1779 GtkMyFixed *myfixed = GTK_MYFIXED(parent->m_wxwindow);
1780 child->m_x += myfixed->xoffset;
1781 child->m_y += myfixed->yoffset;
1782
1783 gtk_myfixed_put( GTK_MYFIXED(parent->m_wxwindow),
1784 GTK_WIDGET(child->m_widget),
1785 child->m_x,
1786 child->m_y,
1787 child->m_width,
1788 child->m_height );
1789
1790 if (parent->HasFlag(wxTAB_TRAVERSAL))
1791 {
1792 /* we now allow a window to get the focus as long as it
1793 doesn't have any children. */
1794 GTK_WIDGET_UNSET_FLAGS( parent->m_wxwindow, GTK_CAN_FOCUS );
1795 }
1796 }
1797
1798 //-----------------------------------------------------------------------------
1799 // global functions
1800 //-----------------------------------------------------------------------------
1801
1802 wxWindow* wxGetActiveWindow()
1803 {
1804 return g_focusWindow;
1805 }
1806
1807 //-----------------------------------------------------------------------------
1808 // wxWindow
1809 //-----------------------------------------------------------------------------
1810
1811 IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
1812
1813 void wxWindow::Init()
1814 {
1815 // common init
1816 InitBase();
1817
1818 // GTK specific
1819 m_widget = (GtkWidget *) NULL;
1820 m_wxwindow = (GtkWidget *) NULL;
1821
1822 // position/size
1823 m_x = 0;
1824 m_y = 0;
1825 m_width = 0;
1826 m_height = 0;
1827
1828 m_sizeSet = FALSE;
1829 m_hasVMT = FALSE;
1830 m_needParent = TRUE;
1831 m_isBeingDeleted = FALSE;
1832
1833 m_noExpose = FALSE;
1834 m_nativeSizeEvent = FALSE;
1835
1836 m_hasScrolling = FALSE;
1837 m_isScrolling = FALSE;
1838
1839 m_hAdjust = (GtkAdjustment*) NULL;
1840 m_vAdjust = (GtkAdjustment*) NULL;
1841 m_oldHorizontalPos = 0.0;
1842 m_oldVerticalPos = 0.0;
1843
1844 m_resizing = FALSE;
1845 m_widgetStyle = (GtkStyle*) NULL;
1846
1847 m_insertCallback = (wxInsertChildFunction) NULL;
1848
1849 m_isStaticBox = FALSE;
1850 m_isRadioButton = FALSE;
1851 m_isFrame = FALSE;
1852 m_acceptsFocus = FALSE;
1853
1854 m_cursor = *wxSTANDARD_CURSOR;
1855 }
1856
1857 wxWindow::wxWindow()
1858 {
1859 Init();
1860 }
1861
1862 wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
1863 const wxPoint &pos, const wxSize &size,
1864 long style, const wxString &name )
1865 {
1866 Init();
1867
1868 Create( parent, id, pos, size, style, name );
1869 }
1870
1871 bool wxWindow::Create( wxWindow *parent, wxWindowID id,
1872 const wxPoint &pos, const wxSize &size,
1873 long style, const wxString &name )
1874 {
1875 if (!PreCreation( parent, pos, size ) ||
1876 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
1877 {
1878 wxFAIL_MSG( wxT("wxWindow creation failed") );
1879 return FALSE;
1880 }
1881
1882 m_insertCallback = wxInsertChildInWindow;
1883
1884 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
1885 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
1886
1887 #ifdef __WXDEBUG__
1888 debug_focus_in( m_widget, wxT("wxWindow::m_widget"), name );
1889 #endif
1890
1891 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
1892
1893 #ifdef __WXDEBUG__
1894 debug_focus_in( scrolledWindow->hscrollbar, wxT("wxWindow::hsrcollbar"), name );
1895 debug_focus_in( scrolledWindow->vscrollbar, wxT("wxWindow::vsrcollbar"), name );
1896 #endif
1897
1898 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1899 scroll_class->scrollbar_spacing = 0;
1900
1901 gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
1902
1903 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->hscrollbar) );
1904 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->vscrollbar) );
1905
1906 m_wxwindow = gtk_myfixed_new();
1907
1908 #ifdef __WXDEBUG__
1909 debug_focus_in( m_wxwindow, wxT("wxWindow::m_wxwindow"), name );
1910 #endif
1911
1912 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
1913
1914 #if (GTK_MINOR_VERSION > 0)
1915 GtkMyFixed *myfixed = GTK_MYFIXED(m_wxwindow);
1916
1917 if (HasFlag(wxRAISED_BORDER))
1918 {
1919 gtk_myfixed_set_shadow_type( myfixed, GTK_MYSHADOW_OUT );
1920 }
1921 else if (HasFlag(wxSUNKEN_BORDER))
1922 {
1923 gtk_myfixed_set_shadow_type( myfixed, GTK_MYSHADOW_IN );
1924 }
1925 else if (HasFlag(wxSIMPLE_BORDER))
1926 {
1927 gtk_myfixed_set_shadow_type( myfixed, GTK_MYSHADOW_THIN );
1928 }
1929 else
1930 {
1931 gtk_myfixed_set_shadow_type( myfixed, GTK_MYSHADOW_NONE );
1932 }
1933 #else // GTK_MINOR_VERSION == 0
1934 GtkViewport *viewport = GTK_VIEWPORT(scrolledWindow->viewport);
1935
1936 if (HasFlag(wxRAISED_BORDER))
1937 {
1938 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
1939 }
1940 else if (HasFlag(wxSUNKEN_BORDER))
1941 {
1942 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
1943 }
1944 else
1945 {
1946 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
1947 }
1948 #endif // GTK_MINOR_VERSION
1949
1950 if (HasFlag(wxTAB_TRAVERSAL))
1951 {
1952 /* we now allow a window to get the focus as long as it
1953 doesn't have any children. */
1954 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
1955 m_acceptsFocus = FALSE;
1956 }
1957 else
1958 {
1959 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
1960 m_acceptsFocus = TRUE;
1961 }
1962
1963 #if (GTK_MINOR_VERSION == 0)
1964 // shut the viewport up
1965 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1966 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1967 #endif // GTK_MINOR_VERSION == 0
1968
1969 // I _really_ don't want scrollbars in the beginning
1970 m_vAdjust->lower = 0.0;
1971 m_vAdjust->upper = 1.0;
1972 m_vAdjust->value = 0.0;
1973 m_vAdjust->step_increment = 1.0;
1974 m_vAdjust->page_increment = 1.0;
1975 m_vAdjust->page_size = 5.0;
1976 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1977 m_hAdjust->lower = 0.0;
1978 m_hAdjust->upper = 1.0;
1979 m_hAdjust->value = 0.0;
1980 m_hAdjust->step_increment = 1.0;
1981 m_hAdjust->page_increment = 1.0;
1982 m_hAdjust->page_size = 5.0;
1983 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
1984
1985 // these handlers block mouse events to any window during scrolling such as
1986 // motion events and prevent GTK and wxWindows from fighting over where the
1987 // slider should be
1988
1989 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_press_event",
1990 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1991
1992 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_press_event",
1993 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1994
1995 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_release_event",
1996 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1997
1998 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_release_event",
1999 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
2000
2001 // these handlers get notified when screen updates are required either when
2002 // scrolling or when the window size (and therefore scrollbar configuration)
2003 // has changed
2004
2005 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
2006 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
2007 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
2008 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
2009
2010 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
2011 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
2012 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
2013 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
2014
2015 gtk_widget_show( m_wxwindow );
2016
2017 if (m_parent)
2018 m_parent->DoAddChild( this );
2019
2020 PostCreation();
2021
2022 Show( TRUE );
2023
2024 return TRUE;
2025 }
2026
2027 wxWindow::~wxWindow()
2028 {
2029 m_isBeingDeleted = TRUE;
2030 m_hasVMT = FALSE;
2031
2032 if (m_widget)
2033 Show( FALSE );
2034
2035 DestroyChildren();
2036
2037 if (m_parent)
2038 m_parent->RemoveChild( this );
2039
2040 if (m_widgetStyle)
2041 {
2042 gtk_style_unref( m_widgetStyle );
2043 m_widgetStyle = (GtkStyle*) NULL;
2044 }
2045
2046 if (m_wxwindow)
2047 {
2048 gtk_widget_destroy( m_wxwindow );
2049 m_wxwindow = (GtkWidget*) NULL;
2050 }
2051
2052 if (m_widget)
2053 {
2054 gtk_widget_destroy( m_widget );
2055 m_widget = (GtkWidget*) NULL;
2056 }
2057 }
2058
2059 bool wxWindow::PreCreation( wxWindow *parent, const wxPoint &pos, const wxSize &size )
2060 {
2061 wxCHECK_MSG( !m_needParent || parent, FALSE, wxT("Need complete parent.") );
2062
2063 /* this turns -1 into 20 so that a minimal window is
2064 visible even although -1,-1 has been given as the
2065 size of the window. the same trick is used in other
2066 ports and should make debugging easier */
2067 m_width = WidthDefault(size.x);
2068 m_height = HeightDefault(size.y);
2069
2070 m_x = (int)pos.x;
2071 m_y = (int)pos.y;
2072
2073 /* some reasonable defaults */
2074 if (!parent)
2075 {
2076 if (m_x == -1)
2077 {
2078 m_x = (gdk_screen_width () - m_width) / 2;
2079 if (m_x < 10) m_x = 10;
2080 }
2081 if (m_y == -1)
2082 {
2083 m_y = (gdk_screen_height () - m_height) / 2;
2084 if (m_y < 10) m_y = 10;
2085 }
2086 }
2087
2088 return TRUE;
2089 }
2090
2091 void wxWindow::PostCreation()
2092 {
2093 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
2094
2095 if (m_wxwindow)
2096 {
2097 if (!m_noExpose)
2098 {
2099 /* these get reported to wxWindows -> wxPaintEvent */
2100 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
2101 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
2102
2103 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
2104 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
2105 }
2106
2107 #if (GTK_MINOR_VERSION > 0)
2108 /* these are called when the "sunken" or "raised" borders are drawn */
2109 gtk_signal_connect( GTK_OBJECT(m_widget), "expose_event",
2110 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback), (gpointer)this );
2111
2112 gtk_signal_connect( GTK_OBJECT(m_widget), "draw",
2113 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback), (gpointer)this );
2114 #endif
2115 }
2116
2117 GtkWidget *connect_widget = GetConnectWidget();
2118
2119 ConnectWidget( connect_widget );
2120
2121 /* we cannot set colours, fonts and cursors before the widget has
2122 been realized, so we do this directly after realization */
2123 gtk_signal_connect( GTK_OBJECT(connect_widget), "realize",
2124 GTK_SIGNAL_FUNC(gtk_window_realized_callback), (gpointer) this );
2125
2126 m_hasVMT = TRUE;
2127 }
2128
2129 void wxWindow::ConnectWidget( GtkWidget *widget )
2130 {
2131 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
2132 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
2133
2134 gtk_signal_connect( GTK_OBJECT(widget), "key_release_event",
2135 GTK_SIGNAL_FUNC(gtk_window_key_release_callback), (gpointer)this );
2136
2137 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
2138 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
2139
2140 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
2141 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
2142
2143 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
2144 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
2145
2146 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
2147 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
2148
2149 gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
2150 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
2151
2152 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
2153 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
2154
2155 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
2156 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
2157 }
2158
2159 bool wxWindow::Destroy()
2160 {
2161 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
2162
2163 m_hasVMT = FALSE;
2164
2165 return wxWindowBase::Destroy();
2166 }
2167
2168 void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
2169 {
2170 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
2171 wxASSERT_MSG( (m_parent != NULL), wxT("wxWindow::SetSize requires parent.\n") );
2172
2173 if (m_resizing) return; /* I don't like recursions */
2174 m_resizing = TRUE;
2175
2176 if (m_parent->m_wxwindow == NULL) /* i.e. wxNotebook */
2177 {
2178 /* don't set the size for children of wxNotebook, just take the values. */
2179 m_x = x;
2180 m_y = y;
2181 m_width = width;
2182 m_height = height;
2183 }
2184 else
2185 {
2186 GtkMyFixed *myfixed = GTK_MYFIXED(m_parent->m_wxwindow);
2187
2188 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
2189 {
2190 if (x != -1) m_x = x + myfixed->xoffset;
2191 if (y != -1) m_y = y + myfixed->yoffset;
2192 if (width != -1) m_width = width;
2193 if (height != -1) m_height = height;
2194 }
2195 else
2196 {
2197 m_x = x + myfixed->xoffset;
2198 m_y = y + myfixed->yoffset;
2199 m_width = width;
2200 m_height = height;
2201 }
2202
2203 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
2204 {
2205 if (width == -1) m_width = 80;
2206 }
2207
2208 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
2209 {
2210 if (height == -1) m_height = 26;
2211 }
2212
2213 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
2214 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
2215 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
2216 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
2217
2218 int border = 0;
2219 int bottom_border = 0;
2220
2221 if (GTK_WIDGET_CAN_DEFAULT(m_widget))
2222 {
2223 /* the default button has a border around it */
2224 border = 6;
2225 bottom_border = 5;
2226 }
2227
2228 gtk_myfixed_set_size( GTK_MYFIXED(m_parent->m_wxwindow),
2229 m_widget,
2230 m_x-border,
2231 m_y-border,
2232 m_width+2*border,
2233 m_height+border+bottom_border );
2234 }
2235
2236 /*
2237 wxPrintf( "OnSize sent from " );
2238 if (GetClassInfo() && GetClassInfo()->GetClassName())
2239 wxPrintf( GetClassInfo()->GetClassName() );
2240 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2241 */
2242
2243 if (!m_nativeSizeEvent)
2244 {
2245 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
2246 event.SetEventObject( this );
2247 GetEventHandler()->ProcessEvent( event );
2248 }
2249
2250 m_resizing = FALSE;
2251 }
2252
2253 void wxWindow::OnInternalIdle()
2254 {
2255 wxCursor cursor = m_cursor;
2256 if (g_globalCursor.Ok()) cursor = g_globalCursor;
2257
2258 if (cursor.Ok())
2259 {
2260 /* I now set the cursor anew in every OnInternalIdle call
2261 as setting the cursor in a parent window also effects the
2262 windows above so that checking for the current cursor is
2263 not possible. */
2264
2265 if (m_wxwindow)
2266 {
2267 GdkWindow *window = GTK_MYFIXED(m_wxwindow)->bin_window;
2268 if (window)
2269 gdk_window_set_cursor( window, cursor.GetCursor() );
2270
2271 if (!g_globalCursor.Ok())
2272 cursor = *wxSTANDARD_CURSOR;
2273
2274 window = m_widget->window;
2275 if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
2276 gdk_window_set_cursor( window, cursor.GetCursor() );
2277
2278 }
2279 else
2280 {
2281
2282 GdkWindow *window = m_widget->window;
2283 if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
2284 gdk_window_set_cursor( window, cursor.GetCursor() );
2285
2286 }
2287 }
2288
2289 UpdateWindowUI();
2290 }
2291
2292 void wxWindow::DoGetSize( int *width, int *height ) const
2293 {
2294 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2295
2296 if (width) (*width) = m_width;
2297 if (height) (*height) = m_height;
2298 }
2299
2300 void wxWindow::DoSetClientSize( int width, int height )
2301 {
2302 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2303
2304 if (!m_wxwindow)
2305 {
2306 SetSize( width, height );
2307 }
2308 else
2309 {
2310 int dw = 0;
2311 int dh = 0;
2312
2313 #if (GTK_MINOR_VERSION == 0)
2314 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2315 {
2316 if (HasScrolling())
2317 {
2318 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2319 #if 0 // unused - if this is ok, just remove this line (VZ)
2320 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
2321 #endif // 0
2322
2323 GtkWidget *viewport = scroll_window->viewport;
2324 GtkStyleClass *viewport_class = viewport->style->klass;
2325
2326 dw += 2 * viewport_class->xthickness;
2327 dh += 2 * viewport_class->ythickness;
2328 }
2329 }
2330 #else
2331 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2332 {
2333 /* when using GTK 1.2 we set the shadow border size to 2 */
2334 dw += 2 * 2;
2335 dh += 2 * 2;
2336 }
2337 if (HasFlag(wxSIMPLE_BORDER))
2338 {
2339 /* when using GTK 1.2 we set the simple border size to 1 */
2340 dw += 1 * 2;
2341 dh += 1 * 2;
2342 }
2343 #endif
2344
2345 if (HasScrolling())
2346 {
2347 /*
2348 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2349 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2350
2351 we use this instead: range.slider_width = 11 + 2*2pts edge
2352 */
2353
2354 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2355 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
2356
2357 if (scroll_window->vscrollbar_visible)
2358 {
2359 dw += 15; /* dw += vscrollbar->allocation.width; */
2360 dw += scroll_class->scrollbar_spacing;
2361 }
2362
2363 if (scroll_window->hscrollbar_visible)
2364 {
2365 dh += 15; /* dh += hscrollbar->allocation.height; */
2366 dh += scroll_class->scrollbar_spacing;
2367 }
2368 }
2369
2370 SetSize( width+dw, height+dh );
2371 }
2372 }
2373
2374 void wxWindow::DoGetClientSize( int *width, int *height ) const
2375 {
2376 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2377
2378 if (!m_wxwindow)
2379 {
2380 if (width) (*width) = m_width;
2381 if (height) (*height) = m_height;
2382 }
2383 else
2384 {
2385 int dw = 0;
2386 int dh = 0;
2387
2388 #if (GTK_MINOR_VERSION == 0)
2389 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2390 {
2391 if (HasScrolling())
2392 {
2393 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2394 #if 0 // unused - if this is ok, just remove this line (VZ)
2395 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
2396 #endif // 0
2397
2398 GtkWidget *viewport = scroll_window->viewport;
2399 GtkStyleClass *viewport_class = viewport->style->klass;
2400
2401 dw += 2 * viewport_class->xthickness;
2402 dh += 2 * viewport_class->ythickness;
2403 }
2404 }
2405 #else
2406 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2407 {
2408 /* when using GTK 1.2 we set the shadow border size to 2 */
2409 dw += 2 * 2;
2410 dh += 2 * 2;
2411 }
2412 if (HasFlag(wxSIMPLE_BORDER))
2413 {
2414 /* when using GTK 1.2 we set the simple border size to 1 */
2415 dw += 1 * 2;
2416 dh += 1 * 2;
2417 }
2418 #endif
2419 if (HasScrolling())
2420 {
2421 /*
2422 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2423 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2424
2425 we use this instead: range.slider_width = 11 + 2*2pts edge
2426 */
2427
2428 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2429 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
2430
2431 if (scroll_window->vscrollbar_visible)
2432 {
2433 dw += 15; /* dw += vscrollbar->allocation.width; */
2434 dw += scroll_class->scrollbar_spacing;
2435 }
2436
2437 if (scroll_window->hscrollbar_visible)
2438 {
2439 dh += 15; /* dh += hscrollbar->allocation.height; */
2440 dh += scroll_class->scrollbar_spacing;
2441 }
2442 }
2443
2444 if (width) (*width) = m_width - dw;
2445 if (height) (*height) = m_height - dh;
2446 }
2447 }
2448
2449 void wxWindow::DoGetPosition( int *x, int *y ) const
2450 {
2451 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2452
2453 int dx = 0;
2454 int dy = 0;
2455 if (m_parent && m_parent->m_wxwindow)
2456 {
2457 GtkMyFixed *myfixed = GTK_MYFIXED(m_parent->m_wxwindow);
2458 dx = myfixed->xoffset;
2459 dy = myfixed->yoffset;
2460 }
2461
2462 if (x) (*x) = m_x - dx;
2463 if (y) (*y) = m_y - dy;
2464 }
2465
2466 void wxWindow::DoClientToScreen( int *x, int *y ) const
2467 {
2468 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2469
2470 if (!m_widget->window) return;
2471
2472 GdkWindow *source = (GdkWindow *) NULL;
2473 if (m_wxwindow)
2474 source = GTK_MYFIXED(m_wxwindow)->bin_window;
2475 else
2476 source = m_widget->window;
2477
2478 int org_x = 0;
2479 int org_y = 0;
2480 gdk_window_get_origin( source, &org_x, &org_y );
2481
2482 if (!m_wxwindow)
2483 {
2484 if (GTK_WIDGET_NO_WINDOW (m_widget))
2485 {
2486 org_x += m_widget->allocation.x;
2487 org_y += m_widget->allocation.y;
2488 }
2489 }
2490
2491 if (x) *x += org_x;
2492 if (y) *y += org_y;
2493 }
2494
2495 void wxWindow::DoScreenToClient( int *x, int *y ) const
2496 {
2497 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2498
2499 if (!m_widget->window) return;
2500
2501 GdkWindow *source = (GdkWindow *) NULL;
2502 if (m_wxwindow)
2503 source = GTK_MYFIXED(m_wxwindow)->bin_window;
2504 else
2505 source = m_widget->window;
2506
2507 int org_x = 0;
2508 int org_y = 0;
2509 gdk_window_get_origin( source, &org_x, &org_y );
2510
2511 if (!m_wxwindow)
2512 {
2513 if (GTK_WIDGET_NO_WINDOW (m_widget))
2514 {
2515 org_x += m_widget->allocation.x;
2516 org_y += m_widget->allocation.y;
2517 }
2518 }
2519
2520 if (x) *x -= org_x;
2521 if (y) *y -= org_y;
2522 }
2523
2524 bool wxWindow::Show( bool show )
2525 {
2526 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
2527
2528 if (!wxWindowBase::Show(show))
2529 {
2530 // nothing to do
2531 return FALSE;
2532 }
2533
2534 if (show)
2535 gtk_widget_show( m_widget );
2536 else
2537 gtk_widget_hide( m_widget );
2538
2539 return TRUE;
2540 }
2541
2542 bool wxWindow::Enable( bool enable )
2543 {
2544 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
2545
2546 if (!wxWindowBase::Enable(enable))
2547 {
2548 // nothing to do
2549 return FALSE;
2550 }
2551
2552 gtk_widget_set_sensitive( m_widget, enable );
2553 if ( m_wxwindow )
2554 gtk_widget_set_sensitive( m_wxwindow, enable );
2555
2556 return TRUE;
2557 }
2558
2559 int wxWindow::GetCharHeight() const
2560 {
2561 wxCHECK_MSG( (m_widget != NULL), 12, wxT("invalid window") );
2562
2563 wxCHECK_MSG( m_font.Ok(), 12, wxT("invalid font") );
2564
2565 GdkFont *font = m_font.GetInternalFont( 1.0 );
2566
2567 return font->ascent + font->descent;
2568 }
2569
2570 int wxWindow::GetCharWidth() const
2571 {
2572 wxCHECK_MSG( (m_widget != NULL), 8, wxT("invalid window") );
2573
2574 wxCHECK_MSG( m_font.Ok(), 8, wxT("invalid font") );
2575
2576 GdkFont *font = m_font.GetInternalFont( 1.0 );
2577
2578 return gdk_string_width( font, "H" );
2579 }
2580
2581 void wxWindow::GetTextExtent( const wxString& string,
2582 int *x,
2583 int *y,
2584 int *descent,
2585 int *externalLeading,
2586 const wxFont *theFont ) const
2587 {
2588 wxFont fontToUse = m_font;
2589 if (theFont) fontToUse = *theFont;
2590
2591 wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
2592
2593 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
2594 if (x) (*x) = gdk_string_width( font, string.mbc_str() );
2595 if (y) (*y) = font->ascent + font->descent;
2596 if (descent) (*descent) = font->descent;
2597 if (externalLeading) (*externalLeading) = 0; // ??
2598 }
2599
2600 void wxWindow::SetFocus()
2601 {
2602 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2603
2604 GtkWidget *connect_widget = GetConnectWidget();
2605 if (connect_widget)
2606 {
2607 if (GTK_WIDGET_CAN_FOCUS(connect_widget) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2608 {
2609 gtk_widget_grab_focus (connect_widget);
2610 }
2611 else if (GTK_IS_CONTAINER(connect_widget))
2612 {
2613 gtk_container_focus( GTK_CONTAINER(connect_widget), GTK_DIR_TAB_FORWARD );
2614 }
2615 else
2616 {
2617 }
2618 }
2619 }
2620
2621 bool wxWindow::AcceptsFocus() const
2622 {
2623 return m_acceptsFocus && wxWindowBase::AcceptsFocus();
2624 }
2625
2626 bool wxWindow::Reparent( wxWindowBase *newParentBase )
2627 {
2628 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
2629
2630 wxWindow *oldParent = m_parent,
2631 *newParent = (wxWindow *)newParentBase;
2632
2633 wxASSERT( GTK_IS_WIDGET(m_widget) );
2634
2635 if ( !wxWindowBase::Reparent(newParent) )
2636 return FALSE;
2637
2638 wxASSERT( GTK_IS_WIDGET(m_widget) );
2639
2640 /* prevent GTK from deleting the widget arbitrarily */
2641 gtk_widget_ref( m_widget );
2642
2643 if (oldParent)
2644 {
2645 gtk_container_remove( GTK_CONTAINER(m_widget->parent), m_widget );
2646 }
2647
2648 wxASSERT( GTK_IS_WIDGET(m_widget) );
2649
2650 if (newParent)
2651 {
2652 /* insert GTK representation */
2653 (*(newParent->m_insertCallback))(newParent, this);
2654 }
2655
2656 /* reverse: prevent GTK from deleting the widget arbitrarily */
2657 gtk_widget_unref( m_widget );
2658
2659 return TRUE;
2660 }
2661
2662 void wxWindow::DoAddChild(wxWindow *child)
2663 {
2664 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
2665
2666 wxASSERT_MSG( (child != NULL), wxT("invalid child window") );
2667
2668 wxASSERT_MSG( (m_insertCallback != NULL), wxT("invalid child insertion function") );
2669
2670 /* add to list */
2671 AddChild( child );
2672
2673 /* insert GTK representation */
2674 (*m_insertCallback)(this, child);
2675 }
2676
2677 void wxWindow::Raise()
2678 {
2679 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2680
2681 if (!m_widget->window) return;
2682
2683 gdk_window_raise( m_widget->window );
2684 }
2685
2686 void wxWindow::Lower()
2687 {
2688 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2689
2690 if (!m_widget->window) return;
2691
2692 gdk_window_lower( m_widget->window );
2693 }
2694
2695 bool wxWindow::SetCursor( const wxCursor &cursor )
2696 {
2697 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
2698
2699 return wxWindowBase::SetCursor( cursor );
2700 }
2701
2702 void wxWindow::WarpPointer( int x, int y )
2703 {
2704 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2705
2706 /* we provide this function ourselves as it is
2707 missing in GDK (top of this file) */
2708
2709 GdkWindow *window = (GdkWindow*) NULL;
2710 if (m_wxwindow)
2711 window = GTK_MYFIXED(m_wxwindow)->bin_window;
2712 else
2713 window = GetConnectWidget()->window;
2714
2715 if (window)
2716 gdk_window_warp_pointer( window, x, y );
2717 }
2718
2719 void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
2720 {
2721 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2722
2723 if (!m_widget->window) return;
2724
2725 if (eraseBackground && m_wxwindow && m_wxwindow->window)
2726 {
2727 if (rect)
2728 {
2729 gdk_window_clear_area( GTK_MYFIXED(m_wxwindow)->bin_window,
2730 rect->x, rect->y,
2731 rect->width, rect->height );
2732 }
2733 else
2734 {
2735 gdk_window_clear( GTK_MYFIXED(m_wxwindow)->bin_window );
2736 }
2737 }
2738
2739 /* there is no GTK equivalent of "draw only, don't clear" so we
2740 invent our own in the GtkMyFixed widget */
2741
2742 if (!rect)
2743 {
2744 if (m_wxwindow)
2745 {
2746 GtkMyFixed *myfixed = GTK_MYFIXED(m_wxwindow);
2747 gboolean old_clear = myfixed->clear_on_draw;
2748 gtk_my_fixed_set_clear( myfixed, FALSE );
2749
2750 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
2751
2752 gtk_my_fixed_set_clear( myfixed, old_clear );
2753 }
2754 else
2755 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
2756 }
2757 else
2758 {
2759 GdkRectangle gdk_rect;
2760 gdk_rect.x = rect->x;
2761 gdk_rect.y = rect->y;
2762 gdk_rect.width = rect->width;
2763 gdk_rect.height = rect->height;
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, &gdk_rect );
2772
2773 gtk_my_fixed_set_clear( myfixed, old_clear );
2774 }
2775 else
2776 gtk_widget_draw( m_widget, &gdk_rect );
2777 }
2778 }
2779
2780 void wxWindow::Clear()
2781 {
2782 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
2783
2784 if (!m_widget->window) return;
2785
2786 if (m_wxwindow && m_wxwindow->window)
2787 {
2788 gdk_window_clear( m_wxwindow->window );
2789 }
2790 }
2791
2792 #if wxUSE_TOOLTIPS
2793 void wxWindow::DoSetToolTip( wxToolTip *tip )
2794 {
2795 wxWindowBase::DoSetToolTip(tip);
2796
2797 if (m_tooltip)
2798 m_tooltip->Apply( this );
2799 }
2800
2801 void wxWindow::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
2802 {
2803 gtk_tooltips_set_tip( tips, GetConnectWidget(), wxConvCurrent->cWX2MB(tip), (gchar*) NULL );
2804 }
2805 #endif // wxUSE_TOOLTIPS
2806
2807 bool wxWindow::SetBackgroundColour( const wxColour &colour )
2808 {
2809 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
2810
2811 if (!wxWindowBase::SetBackgroundColour(colour))
2812 {
2813 // don't leave if the GTK widget has just
2814 // been realized
2815 if (!m_delayedBackgroundColour) return FALSE;
2816 }
2817
2818 GdkWindow *window = (GdkWindow*) NULL;
2819 if (m_wxwindow)
2820 window = GTK_MYFIXED(m_wxwindow)->bin_window;
2821 else
2822 window = GetConnectWidget()->window;
2823
2824 if (!window)
2825 {
2826 // indicate that a new style has been set
2827 // but it couldn't get applied as the
2828 // widget hasn't been realized yet.
2829 m_delayedBackgroundColour = TRUE;
2830
2831 // pretend we have done something
2832 return TRUE;
2833 }
2834
2835 if (m_wxwindow)
2836 {
2837 /* wxMSW doesn't clear the window here. I don't do that either to
2838 provide compatibility. call Clear() to do the job. */
2839
2840 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
2841 gdk_window_set_background( window, m_backgroundColour.GetColor() );
2842 }
2843
2844 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2845 if (sysbg == m_backgroundColour)
2846 {
2847 m_backgroundColour = wxNullColour;
2848 ApplyWidgetStyle();
2849 m_backgroundColour = sysbg;
2850 }
2851 else
2852 {
2853 ApplyWidgetStyle();
2854 }
2855
2856 return TRUE;
2857 }
2858
2859 bool wxWindow::SetForegroundColour( const wxColour &colour )
2860 {
2861 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
2862
2863 if (!wxWindowBase::SetForegroundColour(colour))
2864 {
2865 // don't leave if the GTK widget has just
2866 // been realized
2867 if (!m_delayedForegroundColour) return FALSE;
2868 }
2869
2870 GdkWindow *window = (GdkWindow*) NULL;
2871 if (m_wxwindow)
2872 window = GTK_MYFIXED(m_wxwindow)->bin_window;
2873 else
2874 window = GetConnectWidget()->window;
2875
2876 if (!window)
2877 {
2878 // indicate that a new style has been set
2879 // but it couldn't get applied as the
2880 // widget hasn't been realized yet.
2881 m_delayedForegroundColour = TRUE;
2882
2883 // pretend we have done something
2884 return TRUE;
2885 }
2886
2887 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2888 if ( sysbg == m_backgroundColour )
2889 {
2890 m_backgroundColour = wxNullColour;
2891 ApplyWidgetStyle();
2892 m_backgroundColour = sysbg;
2893 }
2894 else
2895 {
2896 ApplyWidgetStyle();
2897 }
2898
2899 return TRUE;
2900 }
2901
2902 GtkStyle *wxWindow::GetWidgetStyle()
2903 {
2904 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
2905
2906 m_widgetStyle = gtk_style_copy( gtk_widget_get_style( m_widget ) );
2907
2908 return m_widgetStyle;
2909 }
2910
2911 void wxWindow::SetWidgetStyle()
2912 {
2913 GtkStyle *style = GetWidgetStyle();
2914
2915 gdk_font_unref( style->font );
2916 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2917
2918 if (m_foregroundColour.Ok())
2919 {
2920 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2921 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2922 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2923 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2924 }
2925
2926 if (m_backgroundColour.Ok())
2927 {
2928 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2929 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2930 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2931 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2932 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2933 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2934 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2935 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2936 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2937 }
2938 }
2939
2940 void wxWindow::ApplyWidgetStyle()
2941 {
2942 }
2943
2944 //-----------------------------------------------------------------------------
2945 // Pop-up menu stuff
2946 //-----------------------------------------------------------------------------
2947
2948 static void gtk_pop_hide_callback( GtkWidget *WXUNUSED(widget), bool* is_waiting )
2949 {
2950 *is_waiting = FALSE;
2951 }
2952
2953 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2954 {
2955 menu->SetInvokingWindow( win );
2956 wxNode *node = menu->GetItems().First();
2957 while (node)
2958 {
2959 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2960 if (menuitem->IsSubMenu())
2961 {
2962 SetInvokingWindow( menuitem->GetSubMenu(), win );
2963 }
2964 node = node->Next();
2965 }
2966 }
2967
2968 static gint gs_pop_x = 0;
2969 static gint gs_pop_y = 0;
2970
2971 static void pop_pos_callback( GtkMenu * WXUNUSED(menu),
2972 gint *x, gint *y,
2973 wxWindow *win )
2974 {
2975 win->ClientToScreen( &gs_pop_x, &gs_pop_y );
2976 *x = gs_pop_x;
2977 *y = gs_pop_y;
2978 }
2979
2980 bool wxWindow::DoPopupMenu( wxMenu *menu, int x, int y )
2981 {
2982 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
2983
2984 wxCHECK_MSG( menu != NULL, FALSE, wxT("invalid popup-menu") );
2985
2986 SetInvokingWindow( menu, this );
2987
2988 menu->UpdateUI();
2989
2990 gs_pop_x = x;
2991 gs_pop_y = y;
2992
2993 bool is_waiting = TRUE;
2994
2995 gtk_signal_connect( GTK_OBJECT(menu->m_menu), "hide",
2996 GTK_SIGNAL_FUNC(gtk_pop_hide_callback), (gpointer)&is_waiting );
2997
2998 gtk_menu_popup(
2999 GTK_MENU(menu->m_menu),
3000 (GtkWidget *) NULL, // parent menu shell
3001 (GtkWidget *) NULL, // parent menu item
3002 (GtkMenuPositionFunc) pop_pos_callback,
3003 (gpointer) this, // client data
3004 0, // button used to activate it
3005 gs_timeLastClick // the time of activation
3006 );
3007
3008 while (is_waiting)
3009 {
3010 while (gtk_events_pending())
3011 gtk_main_iteration();
3012 }
3013
3014 return TRUE;
3015 }
3016
3017 #if wxUSE_DRAG_AND_DROP
3018
3019 void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
3020 {
3021 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
3022
3023 GtkWidget *dnd_widget = GetConnectWidget();
3024
3025 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
3026
3027 if (m_dropTarget) delete m_dropTarget;
3028 m_dropTarget = dropTarget;
3029
3030 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
3031 }
3032
3033 #endif // wxUSE_DRAG_AND_DROP
3034
3035 GtkWidget* wxWindow::GetConnectWidget()
3036 {
3037 GtkWidget *connect_widget = m_widget;
3038 if (m_wxwindow) connect_widget = m_wxwindow;
3039
3040 return connect_widget;
3041 }
3042
3043 bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
3044 {
3045 if (m_wxwindow)
3046 return (window == GTK_MYFIXED(m_wxwindow)->bin_window);
3047
3048 return (window == m_widget->window);
3049 }
3050
3051 bool wxWindow::SetFont( const wxFont &font )
3052 {
3053 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
3054
3055 if (!wxWindowBase::SetFont(font))
3056 {
3057 // don't leave if the GTK widget has just
3058 // been realized
3059 if (!m_delayedFont) return FALSE;
3060 }
3061
3062 GdkWindow *window = (GdkWindow*) NULL;
3063 if (m_wxwindow)
3064 window = GTK_MYFIXED(m_wxwindow)->bin_window;
3065 else
3066 window = GetConnectWidget()->window;
3067
3068 if (!window)
3069 {
3070 // indicate that a new style has been set
3071 // but it couldn't get applied as the
3072 // widget hasn't been realized yet.
3073 m_delayedFont = TRUE;
3074
3075 // pretend we have done something
3076 return TRUE;
3077 }
3078
3079 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
3080 if ( sysbg == m_backgroundColour )
3081 {
3082 m_backgroundColour = wxNullColour;
3083 ApplyWidgetStyle();
3084 m_backgroundColour = sysbg;
3085 }
3086 else
3087 {
3088 ApplyWidgetStyle();
3089 }
3090
3091 return TRUE;
3092 }
3093
3094 void wxWindow::CaptureMouse()
3095 {
3096 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
3097
3098 wxCHECK_RET( g_captureWindow == NULL, wxT("CaptureMouse called twice") );
3099
3100 GdkWindow *window = (GdkWindow*) NULL;
3101 if (m_wxwindow)
3102 window = GTK_MYFIXED(m_wxwindow)->bin_window;
3103 else
3104 window = GetConnectWidget()->window;
3105
3106 if (!window) return;
3107
3108 gdk_pointer_grab( window, FALSE,
3109 (GdkEventMask)
3110 (GDK_BUTTON_PRESS_MASK |
3111 GDK_BUTTON_RELEASE_MASK |
3112 GDK_POINTER_MOTION_HINT_MASK |
3113 GDK_POINTER_MOTION_MASK),
3114 (GdkWindow *) NULL,
3115 m_cursor.GetCursor(),
3116 GDK_CURRENT_TIME );
3117 g_captureWindow = this;
3118 }
3119
3120 void wxWindow::ReleaseMouse()
3121 {
3122 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
3123
3124 wxCHECK_RET( g_captureWindow, wxT("ReleaseMouse called twice") );
3125
3126 GdkWindow *window = (GdkWindow*) NULL;
3127 if (m_wxwindow)
3128 window = GTK_MYFIXED(m_wxwindow)->bin_window;
3129 else
3130 window = GetConnectWidget()->window;
3131
3132 if (!window) return;
3133
3134 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
3135 g_captureWindow = (wxWindow*) NULL;
3136 }
3137
3138 bool wxWindow::IsRetained() const
3139 {
3140 return FALSE;
3141 }
3142
3143 void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
3144 int range, bool refresh )
3145 {
3146 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
3147
3148 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
3149
3150 m_hasScrolling = TRUE;
3151
3152 if (orient == wxHORIZONTAL)
3153 {
3154 float fpos = (float)pos;
3155 float frange = (float)range;
3156 float fthumb = (float)thumbVisible;
3157 if (fpos > frange-fthumb) fpos = frange-fthumb;
3158 if (fpos < 0.0) fpos = 0.0;
3159
3160 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
3161 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
3162 {
3163 SetScrollPos( orient, pos, refresh );
3164 return;
3165 }
3166
3167 m_oldHorizontalPos = fpos;
3168
3169 m_hAdjust->lower = 0.0;
3170 m_hAdjust->upper = frange;
3171 m_hAdjust->value = fpos;
3172 m_hAdjust->step_increment = 1.0;
3173 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
3174 m_hAdjust->page_size = fthumb;
3175 }
3176 else
3177 {
3178 float fpos = (float)pos;
3179 float frange = (float)range;
3180 float fthumb = (float)thumbVisible;
3181 if (fpos > frange-fthumb) fpos = frange-fthumb;
3182 if (fpos < 0.0) fpos = 0.0;
3183
3184 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
3185 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
3186 {
3187 SetScrollPos( orient, pos, refresh );
3188 return;
3189 }
3190
3191 m_oldVerticalPos = fpos;
3192
3193 m_vAdjust->lower = 0.0;
3194 m_vAdjust->upper = frange;
3195 m_vAdjust->value = fpos;
3196 m_vAdjust->step_increment = 1.0;
3197 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
3198 m_vAdjust->page_size = fthumb;
3199 }
3200
3201 if (orient == wxHORIZONTAL)
3202 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
3203 else
3204 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
3205 }
3206
3207 void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
3208 {
3209 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
3210
3211 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
3212
3213 if (orient == wxHORIZONTAL)
3214 {
3215 float fpos = (float)pos;
3216 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
3217 if (fpos < 0.0) fpos = 0.0;
3218 m_oldHorizontalPos = fpos;
3219
3220 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
3221 m_hAdjust->value = fpos;
3222 }
3223 else
3224 {
3225 float fpos = (float)pos;
3226 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
3227 if (fpos < 0.0) fpos = 0.0;
3228 m_oldVerticalPos = fpos;
3229
3230 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
3231 m_vAdjust->value = fpos;
3232 }
3233
3234 /*
3235 if (!m_isScrolling)
3236 {
3237 */
3238 if (m_wxwindow->window)
3239 {
3240 if (orient == wxHORIZONTAL)
3241 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
3242 else
3243 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
3244 }
3245 /*
3246 }
3247 */
3248 }
3249
3250 int wxWindow::GetScrollThumb( int orient ) const
3251 {
3252 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
3253
3254 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
3255
3256 if (orient == wxHORIZONTAL)
3257 return (int)(m_hAdjust->page_size+0.5);
3258 else
3259 return (int)(m_vAdjust->page_size+0.5);
3260 }
3261
3262 int wxWindow::GetScrollPos( int orient ) const
3263 {
3264 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
3265
3266 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
3267
3268 if (orient == wxHORIZONTAL)
3269 return (int)(m_hAdjust->value+0.5);
3270 else
3271 return (int)(m_vAdjust->value+0.5);
3272 }
3273
3274 int wxWindow::GetScrollRange( int orient ) const
3275 {
3276 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
3277
3278 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
3279
3280 if (orient == wxHORIZONTAL)
3281 return (int)(m_hAdjust->upper+0.5);
3282 else
3283 return (int)(m_vAdjust->upper+0.5);
3284 }
3285
3286 void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
3287 {
3288 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
3289
3290 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
3291
3292 gtk_myfixed_scroll( GTK_MYFIXED(m_wxwindow), -dx, -dy );
3293
3294 /*
3295 if (!m_scrollGC)
3296 {
3297 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3298 gdk_gc_set_exposures( m_scrollGC, TRUE );
3299 }
3300
3301 wxNode *node = m_children.First();
3302 while (node)
3303 {
3304 wxWindow *child = (wxWindow*) node->Data();
3305 int sx = 0;
3306 int sy = 0;
3307 child->GetSize( &sx, &sy );
3308 child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
3309 node = node->Next();
3310 }
3311
3312 int cw = 0;
3313 int ch = 0;
3314 GetClientSize( &cw, &ch );
3315 int w = cw - abs(dx);
3316 int h = ch - abs(dy);
3317
3318 if ((h < 0) || (w < 0))
3319 {
3320 Refresh();
3321 }
3322 else
3323 {
3324 int s_x = 0;
3325 int s_y = 0;
3326 if (dx < 0) s_x = -dx;
3327 if (dy < 0) s_y = -dy;
3328 int d_x = 0;
3329 int d_y = 0;
3330 if (dx > 0) d_x = dx;
3331 if (dy > 0) d_y = dy;
3332
3333 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3334 m_wxwindow->window, s_x, s_y, w, h );
3335
3336 wxRect rect;
3337 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3338 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3339 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3340 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3341
3342 Refresh( TRUE, &rect );
3343 }
3344 */
3345 }
3346
3347 void wxWindow::SetScrolling(bool scroll)
3348 {
3349 m_isScrolling = g_blockEventsOnScroll = scroll;
3350 }