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