]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/window.cpp
1. added encoding param to wxFontEncoding::EnumFamilies() which allows to get
[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 GtkWidget *connect_widget = GetConnectWidget();
2490 if (connect_widget)
2491 {
2492 if (GTK_WIDGET_CAN_FOCUS(connect_widget) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2493 {
2494 gtk_widget_grab_focus (connect_widget);
2495 }
2496 else if (GTK_IS_CONTAINER(connect_widget))
2497 {
2498 gtk_container_focus( GTK_CONTAINER(connect_widget), GTK_DIR_TAB_FORWARD );
2499 }
2500 else
2501 {
2502 }
2503 }
2504 }
2505
2506 bool wxWindow::AcceptsFocus() const
2507 {
2508 return m_acceptsFocus && wxWindowBase::AcceptsFocus();
2509 }
2510
2511 bool wxWindow::Reparent( wxWindowBase *newParentBase )
2512 {
2513 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
2514
2515 wxWindow *oldParent = m_parent,
2516 *newParent = (wxWindow *)newParentBase;
2517
2518 wxASSERT( GTK_IS_WIDGET(m_widget) );
2519
2520 if ( !wxWindowBase::Reparent(newParent) )
2521 return FALSE;
2522
2523 wxASSERT( GTK_IS_WIDGET(m_widget) );
2524
2525 /* prevent GTK from deleting the widget arbitrarily */
2526 gtk_widget_ref( m_widget );
2527
2528 if (oldParent)
2529 {
2530 gtk_container_remove( GTK_CONTAINER(m_widget->parent), m_widget );
2531 }
2532
2533 wxASSERT( GTK_IS_WIDGET(m_widget) );
2534
2535 if (newParent)
2536 {
2537 /* insert GTK representation */
2538 (*(newParent->m_insertCallback))(newParent, this);
2539 }
2540
2541 /* reverse: prevent GTK from deleting the widget arbitrarily */
2542 gtk_widget_unref( m_widget );
2543
2544 return TRUE;
2545 }
2546
2547 void wxWindow::DoAddChild(wxWindow *child)
2548 {
2549 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
2550
2551 wxASSERT_MSG( (child != NULL), wxT("invalid child window") );
2552
2553 wxASSERT_MSG( (m_insertCallback != NULL), wxT("invalid child insertion function") );
2554
2555 /* add to list */
2556 AddChild( child );
2557
2558 /* insert GTK representation */
2559 (*m_insertCallback)(this, child);
2560 }
2561
2562 void wxWindow::Raise()
2563 {
2564 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2565
2566 if (!m_widget->window) return;
2567
2568 gdk_window_raise( m_widget->window );
2569 }
2570
2571 void wxWindow::Lower()
2572 {
2573 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2574
2575 if (!m_widget->window) return;
2576
2577 gdk_window_lower( m_widget->window );
2578 }
2579
2580 bool wxWindow::SetCursor( const wxCursor &cursor )
2581 {
2582 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
2583
2584 return wxWindowBase::SetCursor( cursor );
2585 }
2586
2587 void wxWindow::WarpPointer( int x, int y )
2588 {
2589 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2590
2591 /* we provide this function ourselves as it is
2592 missing in GDK (top of this file) */
2593
2594 GdkWindow *window = (GdkWindow*) NULL;
2595 if (m_wxwindow)
2596 window = GTK_PIZZA(m_wxwindow)->bin_window;
2597 else
2598 window = GetConnectWidget()->window;
2599
2600 if (window)
2601 gdk_window_warp_pointer( window, x, y );
2602 }
2603
2604 void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
2605 {
2606 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2607
2608 if (!m_widget->window) return;
2609
2610 if (eraseBackground && m_wxwindow && m_wxwindow->window)
2611 {
2612 if (rect)
2613 {
2614 gdk_window_clear_area( GTK_PIZZA(m_wxwindow)->bin_window,
2615 rect->x, rect->y,
2616 rect->width, rect->height );
2617 }
2618 else
2619 {
2620 gdk_window_clear( GTK_PIZZA(m_wxwindow)->bin_window );
2621 }
2622 }
2623
2624 /* there is no GTK equivalent of "draw only, don't clear" so we
2625 invent our own in the GtkPizza widget */
2626
2627 if (!rect)
2628 {
2629 if (m_wxwindow)
2630 {
2631 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
2632 gboolean old_clear = pizza->clear_on_draw;
2633 gtk_pizza_set_clear( pizza, FALSE );
2634
2635 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
2636
2637 gtk_pizza_set_clear( pizza, old_clear );
2638 }
2639 else
2640 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
2641 }
2642 else
2643 {
2644 GdkRectangle gdk_rect;
2645 gdk_rect.x = rect->x;
2646 gdk_rect.y = rect->y;
2647 gdk_rect.width = rect->width;
2648 gdk_rect.height = rect->height;
2649
2650 if (m_wxwindow)
2651 {
2652 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
2653 gboolean old_clear = pizza->clear_on_draw;
2654 gtk_pizza_set_clear( pizza, FALSE );
2655
2656 gtk_widget_draw( m_wxwindow, &gdk_rect );
2657
2658 gtk_pizza_set_clear( pizza, old_clear );
2659 }
2660 else
2661 gtk_widget_draw( m_widget, &gdk_rect );
2662 }
2663 }
2664
2665 void wxWindow::Clear()
2666 {
2667 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
2668
2669 if (!m_widget->window) return;
2670
2671 if (m_wxwindow && m_wxwindow->window)
2672 {
2673 gdk_window_clear( m_wxwindow->window );
2674 }
2675 }
2676
2677 #if wxUSE_TOOLTIPS
2678 void wxWindow::DoSetToolTip( wxToolTip *tip )
2679 {
2680 wxWindowBase::DoSetToolTip(tip);
2681
2682 if (m_tooltip)
2683 m_tooltip->Apply( this );
2684 }
2685
2686 void wxWindow::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
2687 {
2688 gtk_tooltips_set_tip( tips, GetConnectWidget(), wxConvCurrent->cWX2MB(tip), (gchar*) NULL );
2689 }
2690 #endif // wxUSE_TOOLTIPS
2691
2692 bool wxWindow::SetBackgroundColour( const wxColour &colour )
2693 {
2694 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
2695
2696 if (!wxWindowBase::SetBackgroundColour(colour))
2697 {
2698 // don't leave if the GTK widget has just
2699 // been realized
2700 if (!m_delayedBackgroundColour) return FALSE;
2701 }
2702
2703 GdkWindow *window = (GdkWindow*) NULL;
2704 if (m_wxwindow)
2705 window = GTK_PIZZA(m_wxwindow)->bin_window;
2706 else
2707 window = GetConnectWidget()->window;
2708
2709 if (!window)
2710 {
2711 // indicate that a new style has been set
2712 // but it couldn't get applied as the
2713 // widget hasn't been realized yet.
2714 m_delayedBackgroundColour = TRUE;
2715
2716 // pretend we have done something
2717 return TRUE;
2718 }
2719
2720 if (m_wxwindow)
2721 {
2722 /* wxMSW doesn't clear the window here. I don't do that either to
2723 provide compatibility. call Clear() to do the job. */
2724
2725 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
2726 gdk_window_set_background( window, m_backgroundColour.GetColor() );
2727 }
2728
2729 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2730 if (sysbg == m_backgroundColour)
2731 {
2732 m_backgroundColour = wxNullColour;
2733 ApplyWidgetStyle();
2734 m_backgroundColour = sysbg;
2735 }
2736 else
2737 {
2738 ApplyWidgetStyle();
2739 }
2740
2741 return TRUE;
2742 }
2743
2744 bool wxWindow::SetForegroundColour( const wxColour &colour )
2745 {
2746 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
2747
2748 if (!wxWindowBase::SetForegroundColour(colour))
2749 {
2750 // don't leave if the GTK widget has just
2751 // been realized
2752 if (!m_delayedForegroundColour) return FALSE;
2753 }
2754
2755 GdkWindow *window = (GdkWindow*) NULL;
2756 if (m_wxwindow)
2757 window = GTK_PIZZA(m_wxwindow)->bin_window;
2758 else
2759 window = GetConnectWidget()->window;
2760
2761 if (!window)
2762 {
2763 // indicate that a new style has been set
2764 // but it couldn't get applied as the
2765 // widget hasn't been realized yet.
2766 m_delayedForegroundColour = TRUE;
2767
2768 // pretend we have done something
2769 return TRUE;
2770 }
2771
2772 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2773 if ( sysbg == m_backgroundColour )
2774 {
2775 m_backgroundColour = wxNullColour;
2776 ApplyWidgetStyle();
2777 m_backgroundColour = sysbg;
2778 }
2779 else
2780 {
2781 ApplyWidgetStyle();
2782 }
2783
2784 return TRUE;
2785 }
2786
2787 GtkStyle *wxWindow::GetWidgetStyle()
2788 {
2789 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
2790
2791 m_widgetStyle = gtk_style_copy( gtk_widget_get_style( m_widget ) );
2792
2793 return m_widgetStyle;
2794 }
2795
2796 void wxWindow::SetWidgetStyle()
2797 {
2798 GtkStyle *style = GetWidgetStyle();
2799
2800 gdk_font_unref( style->font );
2801 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2802
2803 if (m_foregroundColour.Ok())
2804 {
2805 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2806 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2807 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2808 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2809 }
2810
2811 if (m_backgroundColour.Ok())
2812 {
2813 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2814 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2815 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2816 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2817 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2818 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2819 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2820 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2821 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2822 }
2823 }
2824
2825 void wxWindow::ApplyWidgetStyle()
2826 {
2827 }
2828
2829 //-----------------------------------------------------------------------------
2830 // Pop-up menu stuff
2831 //-----------------------------------------------------------------------------
2832
2833 static void gtk_pop_hide_callback( GtkWidget *WXUNUSED(widget), bool* is_waiting )
2834 {
2835 *is_waiting = FALSE;
2836 }
2837
2838 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2839 {
2840 menu->SetInvokingWindow( win );
2841 wxNode *node = menu->GetItems().First();
2842 while (node)
2843 {
2844 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2845 if (menuitem->IsSubMenu())
2846 {
2847 SetInvokingWindow( menuitem->GetSubMenu(), win );
2848 }
2849 node = node->Next();
2850 }
2851 }
2852
2853 static gint gs_pop_x = 0;
2854 static gint gs_pop_y = 0;
2855
2856 static void pop_pos_callback( GtkMenu * WXUNUSED(menu),
2857 gint *x, gint *y,
2858 wxWindow *win )
2859 {
2860 win->ClientToScreen( &gs_pop_x, &gs_pop_y );
2861 *x = gs_pop_x;
2862 *y = gs_pop_y;
2863 }
2864
2865 bool wxWindow::DoPopupMenu( wxMenu *menu, int x, int y )
2866 {
2867 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
2868
2869 wxCHECK_MSG( menu != NULL, FALSE, wxT("invalid popup-menu") );
2870
2871 SetInvokingWindow( menu, this );
2872
2873 menu->UpdateUI();
2874
2875 gs_pop_x = x;
2876 gs_pop_y = y;
2877
2878 bool is_waiting = TRUE;
2879
2880 gtk_signal_connect( GTK_OBJECT(menu->m_menu), "hide",
2881 GTK_SIGNAL_FUNC(gtk_pop_hide_callback), (gpointer)&is_waiting );
2882
2883 gtk_menu_popup(
2884 GTK_MENU(menu->m_menu),
2885 (GtkWidget *) NULL, // parent menu shell
2886 (GtkWidget *) NULL, // parent menu item
2887 (GtkMenuPositionFunc) pop_pos_callback,
2888 (gpointer) this, // client data
2889 0, // button used to activate it
2890 gs_timeLastClick // the time of activation
2891 );
2892
2893 while (is_waiting)
2894 {
2895 while (gtk_events_pending())
2896 gtk_main_iteration();
2897 }
2898
2899 return TRUE;
2900 }
2901
2902 #if wxUSE_DRAG_AND_DROP
2903
2904 void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2905 {
2906 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
2907
2908 GtkWidget *dnd_widget = GetConnectWidget();
2909
2910 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
2911
2912 if (m_dropTarget) delete m_dropTarget;
2913 m_dropTarget = dropTarget;
2914
2915 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
2916 }
2917
2918 #endif // wxUSE_DRAG_AND_DROP
2919
2920 GtkWidget* wxWindow::GetConnectWidget()
2921 {
2922 GtkWidget *connect_widget = m_widget;
2923 if (m_wxwindow) connect_widget = m_wxwindow;
2924
2925 return connect_widget;
2926 }
2927
2928 bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2929 {
2930 if (m_wxwindow)
2931 return (window == GTK_PIZZA(m_wxwindow)->bin_window);
2932
2933 return (window == m_widget->window);
2934 }
2935
2936 bool wxWindow::SetFont( const wxFont &font )
2937 {
2938 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
2939
2940 if (!wxWindowBase::SetFont(font))
2941 {
2942 // don't leave if the GTK widget has just
2943 // been realized
2944 if (!m_delayedFont) return FALSE;
2945 }
2946
2947 GdkWindow *window = (GdkWindow*) NULL;
2948 if (m_wxwindow)
2949 window = GTK_PIZZA(m_wxwindow)->bin_window;
2950 else
2951 window = GetConnectWidget()->window;
2952
2953 if (!window)
2954 {
2955 // indicate that a new style has been set
2956 // but it couldn't get applied as the
2957 // widget hasn't been realized yet.
2958 m_delayedFont = TRUE;
2959
2960 // pretend we have done something
2961 return TRUE;
2962 }
2963
2964 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2965 if ( sysbg == m_backgroundColour )
2966 {
2967 m_backgroundColour = wxNullColour;
2968 ApplyWidgetStyle();
2969 m_backgroundColour = sysbg;
2970 }
2971 else
2972 {
2973 ApplyWidgetStyle();
2974 }
2975
2976 return TRUE;
2977 }
2978
2979 void wxWindow::CaptureMouse()
2980 {
2981 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
2982
2983 wxCHECK_RET( g_captureWindow == NULL, wxT("CaptureMouse called twice") );
2984
2985 GdkWindow *window = (GdkWindow*) NULL;
2986 if (m_wxwindow)
2987 window = GTK_PIZZA(m_wxwindow)->bin_window;
2988 else
2989 window = GetConnectWidget()->window;
2990
2991 if (!window) return;
2992
2993 gdk_pointer_grab( window, FALSE,
2994 (GdkEventMask)
2995 (GDK_BUTTON_PRESS_MASK |
2996 GDK_BUTTON_RELEASE_MASK |
2997 GDK_POINTER_MOTION_HINT_MASK |
2998 GDK_POINTER_MOTION_MASK),
2999 (GdkWindow *) NULL,
3000 m_cursor.GetCursor(),
3001 GDK_CURRENT_TIME );
3002 g_captureWindow = this;
3003 }
3004
3005 void wxWindow::ReleaseMouse()
3006 {
3007 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
3008
3009 wxCHECK_RET( g_captureWindow, wxT("ReleaseMouse called twice") );
3010
3011 GdkWindow *window = (GdkWindow*) NULL;
3012 if (m_wxwindow)
3013 window = GTK_PIZZA(m_wxwindow)->bin_window;
3014 else
3015 window = GetConnectWidget()->window;
3016
3017 if (!window) return;
3018
3019 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
3020 g_captureWindow = (wxWindow*) NULL;
3021 }
3022
3023 bool wxWindow::IsRetained() const
3024 {
3025 return FALSE;
3026 }
3027
3028 void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
3029 int range, bool refresh )
3030 {
3031 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
3032
3033 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
3034
3035 m_hasScrolling = TRUE;
3036
3037 if (orient == wxHORIZONTAL)
3038 {
3039 float fpos = (float)pos;
3040 float frange = (float)range;
3041 float fthumb = (float)thumbVisible;
3042 if (fpos > frange-fthumb) fpos = frange-fthumb;
3043 if (fpos < 0.0) fpos = 0.0;
3044
3045 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
3046 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
3047 {
3048 SetScrollPos( orient, pos, refresh );
3049 return;
3050 }
3051
3052 m_oldHorizontalPos = fpos;
3053
3054 m_hAdjust->lower = 0.0;
3055 m_hAdjust->upper = frange;
3056 m_hAdjust->value = fpos;
3057 m_hAdjust->step_increment = 1.0;
3058 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
3059 m_hAdjust->page_size = fthumb;
3060 }
3061 else
3062 {
3063 float fpos = (float)pos;
3064 float frange = (float)range;
3065 float fthumb = (float)thumbVisible;
3066 if (fpos > frange-fthumb) fpos = frange-fthumb;
3067 if (fpos < 0.0) fpos = 0.0;
3068
3069 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
3070 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
3071 {
3072 SetScrollPos( orient, pos, refresh );
3073 return;
3074 }
3075
3076 m_oldVerticalPos = fpos;
3077
3078 m_vAdjust->lower = 0.0;
3079 m_vAdjust->upper = frange;
3080 m_vAdjust->value = fpos;
3081 m_vAdjust->step_increment = 1.0;
3082 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
3083 m_vAdjust->page_size = fthumb;
3084 }
3085
3086 if (orient == wxHORIZONTAL)
3087 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
3088 else
3089 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
3090 }
3091
3092 void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
3093 {
3094 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
3095
3096 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
3097
3098 if (orient == wxHORIZONTAL)
3099 {
3100 float fpos = (float)pos;
3101 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
3102 if (fpos < 0.0) fpos = 0.0;
3103 m_oldHorizontalPos = fpos;
3104
3105 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
3106 m_hAdjust->value = fpos;
3107 }
3108 else
3109 {
3110 float fpos = (float)pos;
3111 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
3112 if (fpos < 0.0) fpos = 0.0;
3113 m_oldVerticalPos = fpos;
3114
3115 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
3116 m_vAdjust->value = fpos;
3117 }
3118
3119 /*
3120 if (!m_isScrolling)
3121 {
3122 */
3123 if (m_wxwindow->window)
3124 {
3125 if (orient == wxHORIZONTAL)
3126 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
3127 else
3128 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
3129 }
3130 /*
3131 }
3132 */
3133 }
3134
3135 int wxWindow::GetScrollThumb( int orient ) const
3136 {
3137 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
3138
3139 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
3140
3141 if (orient == wxHORIZONTAL)
3142 return (int)(m_hAdjust->page_size+0.5);
3143 else
3144 return (int)(m_vAdjust->page_size+0.5);
3145 }
3146
3147 int wxWindow::GetScrollPos( int orient ) const
3148 {
3149 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
3150
3151 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
3152
3153 if (orient == wxHORIZONTAL)
3154 return (int)(m_hAdjust->value+0.5);
3155 else
3156 return (int)(m_vAdjust->value+0.5);
3157 }
3158
3159 int wxWindow::GetScrollRange( int orient ) const
3160 {
3161 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
3162
3163 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
3164
3165 if (orient == wxHORIZONTAL)
3166 return (int)(m_hAdjust->upper+0.5);
3167 else
3168 return (int)(m_vAdjust->upper+0.5);
3169 }
3170
3171 void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
3172 {
3173 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
3174
3175 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
3176
3177 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3178
3179 /*
3180 if (!m_scrollGC)
3181 {
3182 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3183 gdk_gc_set_exposures( m_scrollGC, TRUE );
3184 }
3185
3186 wxNode *node = m_children.First();
3187 while (node)
3188 {
3189 wxWindow *child = (wxWindow*) node->Data();
3190 int sx = 0;
3191 int sy = 0;
3192 child->GetSize( &sx, &sy );
3193 child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
3194 node = node->Next();
3195 }
3196
3197 int cw = 0;
3198 int ch = 0;
3199 GetClientSize( &cw, &ch );
3200 int w = cw - abs(dx);
3201 int h = ch - abs(dy);
3202
3203 if ((h < 0) || (w < 0))
3204 {
3205 Refresh();
3206 }
3207 else
3208 {
3209 int s_x = 0;
3210 int s_y = 0;
3211 if (dx < 0) s_x = -dx;
3212 if (dy < 0) s_y = -dy;
3213 int d_x = 0;
3214 int d_y = 0;
3215 if (dx > 0) d_x = dx;
3216 if (dy > 0) d_y = dy;
3217
3218 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3219 m_wxwindow->window, s_x, s_y, w, h );
3220
3221 wxRect rect;
3222 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3223 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3224 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3225 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3226
3227 Refresh( TRUE, &rect );
3228 }
3229 */
3230 }
3231
3232 void wxWindow::SetScrolling(bool scroll)
3233 {
3234 m_isScrolling = g_blockEventsOnScroll = scroll;
3235 }