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