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