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