]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/window.cpp
fixed the rule for the DLL so it doesn't build the .lib file twice
[wxWidgets.git] / src / gtk1 / 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;
65045edd 135 wxWindow *g_focusWindow = (wxWindow*) NULL;
f03fc89f
VZ
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),
014b0d06 149 const wxChar *WXUNUSED(name) )
2e563988 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
053f9cc1 815 /* win is a control: tab can be propagated up */
ca298c88 816 if ( (!ret) &&
5664fc32 817 ((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
f03fc89f 818 (win->HasFlag(wxTE_PROCESS_TAB) == 0))
b292e2f5
RR
819 {
820 wxNavigationKeyEvent new_event;
f03fc89f 821 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
5664fc32 822 new_event.SetDirection( (gdk_event->keyval == GDK_Tab) );
f03fc89f 823 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
b98d804b 824 new_event.SetWindowChange( (gdk_event->state & GDK_CONTROL_MASK) );
b292e2f5 825 new_event.SetCurrentFocus( win );
ff8bfdbb 826 ret = win->GetEventHandler()->ProcessEvent( new_event );
b292e2f5 827 }
ff8bfdbb 828
801aa178 829 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
ca298c88 830 if ( (!ret) &&
b98d804b
RR
831 (gdk_event->keyval == GDK_Escape) )
832 {
833 wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
834 new_event.SetEventObject( win );
835 ret = win->GetEventHandler()->ProcessEvent( new_event );
836 }
c50f1fb9 837
6bc8a1c8 838#if (GTK_MINOR_VERSION > 0)
801aa178
RR
839 /* pressing F10 will activate the menu bar of the top frame */
840 if ( (!ret) &&
841 (gdk_event->keyval == GDK_F10) )
842 {
843 wxWindow *ancestor = win;
844 while (ancestor)
845 {
846 if (wxIsKindOf(ancestor,wxFrame))
c50f1fb9
VZ
847 {
848 wxFrame *frame = (wxFrame*) ancestor;
801aa178 849 wxMenuBar *menubar = frame->GetMenuBar();
c50f1fb9
VZ
850 if (menubar)
851 {
801aa178 852 wxNode *node = menubar->GetMenus().First();
c50f1fb9
VZ
853 if (node)
854 {
855 // doesn't work correctly
88ac883a 856 // wxMenu *firstMenu = (wxMenu*) node->Data();
c50f1fb9
VZ
857 // gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
858 // ret = TRUE;
859 break;
860 }
861 }
862 }
801aa178
RR
863 ancestor = ancestor->GetParent();
864 }
865 }
6bc8a1c8 866#endif
ca298c88 867
b292e2f5 868/*
b98d804b
RR
869 Damn, I forgot why this didn't work, but it didn't work.
870
b292e2f5 871 // win is a panel: up can be propagated to the panel
a2053b27 872 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
b292e2f5
RR
873 (gdk_event->keyval == GDK_Up))
874 {
875 win->m_parent->SetFocus();
ff8bfdbb 876 ret = TRUE;
b292e2f5 877 }
ff8bfdbb 878
b292e2f5 879 // win is a panel: left/right can be propagated to the panel
a2053b27 880 if ((!ret) && (win->m_wxwindow) &&
ff8bfdbb 881 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
b292e2f5
RR
882 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
883 {
884 wxNavigationKeyEvent new_event;
885 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
886 new_event.SetCurrentFocus( win );
ff8bfdbb 887 ret = win->GetEventHandler()->ProcessEvent( new_event );
b292e2f5
RR
888 }
889*/
ff8bfdbb 890
f5e27805
RR
891 if (ret)
892 {
b292e2f5 893 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
f03fc89f 894 return TRUE;
f5e27805 895 }
47d67540 896
034be888 897 return FALSE;
362c6693 898}
c801d85f 899
b666df2c
RR
900//-----------------------------------------------------------------------------
901// "key_release_event" from any window
902//-----------------------------------------------------------------------------
903
904static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
905{
c50f1fb9 906 if (g_isIdle)
a2053b27
RR
907 wxapp_install_idle_handler();
908
909 if (!win->m_hasVMT) return FALSE;
b666df2c
RR
910 if (g_blockEventsOnDrag) return FALSE;
911
912/*
d1367c3d
RR
913 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
914 if (gdk_event->state & GDK_SHIFT_MASK)
915 printf( "ShiftDown.\n" );
916 else
917 printf( "ShiftUp.\n" );
918 if (gdk_event->state & GDK_CONTROL_MASK)
919 printf( "ControlDown.\n" );
920 else
921 printf( "ControlUp.\n" );
922 printf( "\n" );
b666df2c
RR
923*/
924
74505862 925 long key_code = map_to_unmodified_wx_keysym( gdk_event->keyval );
c50f1fb9 926
f0492f7d
RR
927 /* sending unknown key events doesn't really make sense */
928 if (key_code == 0) return FALSE;
b666df2c 929
b0e813a0
RR
930 int x = 0;
931 int y = 0;
932 GdkModifierType state;
933 if (gdk_event->window) gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
b666df2c
RR
934
935 wxKeyEvent event( wxEVT_KEY_UP );
d1367c3d 936 event.SetTimestamp( gdk_event->time );
b666df2c
RR
937 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
938 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
939 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
940 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
941 event.m_keyCode = key_code;
b0e813a0
RR
942 event.m_scanCode = gdk_event->keyval;
943 event.m_x = x;
944 event.m_y = y;
b666df2c
RR
945 event.SetEventObject( win );
946
034be888 947 if (win->GetEventHandler()->ProcessEvent( event ))
b666df2c 948 {
b98d804b 949 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_release_event" );
f03fc89f 950 return TRUE;
b666df2c
RR
951 }
952
034be888 953 return FALSE;
b666df2c
RR
954}
955
c801d85f 956//-----------------------------------------------------------------------------
2f2aa628
RR
957// "button_press_event"
958//-----------------------------------------------------------------------------
c801d85f 959
2f2aa628 960static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
903f689b 961{
c50f1fb9 962 if (g_isIdle)
a2053b27
RR
963 wxapp_install_idle_handler();
964
965/*
966 wxPrintf( _T("1) OnButtonPress from ") );
967 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
968 wxPrintf( win->GetClassInfo()->GetClassName() );
969 wxPrintf( _T(".\n") );
970*/
a2053b27 971 if (!win->m_hasVMT) return FALSE;
f5e27805 972 if (g_blockEventsOnDrag) return TRUE;
76ed8f8d 973 if (g_blockEventsOnScroll) return TRUE;
c801d85f 974
034be888
RR
975 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
976
a2053b27 977 if (win->m_wxwindow)
c801d85f 978 {
a2053b27 979 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow) && !GTK_WIDGET_HAS_FOCUS (win->m_wxwindow) )
f5e27805 980 {
a2053b27 981 gtk_widget_grab_focus (win->m_wxwindow);
47d67540 982
c801d85f 983/*
a2053b27 984 wxPrintf( _T("GrabFocus from ") );
f5e27805 985 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
a2053b27
RR
986 wxPrintf( win->GetClassInfo()->GetClassName() );
987 wxPrintf( _T(".\n") );
c801d85f 988*/
47d67540 989
f5e27805 990 }
362c6693 991 }
47d67540 992
8429bec1 993/*
a2053b27 994 wxPrintf( _T("2) OnButtonPress from ") );
f5e27805 995 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
a2053b27
RR
996 wxPrintf( win->GetClassInfo()->GetClassName() );
997 wxPrintf( _T(".\n") );
8429bec1 998*/
30dea054 999
f5e27805 1000 wxEventType event_type = wxEVT_LEFT_DOWN;
47d67540 1001
f5e27805 1002 if (gdk_event->button == 1)
c801d85f 1003 {
f5e27805
RR
1004 switch (gdk_event->type)
1005 {
1006 case GDK_BUTTON_PRESS: event_type = wxEVT_LEFT_DOWN; break;
1007 case GDK_2BUTTON_PRESS: event_type = wxEVT_LEFT_DCLICK; break;
1008 default: break;
1009 }
362c6693 1010 }
f5e27805 1011 else if (gdk_event->button == 2)
c801d85f 1012 {
f5e27805
RR
1013 switch (gdk_event->type)
1014 {
1015 case GDK_BUTTON_PRESS: event_type = wxEVT_MIDDLE_DOWN; break;
1016 case GDK_2BUTTON_PRESS: event_type = wxEVT_MIDDLE_DCLICK; break;
1017 default: break;
1018 }
362c6693 1019 }
f5e27805 1020 else if (gdk_event->button == 3)
c801d85f 1021 {
f5e27805
RR
1022 switch (gdk_event->type)
1023 {
1024 case GDK_BUTTON_PRESS: event_type = wxEVT_RIGHT_DOWN; break;
1025 case GDK_2BUTTON_PRESS: event_type = wxEVT_RIGHT_DCLICK; break;
1026 default: break;
1027 }
362c6693 1028 }
47d67540 1029
f5e27805 1030 wxMouseEvent event( event_type );
d1367c3d 1031 event.SetTimestamp( gdk_event->time );
f5e27805
RR
1032 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1033 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1034 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1035 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1036 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1037 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1038 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
47d67540 1039
f5e27805
RR
1040 event.m_x = (long)gdk_event->x;
1041 event.m_y = (long)gdk_event->y;
47d67540 1042
f5e27805
RR
1043 // Some control don't have their own X window and thus cannot get
1044 // any events.
47d67540 1045
72195a0f 1046 if (!g_captureWindow)
2f2aa628 1047 {
db1b4961 1048 wxNode *node = win->GetChildren().First();
f5e27805
RR
1049 while (node)
1050 {
1051 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb 1052
a2053b27 1053 if (child->m_isStaticBox)
ff8bfdbb
VZ
1054 {
1055 // wxStaticBox is transparent in the box itself
a2053b27
RR
1056 int x = event.m_x;
1057 int y = event.m_y;
1058 int xx1 = child->m_x;
1059 int yy1 = child->m_y;
1060 int xx2 = child->m_x + child->m_width;
1061 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1062
1063 // left
1064 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1065 // right
1066 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1067 // top
1068 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1069 // bottom
1070 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1071 {
1ecc4d80 1072 win = child;
a2053b27
RR
1073 event.m_x -= child->m_x;
1074 event.m_y -= child->m_y;
1ecc4d80 1075 break;
ff8bfdbb
VZ
1076 }
1077
1078 }
1079 else
1080 {
a2053b27
RR
1081 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
1082 (child->m_x <= event.m_x) &&
1083 (child->m_y <= event.m_y) &&
1084 (child->m_x+child->m_width >= event.m_x) &&
1085 (child->m_y+child->m_height >= event.m_y))
1ecc4d80
RR
1086 {
1087 win = child;
a2053b27
RR
1088 event.m_x -= child->m_x;
1089 event.m_y -= child->m_y;
1ecc4d80 1090 break;
ff8bfdbb 1091 }
f5e27805
RR
1092 }
1093 node = node->Next();
1094 }
2f2aa628 1095 }
ff8bfdbb 1096
f5e27805 1097 event.SetEventObject( win );
47d67540 1098
f5e27805 1099 gs_timeLastClick = gdk_event->time;
47d67540 1100
f5e27805 1101 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1102 {
f5e27805 1103 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
f03fc89f 1104 return TRUE;
034be888 1105 }
47d67540 1106
034be888 1107 return FALSE;
362c6693 1108}
c801d85f
KB
1109
1110//-----------------------------------------------------------------------------
97b3455a 1111// "button_release_event"
2f2aa628 1112//-----------------------------------------------------------------------------
c801d85f 1113
2f2aa628 1114static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
47d67540 1115{
c50f1fb9 1116 if (g_isIdle)
a2053b27
RR
1117 wxapp_install_idle_handler();
1118
1119 if (!win->m_hasVMT) return FALSE;
034be888
RR
1120 if (g_blockEventsOnDrag) return FALSE;
1121 if (g_blockEventsOnScroll) return FALSE;
c801d85f 1122
034be888 1123 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
47d67540 1124
c801d85f 1125/*
f5e27805
RR
1126 printf( "OnButtonRelease from " );
1127 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1128 printf( win->GetClassInfo()->GetClassName() );
1129 printf( ".\n" );
c801d85f 1130*/
47d67540 1131
f5e27805 1132 wxEventType event_type = wxEVT_NULL;
47d67540 1133
f5e27805
RR
1134 switch (gdk_event->button)
1135 {
1136 case 1: event_type = wxEVT_LEFT_UP; break;
1137 case 2: event_type = wxEVT_MIDDLE_UP; break;
1138 case 3: event_type = wxEVT_RIGHT_UP; break;
1139 }
47d67540 1140
f5e27805 1141 wxMouseEvent event( event_type );
d1367c3d 1142 event.SetTimestamp( gdk_event->time );
f5e27805
RR
1143 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1144 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1145 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1146 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1147 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1148 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1149 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
1150 event.m_x = (long)gdk_event->x;
1151 event.m_y = (long)gdk_event->y;
1152
1153 // Some control don't have their own X window and thus cannot get
1154 // any events.
1155
72195a0f 1156 if (!g_captureWindow)
2f2aa628 1157 {
db1b4961 1158 wxNode *node = win->GetChildren().First();
f5e27805
RR
1159 while (node)
1160 {
1161 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb 1162
a2053b27 1163 if (child->m_isStaticBox)
ff8bfdbb
VZ
1164 {
1165 // wxStaticBox is transparent in the box itself
1166 int x = event.m_x;
1167 int y = event.m_y;
a2053b27
RR
1168 int xx1 = child->m_x;
1169 int yy1 = child->m_y;
1170 int xx2 = child->m_x + child->m_width;
1171 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1172
1173 // left
1174 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1175 // right
1176 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1177 // top
1178 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1179 // bottom
1180 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1181 {
1ecc4d80 1182 win = child;
a2053b27
RR
1183 event.m_x -= child->m_x;
1184 event.m_y -= child->m_y;
1ecc4d80 1185 break;
ff8bfdbb
VZ
1186 }
1187
1188 }
1189 else
1190 {
a2053b27
RR
1191 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
1192 (child->m_x <= event.m_x) &&
1193 (child->m_y <= event.m_y) &&
1194 (child->m_x+child->m_width >= event.m_x) &&
1195 (child->m_y+child->m_height >= event.m_y))
1ecc4d80
RR
1196 {
1197 win = child;
a2053b27
RR
1198 event.m_x -= child->m_x;
1199 event.m_y -= child->m_y;
1ecc4d80 1200 break;
ff8bfdbb 1201 }
f5e27805
RR
1202 }
1203 node = node->Next();
1204 }
2f2aa628 1205 }
47d67540 1206
f5e27805 1207 event.SetEventObject( win );
47d67540 1208
f5e27805 1209 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1210 {
f5e27805 1211 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" );
f03fc89f 1212 return TRUE;
034be888 1213 }
47d67540 1214
034be888 1215 return FALSE;
362c6693 1216}
c801d85f
KB
1217
1218//-----------------------------------------------------------------------------
2f2aa628
RR
1219// "motion_notify_event"
1220//-----------------------------------------------------------------------------
c801d85f 1221
2f2aa628 1222static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
47d67540 1223{
c50f1fb9 1224 if (g_isIdle)
a2053b27
RR
1225 wxapp_install_idle_handler();
1226
1227 if (!win->m_hasVMT) return FALSE;
034be888
RR
1228 if (g_blockEventsOnDrag) return FALSE;
1229 if (g_blockEventsOnScroll) return FALSE;
1230
1231 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1232
ff8bfdbb 1233 if (gdk_event->is_hint)
aae24d21
RR
1234 {
1235 int x = 0;
1236 int y = 0;
1237 GdkModifierType state;
1238 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
1239 gdk_event->x = x;
1240 gdk_event->y = y;
1241 gdk_event->state = state;
1242 }
ff8bfdbb 1243
c801d85f 1244/*
e380f72b
RR
1245 printf( "OnMotion from " );
1246 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1247 printf( win->GetClassInfo()->GetClassName() );
1248 printf( ".\n" );
aae24d21 1249*/
47d67540 1250
e380f72b 1251 wxMouseEvent event( wxEVT_MOTION );
d1367c3d 1252 event.SetTimestamp( gdk_event->time );
e380f72b
RR
1253 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1254 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1255 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1256 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1257 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1258 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1259 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
1260
1261 event.m_x = (long)gdk_event->x;
1262 event.m_y = (long)gdk_event->y;
1263
1264 // Some control don't have their own X window and thus cannot get
1265 // any events.
1266
72195a0f 1267 if (!g_captureWindow)
2f2aa628 1268 {
db1b4961 1269 wxNode *node = win->GetChildren().First();
e380f72b
RR
1270 while (node)
1271 {
1272 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb 1273
a2053b27 1274 if (child->m_isStaticBox)
ff8bfdbb
VZ
1275 {
1276 // wxStaticBox is transparent in the box itself
1277 int x = event.m_x;
1278 int y = event.m_y;
a2053b27
RR
1279 int xx1 = child->m_x;
1280 int yy1 = child->m_y;
1281 int xx2 = child->m_x + child->m_width;
1282 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1283
1284 // left
1285 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1286 // right
1287 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1288 // top
1289 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1290 // bottom
1291 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1292 {
1ecc4d80 1293 win = child;
a2053b27
RR
1294 event.m_x -= child->m_x;
1295 event.m_y -= child->m_y;
1ecc4d80 1296 break;
ff8bfdbb
VZ
1297 }
1298
1299 }
1300 else
1301 {
a2053b27
RR
1302 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
1303 (child->m_x <= event.m_x) &&
1304 (child->m_y <= event.m_y) &&
1305 (child->m_x+child->m_width >= event.m_x) &&
1306 (child->m_y+child->m_height >= event.m_y))
1ecc4d80
RR
1307 {
1308 win = child;
a2053b27
RR
1309 event.m_x -= child->m_x;
1310 event.m_y -= child->m_y;
1ecc4d80 1311 break;
ff8bfdbb 1312 }
e380f72b
RR
1313 }
1314 node = node->Next();
1315 }
2f2aa628 1316 }
47d67540 1317
e380f72b 1318 event.SetEventObject( win );
47d67540 1319
e380f72b 1320 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1321 {
e380f72b 1322 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
f03fc89f 1323 return TRUE;
034be888 1324 }
47d67540 1325
034be888 1326 return FALSE;
362c6693 1327}
c801d85f
KB
1328
1329//-----------------------------------------------------------------------------
2f2aa628
RR
1330// "focus_in_event"
1331//-----------------------------------------------------------------------------
c801d85f 1332
2f2aa628 1333static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
c801d85f 1334{
c50f1fb9 1335 if (g_isIdle)
a2053b27
RR
1336 wxapp_install_idle_handler();
1337
1338 if (!win->m_hasVMT) return FALSE;
034be888 1339 if (g_blockEventsOnDrag) return FALSE;
ff8bfdbb 1340
b292e2f5 1341 g_focusWindow = win;
ff8bfdbb 1342
a2053b27 1343 if (win->m_wxwindow)
c801d85f 1344 {
a2053b27 1345 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
e380f72b 1346 {
a2053b27 1347 GTK_WIDGET_SET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
47d67540 1348/*
e380f72b
RR
1349 printf( "SetFocus flag from " );
1350 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1351 printf( win->GetClassInfo()->GetClassName() );
1352 printf( ".\n" );
c801d85f 1353*/
e380f72b 1354 }
362c6693 1355 }
47d67540 1356
47d67540 1357
c801d85f 1358/*
f03fc89f 1359 printf( "OnSetFocus from " );
e380f72b 1360 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
f03fc89f
VZ
1361 printf( win->GetClassInfo()->GetClassName() );
1362 printf( " " );
1363 printf( WXSTRINGCAST win->GetLabel() );
1364 printf( ".\n" );
c801d85f 1365*/
47d67540 1366
e380f72b
RR
1367 wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
1368 event.SetEventObject( win );
47d67540 1369
e380f72b 1370 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1371 {
e380f72b 1372 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
034be888
RR
1373 return TRUE;
1374 }
ca298c88 1375
034be888 1376 return FALSE;
362c6693 1377}
c801d85f
KB
1378
1379//-----------------------------------------------------------------------------
2f2aa628
RR
1380// "focus_out_event"
1381//-----------------------------------------------------------------------------
c801d85f 1382
2f2aa628 1383static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
c801d85f 1384{
c50f1fb9 1385 if (g_isIdle)
a2053b27
RR
1386 wxapp_install_idle_handler();
1387
1388 if (!win->m_hasVMT) return FALSE;
034be888 1389 if (g_blockEventsOnDrag) return FALSE;
ca298c88 1390
a2053b27 1391 if (win->m_wxwindow)
e380f72b 1392 {
a2053b27
RR
1393 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
1394 GTK_WIDGET_UNSET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
e380f72b 1395 }
47d67540 1396
c801d85f 1397/*
f03fc89f 1398 printf( "OnKillFocus from " );
e380f72b 1399 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
f03fc89f
VZ
1400 printf( win->GetClassInfo()->GetClassName() );
1401 printf( ".\n" );
c801d85f 1402*/
47d67540 1403
e380f72b
RR
1404 wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
1405 event.SetEventObject( win );
47d67540 1406
e380f72b 1407 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1408 {
e380f72b 1409 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
034be888
RR
1410 return TRUE;
1411 }
ca298c88 1412
034be888 1413 return FALSE;
362c6693 1414}
c801d85f 1415
b4071e91
RR
1416//-----------------------------------------------------------------------------
1417// "enter_notify_event"
1418//-----------------------------------------------------------------------------
1419
1420static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1421{
c50f1fb9 1422 if (g_isIdle)
a2053b27 1423 wxapp_install_idle_handler();
ca298c88 1424
a2053b27
RR
1425 if (!win->m_hasVMT) return FALSE;
1426 if (g_blockEventsOnDrag) return FALSE;
47d67540 1427
a2053b27 1428 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
b292e2f5 1429
e380f72b 1430 wxMouseEvent event( wxEVT_ENTER_WINDOW );
6bc8a1c8 1431#if (GTK_MINOR_VERSION > 0)
d1367c3d 1432 event.SetTimestamp( gdk_event->time );
6bc8a1c8 1433#endif
e380f72b 1434 event.SetEventObject( win );
ff8bfdbb 1435
4a33eba6
RR
1436 int x = 0;
1437 int y = 0;
1438 GdkModifierType state = (GdkModifierType)0;
ff8bfdbb 1439
a2053b27 1440 gdk_window_get_pointer( widget->window, &x, &y, &state );
ff8bfdbb 1441
4a33eba6
RR
1442 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1443 event.m_controlDown = (state & GDK_CONTROL_MASK);
1444 event.m_altDown = (state & GDK_MOD1_MASK);
1445 event.m_metaDown = (state & GDK_MOD2_MASK);
1446 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1447 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1448 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1449
1450 event.m_x = (long)x;
1451 event.m_y = (long)y;
ff8bfdbb 1452
e380f72b 1453 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1454 {
e380f72b 1455 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "enter_notify_event" );
034be888
RR
1456 return TRUE;
1457 }
ca298c88 1458
034be888 1459 return FALSE;
b4071e91 1460}
47d67540 1461
b4071e91
RR
1462//-----------------------------------------------------------------------------
1463// "leave_notify_event"
1464//-----------------------------------------------------------------------------
1465
1466static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1467{
c50f1fb9 1468 if (g_isIdle)
a2053b27 1469 wxapp_install_idle_handler();
acfd422a 1470
a2053b27
RR
1471 if (!win->m_hasVMT) return FALSE;
1472 if (g_blockEventsOnDrag) return FALSE;
b292e2f5 1473
a2053b27 1474 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
c50f1fb9 1475
e380f72b 1476 wxMouseEvent event( wxEVT_LEAVE_WINDOW );
6bc8a1c8 1477#if (GTK_MINOR_VERSION > 0)
d1367c3d 1478 event.SetTimestamp( gdk_event->time );
6bc8a1c8 1479#endif
e380f72b 1480 event.SetEventObject( win );
47d67540 1481
4a33eba6
RR
1482 int x = 0;
1483 int y = 0;
1484 GdkModifierType state = (GdkModifierType)0;
ff8bfdbb 1485
4a33eba6 1486 gdk_window_get_pointer( widget->window, &x, &y, &state );
ff8bfdbb 1487
4a33eba6
RR
1488 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1489 event.m_controlDown = (state & GDK_CONTROL_MASK);
1490 event.m_altDown = (state & GDK_MOD1_MASK);
1491 event.m_metaDown = (state & GDK_MOD2_MASK);
1492 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1493 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1494 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1495
1496 event.m_x = (long)x;
1497 event.m_y = (long)y;
ff8bfdbb 1498
e380f72b 1499 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1500 {
e380f72b 1501 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "leave_notify_event" );
034be888
RR
1502 return TRUE;
1503 }
ca298c88 1504
034be888 1505 return FALSE;
b4071e91 1506}
47d67540 1507
c801d85f 1508//-----------------------------------------------------------------------------
2f2aa628
RR
1509// "value_changed" from m_vAdjust
1510//-----------------------------------------------------------------------------
c801d85f 1511
2f2aa628 1512static void gtk_window_vscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
c801d85f 1513{
c50f1fb9 1514 if (g_isIdle)
a2053b27 1515 wxapp_install_idle_handler();
c801d85f 1516
a2053b27 1517 if (g_blockEventsOnDrag) return;
47d67540 1518
a2053b27 1519 if (!win->m_hasVMT) return;
47d67540 1520
a2053b27 1521 float diff = win->m_vAdjust->value - win->m_oldVerticalPos;
e380f72b 1522 if (fabs(diff) < 0.2) return;
a2053b27 1523 win->m_oldVerticalPos = win->m_vAdjust->value;
47d67540 1524
e380f72b 1525 wxEventType command = wxEVT_NULL;
47d67540 1526
a2053b27
RR
1527 float line_step = win->m_vAdjust->step_increment;
1528 float page_step = win->m_vAdjust->page_increment;
47d67540 1529
f03fc89f 1530 if (win->IsScrolling())
76ed8f8d 1531 {
c5b42c87 1532 command = wxEVT_SCROLLWIN_THUMBTRACK;
76ed8f8d
RR
1533 }
1534 else
1535 {
c5b42c87
RR
1536 if (fabs(win->m_vAdjust->value-win->m_vAdjust->lower) < 0.2) command = wxEVT_SCROLLWIN_BOTTOM;
1537 else if (fabs(win->m_vAdjust->value-win->m_vAdjust->upper) < 0.2) command = wxEVT_SCROLLWIN_TOP;
1538 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLLWIN_LINEDOWN;
1539 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLLWIN_LINEUP;
1540 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLLWIN_PAGEDOWN;
1541 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLLWIN_PAGEUP;
1542 else command = wxEVT_SCROLLWIN_THUMBTRACK;
76ed8f8d 1543 }
47d67540 1544
a2053b27 1545 int value = (int)(win->m_vAdjust->value+0.5);
c801d85f 1546
c5b42c87 1547 wxScrollWinEvent event( command, value, wxVERTICAL );
e380f72b
RR
1548 event.SetEventObject( win );
1549 win->GetEventHandler()->ProcessEvent( event );
362c6693 1550}
c801d85f
KB
1551
1552//-----------------------------------------------------------------------------
2f2aa628
RR
1553// "value_changed" from m_hAdjust
1554//-----------------------------------------------------------------------------
c801d85f 1555
2f2aa628 1556static void gtk_window_hscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
47d67540 1557{
c50f1fb9 1558 if (g_isIdle)
a2053b27 1559 wxapp_install_idle_handler();
47d67540 1560
a2053b27
RR
1561 if (g_blockEventsOnDrag) return;
1562 if (!win->m_hasVMT) return;
47d67540 1563
a2053b27 1564 float diff = win->m_hAdjust->value - win->m_oldHorizontalPos;
e380f72b 1565 if (fabs(diff) < 0.2) return;
a2053b27 1566 win->m_oldHorizontalPos = win->m_hAdjust->value;
47d67540 1567
e380f72b 1568 wxEventType command = wxEVT_NULL;
47d67540 1569
a2053b27
RR
1570 float line_step = win->m_hAdjust->step_increment;
1571 float page_step = win->m_hAdjust->page_increment;
8bbe427f 1572
f03fc89f 1573 if (win->IsScrolling())
76ed8f8d 1574 {
c5b42c87 1575 command = wxEVT_SCROLLWIN_THUMBTRACK;
76ed8f8d
RR
1576 }
1577 else
1578 {
c5b42c87
RR
1579 if (fabs(win->m_hAdjust->value-win->m_hAdjust->lower) < 0.2) command = wxEVT_SCROLLWIN_BOTTOM;
1580 else if (fabs(win->m_hAdjust->value-win->m_hAdjust->upper) < 0.2) command = wxEVT_SCROLLWIN_TOP;
1581 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLLWIN_LINEDOWN;
1582 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLLWIN_LINEUP;
1583 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLLWIN_PAGEDOWN;
1584 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLLWIN_PAGEUP;
1585 else command = wxEVT_SCROLLWIN_THUMBTRACK;
76ed8f8d 1586 }
c801d85f 1587
a2053b27 1588 int value = (int)(win->m_hAdjust->value+0.5);
47d67540 1589
c5b42c87 1590 wxScrollWinEvent event( command, value, wxHORIZONTAL );
e380f72b
RR
1591 event.SetEventObject( win );
1592 win->GetEventHandler()->ProcessEvent( event );
362c6693 1593}
c801d85f
KB
1594
1595//-----------------------------------------------------------------------------
2f2aa628
RR
1596// "changed" from m_vAdjust
1597//-----------------------------------------------------------------------------
c801d85f 1598
2f2aa628 1599static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
c801d85f 1600{
c50f1fb9 1601 if (g_isIdle)
a2053b27 1602 wxapp_install_idle_handler();
c801d85f 1603
a2053b27
RR
1604 if (g_blockEventsOnDrag) return;
1605 if (!win->m_hasVMT) return;
47d67540 1606
c5b42c87 1607 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
a2053b27 1608 int value = (int)(win->m_vAdjust->value+0.5);
c801d85f 1609
c5b42c87 1610 wxScrollWinEvent event( command, value, wxVERTICAL );
e380f72b
RR
1611 event.SetEventObject( win );
1612 win->GetEventHandler()->ProcessEvent( event );
362c6693 1613}
c801d85f
KB
1614
1615//-----------------------------------------------------------------------------
2f2aa628
RR
1616// "changed" from m_hAdjust
1617//-----------------------------------------------------------------------------
c801d85f 1618
2f2aa628 1619static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
47d67540 1620{
c50f1fb9 1621 if (g_isIdle)
a2053b27 1622 wxapp_install_idle_handler();
47d67540 1623
a2053b27
RR
1624 if (g_blockEventsOnDrag) return;
1625 if (!win->m_hasVMT) return;
47d67540 1626
c5b42c87 1627 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
a2053b27 1628 int value = (int)(win->m_hAdjust->value+0.5);
47d67540 1629
c5b42c87 1630 wxScrollWinEvent event( command, value, wxHORIZONTAL );
e380f72b
RR
1631 event.SetEventObject( win );
1632 win->GetEventHandler()->ProcessEvent( event );
362c6693 1633}
c801d85f 1634
cb43b372
RR
1635//-----------------------------------------------------------------------------
1636// "button_press_event" from scrollbar
1637//-----------------------------------------------------------------------------
1638
8bbe427f
VZ
1639static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
1640 GdkEventButton *WXUNUSED(gdk_event),
ff8bfdbb 1641 wxWindow *win )
cb43b372 1642{
c50f1fb9 1643 if (g_isIdle)
a2053b27
RR
1644 wxapp_install_idle_handler();
1645
1ecc4d80
RR
1646// don't test here as we can release the mouse while being over
1647// a different window then the slider
1648//
76ed8f8d 1649// if (gdk_event->window != widget->slider) return FALSE;
8bbe427f 1650
f03fc89f 1651 win->SetScrolling( TRUE );
47d67540 1652
e380f72b 1653 return FALSE;
cb43b372
RR
1654}
1655
1656//-----------------------------------------------------------------------------
1657// "button_release_event" from scrollbar
1658//-----------------------------------------------------------------------------
1659
8bbe427f
VZ
1660static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
1661 GdkEventButton *WXUNUSED(gdk_event),
ff8bfdbb 1662 wxWindow *win )
cb43b372 1663{
76ed8f8d 1664
1ecc4d80 1665// don't test here as we can release the mouse while being over
76ed8f8d
RR
1666// a different window then the slider
1667//
1668// if (gdk_event->window != widget->slider) return FALSE;
cb43b372 1669
a2053b27 1670 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
47d67540 1671
f03fc89f 1672 if (widget == GTK_RANGE(scrolledWindow->vscrollbar))
a2053b27 1673 gtk_signal_emit_by_name( GTK_OBJECT(win->m_hAdjust), "value_changed" );
e380f72b 1674 else
a2053b27 1675 gtk_signal_emit_by_name( GTK_OBJECT(win->m_vAdjust), "value_changed" );
47d67540 1676
f03fc89f 1677 win->SetScrolling( FALSE );
47d67540 1678
e380f72b 1679 return FALSE;
cb43b372
RR
1680}
1681
f03fc89f
VZ
1682// ----------------------------------------------------------------------------
1683// this wxWindowBase function is implemented here (in platform-specific file)
1684// because it is static and so couldn't be made virtual
1685// ----------------------------------------------------------------------------
2b07d713 1686
f03fc89f 1687wxWindow *wxWindowBase::FindFocus()
2b07d713 1688{
f03fc89f 1689 return g_focusWindow;
2b07d713 1690}
ca298c88 1691
a2053b27
RR
1692//-----------------------------------------------------------------------------
1693// "realize" from m_widget
1694//-----------------------------------------------------------------------------
1695
1696/* we cannot set colours, fonts and cursors before the widget has
1697 been realized, so we do this directly after realization */
1698
1699static gint
a234a61a 1700gtk_window_realized_callback( GtkWidget * WXUNUSED(widget), wxWindow *win )
a2053b27 1701{
c50f1fb9 1702 if (g_isIdle)
a2053b27
RR
1703 wxapp_install_idle_handler();
1704
739730ca
RR
1705 if (win->m_delayedFont)
1706 win->SetFont( win->GetFont() );
a2053b27 1707
739730ca
RR
1708 if (win->m_delayedBackgroundColour)
1709 win->SetBackgroundColour( win->GetBackgroundColour() );
a2053b27 1710
739730ca
RR
1711 if (win->m_delayedForegroundColour)
1712 win->SetForegroundColour( win->GetForegroundColour() );
a2053b27 1713
739730ca 1714 win->SetCursor( win->GetCursor() );
c50f1fb9 1715
3c679789
RR
1716 wxWindowCreateEvent event( win );
1717 event.SetEventObject( win );
1718 win->GetEventHandler()->ProcessEvent( event );
a2053b27
RR
1719
1720 return FALSE;
1721}
1722
6ca41e57
RR
1723//-----------------------------------------------------------------------------
1724// InsertChild for wxWindow.
1725//-----------------------------------------------------------------------------
1726
b1170810
RR
1727/* Callback for wxWindow. This very strange beast has to be used because
1728 * C++ has no virtual methods in a constructor. We have to emulate a
1729 * virtual function here as wxNotebook requires a different way to insert
1730 * a child in it. I had opted for creating a wxNotebookPage window class
1731 * which would have made this superfluous (such in the MDI window system),
1732 * but no-one was listening to me... */
6ca41e57
RR
1733
1734static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
1735{
a2053b27
RR
1736 gtk_myfixed_put( GTK_MYFIXED(parent->m_wxwindow),
1737 GTK_WIDGET(child->m_widget),
1738 child->m_x,
1739 child->m_y,
1740 child->m_width,
1741 child->m_height );
f03fc89f
VZ
1742
1743 if (parent->HasFlag(wxTAB_TRAVERSAL))
3e61c765
RR
1744 {
1745 /* we now allow a window to get the focus as long as it
ff8bfdbb 1746 doesn't have any children. */
a2053b27 1747 GTK_WIDGET_UNSET_FLAGS( parent->m_wxwindow, GTK_CAN_FOCUS );
3e61c765 1748 }
6ca41e57
RR
1749}
1750
bbe0af5b
RR
1751//-----------------------------------------------------------------------------
1752// global functions
1753//-----------------------------------------------------------------------------
1754
1755wxWindow* wxGetActiveWindow()
1756{
f03fc89f 1757 return g_focusWindow;
bbe0af5b
RR
1758}
1759
c801d85f 1760//-----------------------------------------------------------------------------
2f2aa628 1761// wxWindow
c801d85f
KB
1762//-----------------------------------------------------------------------------
1763
f03fc89f 1764IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
c801d85f 1765
68995f26 1766void wxWindow::Init()
c801d85f 1767{
f03fc89f
VZ
1768 // common init
1769 InitBase();
68995f26 1770
f03fc89f 1771 // GTK specific
a2053b27 1772 m_widget = (GtkWidget *) NULL;
e380f72b 1773 m_wxwindow = (GtkWidget *) NULL;
8bbe427f 1774
f03fc89f 1775 // position/size
a2053b27
RR
1776 m_x = 0;
1777 m_y = 0;
1778 m_width = 0;
e380f72b 1779 m_height = 0;
8bbe427f 1780
e380f72b
RR
1781 m_sizeSet = FALSE;
1782 m_hasVMT = FALSE;
1783 m_needParent = TRUE;
31c6b4fc 1784 m_isBeingDeleted = FALSE;
8bbe427f 1785
a2053b27 1786 m_hasScrolling = FALSE;
e380f72b 1787 m_isScrolling = FALSE;
f03fc89f 1788
a2053b27 1789 m_hAdjust = (GtkAdjustment*) NULL;
e380f72b 1790 m_vAdjust = (GtkAdjustment*) NULL;
a2053b27 1791 m_oldHorizontalPos = 0.0;
e380f72b 1792 m_oldVerticalPos = 0.0;
8bbe427f 1793
e380f72b
RR
1794 m_resizing = FALSE;
1795 m_scrollGC = (GdkGC*) NULL;
1796 m_widgetStyle = (GtkStyle*) NULL;
8bbe427f 1797
ddb6bc71 1798 m_insertCallback = (wxInsertChildFunction) NULL;
8bbe427f 1799
1ecc4d80 1800 m_isStaticBox = FALSE;
953704c1 1801 m_isRadioButton = FALSE;
b292e2f5 1802 m_acceptsFocus = FALSE;
362c6693 1803}
c801d85f 1804
68995f26
VZ
1805wxWindow::wxWindow()
1806{
1807 Init();
1808}
1809
6ca41e57 1810wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
e380f72b
RR
1811 const wxPoint &pos, const wxSize &size,
1812 long style, const wxString &name )
6ca41e57 1813{
68995f26
VZ
1814 Init();
1815
e380f72b 1816 Create( parent, id, pos, size, style, name );
6ca41e57 1817}
8bbe427f 1818
debe6624 1819bool wxWindow::Create( wxWindow *parent, wxWindowID id,
e380f72b
RR
1820 const wxPoint &pos, const wxSize &size,
1821 long style, const wxString &name )
c801d85f 1822{
4dcaf11a
RR
1823 if (!PreCreation( parent, pos, size ) ||
1824 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
1825 {
1826 wxFAIL_MSG( _T("wxWindow creation failed") );
1827 return FALSE;
1828 }
47d67540 1829
ddb6bc71
RR
1830 m_insertCallback = wxInsertChildInWindow;
1831
e380f72b 1832 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
38c7b3d3 1833 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
ff8bfdbb 1834
2e563988
RR
1835#ifdef __WXDEBUG__
1836 debug_focus_in( m_widget, _T("wxWindow::m_widget"), name );
1837#endif
1838
f03fc89f 1839 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
47d67540 1840
2e563988 1841#ifdef __WXDEBUG__
f03fc89f
VZ
1842 debug_focus_in( scrolledWindow->hscrollbar, _T("wxWindow::hsrcollbar"), name );
1843 debug_focus_in( scrolledWindow->vscrollbar, _T("wxWindow::vsrcollbar"), name );
2e563988
RR
1844#endif
1845
e380f72b
RR
1846 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1847 scroll_class->scrollbar_spacing = 0;
47d67540 1848
f03fc89f 1849 gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
47d67540 1850
f03fc89f
VZ
1851 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->hscrollbar) );
1852 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->vscrollbar) );
47d67540 1853
38c7b3d3
RR
1854 m_wxwindow = gtk_myfixed_new();
1855
2e563988
RR
1856#ifdef __WXDEBUG__
1857 debug_focus_in( m_wxwindow, _T("wxWindow::m_wxwindow"), name );
1858#endif
1859
034be888 1860 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
58dea4b0 1861
034be888
RR
1862#if (GTK_MINOR_VERSION > 0)
1863 GtkMyFixed *myfixed = GTK_MYFIXED(m_wxwindow);
b292e2f5 1864
f03fc89f 1865 if (HasFlag(wxRAISED_BORDER))
034be888
RR
1866 {
1867 gtk_myfixed_set_shadow_type( myfixed, GTK_SHADOW_OUT );
1868 }
f03fc89f 1869 else if (HasFlag(wxSUNKEN_BORDER))
034be888
RR
1870 {
1871 gtk_myfixed_set_shadow_type( myfixed, GTK_SHADOW_IN );
1872 }
1873 else
1874 {
1875 gtk_myfixed_set_shadow_type( myfixed, GTK_SHADOW_NONE );
1876 }
f03fc89f
VZ
1877#else // GTK_MINOR_VERSION == 0
1878 GtkViewport *viewport = GTK_VIEWPORT(scrolledWindow->viewport);
b292e2f5 1879
f03fc89f 1880 if (HasFlag(wxRAISED_BORDER))
e380f72b
RR
1881 {
1882 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
1883 }
f03fc89f 1884 else if (HasFlag(wxSUNKEN_BORDER))
e380f72b
RR
1885 {
1886 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
1887 }
1888 else
1889 {
1890 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
1891 }
f03fc89f 1892#endif // GTK_MINOR_VERSION
47d67540 1893
f03fc89f 1894 if (HasFlag(wxTAB_TRAVERSAL))
b292e2f5 1895 {
f03fc89f
VZ
1896 /* we now allow a window to get the focus as long as it
1897 doesn't have any children. */
ff8bfdbb 1898 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
b292e2f5
RR
1899 m_acceptsFocus = FALSE;
1900 }
e380f72b 1901 else
b292e2f5 1902 {
e380f72b 1903 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
b292e2f5
RR
1904 m_acceptsFocus = TRUE;
1905 }
ca298c88 1906
034be888 1907#if (GTK_MINOR_VERSION == 0)
e380f72b
RR
1908 // shut the viewport up
1909 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1910 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
f03fc89f 1911#endif // GTK_MINOR_VERSION == 0
e380f72b
RR
1912
1913 // I _really_ don't want scrollbars in the beginning
a2053b27
RR
1914 m_vAdjust->lower = 0.0;
1915 m_vAdjust->upper = 1.0;
1916 m_vAdjust->value = 0.0;
1917 m_vAdjust->step_increment = 1.0;
1918 m_vAdjust->page_increment = 1.0;
1919 m_vAdjust->page_size = 5.0;
1920 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1921 m_hAdjust->lower = 0.0;
1922 m_hAdjust->upper = 1.0;
1923 m_hAdjust->value = 0.0;
1924 m_hAdjust->step_increment = 1.0;
1925 m_hAdjust->page_increment = 1.0;
1926 m_hAdjust->page_size = 5.0;
1927 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
f03fc89f
VZ
1928
1929 // these handlers block mouse events to any window during scrolling such as
1930 // motion events and prevent GTK and wxWindows from fighting over where the
1931 // slider should be
1932
1933 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_press_event",
76ed8f8d
RR
1934 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1935
f03fc89f 1936 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_press_event",
76ed8f8d
RR
1937 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1938
f03fc89f 1939 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_release_event",
76ed8f8d
RR
1940 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1941
f03fc89f 1942 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_release_event",
76ed8f8d 1943 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
8bbe427f 1944
034be888 1945 // these handlers get notified when screen updates are required either when
76ed8f8d
RR
1946 // scrolling or when the window size (and therefore scrollbar configuration)
1947 // has changed
1948
1949 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
1950 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
1951 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
1952 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
1953
1954 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
1955 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
1956 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
1957 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
1958
f03fc89f 1959 gtk_widget_show( m_wxwindow );
47d67540 1960
f03fc89f
VZ
1961 if (m_parent)
1962 m_parent->DoAddChild( this );
8bbe427f 1963
e380f72b 1964 PostCreation();
8bbe427f 1965
e380f72b 1966 Show( TRUE );
c801d85f 1967
e380f72b 1968 return TRUE;
362c6693 1969}
c801d85f 1970
68dda785 1971wxWindow::~wxWindow()
c801d85f 1972{
31c6b4fc 1973 m_isBeingDeleted = TRUE;
43a18898 1974 m_hasVMT = FALSE;
47d67540 1975
f03fc89f
VZ
1976 if (m_widget)
1977 Show( FALSE );
8bbe427f 1978
a2053b27
RR
1979 DestroyChildren();
1980
f03fc89f
VZ
1981 if (m_parent)
1982 m_parent->RemoveChild( this );
c801d85f 1983
f03fc89f 1984 if (m_widgetStyle)
a2053b27 1985 {
f03fc89f 1986 gtk_style_unref( m_widgetStyle );
c50f1fb9 1987 m_widgetStyle = (GtkStyle*) NULL;
a2053b27 1988 }
c801d85f 1989
f03fc89f 1990 if (m_scrollGC)
a2053b27 1991 {
f03fc89f 1992 gdk_gc_unref( m_scrollGC );
c50f1fb9 1993 m_scrollGC = (GdkGC*) NULL;
a2053b27 1994 }
47d67540 1995
f03fc89f 1996 if (m_wxwindow)
a2053b27 1997 {
f03fc89f 1998 gtk_widget_destroy( m_wxwindow );
c50f1fb9 1999 m_wxwindow = (GtkWidget*) NULL;
a2053b27 2000 }
8bbe427f 2001
f03fc89f 2002 if (m_widget)
a2053b27 2003 {
f03fc89f 2004 gtk_widget_destroy( m_widget );
c50f1fb9 2005 m_widget = (GtkWidget*) NULL;
a2053b27 2006 }
362c6693 2007}
c801d85f 2008
4dcaf11a 2009bool wxWindow::PreCreation( wxWindow *parent, const wxPoint &pos, const wxSize &size )
c801d85f 2010{
4dcaf11a 2011 wxCHECK_MSG( !m_needParent || parent, FALSE, _T("Need complete parent.") );
8bbe427f 2012
4dcaf11a
RR
2013 /* this turns -1 into 20 so that a minimal window is
2014 visible even although -1,-1 has been given as the
2015 size of the window. the same trick is used in other
2016 ports and should make debugging easier */
f03fc89f
VZ
2017 m_width = WidthDefault(size.x);
2018 m_height = HeightDefault(size.y);
8bbe427f 2019
43a18898
RR
2020 m_x = (int)pos.x;
2021 m_y = (int)pos.y;
8bbe427f 2022
4dcaf11a
RR
2023 /* some reasonable defaults */
2024 if (!parent)
6ca41e57 2025 {
43a18898
RR
2026 if (m_x == -1)
2027 {
2028 m_x = (gdk_screen_width () - m_width) / 2;
2029 if (m_x < 10) m_x = 10;
2030 }
2031 if (m_y == -1)
2032 {
2033 m_y = (gdk_screen_height () - m_height) / 2;
2034 if (m_y < 10) m_y = 10;
2035 }
6ca41e57 2036 }
4dcaf11a
RR
2037
2038 return TRUE;
c801d85f
KB
2039}
2040
68dda785 2041void wxWindow::PostCreation()
c801d85f 2042{
05939a81 2043 wxASSERT_MSG( (m_widget != NULL), _T("invalid window") );
ca298c88 2044
43a18898
RR
2045 if (m_wxwindow)
2046 {
034be888 2047 /* these get reported to wxWindows -> wxPaintEvent */
20239453
RR
2048 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
2049 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
47d67540 2050
20239453
RR
2051 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
2052 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
ca298c88 2053
ef47f9b3 2054#if (GTK_MINOR_VERSION > 0)
f03fc89f 2055 /* these are called when the "sunken" or "raised" borders are drawn */
034be888
RR
2056 gtk_signal_connect( GTK_OBJECT(m_widget), "expose_event",
2057 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback), (gpointer)this );
2058
2059 gtk_signal_connect( GTK_OBJECT(m_widget), "draw",
2060 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback), (gpointer)this );
ef47f9b3 2061#endif
43a18898 2062 }
47d67540 2063
a2053b27 2064 GtkWidget *connect_widget = GetConnectWidget();
f03fc89f 2065
a2053b27 2066 ConnectWidget( connect_widget );
47d67540 2067
a2053b27
RR
2068 /* we cannot set colours, fonts and cursors before the widget has
2069 been realized, so we do this directly after realization */
2070 gtk_signal_connect( GTK_OBJECT(connect_widget), "realize",
c50f1fb9 2071 GTK_SIGNAL_FUNC(gtk_window_realized_callback), (gpointer) this );
ca298c88 2072
43a18898 2073 m_hasVMT = TRUE;
b4071e91
RR
2074}
2075
2076void wxWindow::ConnectWidget( GtkWidget *widget )
2077{
43a18898
RR
2078 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
2079 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
c801d85f 2080
b666df2c
RR
2081 gtk_signal_connect( GTK_OBJECT(widget), "key_release_event",
2082 GTK_SIGNAL_FUNC(gtk_window_key_release_callback), (gpointer)this );
2083
43a18898
RR
2084 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
2085 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
47d67540 2086
43a18898
RR
2087 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
2088 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
47d67540 2089
43a18898
RR
2090 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
2091 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
47d67540 2092
43a18898
RR
2093 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
2094 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
c801d85f 2095
43a18898
RR
2096 gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
2097 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
c801d85f 2098
43a18898
RR
2099 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
2100 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
47d67540 2101
43a18898
RR
2102 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
2103 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
362c6693 2104}
c801d85f 2105
68dda785 2106bool wxWindow::Destroy()
c801d85f 2107{
05939a81 2108 wxASSERT_MSG( (m_widget != NULL), _T("invalid window") );
47d67540 2109
43a18898 2110 m_hasVMT = FALSE;
c801d85f 2111
f03fc89f 2112 return wxWindowBase::Destroy();
362c6693 2113}
c801d85f 2114
bfc6fde4 2115void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
c801d85f 2116{
05939a81
OK
2117 wxASSERT_MSG( (m_widget != NULL), _T("invalid window") );
2118 wxASSERT_MSG( (m_parent != NULL), _T("wxWindow::SetSize requires parent.\n") );
8bbe427f 2119
e27ce4e9 2120 if (m_resizing) return; /* I don't like recursions */
fb1585ae 2121 m_resizing = TRUE;
47d67540 2122
a2053b27 2123 if (m_parent->m_wxwindow == NULL) /* i.e. wxNotebook */
fb1585ae 2124 {
e27ce4e9 2125 /* don't set the size for children of wxNotebook, just take the values. */
fb1585ae
RR
2126 m_x = x;
2127 m_y = y;
2128 m_width = width;
ba4e3652 2129 m_height = height;
fb1585ae 2130 }
ba4e3652 2131 else
fb1585ae 2132 {
85ad5eb5 2133 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
ba4e3652
RR
2134 {
2135 if (x != -1) m_x = x;
2136 if (y != -1) m_y = y;
2137 if (width != -1) m_width = width;
2138 if (height != -1) m_height = height;
2139 }
2140 else
2141 {
2142 m_x = x;
2143 m_y = y;
2144 m_width = width;
2145 m_height = height;
2146 }
47d67540 2147
ba4e3652
RR
2148 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
2149 {
2150 if (width == -1) m_width = 80;
2151 }
2152
2153 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
2154 {
2155 if (height == -1) m_height = 26;
2156 }
8bbe427f 2157
ba4e3652
RR
2158 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
2159 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
d3b4d113
RR
2160 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
2161 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
47d67540 2162
a2053b27 2163 int border = 0;
c50f1fb9 2164 int bottom_border = 0;
f03fc89f 2165
29f538ce 2166 if (GTK_WIDGET_CAN_DEFAULT(m_widget))
c50f1fb9
VZ
2167 {
2168 /* the default button has a border around it */
2169 border = 6;
2170 bottom_border = 5;
2171 }
2172
2173 /* this is the result of hours of debugging: the following code
2174 means that if we have a m_wxwindow and we set the size of
2175 m_widget, m_widget (which is a GtkScrolledWindow) does NOT
2176 automatically propagate its size down to its m_wxwindow,
2177 which is its client area. therefore, we have to tell the
2178 client area directly that it has to resize itself.
2179 this will lead to that m_widget (GtkScrolledWindow) will
2180 calculate how much size it needs for scrollbars etc and
2181 it will then call XXX_size_allocate of its child, which
2182 is m_wxwindow. m_wxwindow in turn will do the same with its
2183 children and so on. problems can arise if this happens
2184 before all the children have been realized as some widgets
2185 stupidy need to be realized during XXX_size_allocate (e.g.
2186 GtkNotebook) and they will segv if called otherwise. this
2187 emergency is tested in gtk_myfixed_size_allocate. Normally
2188 this shouldn't be needed and only gtk_widget_queue_resize()
2189 should be enough to provoke a resize at the next appropriate
2190 moment, but this seems to fail, e.g. when a wxNotebook contains
2191 a wxSplitterWindow: the splitter window's children won't
2192 show up properly resized then. */
2193
2194 gtk_myfixed_set_size( GTK_MYFIXED(m_parent->m_wxwindow),
2195 m_widget,
2196 m_x-border,
2197 m_y-border,
2198 m_width+2*border,
2199 m_height+border+bottom_border );
ba4e3652 2200 }
8bbe427f 2201
fb1585ae 2202 m_sizeSet = TRUE;
47d67540 2203
fb1585ae
RR
2204 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
2205 event.SetEventObject( this );
ba4e3652 2206 GetEventHandler()->ProcessEvent( event );
47d67540 2207
fb1585ae 2208 m_resizing = FALSE;
362c6693 2209}
c801d85f 2210
9390a202
RR
2211void wxWindow::OnInternalIdle()
2212{
9146082c
RR
2213 wxCursor cursor = m_cursor;
2214 if (g_globalCursor.Ok()) cursor = g_globalCursor;
c50f1fb9 2215
9146082c
RR
2216 if (cursor.Ok() && m_currentGdkCursor != cursor)
2217 {
d30e0edd
RR
2218 m_currentGdkCursor = cursor;
2219
9146082c 2220 if (m_wxwindow)
6a008b33 2221 {
9146082c 2222 GdkWindow *window = m_wxwindow->window;
6a008b33 2223 if (window)
c50f1fb9 2224 gdk_window_set_cursor( window, cursor.GetCursor() );
6a008b33
VZ
2225
2226 if (!g_globalCursor.Ok())
2227 cursor = *wxSTANDARD_CURSOR;
2228
2229 window = m_widget->window;
2230 if (window)
9146082c 2231 gdk_window_set_cursor( window, cursor.GetCursor() );
6a008b33
VZ
2232 }
2233 else
2234 {
9146082c 2235 GdkWindow *window = m_widget->window;
6a008b33 2236 if (window)
9146082c 2237 gdk_window_set_cursor( window, cursor.GetCursor() );
6a008b33 2238 }
9146082c 2239 }
6a008b33 2240
9390a202
RR
2241 UpdateWindowUI();
2242}
2243
f03fc89f 2244void wxWindow::DoGetSize( int *width, int *height ) const
c801d85f 2245{
05939a81 2246 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2247
fb1585ae
RR
2248 if (width) (*width) = m_width;
2249 if (height) (*height) = m_height;
362c6693 2250}
c801d85f 2251
bfc6fde4 2252void wxWindow::DoSetClientSize( int width, int height )
c801d85f 2253{
05939a81 2254 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2255
1ecc4d80 2256 if (!m_wxwindow)
c801d85f 2257 {
1ecc4d80 2258 SetSize( width, height );
c801d85f
KB
2259 }
2260 else
2261 {
1ecc4d80
RR
2262 int dw = 0;
2263 int dh = 0;
2264
034be888 2265#if (GTK_MINOR_VERSION == 0)
98d3fdbe
RR
2266 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2267 {
324dbfec
RR
2268 if (HasScrolling())
2269 {
2270 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
014b0d06 2271#if 0 // unused - if this is ok, just remove this line (VZ)
324dbfec 2272 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
014b0d06 2273#endif // 0
324dbfec
RR
2274
2275 GtkWidget *viewport = scroll_window->viewport;
2276 GtkStyleClass *viewport_class = viewport->style->klass;
2277
2278 dw += 2 * viewport_class->xthickness;
2279 dh += 2 * viewport_class->ythickness;
2280 }
98d3fdbe
RR
2281 }
2282#else
2283 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2284 {
6a008b33
VZ
2285 /* when using GTK 1.2 we set the border size to 2 */
2286 dw += 2 * 2;
98d3fdbe
RR
2287 dh += 2 * 2;
2288 }
034be888
RR
2289#endif
2290
98d3fdbe
RR
2291 if (HasScrolling())
2292 {
034be888
RR
2293/*
2294 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2295 GtkWidget *vscrollbar = scroll_window->vscrollbar;
ca298c88 2296
f03fc89f 2297 we use this instead: range.slider_width = 11 + 2*2pts edge
034be888 2298*/
47d67540 2299
324dbfec
RR
2300 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2301 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
2302
1ecc4d80
RR
2303 if (scroll_window->vscrollbar_visible)
2304 {
034be888 2305 dw += 15; /* dw += vscrollbar->allocation.width; */
1ecc4d80
RR
2306 dw += scroll_class->scrollbar_spacing;
2307 }
2308
2309 if (scroll_window->hscrollbar_visible)
2310 {
034be888 2311 dh += 15; /* dh += hscrollbar->allocation.height; */
63cc5d9d 2312 dh += scroll_class->scrollbar_spacing;
1ecc4d80
RR
2313 }
2314 }
2315
034be888 2316 SetSize( width+dw, height+dh );
1ecc4d80 2317 }
362c6693 2318}
c801d85f 2319
f03fc89f 2320void wxWindow::DoGetClientSize( int *width, int *height ) const
c801d85f 2321{
05939a81 2322 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2323
1ecc4d80
RR
2324 if (!m_wxwindow)
2325 {
2326 if (width) (*width) = m_width;
2327 if (height) (*height) = m_height;
c801d85f
KB
2328 }
2329 else
2330 {
1ecc4d80
RR
2331 int dw = 0;
2332 int dh = 0;
2333
034be888 2334#if (GTK_MINOR_VERSION == 0)
98d3fdbe
RR
2335 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2336 {
6a008b33
VZ
2337 if (HasScrolling())
2338 {
2339 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
ec6e0a19 2340#if 0 // unused - if this is ok, just remove this line (VZ)
6a008b33 2341 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
ec6e0a19 2342#endif // 0
6a008b33
VZ
2343
2344 GtkWidget *viewport = scroll_window->viewport;
2345 GtkStyleClass *viewport_class = viewport->style->klass;
2346
2347 dw += 2 * viewport_class->xthickness;
2348 dh += 2 * viewport_class->ythickness;
2349 }
98d3fdbe
RR
2350 }
2351#else
2352 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2353 {
6a008b33
VZ
2354 /* when using GTK 1.2 we set the border size to 2 */
2355 dw += 2 * 2;
98d3fdbe
RR
2356 dh += 2 * 2;
2357 }
034be888 2358#endif
98d3fdbe
RR
2359 if (HasScrolling())
2360 {
034be888
RR
2361/*
2362 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2363 GtkWidget *vscrollbar = scroll_window->vscrollbar;
ca298c88 2364
f03fc89f 2365 we use this instead: range.slider_width = 11 + 2*2pts edge
034be888 2366*/
1ecc4d80 2367
6a008b33
VZ
2368 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2369 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
2370
1ecc4d80
RR
2371 if (scroll_window->vscrollbar_visible)
2372 {
034be888 2373 dw += 15; /* dw += vscrollbar->allocation.width; */
1ecc4d80
RR
2374 dw += scroll_class->scrollbar_spacing;
2375 }
2376
2377 if (scroll_window->hscrollbar_visible)
2378 {
034be888 2379 dh += 15; /* dh += hscrollbar->allocation.height; */
1ecc4d80
RR
2380 dh += scroll_class->scrollbar_spacing;
2381 }
6a008b33 2382 }
47d67540 2383
1ecc4d80
RR
2384 if (width) (*width) = m_width - dw;
2385 if (height) (*height) = m_height - dh;
2386 }
362c6693 2387}
c801d85f 2388
f03fc89f 2389void wxWindow::DoGetPosition( int *x, int *y ) const
c801d85f 2390{
05939a81 2391 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2392
43a18898
RR
2393 if (x) (*x) = m_x;
2394 if (y) (*y) = m_y;
362c6693 2395}
c801d85f 2396
dabc0cd5 2397void wxWindow::DoClientToScreen( int *x, int *y ) const
c801d85f 2398{
05939a81 2399 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2400
a2053b27
RR
2401 if (!m_widget->window) return;
2402
43a18898
RR
2403 GdkWindow *source = (GdkWindow *) NULL;
2404 if (m_wxwindow)
2405 source = m_wxwindow->window;
2406 else
2407 source = m_widget->window;
47d67540 2408
43a18898
RR
2409 int org_x = 0;
2410 int org_y = 0;
2411 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2412
43a18898 2413 if (!m_wxwindow)
c801d85f 2414 {
43a18898
RR
2415 if (GTK_WIDGET_NO_WINDOW (m_widget))
2416 {
2417 org_x += m_widget->allocation.x;
2418 org_y += m_widget->allocation.y;
2419 }
362c6693 2420 }
47d67540 2421
43a18898
RR
2422 if (x) *x += org_x;
2423 if (y) *y += org_y;
362c6693 2424}
c801d85f 2425
dabc0cd5 2426void wxWindow::DoScreenToClient( int *x, int *y ) const
c801d85f 2427{
05939a81 2428 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2429
a2053b27
RR
2430 if (!m_widget->window) return;
2431
1ecc4d80
RR
2432 GdkWindow *source = (GdkWindow *) NULL;
2433 if (m_wxwindow)
2434 source = m_wxwindow->window;
2435 else
2436 source = m_widget->window;
47d67540 2437
1ecc4d80
RR
2438 int org_x = 0;
2439 int org_y = 0;
2440 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2441
1ecc4d80 2442 if (!m_wxwindow)
c801d85f 2443 {
1ecc4d80
RR
2444 if (GTK_WIDGET_NO_WINDOW (m_widget))
2445 {
2446 org_x += m_widget->allocation.x;
2447 org_y += m_widget->allocation.y;
2448 }
362c6693 2449 }
47d67540 2450
1ecc4d80
RR
2451 if (x) *x -= org_x;
2452 if (y) *y -= org_y;
362c6693 2453}
c801d85f 2454
f03fc89f 2455bool wxWindow::Show( bool show )
c801d85f 2456{
f03fc89f 2457 wxCHECK_MSG( (m_widget != NULL), FALSE, _T("invalid window") );
47d67540 2458
739730ca
RR
2459 if (!wxWindowBase::Show(show))
2460 {
2461 // nothing to do
f03fc89f 2462 return FALSE;
739730ca 2463 }
8bbe427f 2464
f03fc89f
VZ
2465 if (show)
2466 gtk_widget_show( m_widget );
1ecc4d80 2467 else
f03fc89f 2468 gtk_widget_hide( m_widget );
8bbe427f 2469
f03fc89f 2470 return TRUE;
362c6693 2471}
c801d85f 2472
f03fc89f 2473bool wxWindow::Enable( bool enable )
c801d85f 2474{
f03fc89f 2475 wxCHECK_MSG( (m_widget != NULL), FALSE, _T("invalid window") );
5e0aa05a 2476
739730ca
RR
2477 if (!wxWindowBase::Enable(enable))
2478 {
2479 // nothing to do
f03fc89f 2480 return FALSE;
739730ca 2481 }
1ecc4d80 2482
f03fc89f
VZ
2483 gtk_widget_set_sensitive( m_widget, enable );
2484 if ( m_wxwindow )
2485 gtk_widget_set_sensitive( m_wxwindow, enable );
ff8bfdbb 2486
f03fc89f 2487 return TRUE;
362c6693 2488}
c801d85f 2489
f03fc89f 2490int wxWindow::GetCharHeight() const
2f2aa628 2491{
f03fc89f 2492 wxCHECK_MSG( (m_widget != NULL), 12, _T("invalid window") );
47d67540 2493
f03fc89f 2494 wxCHECK_MSG( m_font.Ok(), 12, _T("invalid font") );
2f2aa628 2495
f03fc89f
VZ
2496 GdkFont *font = m_font.GetInternalFont( 1.0 );
2497
2498 return font->ascent + font->descent;
362c6693 2499}
c801d85f 2500
f03fc89f 2501int wxWindow::GetCharWidth() const
c33c4050 2502{
05939a81 2503 wxCHECK_MSG( (m_widget != NULL), 8, _T("invalid window") );
47d67540 2504
05939a81 2505 wxCHECK_MSG( m_font.Ok(), 8, _T("invalid font") );
47d67540 2506
463c1fa1 2507 GdkFont *font = m_font.GetInternalFont( 1.0 );
ff8bfdbb 2508
463c1fa1 2509 return gdk_string_width( font, "H" );
c33c4050
RR
2510}
2511
f03fc89f
VZ
2512void wxWindow::GetTextExtent( const wxString& string,
2513 int *x,
2514 int *y,
2515 int *descent,
2516 int *externalLeading,
2517 const wxFont *theFont ) const
c33c4050 2518{
463c1fa1
RR
2519 wxFont fontToUse = m_font;
2520 if (theFont) fontToUse = *theFont;
47d67540 2521
05939a81 2522 wxCHECK_RET( fontToUse.Ok(), _T("invalid font") );
47d67540 2523
463c1fa1 2524 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
05939a81 2525 if (x) (*x) = gdk_string_width( font, string.mbc_str() );
463c1fa1
RR
2526 if (y) (*y) = font->ascent + font->descent;
2527 if (descent) (*descent) = font->descent;
2528 if (externalLeading) (*externalLeading) = 0; // ??
c33c4050
RR
2529}
2530
68dda785 2531void wxWindow::SetFocus()
c801d85f 2532{
05939a81 2533 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
ff8bfdbb 2534
463c1fa1
RR
2535 GtkWidget *connect_widget = GetConnectWidget();
2536 if (connect_widget)
c801d85f 2537 {
b292e2f5 2538 if (GTK_WIDGET_CAN_FOCUS(connect_widget) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
463c1fa1
RR
2539 {
2540 gtk_widget_grab_focus (connect_widget);
2541 }
ff8bfdbb
VZ
2542 else if (GTK_IS_CONTAINER(connect_widget))
2543 {
2544 gtk_container_focus( GTK_CONTAINER(connect_widget), GTK_DIR_TAB_FORWARD );
2545 }
2546 else
2547 {
2548 }
362c6693 2549 }
362c6693 2550}
c801d85f 2551
b292e2f5
RR
2552bool wxWindow::AcceptsFocus() const
2553{
f03fc89f 2554 return m_acceptsFocus && wxWindowBase::AcceptsFocus();
b292e2f5
RR
2555}
2556
fdb7dadb 2557bool wxWindow::Reparent( wxWindowBase *newParentBase )
463c1fa1 2558{
c693edf3 2559 wxCHECK_MSG( (m_widget != NULL), FALSE, _T("invalid window") );
c50f1fb9 2560
fdb7dadb
VZ
2561 wxWindow *oldParent = m_parent,
2562 *newParent = (wxWindow *)newParentBase;
a2053b27 2563
f03fc89f
VZ
2564 if ( !wxWindowBase::Reparent(newParent) )
2565 return FALSE;
8bbe427f 2566
8ce63e9d
RR
2567 if (oldParent)
2568 {
2569 gtk_container_remove( GTK_CONTAINER(oldParent->m_wxwindow), m_widget );
2570 }
c50f1fb9 2571
8ce63e9d
RR
2572 if (newParent)
2573 {
2574 /* insert GTK representation */
2575 (*(newParent->m_insertCallback))(newParent, this);
2576 }
c50f1fb9 2577
f03fc89f 2578 return TRUE;
362c6693 2579}
c801d85f 2580
c50f1fb9 2581void wxWindow::DoAddChild(wxWindow *child)
ddb6bc71
RR
2582{
2583 wxASSERT_MSG( (m_widget != NULL), _T("invalid window") );
2584
2585 wxASSERT_MSG( (child != NULL), _T("invalid child window") );
2586
2587 wxASSERT_MSG( (m_insertCallback != NULL), _T("invalid child insertion function") );
c50f1fb9 2588
ddb6bc71
RR
2589 /* add to list */
2590 AddChild( child );
c50f1fb9 2591
ddb6bc71
RR
2592 /* insert GTK representation */
2593 (*m_insertCallback)(this, child);
2594}
2595
68dda785 2596void wxWindow::Raise()
362c6693 2597{
05939a81 2598 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2599
a2053b27
RR
2600 if (!m_widget->window) return;
2601
f03fc89f 2602 gdk_window_raise( m_widget->window );
362c6693
RR
2603}
2604
68dda785 2605void wxWindow::Lower()
362c6693 2606{
05939a81 2607 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2608
a2053b27
RR
2609 if (!m_widget->window) return;
2610
f03fc89f 2611 gdk_window_lower( m_widget->window );
362c6693 2612}
c801d85f 2613
f03fc89f 2614bool wxWindow::SetCursor( const wxCursor &cursor )
86b29a61 2615{
f03fc89f 2616 wxCHECK_MSG( (m_widget != NULL), FALSE, _T("invalid window") );
86b29a61 2617
739730ca 2618 if (!wxWindowBase::SetCursor(cursor))
e55ad60e 2619 {
739730ca
RR
2620 // don't leave if the GTK widget has just
2621 // been realized
2622 if (!m_delayedCursor) return FALSE;
2623 }
c50f1fb9 2624
739730ca
RR
2625 GtkWidget *connect_widget = GetConnectWidget();
2626 if (!connect_widget->window)
2627 {
2628 // indicate that a new style has been set
c50f1fb9
VZ
2629 // but it couldn't get applied as the
2630 // widget hasn't been realized yet.
2631 m_delayedCursor = TRUE;
2632
2633 // pretend we have done something
739730ca
RR
2634 return TRUE;
2635 }
a2053b27 2636
238d735d 2637// gdk_window_set_cursor( connect_widget->window, GetCursor().GetCursor() );
fd0eed64 2638
739730ca
RR
2639 // cursor was set
2640 return TRUE;
362c6693 2641}
c801d85f 2642
85eb36c2 2643void wxWindow::WarpPointer( int x, int y )
4f22cf8d 2644{
85eb36c2
RR
2645 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
2646
2647 GtkWidget *connect_widget = GetConnectWidget();
2648 if (connect_widget->window)
2649 {
2650 /* we provide this function ourselves as it is
c50f1fb9 2651 missing in GDK */
85eb36c2
RR
2652 gdk_window_warp_pointer( connect_widget->window, x, y );
2653 }
4f22cf8d
RR
2654}
2655
debe6624 2656void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
c801d85f 2657{
05939a81 2658 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2659
a2053b27
RR
2660 if (!m_widget->window) return;
2661
139adb6a 2662 if (eraseBackground && m_wxwindow && m_wxwindow->window)
c801d85f 2663 {
139adb6a
RR
2664 if (rect)
2665 {
2666 gdk_window_clear_area( m_wxwindow->window,
2667 rect->x, rect->y,
f234c60c 2668 rect->width, rect->height );
139adb6a
RR
2669 }
2670 else
2671 {
f234c60c 2672 gdk_window_clear( m_wxwindow->window );
139adb6a
RR
2673 }
2674 }
ff8bfdbb 2675
139adb6a
RR
2676 if (!rect)
2677 {
2678 if (m_wxwindow)
2679 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
ff8bfdbb 2680 else
139adb6a 2681 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
362c6693 2682 }
c801d85f 2683 else
139adb6a
RR
2684 {
2685 GdkRectangle gdk_rect;
2686 gdk_rect.x = rect->x;
2687 gdk_rect.y = rect->y;
2688 gdk_rect.width = rect->width;
2689 gdk_rect.height = rect->height;
2690
2691 if (m_wxwindow)
2692 gtk_widget_draw( m_wxwindow, &gdk_rect );
2693 else
2694 gtk_widget_draw( m_widget, &gdk_rect );
2695 }
362c6693 2696}
c801d85f 2697
68dda785 2698void wxWindow::Clear()
c801d85f 2699{
05939a81 2700 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
47d67540 2701
a2053b27
RR
2702 if (!m_widget->window) return;
2703
f234c60c
RR
2704 if (m_wxwindow && m_wxwindow->window)
2705 {
2706 gdk_window_clear( m_wxwindow->window );
2707 }
362c6693 2708}
c801d85f 2709
ff8bfdbb 2710#if wxUSE_TOOLTIPS
f03fc89f 2711void wxWindow::DoSetToolTip( wxToolTip *tip )
b1170810 2712{
f03fc89f 2713 wxWindowBase::DoSetToolTip(tip);
ff8bfdbb 2714
f03fc89f
VZ
2715 if (m_tooltip)
2716 m_tooltip->Apply( this );
b1170810
RR
2717}
2718
05939a81 2719void wxWindow::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
b1170810 2720{
dcf924a3 2721 gtk_tooltips_set_tip( tips, GetConnectWidget(), wxConvCurrent->cWX2MB(tip), (gchar*) NULL );
301cd871 2722}
ff8bfdbb 2723#endif // wxUSE_TOOLTIPS
b1170810 2724
f03fc89f 2725bool wxWindow::SetBackgroundColour( const wxColour &colour )
c801d85f 2726{
f03fc89f 2727 wxCHECK_MSG( m_widget != NULL, FALSE, _T("invalid window") );
8bbe427f 2728
739730ca
RR
2729 if (!wxWindowBase::SetBackgroundColour(colour))
2730 {
2731 // don't leave if the GTK widget has just
2732 // been realized
2733 if (!m_delayedBackgroundColour) return FALSE;
2734 }
c50f1fb9 2735
a2053b27 2736 GtkWidget *connect_widget = GetConnectWidget();
739730ca
RR
2737 if (!connect_widget->window)
2738 {
2739 // indicate that a new style has been set
c50f1fb9
VZ
2740 // but it couldn't get applied as the
2741 // widget hasn't been realized yet.
2742 m_delayedBackgroundColour = TRUE;
2743
2744 // pretend we have done something
739730ca
RR
2745 return TRUE;
2746 }
ca298c88 2747
f234c60c 2748 if (m_wxwindow && m_wxwindow->window)
3bc755fc 2749 {
a2053b27
RR
2750 /* wxMSW doesn't clear the window here. I don't do that either to
2751 provide compatibility. call Clear() to do the job. */
ca298c88 2752
f234c60c
RR
2753 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_wxwindow->window ) );
2754 gdk_window_set_background( m_wxwindow->window, m_backgroundColour.GetColor() );
3bc755fc 2755 }
8bbe427f 2756
ae0bdb01 2757 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
121a3581 2758 if (sysbg == m_backgroundColour)
ae0bdb01
RR
2759 {
2760 m_backgroundColour = wxNullColour;
2761 ApplyWidgetStyle();
ff8bfdbb
VZ
2762 m_backgroundColour = sysbg;
2763 }
ae0bdb01
RR
2764 else
2765 {
2766 ApplyWidgetStyle();
2767 }
c801d85f 2768
f03fc89f 2769 return TRUE;
6de97a3b
RR
2770}
2771
f03fc89f 2772bool wxWindow::SetForegroundColour( const wxColour &colour )
6de97a3b 2773{
f03fc89f 2774 wxCHECK_MSG( m_widget != NULL, FALSE, _T("invalid window") );
8bbe427f 2775
739730ca
RR
2776 if (!wxWindowBase::SetForegroundColour(colour))
2777 {
2778 // don't leave if the GTK widget has just
2779 // been realized
2780 if (!m_delayedForegroundColour) return FALSE;
2781 }
c50f1fb9 2782
a2053b27 2783 GtkWidget *connect_widget = GetConnectWidget();
739730ca
RR
2784 if (!connect_widget->window)
2785 {
2786 // indicate that a new style has been set
c50f1fb9
VZ
2787 // but it couldn't get applied as the
2788 // widget hasn't been realized yet.
2789 m_delayedForegroundColour = TRUE;
2790
2791 // pretend we have done something
739730ca
RR
2792 return TRUE;
2793 }
2b07d713 2794
ae0bdb01 2795 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2b62ab35 2796 if ( sysbg == m_backgroundColour )
ae0bdb01
RR
2797 {
2798 m_backgroundColour = wxNullColour;
2799 ApplyWidgetStyle();
ff8bfdbb
VZ
2800 m_backgroundColour = sysbg;
2801 }
ae0bdb01
RR
2802 else
2803 {
2804 ApplyWidgetStyle();
2805 }
f03fc89f
VZ
2806
2807 return TRUE;
58614078
RR
2808}
2809
2810GtkStyle *wxWindow::GetWidgetStyle()
2811{
1ecc4d80 2812 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
8bbe427f 2813
f03fc89f 2814 m_widgetStyle = gtk_style_copy( gtk_widget_get_style( m_widget ) );
8bbe427f 2815
1ecc4d80 2816 return m_widgetStyle;
58614078
RR
2817}
2818
2819void wxWindow::SetWidgetStyle()
2820{
1ecc4d80
RR
2821 GtkStyle *style = GetWidgetStyle();
2822
2823 gdk_font_unref( style->font );
2824 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2825
2826 if (m_foregroundColour.Ok())
2827 {
2828 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2829 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2830 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2831 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2832 }
2833
2834 if (m_backgroundColour.Ok())
2835 {
2836 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2837 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2838 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2839 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2840 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2841 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2842 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2843 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2844 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2845 }
a81258be
RR
2846}
2847
58614078 2848void wxWindow::ApplyWidgetStyle()
a81258be 2849{
6de97a3b
RR
2850}
2851
2259e007
RR
2852//-----------------------------------------------------------------------------
2853// Pop-up menu stuff
2854//-----------------------------------------------------------------------------
2855
2856static void gtk_pop_hide_callback( GtkWidget *WXUNUSED(widget), bool* is_waiting )
2857{
2858 *is_waiting = FALSE;
2859}
2860
30dea054
RR
2861static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2862{
1ecc4d80 2863 menu->SetInvokingWindow( win );
c626a8b7 2864 wxNode *node = menu->GetItems().First();
1ecc4d80
RR
2865 while (node)
2866 {
2867 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2868 if (menuitem->IsSubMenu())
2869 {
ff8bfdbb
VZ
2870 SetInvokingWindow( menuitem->GetSubMenu(), win );
2871 }
1ecc4d80
RR
2872 node = node->Next();
2873 }
362c6693 2874}
30dea054 2875
0c77152e
RR
2876static gint gs_pop_x = 0;
2877static gint gs_pop_y = 0;
2878
a234a61a
VZ
2879static void pop_pos_callback( GtkMenu * WXUNUSED(menu),
2880 gint *x, gint *y,
2881 wxWindow *win )
0c77152e
RR
2882{
2883 win->ClientToScreen( &gs_pop_x, &gs_pop_y );
2884 *x = gs_pop_x;
2885 *y = gs_pop_y;
2886}
2887
a1665b22 2888bool wxWindow::DoPopupMenu( wxMenu *menu, int x, int y )
30dea054 2889{
05939a81 2890 wxCHECK_MSG( m_widget != NULL, FALSE, _T("invalid window") );
47d67540 2891
05939a81 2892 wxCHECK_MSG( menu != NULL, FALSE, _T("invalid popup-menu") );
8bbe427f 2893
1ecc4d80 2894 SetInvokingWindow( menu, this );
ff8bfdbb 2895
631f1bfe
JS
2896 menu->UpdateUI();
2897
0c77152e
RR
2898 gs_pop_x = x;
2899 gs_pop_y = y;
ff8bfdbb 2900
2259e007
RR
2901 bool is_waiting = TRUE;
2902
2903 gtk_signal_connect( GTK_OBJECT(menu->m_menu), "hide",
2904 GTK_SIGNAL_FUNC(gtk_pop_hide_callback), (gpointer)&is_waiting );
2905
1ecc4d80 2906 gtk_menu_popup(
47d67540 2907 GTK_MENU(menu->m_menu),
0c77152e
RR
2908 (GtkWidget *) NULL, // parent menu shell
2909 (GtkWidget *) NULL, // parent menu item
2910 (GtkMenuPositionFunc) pop_pos_callback,
2911 (gpointer) this, // client data
2912 0, // button used to activate it
2913 0 //gs_timeLastClick // the time of activation
47d67540 2914 );
2259e007 2915
956dbab1
RR
2916 while (is_waiting)
2917 {
2918 while (gtk_events_pending())
2919 gtk_main_iteration();
2920 }
2259e007 2921
1ecc4d80 2922 return TRUE;
30dea054
RR
2923}
2924
06cfab17 2925#if wxUSE_DRAG_AND_DROP
ac57418f 2926
c801d85f
KB
2927void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2928{
05939a81 2929 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
47d67540 2930
1ecc4d80 2931 GtkWidget *dnd_widget = GetConnectWidget();
47d67540 2932
1ecc4d80 2933 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
47d67540 2934
1ecc4d80
RR
2935 if (m_dropTarget) delete m_dropTarget;
2936 m_dropTarget = dropTarget;
47d67540 2937
1ecc4d80 2938 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
362c6693 2939}
c801d85f 2940
f03fc89f 2941#endif // wxUSE_DRAG_AND_DROP
ac57418f 2942
68dda785 2943GtkWidget* wxWindow::GetConnectWidget()
e3e65dac 2944{
1ecc4d80
RR
2945 GtkWidget *connect_widget = m_widget;
2946 if (m_wxwindow) connect_widget = m_wxwindow;
47d67540 2947
1ecc4d80 2948 return connect_widget;
e3e65dac 2949}
47d67540 2950
903f689b
RR
2951bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2952{
1ecc4d80
RR
2953 if (m_wxwindow) return (window == m_wxwindow->window);
2954 return (window == m_widget->window);
903f689b
RR
2955}
2956
f03fc89f 2957bool wxWindow::SetFont( const wxFont &font )
c801d85f 2958{
c50f1fb9 2959 wxCHECK_MSG( m_widget != NULL, FALSE, _T( "invalid window") );
c801d85f 2960
739730ca
RR
2961 if (!wxWindowBase::SetFont(font))
2962 {
2963 // don't leave if the GTK widget has just
2964 // been realized
2965 if (!m_delayedFont) return FALSE;
2966 }
c50f1fb9 2967
a2053b27 2968 GtkWidget *connect_widget = GetConnectWidget();
739730ca
RR
2969 if (!connect_widget->window)
2970 {
2971 // indicate that a new style has been set
c50f1fb9
VZ
2972 // but it couldn't get applied as the
2973 // widget hasn't been realized yet.
2974 m_delayedFont = TRUE;
2975
2976 // pretend we have done something
739730ca
RR
2977 return TRUE;
2978 }
9c288e4d 2979
ae0bdb01 2980 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
f03fc89f 2981 if ( sysbg == m_backgroundColour )
ae0bdb01
RR
2982 {
2983 m_backgroundColour = wxNullColour;
2984 ApplyWidgetStyle();
ff8bfdbb
VZ
2985 m_backgroundColour = sysbg;
2986 }
ae0bdb01
RR
2987 else
2988 {
2989 ApplyWidgetStyle();
2990 }
c801d85f 2991
f03fc89f 2992 return TRUE;
362c6693 2993}
c801d85f 2994
68dda785 2995void wxWindow::CaptureMouse()
c801d85f 2996{
05939a81 2997 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
47d67540 2998
72195a0f 2999 wxCHECK_RET( g_captureWindow == NULL, _T("CaptureMouse called twice") );
47d67540 3000
1ecc4d80 3001 GtkWidget *connect_widget = GetConnectWidget();
a2053b27 3002 if (!connect_widget->window) return;
c50f1fb9 3003
1ecc4d80
RR
3004 gdk_pointer_grab( connect_widget->window, FALSE,
3005 (GdkEventMask)
3006 (GDK_BUTTON_PRESS_MASK |
3007 GDK_BUTTON_RELEASE_MASK |
3008 GDK_POINTER_MOTION_MASK),
ff8bfdbb 3009 (GdkWindow *) NULL,
72195a0f 3010 m_cursor.GetCursor(),
ff8bfdbb 3011 GDK_CURRENT_TIME );
72195a0f 3012 g_captureWindow = this;
362c6693 3013}
c801d85f 3014
68dda785 3015void wxWindow::ReleaseMouse()
c801d85f 3016{
05939a81 3017 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
47d67540 3018
72195a0f 3019 wxCHECK_RET( g_captureWindow, _T("ReleaseMouse called twice") );
47d67540 3020
1ecc4d80 3021 GtkWidget *connect_widget = GetConnectWidget();
a2053b27 3022 if (!connect_widget->window) return;
c50f1fb9 3023
1ecc4d80 3024 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
72195a0f 3025 g_captureWindow = (wxWindow*) NULL;
362c6693 3026}
c801d85f 3027
f03fc89f 3028bool wxWindow::IsRetained() const
c801d85f 3029{
1ecc4d80 3030 return FALSE;
362c6693 3031}
c801d85f 3032
debe6624 3033void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
cb43b372 3034 int range, bool refresh )
c801d85f 3035{
05939a81 3036 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
8bbe427f 3037
05939a81 3038 wxCHECK_RET( m_wxwindow != NULL, _T("window needs client area for scrolling") );
c801d85f 3039
1ecc4d80 3040 m_hasScrolling = TRUE;
47d67540 3041
1ecc4d80 3042 if (orient == wxHORIZONTAL)
cb43b372 3043 {
1ecc4d80
RR
3044 float fpos = (float)pos;
3045 float frange = (float)range;
3046 float fthumb = (float)thumbVisible;
3047 if (fpos > frange-fthumb) fpos = frange-fthumb;
3048 if (fpos < 0.0) fpos = 0.0;
3049
3050 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
3051 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
3052 {
3053 SetScrollPos( orient, pos, refresh );
3054 return;
3055 }
47d67540 3056
1ecc4d80 3057 m_oldHorizontalPos = fpos;
47d67540 3058
1ecc4d80
RR
3059 m_hAdjust->lower = 0.0;
3060 m_hAdjust->upper = frange;
3061 m_hAdjust->value = fpos;
3062 m_hAdjust->step_increment = 1.0;
3063 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
3064 m_hAdjust->page_size = fthumb;
cb43b372 3065 }
1ecc4d80
RR
3066 else
3067 {
3068 float fpos = (float)pos;
3069 float frange = (float)range;
3070 float fthumb = (float)thumbVisible;
3071 if (fpos > frange-fthumb) fpos = frange-fthumb;
3072 if (fpos < 0.0) fpos = 0.0;
3073
3074 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
3075 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
3076 {
3077 SetScrollPos( orient, pos, refresh );
3078 return;
3079 }
47d67540 3080
1ecc4d80 3081 m_oldVerticalPos = fpos;
47d67540 3082
1ecc4d80
RR
3083 m_vAdjust->lower = 0.0;
3084 m_vAdjust->upper = frange;
3085 m_vAdjust->value = fpos;
3086 m_vAdjust->step_increment = 1.0;
3087 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
3088 m_vAdjust->page_size = fthumb;
3089 }
47d67540 3090
eb082a08
RR
3091 if (orient == wxHORIZONTAL)
3092 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
3093 else
3094 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
362c6693 3095}
c801d85f 3096
debe6624 3097void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
c801d85f 3098{
05939a81 3099 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
1ecc4d80 3100
05939a81 3101 wxCHECK_RET( m_wxwindow != NULL, _T("window needs client area for scrolling") );
1ecc4d80
RR
3102
3103 if (orient == wxHORIZONTAL)
3104 {
3105 float fpos = (float)pos;
3106 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
3107 if (fpos < 0.0) fpos = 0.0;
3108 m_oldHorizontalPos = fpos;
3109
3110 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
3111 m_hAdjust->value = fpos;
3112 }
3113 else
3114 {
3115 float fpos = (float)pos;
3116 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
3117 if (fpos < 0.0) fpos = 0.0;
3118 m_oldVerticalPos = fpos;
ff8bfdbb 3119
1ecc4d80
RR
3120 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
3121 m_vAdjust->value = fpos;
3122 }
47d67540 3123
eb082a08 3124 if (!m_isScrolling) /* prevent recursion */
47d67540 3125 {
1ecc4d80
RR
3126 if (m_wxwindow->window)
3127 {
3128 if (orient == wxHORIZONTAL)
3129 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
3130 else
3131 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
3132 }
cb43b372 3133 }
362c6693 3134}
c801d85f 3135
debe6624 3136int wxWindow::GetScrollThumb( int orient ) const
c801d85f 3137{
05939a81 3138 wxCHECK_MSG( m_widget != NULL, 0, _T("invalid window") );
47d67540 3139
05939a81 3140 wxCHECK_MSG( m_wxwindow != NULL, 0, _T("window needs client area for scrolling") );
47d67540 3141
1ecc4d80
RR
3142 if (orient == wxHORIZONTAL)
3143 return (int)(m_hAdjust->page_size+0.5);
3144 else
3145 return (int)(m_vAdjust->page_size+0.5);
362c6693 3146}
c801d85f 3147
debe6624 3148int wxWindow::GetScrollPos( int orient ) const
c801d85f 3149{
05939a81 3150 wxCHECK_MSG( m_widget != NULL, 0, _T("invalid window") );
47d67540 3151
05939a81 3152 wxCHECK_MSG( m_wxwindow != NULL, 0, _T("window needs client area for scrolling") );
c801d85f 3153
1ecc4d80
RR
3154 if (orient == wxHORIZONTAL)
3155 return (int)(m_hAdjust->value+0.5);
3156 else
3157 return (int)(m_vAdjust->value+0.5);
362c6693 3158}
c801d85f 3159
debe6624 3160int wxWindow::GetScrollRange( int orient ) const
c801d85f 3161{
05939a81 3162 wxCHECK_MSG( m_widget != NULL, 0, _T("invalid window") );
47d67540 3163
05939a81 3164 wxCHECK_MSG( m_wxwindow != NULL, 0, _T("window needs client area for scrolling") );
c801d85f 3165
1ecc4d80
RR
3166 if (orient == wxHORIZONTAL)
3167 return (int)(m_hAdjust->upper+0.5);
3168 else
3169 return (int)(m_vAdjust->upper+0.5);
362c6693 3170}
c801d85f 3171
debe6624 3172void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
c801d85f 3173{
05939a81 3174 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
47d67540 3175
05939a81 3176 wxCHECK_RET( m_wxwindow != NULL, _T("window needs client area for scrolling") );
c801d85f 3177
a2053b27 3178 if (!m_scrollGC)
96d5ab4d 3179 {
a2053b27
RR
3180 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3181 gdk_gc_set_exposures( m_scrollGC, TRUE );
96d5ab4d 3182 }
c50f1fb9 3183
ea5c6ca7
RR
3184 wxNode *node = m_children.First();
3185 while (node)
3186 {
3187 wxWindow *child = (wxWindow*) node->Data();
c50f1fb9
VZ
3188 int sx = 0;
3189 int sy = 0;
3190 child->GetSize( &sx, &sy );
3191 child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
3192 node = node->Next();
ea5c6ca7 3193 }
96d5ab4d 3194
c801d85f
KB
3195 int cw = 0;
3196 int ch = 0;
3197 GetClientSize( &cw, &ch );
c801d85f
KB
3198 int w = cw - abs(dx);
3199 int h = ch - abs(dy);
c50f1fb9 3200
c801d85f
KB
3201 if ((h < 0) || (w < 0))
3202 {
1ecc4d80 3203 Refresh();
362c6693 3204 }
a2053b27 3205 else
c801d85f 3206 {
a2053b27
RR
3207 int s_x = 0;
3208 int s_y = 0;
3209 if (dx < 0) s_x = -dx;
3210 if (dy < 0) s_y = -dy;
3211 int d_x = 0;
3212 int d_y = 0;
3213 if (dx > 0) d_x = dx;
3214 if (dy > 0) d_y = dy;
c801d85f 3215
a2053b27
RR
3216 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3217 m_wxwindow->window, s_x, s_y, w, h );
c801d85f 3218
a2053b27
RR
3219 wxRect rect;
3220 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3221 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3222 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3223 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
c801d85f 3224
a2053b27
RR
3225 Refresh( TRUE, &rect );
3226 }
c801d85f
KB
3227}
3228
f03fc89f 3229void wxWindow::SetScrolling(bool scroll)
c801d85f 3230{
f03fc89f 3231 m_isScrolling = g_blockEventsOnScroll = scroll;
c801d85f 3232}