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