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