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