]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/window.cpp
include <wx/...> => include "wx/..."
[wxWidgets.git] / src / gtk1 / window.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: window.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10
11 #ifdef __GNUG__
12 #pragma implementation "window.h"
13 #endif
14
15 #include "wx/defs.h"
16 #include "wx/window.h"
17 #include "wx/dc.h"
18 #include "wx/frame.h"
19 #include "wx/app.h"
20 #include "wx/layout.h"
21 #include "wx/utils.h"
22 #include "wx/dialog.h"
23 #include "wx/msgdlg.h"
24
25 #if wxUSE_DRAG_AND_DROP
26 #include "wx/dnd.h"
27 #endif
28
29 #if wxUSE_TOOLTIPS
30 #include "wx/tooltip.h"
31 #endif
32
33 #include "wx/menu.h"
34 #include "wx/statusbr.h"
35 #include "wx/intl.h"
36 #include "wx/settings.h"
37 #include "wx/log.h"
38
39 #include <math.h>
40
41 #include "gdk/gdk.h"
42 #include "gtk/gtk.h"
43 #include "gdk/gdkprivate.h"
44 #include "gdk/gdkkeysyms.h"
45 #include "wx/gtk/win_gtk.h"
46
47 #include "gdk/gdkx.h"
48
49 //-----------------------------------------------------------------------------
50 // documentation on internals
51 //-----------------------------------------------------------------------------
52
53 /*
54 I have been asked several times about writing some documentation about
55 the GTK port of wxWindows, especially its internal structures. Obviously,
56 you cannot understand wxGTK without knowing a little about the GTK, but
57 some more information about what the wxWindow, which is the base class
58 for all other window classes, does seems required as well.
59
60 I)
61
62 What does wxWindow do? It contains the common interface for the following
63 jobs of its descendants:
64
65 1) Define the rudimentary behaviour common to all window classes, such as
66 resizing, intercepting user input (so as to make it possible to use these
67 events for special purposes in a derived class), window names etc.
68
69 2) Provide the possibility to contain and manage children, if the derived
70 class is allowed to contain children, which holds true for those window
71 classes which do not display a native GTK widget. To name them, these
72 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
73 work classes are a special case and are handled a bit differently from
74 the rest. The same holds true for the wxNotebook class.
75
76 3) Provide the possibility to draw into a client area of a window. This,
77 too, only holds true for classes that do not display a native GTK widget
78 as above.
79
80 4) Provide the entire mechanism for scrolling widgets. This actual inter-
81 face for this is usually in wxScrolledWindow, but the GTK implementation
82 is in this class.
83
84 5) A multitude of helper or extra methods for special purposes, such as
85 Drag'n'Drop, managing validators etc.
86
87 6) Display a border (sunken, raised, simple or none).
88
89 Normally one might expect, that one wxWindows window would always correspond
90 to one GTK widget. Under GTK, there is no such allround widget that has all
91 the functionality. Moreover, the GTK defines a client area as a different
92 widget from the actual widget you are handling. Last but not least some
93 special classes (e.g. wxFrame) handle different categories of widgets and
94 still have the possibility to draw something in the client area.
95 It was therefore required to write a special purpose GTK widget, that would
96 represent a client area in the sense of wxWindows capable to do the jobs
97 2), 3) and 4). I have written this class and it resides in win_gtk.c of
98 this directory.
99
100 All windows must have a widget, with which they interact with other under-
101 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
102 thw wxWindow class has a member variable called m_widget which holds a
103 pointer to this widget. When the window class represents a GTK native widget,
104 this is (in most cases) the only GTK widget the class manages. E.g. the
105 wxStatitText class handles only a GtkLabel widget a pointer to which you
106 can find in m_widget (defined in wxWindow)
107
108 When the class has a client area for drawing into and for containing children
109 it has to handle the client area widget (of the type 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 gtk_widget_grab_focus (m_wxwindow);
2463 return;
2464 }
2465
2466 if (m_widget)
2467 {
2468 if (GTK_WIDGET_CAN_FOCUS(m_widget) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2469 {
2470 gtk_widget_grab_focus (m_widget);
2471 }
2472 else if (GTK_IS_CONTAINER(m_widget))
2473 {
2474 gtk_container_focus( GTK_CONTAINER(m_widget), GTK_DIR_TAB_FORWARD );
2475 }
2476 else
2477 {
2478 // ?
2479 }
2480 }
2481 }
2482
2483 bool wxWindow::AcceptsFocus() const
2484 {
2485 return m_acceptsFocus && wxWindowBase::AcceptsFocus();
2486 }
2487
2488 bool wxWindow::Reparent( wxWindowBase *newParentBase )
2489 {
2490 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
2491
2492 wxWindow *oldParent = m_parent,
2493 *newParent = (wxWindow *)newParentBase;
2494
2495 wxASSERT( GTK_IS_WIDGET(m_widget) );
2496
2497 if ( !wxWindowBase::Reparent(newParent) )
2498 return FALSE;
2499
2500 wxASSERT( GTK_IS_WIDGET(m_widget) );
2501
2502 /* prevent GTK from deleting the widget arbitrarily */
2503 gtk_widget_ref( m_widget );
2504
2505 if (oldParent)
2506 {
2507 gtk_container_remove( GTK_CONTAINER(m_widget->parent), m_widget );
2508 }
2509
2510 wxASSERT( GTK_IS_WIDGET(m_widget) );
2511
2512 if (newParent)
2513 {
2514 /* insert GTK representation */
2515 (*(newParent->m_insertCallback))(newParent, this);
2516 }
2517
2518 /* reverse: prevent GTK from deleting the widget arbitrarily */
2519 gtk_widget_unref( m_widget );
2520
2521 return TRUE;
2522 }
2523
2524 void wxWindow::DoAddChild(wxWindow *child)
2525 {
2526 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
2527
2528 wxASSERT_MSG( (child != NULL), wxT("invalid child window") );
2529
2530 wxASSERT_MSG( (m_insertCallback != NULL), wxT("invalid child insertion function") );
2531
2532 /* add to list */
2533 AddChild( child );
2534
2535 /* insert GTK representation */
2536 (*m_insertCallback)(this, child);
2537 }
2538
2539 void wxWindow::Raise()
2540 {
2541 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2542
2543 if (!m_widget->window) return;
2544
2545 gdk_window_raise( m_widget->window );
2546 }
2547
2548 void wxWindow::Lower()
2549 {
2550 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2551
2552 if (!m_widget->window) return;
2553
2554 gdk_window_lower( m_widget->window );
2555 }
2556
2557 bool wxWindow::SetCursor( const wxCursor &cursor )
2558 {
2559 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
2560
2561 return wxWindowBase::SetCursor( cursor );
2562 }
2563
2564 void wxWindow::WarpPointer( int x, int y )
2565 {
2566 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2567
2568 /* we provide this function ourselves as it is
2569 missing in GDK (top of this file) */
2570
2571 GdkWindow *window = (GdkWindow*) NULL;
2572 if (m_wxwindow)
2573 window = GTK_PIZZA(m_wxwindow)->bin_window;
2574 else
2575 window = GetConnectWidget()->window;
2576
2577 if (window)
2578 gdk_window_warp_pointer( window, x, y );
2579 }
2580
2581 void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
2582 {
2583 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2584
2585 if (!m_widget->window) return;
2586
2587 if (eraseBackground && m_wxwindow && m_wxwindow->window)
2588 {
2589 if (rect)
2590 {
2591 gdk_window_clear_area( GTK_PIZZA(m_wxwindow)->bin_window,
2592 rect->x, rect->y,
2593 rect->width, rect->height );
2594 }
2595 else
2596 {
2597 gdk_window_clear( GTK_PIZZA(m_wxwindow)->bin_window );
2598 }
2599 }
2600
2601 /* there is no GTK equivalent of "draw only, don't clear" so we
2602 invent our own in the GtkPizza widget */
2603
2604 if (!rect)
2605 {
2606 if (m_wxwindow)
2607 {
2608 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
2609 gboolean old_clear = pizza->clear_on_draw;
2610 gtk_pizza_set_clear( pizza, FALSE );
2611
2612 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
2613
2614 gtk_pizza_set_clear( pizza, old_clear );
2615 }
2616 else
2617 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
2618 }
2619 else
2620 {
2621 GdkRectangle gdk_rect;
2622 gdk_rect.x = rect->x;
2623 gdk_rect.y = rect->y;
2624 gdk_rect.width = rect->width;
2625 gdk_rect.height = rect->height;
2626
2627 if (m_wxwindow)
2628 {
2629 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
2630 gboolean old_clear = pizza->clear_on_draw;
2631 gtk_pizza_set_clear( pizza, FALSE );
2632
2633 gtk_widget_draw( m_wxwindow, &gdk_rect );
2634
2635 gtk_pizza_set_clear( pizza, old_clear );
2636 }
2637 else
2638 gtk_widget_draw( m_widget, &gdk_rect );
2639 }
2640 }
2641
2642 void wxWindow::Clear()
2643 {
2644 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
2645
2646 if (!m_widget->window) return;
2647
2648 if (m_wxwindow && m_wxwindow->window)
2649 {
2650 gdk_window_clear( m_wxwindow->window );
2651 }
2652 }
2653
2654 #if wxUSE_TOOLTIPS
2655 void wxWindow::DoSetToolTip( wxToolTip *tip )
2656 {
2657 wxWindowBase::DoSetToolTip(tip);
2658
2659 if (m_tooltip)
2660 m_tooltip->Apply( this );
2661 }
2662
2663 void wxWindow::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
2664 {
2665 gtk_tooltips_set_tip( tips, GetConnectWidget(), wxConvCurrent->cWX2MB(tip), (gchar*) NULL );
2666 }
2667 #endif // wxUSE_TOOLTIPS
2668
2669 bool wxWindow::SetBackgroundColour( const wxColour &colour )
2670 {
2671 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
2672
2673 if (!wxWindowBase::SetBackgroundColour(colour))
2674 {
2675 // don't leave if the GTK widget has just
2676 // been realized
2677 if (!m_delayedBackgroundColour) return FALSE;
2678 }
2679
2680 GdkWindow *window = (GdkWindow*) NULL;
2681 if (m_wxwindow)
2682 window = GTK_PIZZA(m_wxwindow)->bin_window;
2683 else
2684 window = GetConnectWidget()->window;
2685
2686 if (!window)
2687 {
2688 // indicate that a new style has been set
2689 // but it couldn't get applied as the
2690 // widget hasn't been realized yet.
2691 m_delayedBackgroundColour = TRUE;
2692
2693 // pretend we have done something
2694 return TRUE;
2695 }
2696
2697 if (m_wxwindow)
2698 {
2699 /* wxMSW doesn't clear the window here. I don't do that either to
2700 provide compatibility. call Clear() to do the job. */
2701
2702 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
2703 gdk_window_set_background( window, m_backgroundColour.GetColor() );
2704 }
2705
2706 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2707 if (sysbg == m_backgroundColour)
2708 {
2709 m_backgroundColour = wxNullColour;
2710 ApplyWidgetStyle();
2711 m_backgroundColour = sysbg;
2712 }
2713 else
2714 {
2715 ApplyWidgetStyle();
2716 }
2717
2718 return TRUE;
2719 }
2720
2721 bool wxWindow::SetForegroundColour( const wxColour &colour )
2722 {
2723 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
2724
2725 if (!wxWindowBase::SetForegroundColour(colour))
2726 {
2727 // don't leave if the GTK widget has just
2728 // been realized
2729 if (!m_delayedForegroundColour) return FALSE;
2730 }
2731
2732 GdkWindow *window = (GdkWindow*) NULL;
2733 if (m_wxwindow)
2734 window = GTK_PIZZA(m_wxwindow)->bin_window;
2735 else
2736 window = GetConnectWidget()->window;
2737
2738 if (!window)
2739 {
2740 // indicate that a new style has been set
2741 // but it couldn't get applied as the
2742 // widget hasn't been realized yet.
2743 m_delayedForegroundColour = TRUE;
2744
2745 // pretend we have done something
2746 return TRUE;
2747 }
2748
2749 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2750 if ( sysbg == m_backgroundColour )
2751 {
2752 m_backgroundColour = wxNullColour;
2753 ApplyWidgetStyle();
2754 m_backgroundColour = sysbg;
2755 }
2756 else
2757 {
2758 ApplyWidgetStyle();
2759 }
2760
2761 return TRUE;
2762 }
2763
2764 GtkStyle *wxWindow::GetWidgetStyle()
2765 {
2766 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
2767
2768 m_widgetStyle = gtk_style_copy( gtk_widget_get_style( m_widget ) );
2769
2770 return m_widgetStyle;
2771 }
2772
2773 void wxWindow::SetWidgetStyle()
2774 {
2775 GtkStyle *style = GetWidgetStyle();
2776
2777 gdk_font_unref( style->font );
2778 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2779
2780 if (m_foregroundColour.Ok())
2781 {
2782 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2783 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2784 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2785 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2786 }
2787
2788 if (m_backgroundColour.Ok())
2789 {
2790 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2791 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2792 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2793 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2794 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2795 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2796 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2797 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2798 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2799 }
2800 }
2801
2802 void wxWindow::ApplyWidgetStyle()
2803 {
2804 }
2805
2806 //-----------------------------------------------------------------------------
2807 // Pop-up menu stuff
2808 //-----------------------------------------------------------------------------
2809
2810 static void gtk_pop_hide_callback( GtkWidget *WXUNUSED(widget), bool* is_waiting )
2811 {
2812 *is_waiting = FALSE;
2813 }
2814
2815 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2816 {
2817 menu->SetInvokingWindow( win );
2818 wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
2819 while (node)
2820 {
2821 wxMenuItem *menuitem = node->GetData();
2822 if (menuitem->IsSubMenu())
2823 {
2824 SetInvokingWindow( menuitem->GetSubMenu(), win );
2825 }
2826
2827 node = node->GetNext();
2828 }
2829 }
2830
2831 static gint gs_pop_x = 0;
2832 static gint gs_pop_y = 0;
2833
2834 static void pop_pos_callback( GtkMenu * WXUNUSED(menu),
2835 gint *x, gint *y,
2836 wxWindow *win )
2837 {
2838 win->ClientToScreen( &gs_pop_x, &gs_pop_y );
2839 *x = gs_pop_x;
2840 *y = gs_pop_y;
2841 }
2842
2843 bool wxWindow::DoPopupMenu( wxMenu *menu, int x, int y )
2844 {
2845 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
2846
2847 wxCHECK_MSG( menu != NULL, FALSE, wxT("invalid popup-menu") );
2848
2849 SetInvokingWindow( menu, this );
2850
2851 menu->UpdateUI();
2852
2853 gs_pop_x = x;
2854 gs_pop_y = y;
2855
2856 bool is_waiting = TRUE;
2857
2858 gtk_signal_connect( GTK_OBJECT(menu->m_menu), "hide",
2859 GTK_SIGNAL_FUNC(gtk_pop_hide_callback), (gpointer)&is_waiting );
2860
2861 gtk_menu_popup(
2862 GTK_MENU(menu->m_menu),
2863 (GtkWidget *) NULL, // parent menu shell
2864 (GtkWidget *) NULL, // parent menu item
2865 (GtkMenuPositionFunc) pop_pos_callback,
2866 (gpointer) this, // client data
2867 0, // button used to activate it
2868 gs_timeLastClick // the time of activation
2869 );
2870
2871 while (is_waiting)
2872 {
2873 while (gtk_events_pending())
2874 gtk_main_iteration();
2875 }
2876
2877 return TRUE;
2878 }
2879
2880 #if wxUSE_DRAG_AND_DROP
2881
2882 void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2883 {
2884 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
2885
2886 GtkWidget *dnd_widget = GetConnectWidget();
2887
2888 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
2889
2890 if (m_dropTarget) delete m_dropTarget;
2891 m_dropTarget = dropTarget;
2892
2893 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
2894 }
2895
2896 #endif // wxUSE_DRAG_AND_DROP
2897
2898 GtkWidget* wxWindow::GetConnectWidget()
2899 {
2900 GtkWidget *connect_widget = m_widget;
2901 if (m_wxwindow) connect_widget = m_wxwindow;
2902
2903 return connect_widget;
2904 }
2905
2906 bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2907 {
2908 if (m_wxwindow)
2909 return (window == GTK_PIZZA(m_wxwindow)->bin_window);
2910
2911 return (window == m_widget->window);
2912 }
2913
2914 bool wxWindow::SetFont( const wxFont &font )
2915 {
2916 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
2917
2918 if (!wxWindowBase::SetFont(font))
2919 {
2920 // don't leave if the GTK widget has just
2921 // been realized
2922 if (!m_delayedFont) return FALSE;
2923 }
2924
2925 GdkWindow *window = (GdkWindow*) NULL;
2926 if (m_wxwindow)
2927 window = GTK_PIZZA(m_wxwindow)->bin_window;
2928 else
2929 window = GetConnectWidget()->window;
2930
2931 if (!window)
2932 {
2933 // indicate that a new style has been set
2934 // but it couldn't get applied as the
2935 // widget hasn't been realized yet.
2936 m_delayedFont = TRUE;
2937
2938 // pretend we have done something
2939 return TRUE;
2940 }
2941
2942 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2943 if ( sysbg == m_backgroundColour )
2944 {
2945 m_backgroundColour = wxNullColour;
2946 ApplyWidgetStyle();
2947 m_backgroundColour = sysbg;
2948 }
2949 else
2950 {
2951 ApplyWidgetStyle();
2952 }
2953
2954 return TRUE;
2955 }
2956
2957 void wxWindow::CaptureMouse()
2958 {
2959 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
2960
2961 wxCHECK_RET( g_captureWindow == NULL, wxT("CaptureMouse called twice") );
2962
2963 GdkWindow *window = (GdkWindow*) NULL;
2964 if (m_wxwindow)
2965 window = GTK_PIZZA(m_wxwindow)->bin_window;
2966 else
2967 window = GetConnectWidget()->window;
2968
2969 if (!window) return;
2970
2971 gdk_pointer_grab( window, FALSE,
2972 (GdkEventMask)
2973 (GDK_BUTTON_PRESS_MASK |
2974 GDK_BUTTON_RELEASE_MASK |
2975 GDK_POINTER_MOTION_HINT_MASK |
2976 GDK_POINTER_MOTION_MASK),
2977 (GdkWindow *) NULL,
2978 m_cursor.GetCursor(),
2979 GDK_CURRENT_TIME );
2980 g_captureWindow = this;
2981 }
2982
2983 void wxWindow::ReleaseMouse()
2984 {
2985 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
2986
2987 wxCHECK_RET( g_captureWindow, wxT("ReleaseMouse called twice") );
2988
2989 GdkWindow *window = (GdkWindow*) NULL;
2990 if (m_wxwindow)
2991 window = GTK_PIZZA(m_wxwindow)->bin_window;
2992 else
2993 window = GetConnectWidget()->window;
2994
2995 if (!window) return;
2996
2997 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
2998 g_captureWindow = (wxWindow*) NULL;
2999 }
3000
3001 bool wxWindow::IsRetained() const
3002 {
3003 return FALSE;
3004 }
3005
3006 void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
3007 int range, bool refresh )
3008 {
3009 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
3010
3011 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
3012
3013 m_hasScrolling = TRUE;
3014
3015 if (orient == wxHORIZONTAL)
3016 {
3017 float fpos = (float)pos;
3018 float frange = (float)range;
3019 float fthumb = (float)thumbVisible;
3020 if (fpos > frange-fthumb) fpos = frange-fthumb;
3021 if (fpos < 0.0) fpos = 0.0;
3022
3023 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
3024 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
3025 {
3026 SetScrollPos( orient, pos, refresh );
3027 return;
3028 }
3029
3030 m_oldHorizontalPos = fpos;
3031
3032 m_hAdjust->lower = 0.0;
3033 m_hAdjust->upper = frange;
3034 m_hAdjust->value = fpos;
3035 m_hAdjust->step_increment = 1.0;
3036 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
3037 m_hAdjust->page_size = fthumb;
3038 }
3039 else
3040 {
3041 float fpos = (float)pos;
3042 float frange = (float)range;
3043 float fthumb = (float)thumbVisible;
3044 if (fpos > frange-fthumb) fpos = frange-fthumb;
3045 if (fpos < 0.0) fpos = 0.0;
3046
3047 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
3048 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
3049 {
3050 SetScrollPos( orient, pos, refresh );
3051 return;
3052 }
3053
3054 m_oldVerticalPos = fpos;
3055
3056 m_vAdjust->lower = 0.0;
3057 m_vAdjust->upper = frange;
3058 m_vAdjust->value = fpos;
3059 m_vAdjust->step_increment = 1.0;
3060 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
3061 m_vAdjust->page_size = fthumb;
3062 }
3063
3064 if (orient == wxHORIZONTAL)
3065 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
3066 else
3067 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
3068 }
3069
3070 void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
3071 {
3072 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
3073
3074 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
3075
3076 if (orient == wxHORIZONTAL)
3077 {
3078 float fpos = (float)pos;
3079 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
3080 if (fpos < 0.0) fpos = 0.0;
3081 m_oldHorizontalPos = fpos;
3082
3083 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
3084 m_hAdjust->value = fpos;
3085 }
3086 else
3087 {
3088 float fpos = (float)pos;
3089 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
3090 if (fpos < 0.0) fpos = 0.0;
3091 m_oldVerticalPos = fpos;
3092
3093 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
3094 m_vAdjust->value = fpos;
3095 }
3096
3097 /*
3098 if (!m_isScrolling)
3099 {
3100 */
3101 if (m_wxwindow->window)
3102 {
3103 if (orient == wxHORIZONTAL)
3104 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
3105 else
3106 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
3107 }
3108 /*
3109 }
3110 */
3111 }
3112
3113 int wxWindow::GetScrollThumb( int orient ) const
3114 {
3115 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
3116
3117 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
3118
3119 if (orient == wxHORIZONTAL)
3120 return (int)(m_hAdjust->page_size+0.5);
3121 else
3122 return (int)(m_vAdjust->page_size+0.5);
3123 }
3124
3125 int wxWindow::GetScrollPos( int orient ) const
3126 {
3127 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
3128
3129 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
3130
3131 if (orient == wxHORIZONTAL)
3132 return (int)(m_hAdjust->value+0.5);
3133 else
3134 return (int)(m_vAdjust->value+0.5);
3135 }
3136
3137 int wxWindow::GetScrollRange( int orient ) const
3138 {
3139 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
3140
3141 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
3142
3143 if (orient == wxHORIZONTAL)
3144 return (int)(m_hAdjust->upper+0.5);
3145 else
3146 return (int)(m_vAdjust->upper+0.5);
3147 }
3148
3149 void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
3150 {
3151 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
3152
3153 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
3154
3155 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3156
3157 /*
3158 if (!m_scrollGC)
3159 {
3160 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3161 gdk_gc_set_exposures( m_scrollGC, TRUE );
3162 }
3163
3164 wxNode *node = m_children.First();
3165 while (node)
3166 {
3167 wxWindow *child = (wxWindow*) node->Data();
3168 int sx = 0;
3169 int sy = 0;
3170 child->GetSize( &sx, &sy );
3171 child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
3172 node = node->Next();
3173 }
3174
3175 int cw = 0;
3176 int ch = 0;
3177 GetClientSize( &cw, &ch );
3178 int w = cw - abs(dx);
3179 int h = ch - abs(dy);
3180
3181 if ((h < 0) || (w < 0))
3182 {
3183 Refresh();
3184 }
3185 else
3186 {
3187 int s_x = 0;
3188 int s_y = 0;
3189 if (dx < 0) s_x = -dx;
3190 if (dy < 0) s_y = -dy;
3191 int d_x = 0;
3192 int d_y = 0;
3193 if (dx > 0) d_x = dx;
3194 if (dy > 0) d_y = dy;
3195
3196 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3197 m_wxwindow->window, s_x, s_y, w, h );
3198
3199 wxRect rect;
3200 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3201 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3202 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3203 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3204
3205 Refresh( TRUE, &rect );
3206 }
3207 */
3208 }
3209
3210 void wxWindow::SetScrolling(bool scroll)
3211 {
3212 m_isScrolling = g_blockEventsOnScroll = scroll;
3213 }