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