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