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