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