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