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