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