]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/window.cpp
wxDataObejct and related changes (won't compile right now)
[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();
ff8bfdbb 1125
a2053b27 1126 if (child->m_isStaticBox)
ff8bfdbb
VZ
1127 {
1128 // wxStaticBox is transparent in the box itself
a2053b27
RR
1129 int xx1 = child->m_x;
1130 int yy1 = child->m_y;
1131 int xx2 = child->m_x + child->m_width;
1132 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1133
1134 // left
1135 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1136 // right
1137 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1138 // top
1139 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1140 // bottom
1141 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1142 {
1ecc4d80 1143 win = child;
a2053b27
RR
1144 event.m_x -= child->m_x;
1145 event.m_y -= child->m_y;
1ecc4d80 1146 break;
ff8bfdbb
VZ
1147 }
1148
1149 }
1150 else
1151 {
a2053b27 1152 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
2f073eb2
RR
1153 (child->m_x <= x) &&
1154 (child->m_y <= y) &&
1155 (child->m_x+child->m_width >= x) &&
1156 (child->m_y+child->m_height >= y))
1ecc4d80
RR
1157 {
1158 win = child;
a2053b27
RR
1159 event.m_x -= child->m_x;
1160 event.m_y -= child->m_y;
1ecc4d80 1161 break;
ff8bfdbb 1162 }
f5e27805
RR
1163 }
1164 node = node->Next();
1165 }
2f2aa628 1166 }
ff8bfdbb 1167
f5e27805 1168 event.SetEventObject( win );
47d67540 1169
f5e27805 1170 gs_timeLastClick = gdk_event->time;
47d67540 1171
2f073eb2
RR
1172/*
1173 wxPrintf( wxT("2) OnButtonPress from ") );
1174 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1175 wxPrintf( win->GetClassInfo()->GetClassName() );
1176 wxPrintf( wxT(".\n") );
1177*/
1178
f5e27805 1179 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1180 {
f5e27805 1181 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
f03fc89f 1182 return TRUE;
034be888 1183 }
47d67540 1184
034be888 1185 return FALSE;
362c6693 1186}
c801d85f
KB
1187
1188//-----------------------------------------------------------------------------
97b3455a 1189// "button_release_event"
2f2aa628 1190//-----------------------------------------------------------------------------
c801d85f 1191
2f2aa628 1192static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
47d67540 1193{
c50f1fb9 1194 if (g_isIdle)
a2053b27
RR
1195 wxapp_install_idle_handler();
1196
1197 if (!win->m_hasVMT) return FALSE;
034be888
RR
1198 if (g_blockEventsOnDrag) return FALSE;
1199 if (g_blockEventsOnScroll) return FALSE;
c801d85f 1200
034be888 1201 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
47d67540 1202
c801d85f 1203/*
f5e27805
RR
1204 printf( "OnButtonRelease from " );
1205 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1206 printf( win->GetClassInfo()->GetClassName() );
1207 printf( ".\n" );
c801d85f 1208*/
47d67540 1209
f5e27805 1210 wxEventType event_type = wxEVT_NULL;
47d67540 1211
f5e27805
RR
1212 switch (gdk_event->button)
1213 {
1214 case 1: event_type = wxEVT_LEFT_UP; break;
1215 case 2: event_type = wxEVT_MIDDLE_UP; break;
1216 case 3: event_type = wxEVT_RIGHT_UP; break;
1217 }
47d67540 1218
f5e27805 1219 wxMouseEvent event( event_type );
d1367c3d 1220 event.SetTimestamp( gdk_event->time );
f5e27805
RR
1221 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1222 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1223 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1224 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1225 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1226 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1227 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
1228 event.m_x = (long)gdk_event->x;
1229 event.m_y = (long)gdk_event->y;
1230
1231 // Some control don't have their own X window and thus cannot get
1232 // any events.
1233
72195a0f 1234 if (!g_captureWindow)
2f2aa628 1235 {
2f073eb2
RR
1236 int x = event.m_x;
1237 int y = event.m_y;
1238 if (win->m_wxwindow)
1239 {
1240 GtkMyFixed *myfixed = GTK_MYFIXED(win->m_wxwindow);
1241 x += myfixed->xoffset;
1242 y += myfixed->yoffset;
1243 }
1244
db1b4961 1245 wxNode *node = win->GetChildren().First();
f5e27805
RR
1246 while (node)
1247 {
1248 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb 1249
a2053b27 1250 if (child->m_isStaticBox)
ff8bfdbb
VZ
1251 {
1252 // wxStaticBox is transparent in the box itself
a2053b27
RR
1253 int xx1 = child->m_x;
1254 int yy1 = child->m_y;
1255 int xx2 = child->m_x + child->m_width;
1256 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1257
1258 // left
1259 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1260 // right
1261 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1262 // top
1263 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1264 // bottom
1265 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1266 {
1ecc4d80 1267 win = child;
a2053b27
RR
1268 event.m_x -= child->m_x;
1269 event.m_y -= child->m_y;
1ecc4d80 1270 break;
ff8bfdbb
VZ
1271 }
1272
1273 }
1274 else
1275 {
a2053b27 1276 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
2f073eb2
RR
1277 (child->m_x <= x) &&
1278 (child->m_y <= y) &&
1279 (child->m_x+child->m_width >= x) &&
1280 (child->m_y+child->m_height >= y))
1ecc4d80
RR
1281 {
1282 win = child;
a2053b27
RR
1283 event.m_x -= child->m_x;
1284 event.m_y -= child->m_y;
1ecc4d80 1285 break;
ff8bfdbb 1286 }
f5e27805
RR
1287 }
1288 node = node->Next();
1289 }
2f2aa628 1290 }
47d67540 1291
f5e27805 1292 event.SetEventObject( win );
47d67540 1293
f5e27805 1294 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1295 {
f5e27805 1296 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" );
f03fc89f 1297 return TRUE;
034be888 1298 }
47d67540 1299
034be888 1300 return FALSE;
362c6693 1301}
c801d85f
KB
1302
1303//-----------------------------------------------------------------------------
2f2aa628
RR
1304// "motion_notify_event"
1305//-----------------------------------------------------------------------------
c801d85f 1306
2f2aa628 1307static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
47d67540 1308{
c50f1fb9 1309 if (g_isIdle)
a2053b27
RR
1310 wxapp_install_idle_handler();
1311
1312 if (!win->m_hasVMT) return FALSE;
034be888
RR
1313 if (g_blockEventsOnDrag) return FALSE;
1314 if (g_blockEventsOnScroll) return FALSE;
5e014a0c 1315
034be888
RR
1316 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1317
ff8bfdbb 1318 if (gdk_event->is_hint)
aae24d21 1319 {
f7a11f8c
RR
1320 int x = 0;
1321 int y = 0;
1322 GdkModifierType state;
1323 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
1324 gdk_event->x = x;
1325 gdk_event->y = y;
aae24d21 1326 }
ff8bfdbb 1327
c801d85f 1328/*
e380f72b
RR
1329 printf( "OnMotion from " );
1330 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1331 printf( win->GetClassInfo()->GetClassName() );
1332 printf( ".\n" );
aae24d21 1333*/
47d67540 1334
e380f72b 1335 wxMouseEvent event( wxEVT_MOTION );
d1367c3d 1336 event.SetTimestamp( gdk_event->time );
e380f72b
RR
1337 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1338 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1339 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1340 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1341 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1342 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1343 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
1344
1345 event.m_x = (long)gdk_event->x;
1346 event.m_y = (long)gdk_event->y;
1347
1348 // Some control don't have their own X window and thus cannot get
1349 // any events.
1350
72195a0f 1351 if (!g_captureWindow)
2f2aa628 1352 {
2f073eb2
RR
1353 int x = event.m_x;
1354 int y = event.m_y;
1355 if (win->m_wxwindow)
1356 {
1357 GtkMyFixed *myfixed = GTK_MYFIXED(win->m_wxwindow);
1358 x += myfixed->xoffset;
1359 y += myfixed->yoffset;
1360 }
1361
db1b4961 1362 wxNode *node = win->GetChildren().First();
e380f72b
RR
1363 while (node)
1364 {
1365 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb 1366
a2053b27 1367 if (child->m_isStaticBox)
ff8bfdbb
VZ
1368 {
1369 // wxStaticBox is transparent in the box itself
a2053b27
RR
1370 int xx1 = child->m_x;
1371 int yy1 = child->m_y;
1372 int xx2 = child->m_x + child->m_width;
1373 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1374
1375 // left
1376 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1377 // right
1378 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1379 // top
1380 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1381 // bottom
1382 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1383 {
1ecc4d80 1384 win = child;
a2053b27
RR
1385 event.m_x -= child->m_x;
1386 event.m_y -= child->m_y;
1ecc4d80 1387 break;
ff8bfdbb
VZ
1388 }
1389
1390 }
1391 else
1392 {
a2053b27 1393 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
2f073eb2
RR
1394 (child->m_x <= x) &&
1395 (child->m_y <= y) &&
1396 (child->m_x+child->m_width >= x) &&
1397 (child->m_y+child->m_height >= y))
1ecc4d80
RR
1398 {
1399 win = child;
a2053b27
RR
1400 event.m_x -= child->m_x;
1401 event.m_y -= child->m_y;
1ecc4d80 1402 break;
ff8bfdbb 1403 }
e380f72b
RR
1404 }
1405 node = node->Next();
1406 }
2f2aa628 1407 }
47d67540 1408
e380f72b 1409 event.SetEventObject( win );
47d67540 1410
e380f72b 1411 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1412 {
e380f72b 1413 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
f03fc89f 1414 return TRUE;
034be888 1415 }
47d67540 1416
034be888 1417 return FALSE;
362c6693 1418}
c801d85f
KB
1419
1420//-----------------------------------------------------------------------------
2f2aa628
RR
1421// "focus_in_event"
1422//-----------------------------------------------------------------------------
c801d85f 1423
2f2aa628 1424static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
c801d85f 1425{
c50f1fb9 1426 if (g_isIdle)
a2053b27
RR
1427 wxapp_install_idle_handler();
1428
1429 if (!win->m_hasVMT) return FALSE;
034be888 1430 if (g_blockEventsOnDrag) return FALSE;
ff8bfdbb 1431
b292e2f5 1432 g_focusWindow = win;
ff8bfdbb 1433
a2053b27 1434 if (win->m_wxwindow)
c801d85f 1435 {
a2053b27 1436 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
e380f72b 1437 {
a2053b27 1438 GTK_WIDGET_SET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
47d67540 1439/*
e380f72b
RR
1440 printf( "SetFocus flag from " );
1441 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1442 printf( win->GetClassInfo()->GetClassName() );
1443 printf( ".\n" );
c801d85f 1444*/
e380f72b 1445 }
362c6693 1446 }
47d67540 1447
47d67540 1448
c801d85f 1449/*
f03fc89f 1450 printf( "OnSetFocus from " );
e380f72b 1451 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
f03fc89f
VZ
1452 printf( win->GetClassInfo()->GetClassName() );
1453 printf( " " );
1454 printf( WXSTRINGCAST win->GetLabel() );
1455 printf( ".\n" );
c801d85f 1456*/
47d67540 1457
e380f72b
RR
1458 wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
1459 event.SetEventObject( win );
47d67540 1460
e380f72b 1461 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1462 {
e380f72b 1463 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
034be888
RR
1464 return TRUE;
1465 }
ca298c88 1466
034be888 1467 return FALSE;
362c6693 1468}
c801d85f
KB
1469
1470//-----------------------------------------------------------------------------
2f2aa628
RR
1471// "focus_out_event"
1472//-----------------------------------------------------------------------------
c801d85f 1473
2f2aa628 1474static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
c801d85f 1475{
c50f1fb9 1476 if (g_isIdle)
a2053b27
RR
1477 wxapp_install_idle_handler();
1478
1479 if (!win->m_hasVMT) return FALSE;
034be888 1480 if (g_blockEventsOnDrag) return FALSE;
ca298c88 1481
a2053b27 1482 if (win->m_wxwindow)
e380f72b 1483 {
a2053b27
RR
1484 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
1485 GTK_WIDGET_UNSET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
e380f72b 1486 }
47d67540 1487
c801d85f 1488/*
f03fc89f 1489 printf( "OnKillFocus from " );
e380f72b 1490 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
f03fc89f
VZ
1491 printf( win->GetClassInfo()->GetClassName() );
1492 printf( ".\n" );
c801d85f 1493*/
47d67540 1494
e380f72b
RR
1495 wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
1496 event.SetEventObject( win );
47d67540 1497
e380f72b 1498 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1499 {
e380f72b 1500 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
034be888
RR
1501 return TRUE;
1502 }
ca298c88 1503
034be888 1504 return FALSE;
362c6693 1505}
c801d85f 1506
b4071e91
RR
1507//-----------------------------------------------------------------------------
1508// "enter_notify_event"
1509//-----------------------------------------------------------------------------
1510
1511static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1512{
c50f1fb9 1513 if (g_isIdle)
a2053b27 1514 wxapp_install_idle_handler();
ca298c88 1515
a2053b27
RR
1516 if (!win->m_hasVMT) return FALSE;
1517 if (g_blockEventsOnDrag) return FALSE;
47d67540 1518
a2053b27 1519 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
b292e2f5 1520
e380f72b 1521 wxMouseEvent event( wxEVT_ENTER_WINDOW );
6bc8a1c8 1522#if (GTK_MINOR_VERSION > 0)
d1367c3d 1523 event.SetTimestamp( gdk_event->time );
6bc8a1c8 1524#endif
e380f72b 1525 event.SetEventObject( win );
ff8bfdbb 1526
4a33eba6
RR
1527 int x = 0;
1528 int y = 0;
1529 GdkModifierType state = (GdkModifierType)0;
ff8bfdbb 1530
a2053b27 1531 gdk_window_get_pointer( widget->window, &x, &y, &state );
ff8bfdbb 1532
4a33eba6
RR
1533 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1534 event.m_controlDown = (state & GDK_CONTROL_MASK);
1535 event.m_altDown = (state & GDK_MOD1_MASK);
1536 event.m_metaDown = (state & GDK_MOD2_MASK);
1537 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1538 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1539 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1540
1541 event.m_x = (long)x;
1542 event.m_y = (long)y;
ff8bfdbb 1543
e380f72b 1544 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1545 {
e380f72b 1546 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "enter_notify_event" );
034be888
RR
1547 return TRUE;
1548 }
ca298c88 1549
034be888 1550 return FALSE;
b4071e91 1551}
47d67540 1552
b4071e91
RR
1553//-----------------------------------------------------------------------------
1554// "leave_notify_event"
1555//-----------------------------------------------------------------------------
1556
1557static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1558{
c50f1fb9 1559 if (g_isIdle)
a2053b27 1560 wxapp_install_idle_handler();
acfd422a 1561
a2053b27
RR
1562 if (!win->m_hasVMT) return FALSE;
1563 if (g_blockEventsOnDrag) return FALSE;
b292e2f5 1564
a2053b27 1565 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
c50f1fb9 1566
e380f72b 1567 wxMouseEvent event( wxEVT_LEAVE_WINDOW );
6bc8a1c8 1568#if (GTK_MINOR_VERSION > 0)
d1367c3d 1569 event.SetTimestamp( gdk_event->time );
6bc8a1c8 1570#endif
e380f72b 1571 event.SetEventObject( win );
47d67540 1572
4a33eba6
RR
1573 int x = 0;
1574 int y = 0;
1575 GdkModifierType state = (GdkModifierType)0;
ff8bfdbb 1576
4a33eba6 1577 gdk_window_get_pointer( widget->window, &x, &y, &state );
ff8bfdbb 1578
4a33eba6
RR
1579 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1580 event.m_controlDown = (state & GDK_CONTROL_MASK);
1581 event.m_altDown = (state & GDK_MOD1_MASK);
1582 event.m_metaDown = (state & GDK_MOD2_MASK);
1583 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1584 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1585 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1586
1587 event.m_x = (long)x;
1588 event.m_y = (long)y;
ff8bfdbb 1589
e380f72b 1590 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1591 {
e380f72b 1592 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "leave_notify_event" );
034be888
RR
1593 return TRUE;
1594 }
ca298c88 1595
034be888 1596 return FALSE;
b4071e91 1597}
47d67540 1598
c801d85f 1599//-----------------------------------------------------------------------------
2f2aa628
RR
1600// "value_changed" from m_vAdjust
1601//-----------------------------------------------------------------------------
c801d85f 1602
5e014a0c 1603static void gtk_window_vscroll_callback( GtkAdjustment *adjust, wxWindow *win )
c801d85f 1604{
c50f1fb9 1605 if (g_isIdle)
a2053b27 1606 wxapp_install_idle_handler();
c801d85f 1607
a2053b27 1608 if (g_blockEventsOnDrag) return;
47d67540 1609
a2053b27 1610 if (!win->m_hasVMT) return;
5e014a0c
RR
1611
1612 float diff = adjust->value - win->m_oldVerticalPos;
e380f72b 1613 if (fabs(diff) < 0.2) return;
5e014a0c
RR
1614
1615 win->m_oldVerticalPos = adjust->value;
47d67540 1616
5e014a0c
RR
1617 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
1618 GtkRange *range = GTK_RANGE( scrolledWindow->vscrollbar );
1619
1620 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
1621 if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP;
1622 else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN;
1623 else if (range->scroll_type == GTK_SCROLL_PAGE_BACKWARD) command = wxEVT_SCROLLWIN_PAGEUP;
1624 else if (range->scroll_type == GTK_SCROLL_PAGE_FORWARD) command = wxEVT_SCROLLWIN_PAGEDOWN;
1625
5e014a0c 1626 int value = (int)(adjust->value+0.5);
c801d85f 1627
c5b42c87 1628 wxScrollWinEvent event( command, value, wxVERTICAL );
e380f72b
RR
1629 event.SetEventObject( win );
1630 win->GetEventHandler()->ProcessEvent( event );
362c6693 1631}
c801d85f
KB
1632
1633//-----------------------------------------------------------------------------
2f2aa628
RR
1634// "value_changed" from m_hAdjust
1635//-----------------------------------------------------------------------------
c801d85f 1636
5e014a0c 1637static void gtk_window_hscroll_callback( GtkAdjustment *adjust, wxWindow *win )
47d67540 1638{
c50f1fb9 1639 if (g_isIdle)
a2053b27 1640 wxapp_install_idle_handler();
47d67540 1641
a2053b27
RR
1642 if (g_blockEventsOnDrag) return;
1643 if (!win->m_hasVMT) return;
47d67540 1644
5e014a0c 1645 float diff = adjust->value - win->m_oldHorizontalPos;
e380f72b 1646 if (fabs(diff) < 0.2) return;
5e014a0c
RR
1647
1648 win->m_oldHorizontalPos = adjust->value;
8bbe427f 1649
5e014a0c
RR
1650 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
1651 GtkRange *range = GTK_RANGE( scrolledWindow->hscrollbar );
1652
1653 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
1654 if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP;
1655 else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN;
1656 else if (range->scroll_type == GTK_SCROLL_PAGE_BACKWARD) command = wxEVT_SCROLLWIN_PAGEUP;
1657 else if (range->scroll_type == GTK_SCROLL_PAGE_FORWARD) command = wxEVT_SCROLLWIN_PAGEDOWN;
1658
5e014a0c 1659 int value = (int)(adjust->value+0.5);
47d67540 1660
c5b42c87 1661 wxScrollWinEvent event( command, value, wxHORIZONTAL );
e380f72b
RR
1662 event.SetEventObject( win );
1663 win->GetEventHandler()->ProcessEvent( event );
362c6693 1664}
c801d85f
KB
1665
1666//-----------------------------------------------------------------------------
2f2aa628
RR
1667// "changed" from m_vAdjust
1668//-----------------------------------------------------------------------------
c801d85f 1669
2f2aa628 1670static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
c801d85f 1671{
c50f1fb9 1672 if (g_isIdle)
a2053b27 1673 wxapp_install_idle_handler();
c801d85f 1674
a2053b27
RR
1675 if (g_blockEventsOnDrag) return;
1676 if (!win->m_hasVMT) return;
47d67540 1677
c5b42c87 1678 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
a2053b27 1679 int value = (int)(win->m_vAdjust->value+0.5);
c801d85f 1680
c5b42c87 1681 wxScrollWinEvent event( command, value, wxVERTICAL );
e380f72b
RR
1682 event.SetEventObject( win );
1683 win->GetEventHandler()->ProcessEvent( event );
362c6693 1684}
c801d85f
KB
1685
1686//-----------------------------------------------------------------------------
2f2aa628
RR
1687// "changed" from m_hAdjust
1688//-----------------------------------------------------------------------------
c801d85f 1689
2f2aa628 1690static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
47d67540 1691{
c50f1fb9 1692 if (g_isIdle)
a2053b27 1693 wxapp_install_idle_handler();
47d67540 1694
a2053b27
RR
1695 if (g_blockEventsOnDrag) return;
1696 if (!win->m_hasVMT) return;
47d67540 1697
c5b42c87 1698 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
a2053b27 1699 int value = (int)(win->m_hAdjust->value+0.5);
47d67540 1700
c5b42c87 1701 wxScrollWinEvent event( command, value, wxHORIZONTAL );
e380f72b
RR
1702 event.SetEventObject( win );
1703 win->GetEventHandler()->ProcessEvent( event );
362c6693 1704}
c801d85f 1705
cb43b372
RR
1706//-----------------------------------------------------------------------------
1707// "button_press_event" from scrollbar
1708//-----------------------------------------------------------------------------
1709
8bbe427f
VZ
1710static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
1711 GdkEventButton *WXUNUSED(gdk_event),
ff8bfdbb 1712 wxWindow *win )
cb43b372 1713{
c50f1fb9 1714 if (g_isIdle)
a2053b27
RR
1715 wxapp_install_idle_handler();
1716
1ecc4d80 1717// don't test here as we can release the mouse while being over
5e014a0c 1718// a different window than the slider
1ecc4d80 1719//
76ed8f8d 1720// if (gdk_event->window != widget->slider) return FALSE;
8bbe427f 1721
f03fc89f 1722 win->SetScrolling( TRUE );
47d67540 1723
e380f72b 1724 return FALSE;
cb43b372
RR
1725}
1726
1727//-----------------------------------------------------------------------------
1728// "button_release_event" from scrollbar
1729//-----------------------------------------------------------------------------
1730
5e0201ea 1731static gint gtk_scrollbar_button_release_callback( GtkRange *WXUNUSED(widget),
8bbe427f 1732 GdkEventButton *WXUNUSED(gdk_event),
ff8bfdbb 1733 wxWindow *win )
cb43b372 1734{
76ed8f8d 1735
1ecc4d80 1736// don't test here as we can release the mouse while being over
5e014a0c 1737// a different window than the slider
76ed8f8d
RR
1738//
1739// if (gdk_event->window != widget->slider) return FALSE;
cb43b372 1740
f03fc89f 1741 win->SetScrolling( FALSE );
47d67540 1742
e380f72b 1743 return FALSE;
cb43b372
RR
1744}
1745
f03fc89f
VZ
1746// ----------------------------------------------------------------------------
1747// this wxWindowBase function is implemented here (in platform-specific file)
1748// because it is static and so couldn't be made virtual
1749// ----------------------------------------------------------------------------
2b07d713 1750
f03fc89f 1751wxWindow *wxWindowBase::FindFocus()
2b07d713 1752{
f03fc89f 1753 return g_focusWindow;
2b07d713 1754}
ca298c88 1755
a2053b27
RR
1756//-----------------------------------------------------------------------------
1757// "realize" from m_widget
1758//-----------------------------------------------------------------------------
1759
5e014a0c 1760/* we cannot set colours and fonts before the widget has
a2053b27
RR
1761 been realized, so we do this directly after realization */
1762
1763static gint
a234a61a 1764gtk_window_realized_callback( GtkWidget * WXUNUSED(widget), wxWindow *win )
a2053b27 1765{
c50f1fb9 1766 if (g_isIdle)
a2053b27
RR
1767 wxapp_install_idle_handler();
1768
739730ca
RR
1769 if (win->m_delayedFont)
1770 win->SetFont( win->GetFont() );
a2053b27 1771
739730ca
RR
1772 if (win->m_delayedBackgroundColour)
1773 win->SetBackgroundColour( win->GetBackgroundColour() );
a2053b27 1774
739730ca
RR
1775 if (win->m_delayedForegroundColour)
1776 win->SetForegroundColour( win->GetForegroundColour() );
a2053b27 1777
3c679789
RR
1778 wxWindowCreateEvent event( win );
1779 event.SetEventObject( win );
1780 win->GetEventHandler()->ProcessEvent( event );
a2053b27
RR
1781
1782 return FALSE;
1783}
1784
6ca41e57
RR
1785//-----------------------------------------------------------------------------
1786// InsertChild for wxWindow.
1787//-----------------------------------------------------------------------------
1788
b1170810
RR
1789/* Callback for wxWindow. This very strange beast has to be used because
1790 * C++ has no virtual methods in a constructor. We have to emulate a
1791 * virtual function here as wxNotebook requires a different way to insert
1792 * a child in it. I had opted for creating a wxNotebookPage window class
1793 * which would have made this superfluous (such in the MDI window system),
1794 * but no-one was listening to me... */
6ca41e57
RR
1795
1796static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
1797{
bf0c00c6
RR
1798 /* the window might have been scrolled already, do we
1799 have to adapt the position */
1800 GtkMyFixed *myfixed = GTK_MYFIXED(parent->m_wxwindow);
1801 child->m_x += myfixed->xoffset;
1802 child->m_y += myfixed->yoffset;
1803
a2053b27
RR
1804 gtk_myfixed_put( GTK_MYFIXED(parent->m_wxwindow),
1805 GTK_WIDGET(child->m_widget),
1806 child->m_x,
1807 child->m_y,
1808 child->m_width,
1809 child->m_height );
f03fc89f
VZ
1810
1811 if (parent->HasFlag(wxTAB_TRAVERSAL))
3e61c765
RR
1812 {
1813 /* we now allow a window to get the focus as long as it
ff8bfdbb 1814 doesn't have any children. */
a2053b27 1815 GTK_WIDGET_UNSET_FLAGS( parent->m_wxwindow, GTK_CAN_FOCUS );
3e61c765 1816 }
6ca41e57
RR
1817}
1818
bbe0af5b
RR
1819//-----------------------------------------------------------------------------
1820// global functions
1821//-----------------------------------------------------------------------------
1822
1823wxWindow* wxGetActiveWindow()
1824{
f03fc89f 1825 return g_focusWindow;
bbe0af5b
RR
1826}
1827
c801d85f 1828//-----------------------------------------------------------------------------
2f2aa628 1829// wxWindow
c801d85f
KB
1830//-----------------------------------------------------------------------------
1831
f03fc89f 1832IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
c801d85f 1833
68995f26 1834void wxWindow::Init()
c801d85f 1835{
f03fc89f
VZ
1836 // common init
1837 InitBase();
68995f26 1838
f03fc89f 1839 // GTK specific
a2053b27 1840 m_widget = (GtkWidget *) NULL;
e380f72b 1841 m_wxwindow = (GtkWidget *) NULL;
8bbe427f 1842
f03fc89f 1843 // position/size
a2053b27
RR
1844 m_x = 0;
1845 m_y = 0;
1846 m_width = 0;
e380f72b 1847 m_height = 0;
8bbe427f 1848
e380f72b
RR
1849 m_sizeSet = FALSE;
1850 m_hasVMT = FALSE;
1851 m_needParent = TRUE;
31c6b4fc 1852 m_isBeingDeleted = FALSE;
147bc491
RR
1853
1854 m_noExpose = FALSE;
30760ce7
RR
1855 m_nativeSizeEvent = FALSE;
1856
a2053b27 1857 m_hasScrolling = FALSE;
e380f72b 1858 m_isScrolling = FALSE;
f03fc89f 1859
a2053b27 1860 m_hAdjust = (GtkAdjustment*) NULL;
e380f72b 1861 m_vAdjust = (GtkAdjustment*) NULL;
a2053b27 1862 m_oldHorizontalPos = 0.0;
e380f72b 1863 m_oldVerticalPos = 0.0;
8bbe427f 1864
e380f72b 1865 m_resizing = FALSE;
e380f72b 1866 m_widgetStyle = (GtkStyle*) NULL;
8bbe427f 1867
ddb6bc71 1868 m_insertCallback = (wxInsertChildFunction) NULL;
8bbe427f 1869
1ecc4d80 1870 m_isStaticBox = FALSE;
953704c1 1871 m_isRadioButton = FALSE;
54517652 1872 m_isFrame = FALSE;
b292e2f5 1873 m_acceptsFocus = FALSE;
5e014a0c
RR
1874
1875 m_cursor = *wxSTANDARD_CURSOR;
362c6693 1876}
c801d85f 1877
68995f26
VZ
1878wxWindow::wxWindow()
1879{
1880 Init();
1881}
1882
6ca41e57 1883wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
e380f72b
RR
1884 const wxPoint &pos, const wxSize &size,
1885 long style, const wxString &name )
6ca41e57 1886{
68995f26
VZ
1887 Init();
1888
e380f72b 1889 Create( parent, id, pos, size, style, name );
6ca41e57 1890}
8bbe427f 1891
debe6624 1892bool wxWindow::Create( wxWindow *parent, wxWindowID id,
e380f72b
RR
1893 const wxPoint &pos, const wxSize &size,
1894 long style, const wxString &name )
c801d85f 1895{
4dcaf11a
RR
1896 if (!PreCreation( parent, pos, size ) ||
1897 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
1898 {
223d09f6 1899 wxFAIL_MSG( wxT("wxWindow creation failed") );
4dcaf11a
RR
1900 return FALSE;
1901 }
47d67540 1902
ddb6bc71
RR
1903 m_insertCallback = wxInsertChildInWindow;
1904
e380f72b 1905 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
38c7b3d3 1906 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
ff8bfdbb 1907
2e563988 1908#ifdef __WXDEBUG__
223d09f6 1909 debug_focus_in( m_widget, wxT("wxWindow::m_widget"), name );
2e563988
RR
1910#endif
1911
f03fc89f 1912 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
47d67540 1913
2e563988 1914#ifdef __WXDEBUG__
223d09f6
KB
1915 debug_focus_in( scrolledWindow->hscrollbar, wxT("wxWindow::hsrcollbar"), name );
1916 debug_focus_in( scrolledWindow->vscrollbar, wxT("wxWindow::vsrcollbar"), name );
2e563988
RR
1917#endif
1918
e380f72b
RR
1919 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1920 scroll_class->scrollbar_spacing = 0;
47d67540 1921
f03fc89f 1922 gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
47d67540 1923
f03fc89f
VZ
1924 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->hscrollbar) );
1925 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->vscrollbar) );
47d67540 1926
38c7b3d3
RR
1927 m_wxwindow = gtk_myfixed_new();
1928
2e563988 1929#ifdef __WXDEBUG__
223d09f6 1930 debug_focus_in( m_wxwindow, wxT("wxWindow::m_wxwindow"), name );
2e563988
RR
1931#endif
1932
034be888 1933 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
58dea4b0 1934
034be888
RR
1935#if (GTK_MINOR_VERSION > 0)
1936 GtkMyFixed *myfixed = GTK_MYFIXED(m_wxwindow);
b292e2f5 1937
f03fc89f 1938 if (HasFlag(wxRAISED_BORDER))
034be888 1939 {
5e014a0c 1940 gtk_myfixed_set_shadow_type( myfixed, GTK_MYSHADOW_OUT );
034be888 1941 }
f03fc89f 1942 else if (HasFlag(wxSUNKEN_BORDER))
034be888 1943 {
5e014a0c
RR
1944 gtk_myfixed_set_shadow_type( myfixed, GTK_MYSHADOW_IN );
1945 }
1946 else if (HasFlag(wxSIMPLE_BORDER))
1947 {
1948 gtk_myfixed_set_shadow_type( myfixed, GTK_MYSHADOW_THIN );
034be888
RR
1949 }
1950 else
1951 {
5e014a0c 1952 gtk_myfixed_set_shadow_type( myfixed, GTK_MYSHADOW_NONE );
034be888 1953 }
f03fc89f
VZ
1954#else // GTK_MINOR_VERSION == 0
1955 GtkViewport *viewport = GTK_VIEWPORT(scrolledWindow->viewport);
b292e2f5 1956
f03fc89f 1957 if (HasFlag(wxRAISED_BORDER))
e380f72b
RR
1958 {
1959 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
1960 }
f03fc89f 1961 else if (HasFlag(wxSUNKEN_BORDER))
e380f72b
RR
1962 {
1963 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
1964 }
1965 else
1966 {
1967 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
1968 }
f03fc89f 1969#endif // GTK_MINOR_VERSION
47d67540 1970
f03fc89f 1971 if (HasFlag(wxTAB_TRAVERSAL))
b292e2f5 1972 {
f03fc89f
VZ
1973 /* we now allow a window to get the focus as long as it
1974 doesn't have any children. */
ff8bfdbb 1975 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
b292e2f5
RR
1976 m_acceptsFocus = FALSE;
1977 }
e380f72b 1978 else
b292e2f5 1979 {
e380f72b 1980 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
b292e2f5
RR
1981 m_acceptsFocus = TRUE;
1982 }
ca298c88 1983
034be888 1984#if (GTK_MINOR_VERSION == 0)
e380f72b
RR
1985 // shut the viewport up
1986 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1987 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
f03fc89f 1988#endif // GTK_MINOR_VERSION == 0
e380f72b
RR
1989
1990 // I _really_ don't want scrollbars in the beginning
a2053b27
RR
1991 m_vAdjust->lower = 0.0;
1992 m_vAdjust->upper = 1.0;
1993 m_vAdjust->value = 0.0;
1994 m_vAdjust->step_increment = 1.0;
1995 m_vAdjust->page_increment = 1.0;
1996 m_vAdjust->page_size = 5.0;
1997 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1998 m_hAdjust->lower = 0.0;
1999 m_hAdjust->upper = 1.0;
2000 m_hAdjust->value = 0.0;
2001 m_hAdjust->step_increment = 1.0;
2002 m_hAdjust->page_increment = 1.0;
2003 m_hAdjust->page_size = 5.0;
2004 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
f03fc89f
VZ
2005
2006 // these handlers block mouse events to any window during scrolling such as
2007 // motion events and prevent GTK and wxWindows from fighting over where the
2008 // slider should be
2009
2010 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_press_event",
76ed8f8d
RR
2011 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
2012
f03fc89f 2013 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_press_event",
76ed8f8d
RR
2014 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
2015
f03fc89f 2016 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_release_event",
76ed8f8d
RR
2017 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
2018
f03fc89f 2019 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_release_event",
76ed8f8d 2020 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
8bbe427f 2021
034be888 2022 // these handlers get notified when screen updates are required either when
76ed8f8d
RR
2023 // scrolling or when the window size (and therefore scrollbar configuration)
2024 // has changed
2025
2026 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
2027 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
2028 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
2029 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
2030
2031 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
2032 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
2033 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
2034 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
2035
f03fc89f 2036 gtk_widget_show( m_wxwindow );
47d67540 2037
f03fc89f
VZ
2038 if (m_parent)
2039 m_parent->DoAddChild( this );
8bbe427f 2040
e380f72b 2041 PostCreation();
8bbe427f 2042
e380f72b 2043 Show( TRUE );
c801d85f 2044
e380f72b 2045 return TRUE;
362c6693 2046}
c801d85f 2047
68dda785 2048wxWindow::~wxWindow()
c801d85f 2049{
31c6b4fc 2050 m_isBeingDeleted = TRUE;
43a18898 2051 m_hasVMT = FALSE;
47d67540 2052
f03fc89f
VZ
2053 if (m_widget)
2054 Show( FALSE );
8bbe427f 2055
a2053b27
RR
2056 DestroyChildren();
2057
f03fc89f
VZ
2058 if (m_parent)
2059 m_parent->RemoveChild( this );
c801d85f 2060
f03fc89f 2061 if (m_widgetStyle)
a2053b27 2062 {
f03fc89f 2063 gtk_style_unref( m_widgetStyle );
c50f1fb9 2064 m_widgetStyle = (GtkStyle*) NULL;
a2053b27 2065 }
c801d85f 2066
f03fc89f 2067 if (m_wxwindow)
a2053b27 2068 {
f03fc89f 2069 gtk_widget_destroy( m_wxwindow );
c50f1fb9 2070 m_wxwindow = (GtkWidget*) NULL;
a2053b27 2071 }
8bbe427f 2072
f03fc89f 2073 if (m_widget)
a2053b27 2074 {
f03fc89f 2075 gtk_widget_destroy( m_widget );
c50f1fb9 2076 m_widget = (GtkWidget*) NULL;
a2053b27 2077 }
362c6693 2078}
c801d85f 2079
4dcaf11a 2080bool wxWindow::PreCreation( wxWindow *parent, const wxPoint &pos, const wxSize &size )
c801d85f 2081{
223d09f6 2082 wxCHECK_MSG( !m_needParent || parent, FALSE, wxT("Need complete parent.") );
8bbe427f 2083
4dcaf11a
RR
2084 /* this turns -1 into 20 so that a minimal window is
2085 visible even although -1,-1 has been given as the
2086 size of the window. the same trick is used in other
2087 ports and should make debugging easier */
f03fc89f
VZ
2088 m_width = WidthDefault(size.x);
2089 m_height = HeightDefault(size.y);
8bbe427f 2090
43a18898
RR
2091 m_x = (int)pos.x;
2092 m_y = (int)pos.y;
8bbe427f 2093
4dcaf11a
RR
2094 /* some reasonable defaults */
2095 if (!parent)
6ca41e57 2096 {
43a18898
RR
2097 if (m_x == -1)
2098 {
2099 m_x = (gdk_screen_width () - m_width) / 2;
2100 if (m_x < 10) m_x = 10;
2101 }
2102 if (m_y == -1)
2103 {
2104 m_y = (gdk_screen_height () - m_height) / 2;
2105 if (m_y < 10) m_y = 10;
2106 }
6ca41e57 2107 }
4dcaf11a
RR
2108
2109 return TRUE;
c801d85f
KB
2110}
2111
68dda785 2112void wxWindow::PostCreation()
c801d85f 2113{
223d09f6 2114 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
ca298c88 2115
43a18898
RR
2116 if (m_wxwindow)
2117 {
147bc491
RR
2118 if (!m_noExpose)
2119 {
2120 /* these get reported to wxWindows -> wxPaintEvent */
2121 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
2122 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
2123
2124 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
2125 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
2126 }
f7a11f8c 2127
ef47f9b3 2128#if (GTK_MINOR_VERSION > 0)
ed673c6a 2129 /* these are called when the "sunken" or "raised" borders are drawn */
034be888
RR
2130 gtk_signal_connect( GTK_OBJECT(m_widget), "expose_event",
2131 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback), (gpointer)this );
2132
2133 gtk_signal_connect( GTK_OBJECT(m_widget), "draw",
2134 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback), (gpointer)this );
ef47f9b3 2135#endif
43a18898 2136 }
47d67540 2137
a2053b27 2138 GtkWidget *connect_widget = GetConnectWidget();
f03fc89f 2139
a2053b27 2140 ConnectWidget( connect_widget );
47d67540 2141
a2053b27
RR
2142 /* we cannot set colours, fonts and cursors before the widget has
2143 been realized, so we do this directly after realization */
2144 gtk_signal_connect( GTK_OBJECT(connect_widget), "realize",
c50f1fb9 2145 GTK_SIGNAL_FUNC(gtk_window_realized_callback), (gpointer) this );
ca298c88 2146
43a18898 2147 m_hasVMT = TRUE;
b4071e91
RR
2148}
2149
2150void wxWindow::ConnectWidget( GtkWidget *widget )
2151{
43a18898
RR
2152 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
2153 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
c801d85f 2154
b666df2c
RR
2155 gtk_signal_connect( GTK_OBJECT(widget), "key_release_event",
2156 GTK_SIGNAL_FUNC(gtk_window_key_release_callback), (gpointer)this );
2157
43a18898
RR
2158 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
2159 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
47d67540 2160
43a18898
RR
2161 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
2162 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
47d67540 2163
43a18898
RR
2164 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
2165 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
47d67540 2166
43a18898
RR
2167 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
2168 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
c801d85f 2169
43a18898
RR
2170 gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
2171 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
c801d85f 2172
43a18898
RR
2173 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
2174 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
47d67540 2175
43a18898
RR
2176 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
2177 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
362c6693 2178}
c801d85f 2179
68dda785 2180bool wxWindow::Destroy()
c801d85f 2181{
223d09f6 2182 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
47d67540 2183
43a18898 2184 m_hasVMT = FALSE;
c801d85f 2185
f03fc89f 2186 return wxWindowBase::Destroy();
362c6693 2187}
c801d85f 2188
bfc6fde4 2189void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
c801d85f 2190{
223d09f6
KB
2191 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
2192 wxASSERT_MSG( (m_parent != NULL), wxT("wxWindow::SetSize requires parent.\n") );
8bbe427f 2193
e27ce4e9 2194 if (m_resizing) return; /* I don't like recursions */
fb1585ae 2195 m_resizing = TRUE;
47d67540 2196
a2053b27 2197 if (m_parent->m_wxwindow == NULL) /* i.e. wxNotebook */
fb1585ae 2198 {
e27ce4e9 2199 /* don't set the size for children of wxNotebook, just take the values. */
fb1585ae
RR
2200 m_x = x;
2201 m_y = y;
2202 m_width = width;
ba4e3652 2203 m_height = height;
fb1585ae 2204 }
ba4e3652 2205 else
fb1585ae 2206 {
bf0c00c6
RR
2207 GtkMyFixed *myfixed = GTK_MYFIXED(m_parent->m_wxwindow);
2208
85ad5eb5 2209 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
ba4e3652 2210 {
bf0c00c6
RR
2211 if (x != -1) m_x = x + myfixed->xoffset;
2212 if (y != -1) m_y = y + myfixed->yoffset;
ba4e3652
RR
2213 if (width != -1) m_width = width;
2214 if (height != -1) m_height = height;
2215 }
2216 else
2217 {
bf0c00c6
RR
2218 m_x = x + myfixed->xoffset;
2219 m_y = y + myfixed->yoffset;
ba4e3652
RR
2220 m_width = width;
2221 m_height = height;
2222 }
47d67540 2223
ba4e3652
RR
2224 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
2225 {
2226 if (width == -1) m_width = 80;
2227 }
2228
2229 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
2230 {
2231 if (height == -1) m_height = 26;
2232 }
8bbe427f 2233
ba4e3652
RR
2234 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
2235 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
d3b4d113
RR
2236 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
2237 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
47d67540 2238
a2053b27 2239 int border = 0;
c50f1fb9 2240 int bottom_border = 0;
f03fc89f 2241
29f538ce 2242 if (GTK_WIDGET_CAN_DEFAULT(m_widget))
c50f1fb9
VZ
2243 {
2244 /* the default button has a border around it */
2245 border = 6;
2246 bottom_border = 5;
2247 }
2248
c50f1fb9
VZ
2249 gtk_myfixed_set_size( GTK_MYFIXED(m_parent->m_wxwindow),
2250 m_widget,
2251 m_x-border,
2252 m_y-border,
2253 m_width+2*border,
2254 m_height+border+bottom_border );
54517652 2255 }
6d693bb4 2256
54517652 2257/*
6d693bb4
RR
2258 wxPrintf( "OnSize sent from " );
2259 if (GetClassInfo() && GetClassInfo()->GetClassName())
2260 wxPrintf( GetClassInfo()->GetClassName() );
2261 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2262*/
2263
30760ce7
RR
2264 if (!m_nativeSizeEvent)
2265 {
2266 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
2267 event.SetEventObject( this );
2268 GetEventHandler()->ProcessEvent( event );
2269 }
6d693bb4 2270
fb1585ae 2271 m_resizing = FALSE;
362c6693 2272}
c801d85f 2273
9390a202
RR
2274void wxWindow::OnInternalIdle()
2275{
9146082c
RR
2276 wxCursor cursor = m_cursor;
2277 if (g_globalCursor.Ok()) cursor = g_globalCursor;
c50f1fb9 2278
f7a11f8c 2279 if (cursor.Ok())
9146082c 2280 {
3017f78d 2281 /* I now set the cursor anew in every OnInternalIdle call
f7a11f8c
RR
2282 as setting the cursor in a parent window also effects the
2283 windows above so that checking for the current cursor is
2284 not possible. */
bf0c00c6 2285
9146082c 2286 if (m_wxwindow)
6a008b33 2287 {
ed673c6a 2288 GdkWindow *window = GTK_MYFIXED(m_wxwindow)->bin_window;
6a008b33 2289 if (window)
c50f1fb9 2290 gdk_window_set_cursor( window, cursor.GetCursor() );
6a008b33
VZ
2291
2292 if (!g_globalCursor.Ok())
2293 cursor = *wxSTANDARD_CURSOR;
2294
2295 window = m_widget->window;
5e014a0c 2296 if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
9146082c 2297 gdk_window_set_cursor( window, cursor.GetCursor() );
5e014a0c 2298
6a008b33
VZ
2299 }
2300 else
2301 {
5e014a0c 2302
9146082c 2303 GdkWindow *window = m_widget->window;
5e014a0c 2304 if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
9146082c 2305 gdk_window_set_cursor( window, cursor.GetCursor() );
5e014a0c 2306
6a008b33 2307 }
9146082c 2308 }
6a008b33 2309
9390a202
RR
2310 UpdateWindowUI();
2311}
2312
f03fc89f 2313void wxWindow::DoGetSize( int *width, int *height ) const
c801d85f 2314{
223d09f6 2315 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2316
fb1585ae
RR
2317 if (width) (*width) = m_width;
2318 if (height) (*height) = m_height;
362c6693 2319}
c801d85f 2320
bfc6fde4 2321void wxWindow::DoSetClientSize( int width, int height )
c801d85f 2322{
223d09f6 2323 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2324
1ecc4d80 2325 if (!m_wxwindow)
c801d85f 2326 {
1ecc4d80 2327 SetSize( width, height );
c801d85f
KB
2328 }
2329 else
2330 {
1ecc4d80
RR
2331 int dw = 0;
2332 int dh = 0;
2333
034be888 2334#if (GTK_MINOR_VERSION == 0)
98d3fdbe
RR
2335 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2336 {
324dbfec
RR
2337 if (HasScrolling())
2338 {
2339 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
014b0d06 2340#if 0 // unused - if this is ok, just remove this line (VZ)
324dbfec 2341 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
014b0d06 2342#endif // 0
324dbfec
RR
2343
2344 GtkWidget *viewport = scroll_window->viewport;
2345 GtkStyleClass *viewport_class = viewport->style->klass;
2346
2347 dw += 2 * viewport_class->xthickness;
2348 dh += 2 * viewport_class->ythickness;
2349 }
98d3fdbe
RR
2350 }
2351#else
2352 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2353 {
5e014a0c 2354 /* when using GTK 1.2 we set the shadow border size to 2 */
6a008b33 2355 dw += 2 * 2;
98d3fdbe
RR
2356 dh += 2 * 2;
2357 }
5e014a0c
RR
2358 if (HasFlag(wxSIMPLE_BORDER))
2359 {
2360 /* when using GTK 1.2 we set the simple border size to 1 */
2361 dw += 1 * 2;
2362 dh += 1 * 2;
2363 }
034be888
RR
2364#endif
2365
98d3fdbe
RR
2366 if (HasScrolling())
2367 {
034be888
RR
2368/*
2369 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2370 GtkWidget *vscrollbar = scroll_window->vscrollbar;
ca298c88 2371
f03fc89f 2372 we use this instead: range.slider_width = 11 + 2*2pts edge
034be888 2373*/
47d67540 2374
324dbfec
RR
2375 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2376 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
2377
1ecc4d80
RR
2378 if (scroll_window->vscrollbar_visible)
2379 {
034be888 2380 dw += 15; /* dw += vscrollbar->allocation.width; */
1ecc4d80
RR
2381 dw += scroll_class->scrollbar_spacing;
2382 }
2383
2384 if (scroll_window->hscrollbar_visible)
2385 {
034be888 2386 dh += 15; /* dh += hscrollbar->allocation.height; */
63cc5d9d 2387 dh += scroll_class->scrollbar_spacing;
1ecc4d80
RR
2388 }
2389 }
2390
034be888 2391 SetSize( width+dw, height+dh );
1ecc4d80 2392 }
362c6693 2393}
c801d85f 2394
f03fc89f 2395void wxWindow::DoGetClientSize( int *width, int *height ) const
c801d85f 2396{
223d09f6 2397 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2398
1ecc4d80
RR
2399 if (!m_wxwindow)
2400 {
2401 if (width) (*width) = m_width;
2402 if (height) (*height) = m_height;
c801d85f
KB
2403 }
2404 else
2405 {
1ecc4d80
RR
2406 int dw = 0;
2407 int dh = 0;
2408
034be888 2409#if (GTK_MINOR_VERSION == 0)
98d3fdbe
RR
2410 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2411 {
6a008b33
VZ
2412 if (HasScrolling())
2413 {
2414 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
ec6e0a19 2415#if 0 // unused - if this is ok, just remove this line (VZ)
6a008b33 2416 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
ec6e0a19 2417#endif // 0
6a008b33
VZ
2418
2419 GtkWidget *viewport = scroll_window->viewport;
2420 GtkStyleClass *viewport_class = viewport->style->klass;
2421
2422 dw += 2 * viewport_class->xthickness;
2423 dh += 2 * viewport_class->ythickness;
2424 }
98d3fdbe
RR
2425 }
2426#else
2427 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2428 {
5e014a0c 2429 /* when using GTK 1.2 we set the shadow border size to 2 */
6a008b33 2430 dw += 2 * 2;
98d3fdbe
RR
2431 dh += 2 * 2;
2432 }
5e014a0c
RR
2433 if (HasFlag(wxSIMPLE_BORDER))
2434 {
2435 /* when using GTK 1.2 we set the simple border size to 1 */
2436 dw += 1 * 2;
2437 dh += 1 * 2;
2438 }
034be888 2439#endif
98d3fdbe
RR
2440 if (HasScrolling())
2441 {
034be888
RR
2442/*
2443 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2444 GtkWidget *vscrollbar = scroll_window->vscrollbar;
ca298c88 2445
f03fc89f 2446 we use this instead: range.slider_width = 11 + 2*2pts edge
034be888 2447*/
1ecc4d80 2448
6a008b33
VZ
2449 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2450 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
2451
1ecc4d80
RR
2452 if (scroll_window->vscrollbar_visible)
2453 {
034be888 2454 dw += 15; /* dw += vscrollbar->allocation.width; */
1ecc4d80
RR
2455 dw += scroll_class->scrollbar_spacing;
2456 }
2457
2458 if (scroll_window->hscrollbar_visible)
2459 {
034be888 2460 dh += 15; /* dh += hscrollbar->allocation.height; */
1ecc4d80
RR
2461 dh += scroll_class->scrollbar_spacing;
2462 }
6a008b33 2463 }
47d67540 2464
1ecc4d80
RR
2465 if (width) (*width) = m_width - dw;
2466 if (height) (*height) = m_height - dh;
2467 }
362c6693 2468}
c801d85f 2469
f03fc89f 2470void wxWindow::DoGetPosition( int *x, int *y ) const
c801d85f 2471{
223d09f6 2472 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2473
bf0c00c6
RR
2474 int dx = 0;
2475 int dy = 0;
2476 if (m_parent && m_parent->m_wxwindow)
2477 {
2478 GtkMyFixed *myfixed = GTK_MYFIXED(m_parent->m_wxwindow);
2479 dx = myfixed->xoffset;
2480 dy = myfixed->yoffset;
2481 }
2482
2483 if (x) (*x) = m_x - dx;
2484 if (y) (*y) = m_y - dy;
362c6693 2485}
c801d85f 2486
dabc0cd5 2487void wxWindow::DoClientToScreen( int *x, int *y ) const
c801d85f 2488{
223d09f6 2489 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2490
a2053b27
RR
2491 if (!m_widget->window) return;
2492
43a18898
RR
2493 GdkWindow *source = (GdkWindow *) NULL;
2494 if (m_wxwindow)
ed673c6a 2495 source = GTK_MYFIXED(m_wxwindow)->bin_window;
43a18898
RR
2496 else
2497 source = m_widget->window;
47d67540 2498
43a18898
RR
2499 int org_x = 0;
2500 int org_y = 0;
2501 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2502
43a18898 2503 if (!m_wxwindow)
c801d85f 2504 {
43a18898
RR
2505 if (GTK_WIDGET_NO_WINDOW (m_widget))
2506 {
2507 org_x += m_widget->allocation.x;
2508 org_y += m_widget->allocation.y;
2509 }
362c6693 2510 }
47d67540 2511
43a18898
RR
2512 if (x) *x += org_x;
2513 if (y) *y += org_y;
362c6693 2514}
c801d85f 2515
dabc0cd5 2516void wxWindow::DoScreenToClient( int *x, int *y ) const
c801d85f 2517{
223d09f6 2518 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2519
a2053b27
RR
2520 if (!m_widget->window) return;
2521
1ecc4d80
RR
2522 GdkWindow *source = (GdkWindow *) NULL;
2523 if (m_wxwindow)
ed673c6a 2524 source = GTK_MYFIXED(m_wxwindow)->bin_window;
1ecc4d80
RR
2525 else
2526 source = m_widget->window;
47d67540 2527
1ecc4d80
RR
2528 int org_x = 0;
2529 int org_y = 0;
2530 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2531
1ecc4d80 2532 if (!m_wxwindow)
c801d85f 2533 {
1ecc4d80
RR
2534 if (GTK_WIDGET_NO_WINDOW (m_widget))
2535 {
2536 org_x += m_widget->allocation.x;
2537 org_y += m_widget->allocation.y;
2538 }
362c6693 2539 }
47d67540 2540
1ecc4d80
RR
2541 if (x) *x -= org_x;
2542 if (y) *y -= org_y;
362c6693 2543}
c801d85f 2544
f03fc89f 2545bool wxWindow::Show( bool show )
c801d85f 2546{
223d09f6 2547 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
47d67540 2548
739730ca
RR
2549 if (!wxWindowBase::Show(show))
2550 {
2551 // nothing to do
f03fc89f 2552 return FALSE;
739730ca 2553 }
8bbe427f 2554
f03fc89f
VZ
2555 if (show)
2556 gtk_widget_show( m_widget );
1ecc4d80 2557 else
f03fc89f 2558 gtk_widget_hide( m_widget );
8bbe427f 2559
f03fc89f 2560 return TRUE;
362c6693 2561}
c801d85f 2562
f03fc89f 2563bool wxWindow::Enable( bool enable )
c801d85f 2564{
223d09f6 2565 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
5e0aa05a 2566
739730ca
RR
2567 if (!wxWindowBase::Enable(enable))
2568 {
2569 // nothing to do
f03fc89f 2570 return FALSE;
739730ca 2571 }
1ecc4d80 2572
f03fc89f
VZ
2573 gtk_widget_set_sensitive( m_widget, enable );
2574 if ( m_wxwindow )
2575 gtk_widget_set_sensitive( m_wxwindow, enable );
ff8bfdbb 2576
f03fc89f 2577 return TRUE;
362c6693 2578}
c801d85f 2579
f03fc89f 2580int wxWindow::GetCharHeight() const
2f2aa628 2581{
223d09f6 2582 wxCHECK_MSG( (m_widget != NULL), 12, wxT("invalid window") );
47d67540 2583
223d09f6 2584 wxCHECK_MSG( m_font.Ok(), 12, wxT("invalid font") );
2f2aa628 2585
f03fc89f
VZ
2586 GdkFont *font = m_font.GetInternalFont( 1.0 );
2587
2588 return font->ascent + font->descent;
362c6693 2589}
c801d85f 2590
f03fc89f 2591int wxWindow::GetCharWidth() const
c33c4050 2592{
223d09f6 2593 wxCHECK_MSG( (m_widget != NULL), 8, wxT("invalid window") );
47d67540 2594
223d09f6 2595 wxCHECK_MSG( m_font.Ok(), 8, wxT("invalid font") );
47d67540 2596
463c1fa1 2597 GdkFont *font = m_font.GetInternalFont( 1.0 );
ff8bfdbb 2598
463c1fa1 2599 return gdk_string_width( font, "H" );
c33c4050
RR
2600}
2601
f03fc89f
VZ
2602void wxWindow::GetTextExtent( const wxString& string,
2603 int *x,
2604 int *y,
2605 int *descent,
2606 int *externalLeading,
2607 const wxFont *theFont ) const
c33c4050 2608{
463c1fa1
RR
2609 wxFont fontToUse = m_font;
2610 if (theFont) fontToUse = *theFont;
47d67540 2611
223d09f6 2612 wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
47d67540 2613
463c1fa1 2614 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
05939a81 2615 if (x) (*x) = gdk_string_width( font, string.mbc_str() );
463c1fa1
RR
2616 if (y) (*y) = font->ascent + font->descent;
2617 if (descent) (*descent) = font->descent;
2618 if (externalLeading) (*externalLeading) = 0; // ??
c33c4050
RR
2619}
2620
68dda785 2621void wxWindow::SetFocus()
c801d85f 2622{
223d09f6 2623 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
ff8bfdbb 2624
463c1fa1
RR
2625 GtkWidget *connect_widget = GetConnectWidget();
2626 if (connect_widget)
c801d85f 2627 {
b292e2f5 2628 if (GTK_WIDGET_CAN_FOCUS(connect_widget) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
463c1fa1
RR
2629 {
2630 gtk_widget_grab_focus (connect_widget);
2631 }
ff8bfdbb
VZ
2632 else if (GTK_IS_CONTAINER(connect_widget))
2633 {
2634 gtk_container_focus( GTK_CONTAINER(connect_widget), GTK_DIR_TAB_FORWARD );
2635 }
2636 else
2637 {
2638 }
362c6693 2639 }
362c6693 2640}
c801d85f 2641
b292e2f5
RR
2642bool wxWindow::AcceptsFocus() const
2643{
f03fc89f 2644 return m_acceptsFocus && wxWindowBase::AcceptsFocus();
b292e2f5
RR
2645}
2646
fdb7dadb 2647bool wxWindow::Reparent( wxWindowBase *newParentBase )
463c1fa1 2648{
223d09f6 2649 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
c50f1fb9 2650
fdb7dadb
VZ
2651 wxWindow *oldParent = m_parent,
2652 *newParent = (wxWindow *)newParentBase;
a2053b27 2653
5fd11f09
RR
2654 wxASSERT( GTK_IS_WIDGET(m_widget) );
2655
f03fc89f
VZ
2656 if ( !wxWindowBase::Reparent(newParent) )
2657 return FALSE;
8bbe427f 2658
5fd11f09
RR
2659 wxASSERT( GTK_IS_WIDGET(m_widget) );
2660
2661 /* prevent GTK from deleting the widget arbitrarily */
2662 gtk_widget_ref( m_widget );
2663
8ce63e9d
RR
2664 if (oldParent)
2665 {
3017f78d 2666 gtk_container_remove( GTK_CONTAINER(m_widget->parent), m_widget );
8ce63e9d 2667 }
c50f1fb9 2668
5fd11f09
RR
2669 wxASSERT( GTK_IS_WIDGET(m_widget) );
2670
8ce63e9d
RR
2671 if (newParent)
2672 {
2673 /* insert GTK representation */
2674 (*(newParent->m_insertCallback))(newParent, this);
2675 }
c50f1fb9 2676
5fd11f09
RR
2677 /* reverse: prevent GTK from deleting the widget arbitrarily */
2678 gtk_widget_unref( m_widget );
2679
f03fc89f 2680 return TRUE;
362c6693 2681}
c801d85f 2682
c50f1fb9 2683void wxWindow::DoAddChild(wxWindow *child)
ddb6bc71 2684{
223d09f6 2685 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
ddb6bc71 2686
223d09f6 2687 wxASSERT_MSG( (child != NULL), wxT("invalid child window") );
ddb6bc71 2688
223d09f6 2689 wxASSERT_MSG( (m_insertCallback != NULL), wxT("invalid child insertion function") );
c50f1fb9 2690
ddb6bc71
RR
2691 /* add to list */
2692 AddChild( child );
c50f1fb9 2693
ddb6bc71
RR
2694 /* insert GTK representation */
2695 (*m_insertCallback)(this, child);
2696}
2697
68dda785 2698void wxWindow::Raise()
362c6693 2699{
223d09f6 2700 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2701
a2053b27
RR
2702 if (!m_widget->window) return;
2703
f03fc89f 2704 gdk_window_raise( m_widget->window );
362c6693
RR
2705}
2706
68dda785 2707void wxWindow::Lower()
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_lower( m_widget->window );
362c6693 2714}
c801d85f 2715
f03fc89f 2716bool wxWindow::SetCursor( const wxCursor &cursor )
86b29a61 2717{
223d09f6 2718 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
86b29a61 2719
5e014a0c 2720 return wxWindowBase::SetCursor( cursor );
362c6693 2721}
c801d85f 2722
85eb36c2 2723void wxWindow::WarpPointer( int x, int y )
4f22cf8d 2724{
223d09f6 2725 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
85eb36c2 2726
ed673c6a
RR
2727 /* we provide this function ourselves as it is
2728 missing in GDK (top of this file) */
2729
2730 GdkWindow *window = (GdkWindow*) NULL;
2731 if (m_wxwindow)
2732 window = GTK_MYFIXED(m_wxwindow)->bin_window;
2733 else
2734 window = GetConnectWidget()->window;
2735
2736 if (window)
2737 gdk_window_warp_pointer( window, x, y );
4f22cf8d
RR
2738}
2739
debe6624 2740void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
c801d85f 2741{
223d09f6 2742 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2743
a2053b27
RR
2744 if (!m_widget->window) return;
2745
139adb6a 2746 if (eraseBackground && m_wxwindow && m_wxwindow->window)
c801d85f 2747 {
139adb6a
RR
2748 if (rect)
2749 {
ed673c6a 2750 gdk_window_clear_area( GTK_MYFIXED(m_wxwindow)->bin_window,
139adb6a 2751 rect->x, rect->y,
f234c60c 2752 rect->width, rect->height );
139adb6a
RR
2753 }
2754 else
2755 {
ed673c6a 2756 gdk_window_clear( GTK_MYFIXED(m_wxwindow)->bin_window );
139adb6a
RR
2757 }
2758 }
ff8bfdbb 2759
1b68e0b5
RR
2760 /* there is no GTK equivalent of "draw only, don't clear" so we
2761 invent our own in the GtkMyFixed widget */
2762
139adb6a
RR
2763 if (!rect)
2764 {
2765 if (m_wxwindow)
e8b04eb3 2766 {
1b68e0b5
RR
2767 GtkMyFixed *myfixed = GTK_MYFIXED(m_wxwindow);
2768 gboolean old_clear = myfixed->clear_on_draw;
2769 gtk_my_fixed_set_clear( myfixed, FALSE );
2770
2771 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
f7a11f8c 2772
1b68e0b5 2773 gtk_my_fixed_set_clear( myfixed, old_clear );
e8b04eb3 2774 }
ff8bfdbb 2775 else
139adb6a 2776 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
362c6693 2777 }
c801d85f 2778 else
139adb6a 2779 {
1b68e0b5
RR
2780 GdkRectangle gdk_rect;
2781 gdk_rect.x = rect->x;
2782 gdk_rect.y = rect->y;
2783 gdk_rect.width = rect->width;
2784 gdk_rect.height = rect->height;
139adb6a
RR
2785
2786 if (m_wxwindow)
e8b04eb3 2787 {
1b68e0b5
RR
2788 GtkMyFixed *myfixed = GTK_MYFIXED(m_wxwindow);
2789 gboolean old_clear = myfixed->clear_on_draw;
2790 gtk_my_fixed_set_clear( myfixed, FALSE );
2791
2792 gtk_widget_draw( m_wxwindow, &gdk_rect );
2793
2794 gtk_my_fixed_set_clear( myfixed, old_clear );
e8b04eb3 2795 }
139adb6a
RR
2796 else
2797 gtk_widget_draw( m_widget, &gdk_rect );
2798 }
362c6693 2799}
c801d85f 2800
68dda785 2801void wxWindow::Clear()
c801d85f 2802{
223d09f6 2803 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 2804
a2053b27
RR
2805 if (!m_widget->window) return;
2806
f234c60c
RR
2807 if (m_wxwindow && m_wxwindow->window)
2808 {
2809 gdk_window_clear( m_wxwindow->window );
2810 }
362c6693 2811}
c801d85f 2812
ff8bfdbb 2813#if wxUSE_TOOLTIPS
f03fc89f 2814void wxWindow::DoSetToolTip( wxToolTip *tip )
b1170810 2815{
f03fc89f 2816 wxWindowBase::DoSetToolTip(tip);
ff8bfdbb 2817
f03fc89f
VZ
2818 if (m_tooltip)
2819 m_tooltip->Apply( this );
b1170810
RR
2820}
2821
05939a81 2822void wxWindow::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
b1170810 2823{
dcf924a3 2824 gtk_tooltips_set_tip( tips, GetConnectWidget(), wxConvCurrent->cWX2MB(tip), (gchar*) NULL );
301cd871 2825}
ff8bfdbb 2826#endif // wxUSE_TOOLTIPS
b1170810 2827
f03fc89f 2828bool wxWindow::SetBackgroundColour( const wxColour &colour )
c801d85f 2829{
223d09f6 2830 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
8bbe427f 2831
739730ca
RR
2832 if (!wxWindowBase::SetBackgroundColour(colour))
2833 {
2834 // don't leave if the GTK widget has just
2835 // been realized
2836 if (!m_delayedBackgroundColour) return FALSE;
2837 }
c50f1fb9 2838
ed673c6a
RR
2839 GdkWindow *window = (GdkWindow*) NULL;
2840 if (m_wxwindow)
2841 window = GTK_MYFIXED(m_wxwindow)->bin_window;
2842 else
2843 window = GetConnectWidget()->window;
2844
2845 if (!window)
739730ca
RR
2846 {
2847 // indicate that a new style has been set
c50f1fb9
VZ
2848 // but it couldn't get applied as the
2849 // widget hasn't been realized yet.
2850 m_delayedBackgroundColour = TRUE;
2851
2852 // pretend we have done something
739730ca
RR
2853 return TRUE;
2854 }
ca298c88 2855
ed673c6a 2856 if (m_wxwindow)
3bc755fc 2857 {
a2053b27
RR
2858 /* wxMSW doesn't clear the window here. I don't do that either to
2859 provide compatibility. call Clear() to do the job. */
ca298c88 2860
ed673c6a
RR
2861 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
2862 gdk_window_set_background( window, m_backgroundColour.GetColor() );
3bc755fc 2863 }
8bbe427f 2864
ae0bdb01 2865 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
121a3581 2866 if (sysbg == m_backgroundColour)
ae0bdb01
RR
2867 {
2868 m_backgroundColour = wxNullColour;
2869 ApplyWidgetStyle();
ff8bfdbb
VZ
2870 m_backgroundColour = sysbg;
2871 }
ae0bdb01
RR
2872 else
2873 {
2874 ApplyWidgetStyle();
2875 }
c801d85f 2876
f03fc89f 2877 return TRUE;
6de97a3b
RR
2878}
2879
f03fc89f 2880bool wxWindow::SetForegroundColour( const wxColour &colour )
6de97a3b 2881{
223d09f6 2882 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
8bbe427f 2883
739730ca
RR
2884 if (!wxWindowBase::SetForegroundColour(colour))
2885 {
2886 // don't leave if the GTK widget has just
2887 // been realized
2888 if (!m_delayedForegroundColour) return FALSE;
2889 }
c50f1fb9 2890
ed673c6a
RR
2891 GdkWindow *window = (GdkWindow*) NULL;
2892 if (m_wxwindow)
2893 window = GTK_MYFIXED(m_wxwindow)->bin_window;
2894 else
2895 window = GetConnectWidget()->window;
2896
2897 if (!window)
739730ca
RR
2898 {
2899 // indicate that a new style has been set
c50f1fb9
VZ
2900 // but it couldn't get applied as the
2901 // widget hasn't been realized yet.
2902 m_delayedForegroundColour = TRUE;
2903
2904 // pretend we have done something
739730ca
RR
2905 return TRUE;
2906 }
2b07d713 2907
ae0bdb01 2908 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2b62ab35 2909 if ( sysbg == m_backgroundColour )
ae0bdb01
RR
2910 {
2911 m_backgroundColour = wxNullColour;
2912 ApplyWidgetStyle();
ff8bfdbb
VZ
2913 m_backgroundColour = sysbg;
2914 }
ae0bdb01
RR
2915 else
2916 {
2917 ApplyWidgetStyle();
2918 }
f03fc89f
VZ
2919
2920 return TRUE;
58614078
RR
2921}
2922
2923GtkStyle *wxWindow::GetWidgetStyle()
2924{
1ecc4d80 2925 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
8bbe427f 2926
f03fc89f 2927 m_widgetStyle = gtk_style_copy( gtk_widget_get_style( m_widget ) );
8bbe427f 2928
1ecc4d80 2929 return m_widgetStyle;
58614078
RR
2930}
2931
2932void wxWindow::SetWidgetStyle()
2933{
1ecc4d80
RR
2934 GtkStyle *style = GetWidgetStyle();
2935
2936 gdk_font_unref( style->font );
2937 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2938
2939 if (m_foregroundColour.Ok())
2940 {
2941 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2942 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2943 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2944 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2945 }
2946
2947 if (m_backgroundColour.Ok())
2948 {
2949 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2950 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2951 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2952 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2953 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2954 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2955 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2956 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2957 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2958 }
a81258be
RR
2959}
2960
58614078 2961void wxWindow::ApplyWidgetStyle()
a81258be 2962{
6de97a3b
RR
2963}
2964
2259e007
RR
2965//-----------------------------------------------------------------------------
2966// Pop-up menu stuff
2967//-----------------------------------------------------------------------------
2968
2969static void gtk_pop_hide_callback( GtkWidget *WXUNUSED(widget), bool* is_waiting )
2970{
2971 *is_waiting = FALSE;
2972}
2973
30dea054
RR
2974static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2975{
1ecc4d80 2976 menu->SetInvokingWindow( win );
c626a8b7 2977 wxNode *node = menu->GetItems().First();
1ecc4d80
RR
2978 while (node)
2979 {
2980 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2981 if (menuitem->IsSubMenu())
2982 {
ff8bfdbb
VZ
2983 SetInvokingWindow( menuitem->GetSubMenu(), win );
2984 }
1ecc4d80
RR
2985 node = node->Next();
2986 }
362c6693 2987}
30dea054 2988
0c77152e
RR
2989static gint gs_pop_x = 0;
2990static gint gs_pop_y = 0;
2991
a234a61a
VZ
2992static void pop_pos_callback( GtkMenu * WXUNUSED(menu),
2993 gint *x, gint *y,
2994 wxWindow *win )
0c77152e
RR
2995{
2996 win->ClientToScreen( &gs_pop_x, &gs_pop_y );
2997 *x = gs_pop_x;
2998 *y = gs_pop_y;
2999}
3000
a1665b22 3001bool wxWindow::DoPopupMenu( wxMenu *menu, int x, int y )
30dea054 3002{
223d09f6 3003 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
47d67540 3004
223d09f6 3005 wxCHECK_MSG( menu != NULL, FALSE, wxT("invalid popup-menu") );
8bbe427f 3006
1ecc4d80 3007 SetInvokingWindow( menu, this );
ff8bfdbb 3008
631f1bfe
JS
3009 menu->UpdateUI();
3010
0c77152e
RR
3011 gs_pop_x = x;
3012 gs_pop_y = y;
ff8bfdbb 3013
2259e007
RR
3014 bool is_waiting = TRUE;
3015
3016 gtk_signal_connect( GTK_OBJECT(menu->m_menu), "hide",
3017 GTK_SIGNAL_FUNC(gtk_pop_hide_callback), (gpointer)&is_waiting );
3018
1ecc4d80 3019 gtk_menu_popup(
47d67540 3020 GTK_MENU(menu->m_menu),
0c77152e
RR
3021 (GtkWidget *) NULL, // parent menu shell
3022 (GtkWidget *) NULL, // parent menu item
3023 (GtkMenuPositionFunc) pop_pos_callback,
3024 (gpointer) this, // client data
3025 0, // button used to activate it
54517652 3026 gs_timeLastClick // the time of activation
47d67540 3027 );
2259e007 3028
956dbab1
RR
3029 while (is_waiting)
3030 {
3031 while (gtk_events_pending())
3032 gtk_main_iteration();
3033 }
2259e007 3034
1ecc4d80 3035 return TRUE;
30dea054
RR
3036}
3037
06cfab17 3038#if wxUSE_DRAG_AND_DROP
ac57418f 3039
c801d85f
KB
3040void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
3041{
223d09f6 3042 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3043
1ecc4d80 3044 GtkWidget *dnd_widget = GetConnectWidget();
47d67540 3045
1ecc4d80 3046 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
47d67540 3047
1ecc4d80
RR
3048 if (m_dropTarget) delete m_dropTarget;
3049 m_dropTarget = dropTarget;
47d67540 3050
1ecc4d80 3051 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
362c6693 3052}
c801d85f 3053
f03fc89f 3054#endif // wxUSE_DRAG_AND_DROP
ac57418f 3055
68dda785 3056GtkWidget* wxWindow::GetConnectWidget()
e3e65dac 3057{
1ecc4d80
RR
3058 GtkWidget *connect_widget = m_widget;
3059 if (m_wxwindow) connect_widget = m_wxwindow;
47d67540 3060
1ecc4d80 3061 return connect_widget;
e3e65dac 3062}
47d67540 3063
903f689b
RR
3064bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
3065{
ed673c6a
RR
3066 if (m_wxwindow)
3067 return (window == GTK_MYFIXED(m_wxwindow)->bin_window);
3068
1ecc4d80 3069 return (window == m_widget->window);
903f689b
RR
3070}
3071
f03fc89f 3072bool wxWindow::SetFont( const wxFont &font )
c801d85f 3073{
223d09f6 3074 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
c801d85f 3075
739730ca
RR
3076 if (!wxWindowBase::SetFont(font))
3077 {
3078 // don't leave if the GTK widget has just
3079 // been realized
3080 if (!m_delayedFont) return FALSE;
3081 }
c50f1fb9 3082
ed673c6a
RR
3083 GdkWindow *window = (GdkWindow*) NULL;
3084 if (m_wxwindow)
3085 window = GTK_MYFIXED(m_wxwindow)->bin_window;
3086 else
3087 window = GetConnectWidget()->window;
3088
3089 if (!window)
739730ca
RR
3090 {
3091 // indicate that a new style has been set
c50f1fb9
VZ
3092 // but it couldn't get applied as the
3093 // widget hasn't been realized yet.
3094 m_delayedFont = TRUE;
3095
3096 // pretend we have done something
739730ca
RR
3097 return TRUE;
3098 }
9c288e4d 3099
ae0bdb01 3100 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
f03fc89f 3101 if ( sysbg == m_backgroundColour )
ae0bdb01
RR
3102 {
3103 m_backgroundColour = wxNullColour;
3104 ApplyWidgetStyle();
ff8bfdbb
VZ
3105 m_backgroundColour = sysbg;
3106 }
ae0bdb01
RR
3107 else
3108 {
3109 ApplyWidgetStyle();
3110 }
c801d85f 3111
f03fc89f 3112 return TRUE;
362c6693 3113}
c801d85f 3114
68dda785 3115void wxWindow::CaptureMouse()
c801d85f 3116{
223d09f6 3117 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3118
223d09f6 3119 wxCHECK_RET( g_captureWindow == NULL, wxT("CaptureMouse called twice") );
47d67540 3120
ed673c6a
RR
3121 GdkWindow *window = (GdkWindow*) NULL;
3122 if (m_wxwindow)
3123 window = GTK_MYFIXED(m_wxwindow)->bin_window;
3124 else
3125 window = GetConnectWidget()->window;
3126
3127 if (!window) return;
c50f1fb9 3128
ed673c6a 3129 gdk_pointer_grab( window, FALSE,
1ecc4d80
RR
3130 (GdkEventMask)
3131 (GDK_BUTTON_PRESS_MASK |
3132 GDK_BUTTON_RELEASE_MASK |
f7a11f8c 3133 GDK_POINTER_MOTION_HINT_MASK |
1ecc4d80 3134 GDK_POINTER_MOTION_MASK),
ff8bfdbb 3135 (GdkWindow *) NULL,
72195a0f 3136 m_cursor.GetCursor(),
ff8bfdbb 3137 GDK_CURRENT_TIME );
72195a0f 3138 g_captureWindow = this;
362c6693 3139}
c801d85f 3140
68dda785 3141void wxWindow::ReleaseMouse()
c801d85f 3142{
223d09f6 3143 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3144
223d09f6 3145 wxCHECK_RET( g_captureWindow, wxT("ReleaseMouse called twice") );
47d67540 3146
ed673c6a
RR
3147 GdkWindow *window = (GdkWindow*) NULL;
3148 if (m_wxwindow)
3149 window = GTK_MYFIXED(m_wxwindow)->bin_window;
3150 else
3151 window = GetConnectWidget()->window;
3152
3153 if (!window) return;
c50f1fb9 3154
1ecc4d80 3155 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
72195a0f 3156 g_captureWindow = (wxWindow*) NULL;
362c6693 3157}
c801d85f 3158
f03fc89f 3159bool wxWindow::IsRetained() const
c801d85f 3160{
1ecc4d80 3161 return FALSE;
362c6693 3162}
c801d85f 3163
debe6624 3164void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
cb43b372 3165 int range, bool refresh )
c801d85f 3166{
223d09f6 3167 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
8bbe427f 3168
223d09f6 3169 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
c801d85f 3170
1ecc4d80 3171 m_hasScrolling = TRUE;
47d67540 3172
1ecc4d80 3173 if (orient == wxHORIZONTAL)
cb43b372 3174 {
1ecc4d80
RR
3175 float fpos = (float)pos;
3176 float frange = (float)range;
3177 float fthumb = (float)thumbVisible;
3178 if (fpos > frange-fthumb) fpos = frange-fthumb;
3179 if (fpos < 0.0) fpos = 0.0;
3180
3181 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
3182 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
3183 {
3184 SetScrollPos( orient, pos, refresh );
3185 return;
3186 }
47d67540 3187
1ecc4d80 3188 m_oldHorizontalPos = fpos;
47d67540 3189
1ecc4d80
RR
3190 m_hAdjust->lower = 0.0;
3191 m_hAdjust->upper = frange;
3192 m_hAdjust->value = fpos;
3193 m_hAdjust->step_increment = 1.0;
3194 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
3195 m_hAdjust->page_size = fthumb;
cb43b372 3196 }
1ecc4d80
RR
3197 else
3198 {
3199 float fpos = (float)pos;
3200 float frange = (float)range;
3201 float fthumb = (float)thumbVisible;
3202 if (fpos > frange-fthumb) fpos = frange-fthumb;
3203 if (fpos < 0.0) fpos = 0.0;
3204
3205 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
3206 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
3207 {
3208 SetScrollPos( orient, pos, refresh );
3209 return;
3210 }
47d67540 3211
1ecc4d80 3212 m_oldVerticalPos = fpos;
47d67540 3213
1ecc4d80
RR
3214 m_vAdjust->lower = 0.0;
3215 m_vAdjust->upper = frange;
3216 m_vAdjust->value = fpos;
3217 m_vAdjust->step_increment = 1.0;
3218 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
3219 m_vAdjust->page_size = fthumb;
3220 }
47d67540 3221
eb082a08
RR
3222 if (orient == wxHORIZONTAL)
3223 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
3224 else
3225 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
362c6693 3226}
c801d85f 3227
debe6624 3228void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
c801d85f 3229{
223d09f6 3230 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
1ecc4d80 3231
223d09f6 3232 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
1ecc4d80
RR
3233
3234 if (orient == wxHORIZONTAL)
3235 {
3236 float fpos = (float)pos;
3237 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
3238 if (fpos < 0.0) fpos = 0.0;
3239 m_oldHorizontalPos = fpos;
3240
3241 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
3242 m_hAdjust->value = fpos;
3243 }
3244 else
3245 {
3246 float fpos = (float)pos;
3247 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
3248 if (fpos < 0.0) fpos = 0.0;
3249 m_oldVerticalPos = fpos;
ff8bfdbb 3250
1ecc4d80
RR
3251 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
3252 m_vAdjust->value = fpos;
3253 }
47d67540 3254
5e014a0c
RR
3255/*
3256 if (!m_isScrolling)
47d67540 3257 {
5e014a0c 3258*/
1ecc4d80
RR
3259 if (m_wxwindow->window)
3260 {
3261 if (orient == wxHORIZONTAL)
3262 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
3263 else
3264 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
3265 }
5e014a0c 3266/*
cb43b372 3267 }
5e014a0c 3268*/
362c6693 3269}
c801d85f 3270
debe6624 3271int wxWindow::GetScrollThumb( int orient ) const
c801d85f 3272{
223d09f6 3273 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 3274
223d09f6 3275 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
47d67540 3276
1ecc4d80
RR
3277 if (orient == wxHORIZONTAL)
3278 return (int)(m_hAdjust->page_size+0.5);
3279 else
3280 return (int)(m_vAdjust->page_size+0.5);
362c6693 3281}
c801d85f 3282
debe6624 3283int wxWindow::GetScrollPos( int orient ) const
c801d85f 3284{
223d09f6 3285 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 3286
223d09f6 3287 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
c801d85f 3288
1ecc4d80
RR
3289 if (orient == wxHORIZONTAL)
3290 return (int)(m_hAdjust->value+0.5);
3291 else
3292 return (int)(m_vAdjust->value+0.5);
362c6693 3293}
c801d85f 3294
debe6624 3295int wxWindow::GetScrollRange( int orient ) const
c801d85f 3296{
223d09f6 3297 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 3298
223d09f6 3299 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
c801d85f 3300
1ecc4d80
RR
3301 if (orient == wxHORIZONTAL)
3302 return (int)(m_hAdjust->upper+0.5);
3303 else
3304 return (int)(m_vAdjust->upper+0.5);
362c6693 3305}
c801d85f 3306
debe6624 3307void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
c801d85f 3308{
223d09f6 3309 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3310
223d09f6 3311 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
c801d85f 3312
ed673c6a
RR
3313 gtk_myfixed_scroll( GTK_MYFIXED(m_wxwindow), -dx, -dy );
3314
3315/*
a2053b27 3316 if (!m_scrollGC)
96d5ab4d 3317 {
a2053b27
RR
3318 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3319 gdk_gc_set_exposures( m_scrollGC, TRUE );
96d5ab4d 3320 }
c50f1fb9 3321
ea5c6ca7
RR
3322 wxNode *node = m_children.First();
3323 while (node)
3324 {
3325 wxWindow *child = (wxWindow*) node->Data();
c50f1fb9
VZ
3326 int sx = 0;
3327 int sy = 0;
3328 child->GetSize( &sx, &sy );
3329 child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
3330 node = node->Next();
ea5c6ca7 3331 }
96d5ab4d 3332
c801d85f
KB
3333 int cw = 0;
3334 int ch = 0;
3335 GetClientSize( &cw, &ch );
c801d85f
KB
3336 int w = cw - abs(dx);
3337 int h = ch - abs(dy);
c50f1fb9 3338
c801d85f
KB
3339 if ((h < 0) || (w < 0))
3340 {
1ecc4d80 3341 Refresh();
362c6693 3342 }
a2053b27 3343 else
c801d85f 3344 {
a2053b27
RR
3345 int s_x = 0;
3346 int s_y = 0;
3347 if (dx < 0) s_x = -dx;
3348 if (dy < 0) s_y = -dy;
3349 int d_x = 0;
3350 int d_y = 0;
3351 if (dx > 0) d_x = dx;
3352 if (dy > 0) d_y = dy;
c801d85f 3353
a2053b27
RR
3354 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3355 m_wxwindow->window, s_x, s_y, w, h );
c801d85f 3356
a2053b27
RR
3357 wxRect rect;
3358 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3359 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3360 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3361 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
c801d85f 3362
a2053b27
RR
3363 Refresh( TRUE, &rect );
3364 }
ed673c6a 3365*/
c801d85f
KB
3366}
3367
f03fc89f 3368void wxWindow::SetScrolling(bool scroll)
c801d85f 3369{
f03fc89f 3370 m_isScrolling = g_blockEventsOnScroll = scroll;
c801d85f 3371}