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