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