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