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