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