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