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