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