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