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