]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/window.cpp
Had to #ifdef out wxGetFullHostName for Cygwin b20
[wxWidgets.git] / src / gtk1 / window.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: window.cpp
3// Purpose:
4// Author: Robert Roebling
c67d8618 5// Id: $Id$
01111366 6// Copyright: (c) 1998 Robert Roebling, Julian Smart
5e0aa05a 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
10
11#ifdef __GNUG__
bfc6fde4 12 #pragma implementation "window.h"
c801d85f
KB
13#endif
14
15#include "wx/defs.h"
16#include "wx/window.h"
17#include "wx/dc.h"
18#include "wx/frame.h"
19#include "wx/app.h"
20#include "wx/layout.h"
21#include "wx/utils.h"
22#include "wx/dialog.h"
23#include "wx/msgdlg.h"
bfc6fde4 24
06cfab17 25#if wxUSE_DRAG_AND_DROP
bfc6fde4 26 #include "wx/dnd.h"
ac57418f 27#endif
bfc6fde4 28
cad880f5 29#if wxUSE_TOOLTIPS
bfc6fde4 30 #include "wx/tooltip.h"
cad880f5 31#endif
bfc6fde4 32
30dea054 33#include "wx/menu.h"
d4c99d6f 34#include "wx/statusbr.h"
b4071e91 35#include "wx/intl.h"
3bc755fc 36#include "wx/settings.h"
3069ac4e 37#include "wx/log.h"
b4071e91 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 {
3d6f7261 506 if ((keysym & 0xF000) == 0)
c5b42c87 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 {
3d6f7261 605 if ((keysym & 0xF000) == 0)
c5b42c87 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
3d6f7261 797
7be4c594 798/*
b79395c5
RR
799 wxString tmp;
800 tmp += (char)gdk_event->keyval;
801 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
d1367c3d 802 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
7be4c594 803*/
2daa0ce9 804
b0e813a0
RR
805 int x = 0;
806 int y = 0;
807 GdkModifierType state;
808 if (gdk_event->window) gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
47d67540 809
3017f78d 810 bool ret = FALSE;
148cd9b6 811
74505862 812 long key_code = map_to_unmodified_wx_keysym( gdk_event->keyval );
f0492f7d
RR
813 /* sending unknown key events doesn't really make sense */
814 if (key_code == 0) return FALSE;
815
c50f1fb9 816 wxKeyEvent event( wxEVT_KEY_DOWN );
d1367c3d 817 event.SetTimestamp( gdk_event->time );
f5e27805
RR
818 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
819 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
820 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
821 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
822 event.m_keyCode = key_code;
b0e813a0
RR
823 event.m_scanCode = gdk_event->keyval;
824 event.m_x = x;
825 event.m_y = y;
f5e27805 826 event.SetEventObject( win );
c5b42c87 827 ret = win->GetEventHandler()->ProcessEvent( event );
c50f1fb9 828
88ac883a 829#if wxUSE_ACCEL
f5e27805 830 if (!ret)
47d67540 831 {
f5e27805
RR
832 wxWindow *ancestor = win;
833 while (ancestor)
834 {
835 int command = ancestor->GetAcceleratorTable()->GetCommand( event );
836 if (command != -1)
837 {
838 wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
839 ret = ancestor->GetEventHandler()->ProcessEvent( command_event );
840 break;
841 }
b02da6b1
VZ
842 if (ancestor->m_isFrame)
843 break;
f5e27805
RR
844 ancestor = ancestor->GetParent();
845 }
bcf1fa6b 846 }
88ac883a 847#endif // wxUSE_ACCEL
3017f78d 848
d728dd40
KB
849 /* wxMSW doesn't send char events with Alt pressed */
850 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
3017f78d
RR
851 will only be sent if it is not in an accelerator table. */
852 key_code = map_to_wx_keysym( gdk_event->keyval );
148cd9b6 853
3017f78d
RR
854 if ( (!ret) &&
855 (key_code != 0))
d728dd40 856 {
c50f1fb9 857 wxKeyEvent event2( wxEVT_CHAR );
d728dd40
KB
858 event2.SetTimestamp( gdk_event->time );
859 event2.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
860 event2.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
861 event2.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
862 event2.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
863 event2.m_keyCode = key_code;
864 event2.m_scanCode = gdk_event->keyval;
865 event2.m_x = x;
866 event2.m_y = y;
867 event2.SetEventObject( win );
3017f78d 868 ret = win->GetEventHandler()->ProcessEvent( event2 );
d728dd40
KB
869 }
870
053f9cc1 871 /* win is a control: tab can be propagated up */
ca298c88 872 if ( (!ret) &&
5664fc32 873 ((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
3da17724 874 (!win->HasFlag(wxTE_PROCESS_TAB)) &&
b02da6b1
VZ
875 (win->GetParent()) &&
876 (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
b292e2f5
RR
877 {
878 wxNavigationKeyEvent new_event;
8253c7fd 879 new_event.SetEventObject( win->GetParent() );
f03fc89f 880 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
5664fc32 881 new_event.SetDirection( (gdk_event->keyval == GDK_Tab) );
f03fc89f 882 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
b98d804b 883 new_event.SetWindowChange( (gdk_event->state & GDK_CONTROL_MASK) );
b292e2f5 884 new_event.SetCurrentFocus( win );
8253c7fd 885 ret = win->GetParent()->GetEventHandler()->ProcessEvent( new_event );
b292e2f5 886 }
ff8bfdbb 887
801aa178 888 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
ca298c88 889 if ( (!ret) &&
b98d804b
RR
890 (gdk_event->keyval == GDK_Escape) )
891 {
892 wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
893 new_event.SetEventObject( win );
894 ret = win->GetEventHandler()->ProcessEvent( new_event );
895 }
c50f1fb9 896
6bc8a1c8 897#if (GTK_MINOR_VERSION > 0)
da048e3d
RR
898 /* Pressing F10 will activate the menu bar of the top frame. */
899 /* Doesn't work. */
3017f78d 900/*
801aa178
RR
901 if ( (!ret) &&
902 (gdk_event->keyval == GDK_F10) )
903 {
904 wxWindow *ancestor = win;
905 while (ancestor)
906 {
907 if (wxIsKindOf(ancestor,wxFrame))
c50f1fb9
VZ
908 {
909 wxFrame *frame = (wxFrame*) ancestor;
801aa178 910 wxMenuBar *menubar = frame->GetMenuBar();
c50f1fb9
VZ
911 if (menubar)
912 {
801aa178 913 wxNode *node = menubar->GetMenus().First();
c50f1fb9
VZ
914 if (node)
915 {
3017f78d
RR
916 wxMenu *firstMenu = (wxMenu*) node->Data();
917 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
918 ret = TRUE;
c50f1fb9
VZ
919 break;
920 }
921 }
922 }
801aa178
RR
923 ancestor = ancestor->GetParent();
924 }
925 }
3017f78d 926*/
6bc8a1c8 927#endif
ca298c88 928
f5e27805
RR
929 if (ret)
930 {
b292e2f5 931 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
f03fc89f 932 return TRUE;
f5e27805 933 }
47d67540 934
034be888 935 return FALSE;
362c6693 936}
c801d85f 937
b666df2c
RR
938//-----------------------------------------------------------------------------
939// "key_release_event" from any window
940//-----------------------------------------------------------------------------
941
942static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
943{
3ac8d3bc
RR
944 DEBUG_MAIN_THREAD
945
c50f1fb9 946 if (g_isIdle)
a2053b27
RR
947 wxapp_install_idle_handler();
948
949 if (!win->m_hasVMT) return FALSE;
b666df2c
RR
950 if (g_blockEventsOnDrag) return FALSE;
951
952/*
d1367c3d
RR
953 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
954 if (gdk_event->state & GDK_SHIFT_MASK)
955 printf( "ShiftDown.\n" );
956 else
957 printf( "ShiftUp.\n" );
958 if (gdk_event->state & GDK_CONTROL_MASK)
959 printf( "ControlDown.\n" );
960 else
961 printf( "ControlUp.\n" );
962 printf( "\n" );
b666df2c
RR
963*/
964
74505862 965 long key_code = map_to_unmodified_wx_keysym( gdk_event->keyval );
c50f1fb9 966
f0492f7d
RR
967 /* sending unknown key events doesn't really make sense */
968 if (key_code == 0) return FALSE;
b666df2c 969
b0e813a0
RR
970 int x = 0;
971 int y = 0;
972 GdkModifierType state;
973 if (gdk_event->window) gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
b666df2c
RR
974
975 wxKeyEvent event( wxEVT_KEY_UP );
d1367c3d 976 event.SetTimestamp( gdk_event->time );
b666df2c
RR
977 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
978 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
979 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
980 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
981 event.m_keyCode = key_code;
b0e813a0
RR
982 event.m_scanCode = gdk_event->keyval;
983 event.m_x = x;
984 event.m_y = y;
b666df2c
RR
985 event.SetEventObject( win );
986
034be888 987 if (win->GetEventHandler()->ProcessEvent( event ))
b666df2c 988 {
b98d804b 989 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_release_event" );
f03fc89f 990 return TRUE;
b666df2c
RR
991 }
992
034be888 993 return FALSE;
b666df2c
RR
994}
995
2daa0ce9
VZ
996// ----------------------------------------------------------------------------
997// mouse event processing helper
998// ----------------------------------------------------------------------------
999
1000static void AdjustEventButtonState(wxMouseEvent& event)
1001{
1002 // GDK reports the old state of the button for a button press event, but
1003 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1004 // for a LEFT_DOWN event, not FALSE, so we will invert
1005 // left/right/middleDown for the corresponding click events
1006 switch ( event.GetEventType() )
1007 {
1008 case wxEVT_LEFT_DOWN:
1009 case wxEVT_LEFT_DCLICK:
1010 case wxEVT_LEFT_UP:
1011 event.m_leftDown = !event.m_leftDown;
1012 break;
1013
1014 case wxEVT_MIDDLE_DOWN:
1015 case wxEVT_MIDDLE_DCLICK:
1016 case wxEVT_MIDDLE_UP:
1017 event.m_middleDown = !event.m_middleDown;
1018 break;
1019
1020 case wxEVT_RIGHT_DOWN:
1021 case wxEVT_RIGHT_DCLICK:
1022 case wxEVT_RIGHT_UP:
1023 event.m_rightDown = !event.m_rightDown;
1024 break;
1025 }
1026}
1027
c801d85f 1028//-----------------------------------------------------------------------------
2f2aa628
RR
1029// "button_press_event"
1030//-----------------------------------------------------------------------------
c801d85f 1031
2f2aa628 1032static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
903f689b 1033{
3ac8d3bc
RR
1034 DEBUG_MAIN_THREAD
1035
c50f1fb9 1036 if (g_isIdle)
a2053b27
RR
1037 wxapp_install_idle_handler();
1038
1039/*
223d09f6 1040 wxPrintf( wxT("1) OnButtonPress from ") );
a2053b27
RR
1041 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1042 wxPrintf( win->GetClassInfo()->GetClassName() );
223d09f6 1043 wxPrintf( wxT(".\n") );
a2053b27 1044*/
a2053b27 1045 if (!win->m_hasVMT) return FALSE;
f5e27805 1046 if (g_blockEventsOnDrag) return TRUE;
76ed8f8d 1047 if (g_blockEventsOnScroll) return TRUE;
c801d85f 1048
034be888
RR
1049 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1050
a2053b27 1051 if (win->m_wxwindow)
c801d85f 1052 {
a2053b27 1053 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow) && !GTK_WIDGET_HAS_FOCUS (win->m_wxwindow) )
f5e27805 1054 {
a2053b27 1055 gtk_widget_grab_focus (win->m_wxwindow);
47d67540 1056
c801d85f 1057/*
223d09f6 1058 wxPrintf( wxT("GrabFocus from ") );
f5e27805 1059 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
a2053b27 1060 wxPrintf( win->GetClassInfo()->GetClassName() );
223d09f6 1061 wxPrintf( wxT(".\n") );
c801d85f 1062*/
47d67540 1063
f5e27805 1064 }
362c6693 1065 }
47d67540 1066
2daa0ce9 1067 wxEventType event_type = wxEVT_NULL;
47d67540 1068
f5e27805 1069 if (gdk_event->button == 1)
c801d85f 1070 {
f5e27805
RR
1071 switch (gdk_event->type)
1072 {
1073 case GDK_BUTTON_PRESS: event_type = wxEVT_LEFT_DOWN; break;
1074 case GDK_2BUTTON_PRESS: event_type = wxEVT_LEFT_DCLICK; break;
1075 default: break;
1076 }
362c6693 1077 }
f5e27805 1078 else if (gdk_event->button == 2)
c801d85f 1079 {
f5e27805
RR
1080 switch (gdk_event->type)
1081 {
1082 case GDK_BUTTON_PRESS: event_type = wxEVT_MIDDLE_DOWN; break;
1083 case GDK_2BUTTON_PRESS: event_type = wxEVT_MIDDLE_DCLICK; break;
1084 default: break;
1085 }
362c6693 1086 }
f5e27805 1087 else if (gdk_event->button == 3)
c801d85f 1088 {
f5e27805
RR
1089 switch (gdk_event->type)
1090 {
1091 case GDK_BUTTON_PRESS: event_type = wxEVT_RIGHT_DOWN; break;
1092 case GDK_2BUTTON_PRESS: event_type = wxEVT_RIGHT_DCLICK; break;
1093 default: break;
1094 }
362c6693 1095 }
47d67540 1096
2daa0ce9
VZ
1097 if ( event_type == wxEVT_NULL )
1098 {
1099 // unknown mouse button or click type
1100 return FALSE;
1101 }
1102
f5e27805 1103 wxMouseEvent event( event_type );
d1367c3d 1104 event.SetTimestamp( gdk_event->time );
f5e27805
RR
1105 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1106 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1107 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1108 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1109 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1110 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1111 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
47d67540 1112
13111b2a
VZ
1113 event.m_x = (wxCoord)gdk_event->x;
1114 event.m_y = (wxCoord)gdk_event->y;
47d67540 1115
2daa0ce9
VZ
1116 AdjustEventButtonState(event);
1117
f5e27805
RR
1118 // Some control don't have their own X window and thus cannot get
1119 // any events.
47d67540 1120
72195a0f 1121 if (!g_captureWindow)
2f2aa628 1122 {
b02da6b1
VZ
1123 wxCoord x = event.m_x;
1124 wxCoord y = event.m_y;
2f073eb2
RR
1125 if (win->m_wxwindow)
1126 {
da048e3d 1127 GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
b02da6b1
VZ
1128 x += pizza->xoffset;
1129 y += pizza->yoffset;
2f073eb2
RR
1130 }
1131
db1b4961 1132 wxNode *node = win->GetChildren().First();
f5e27805
RR
1133 while (node)
1134 {
1135 wxWindow *child = (wxWindow*)node->Data();
148cd9b6 1136
f96ac56a 1137 node = node->Next();
b02da6b1
VZ
1138 if (!child->IsShown())
1139 continue;
ff8bfdbb 1140
a2053b27 1141 if (child->m_isStaticBox)
ff8bfdbb
VZ
1142 {
1143 // wxStaticBox is transparent in the box itself
a2053b27
RR
1144 int xx1 = child->m_x;
1145 int yy1 = child->m_y;
1146 int xx2 = child->m_x + child->m_width;
1147 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1148
1149 // left
1150 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1151 // right
1152 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1153 // top
1154 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1155 // bottom
1156 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1157 {
1ecc4d80 1158 win = child;
a2053b27
RR
1159 event.m_x -= child->m_x;
1160 event.m_y -= child->m_y;
1ecc4d80 1161 break;
ff8bfdbb
VZ
1162 }
1163
1164 }
1165 else
1166 {
a2053b27 1167 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
2f073eb2
RR
1168 (child->m_x <= x) &&
1169 (child->m_y <= y) &&
1170 (child->m_x+child->m_width >= x) &&
1171 (child->m_y+child->m_height >= y))
1ecc4d80
RR
1172 {
1173 win = child;
a2053b27
RR
1174 event.m_x -= child->m_x;
1175 event.m_y -= child->m_y;
1ecc4d80 1176 break;
ff8bfdbb 1177 }
f5e27805 1178 }
f5e27805 1179 }
2f2aa628 1180 }
ff8bfdbb 1181
f5e27805 1182 event.SetEventObject( win );
47d67540 1183
f5e27805 1184 gs_timeLastClick = gdk_event->time;
47d67540 1185
2f073eb2
RR
1186/*
1187 wxPrintf( wxT("2) OnButtonPress from ") );
1188 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1189 wxPrintf( win->GetClassInfo()->GetClassName() );
1190 wxPrintf( wxT(".\n") );
1191*/
1192
f5e27805 1193 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1194 {
f5e27805 1195 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
f03fc89f 1196 return TRUE;
034be888 1197 }
47d67540 1198
034be888 1199 return FALSE;
362c6693 1200}
c801d85f
KB
1201
1202//-----------------------------------------------------------------------------
97b3455a 1203// "button_release_event"
2f2aa628 1204//-----------------------------------------------------------------------------
c801d85f 1205
2f2aa628 1206static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
47d67540 1207{
3ac8d3bc
RR
1208 DEBUG_MAIN_THREAD
1209
c50f1fb9 1210 if (g_isIdle)
a2053b27
RR
1211 wxapp_install_idle_handler();
1212
1213 if (!win->m_hasVMT) return FALSE;
034be888
RR
1214 if (g_blockEventsOnDrag) return FALSE;
1215 if (g_blockEventsOnScroll) return FALSE;
c801d85f 1216
034be888 1217 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
47d67540 1218
c801d85f 1219/*
f5e27805
RR
1220 printf( "OnButtonRelease from " );
1221 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1222 printf( win->GetClassInfo()->GetClassName() );
1223 printf( ".\n" );
c801d85f 1224*/
47d67540 1225
f5e27805 1226 wxEventType event_type = wxEVT_NULL;
47d67540 1227
f5e27805
RR
1228 switch (gdk_event->button)
1229 {
1230 case 1: event_type = wxEVT_LEFT_UP; break;
1231 case 2: event_type = wxEVT_MIDDLE_UP; break;
1232 case 3: event_type = wxEVT_RIGHT_UP; break;
2daa0ce9 1233 default: return FALSE;
f5e27805 1234 }
47d67540 1235
f5e27805 1236 wxMouseEvent event( event_type );
d1367c3d 1237 event.SetTimestamp( gdk_event->time );
f5e27805
RR
1238 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1239 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1240 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1241 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1242 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1243 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1244 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
13111b2a
VZ
1245 event.m_x = (wxCoord)gdk_event->x;
1246 event.m_y = (wxCoord)gdk_event->y;
f5e27805 1247
2daa0ce9
VZ
1248 AdjustEventButtonState(event);
1249
f5e27805
RR
1250 // Some control don't have their own X window and thus cannot get
1251 // any events.
1252
72195a0f 1253 if (!g_captureWindow)
2f2aa628 1254 {
b02da6b1
VZ
1255 wxCoord x = event.m_x;
1256 wxCoord y = event.m_y;
2f073eb2
RR
1257 if (win->m_wxwindow)
1258 {
da048e3d 1259 GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
b02da6b1
VZ
1260 x += pizza->xoffset;
1261 y += pizza->yoffset;
2f073eb2
RR
1262 }
1263
db1b4961 1264 wxNode *node = win->GetChildren().First();
f5e27805
RR
1265 while (node)
1266 {
1267 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb 1268
f96ac56a 1269 node = node->Next();
b02da6b1
VZ
1270 if (!child->IsShown())
1271 continue;
f96ac56a 1272
a2053b27 1273 if (child->m_isStaticBox)
ff8bfdbb
VZ
1274 {
1275 // wxStaticBox is transparent in the box itself
a2053b27
RR
1276 int xx1 = child->m_x;
1277 int yy1 = child->m_y;
1278 int xx2 = child->m_x + child->m_width;
1279 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1280
1281 // left
1282 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1283 // right
1284 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1285 // top
1286 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1287 // bottom
1288 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1289 {
1ecc4d80 1290 win = child;
a2053b27
RR
1291 event.m_x -= child->m_x;
1292 event.m_y -= child->m_y;
1ecc4d80 1293 break;
ff8bfdbb
VZ
1294 }
1295
1296 }
1297 else
1298 {
a2053b27 1299 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
2f073eb2
RR
1300 (child->m_x <= x) &&
1301 (child->m_y <= y) &&
1302 (child->m_x+child->m_width >= x) &&
1303 (child->m_y+child->m_height >= y))
1ecc4d80
RR
1304 {
1305 win = child;
a2053b27
RR
1306 event.m_x -= child->m_x;
1307 event.m_y -= child->m_y;
1ecc4d80 1308 break;
ff8bfdbb 1309 }
f5e27805 1310 }
f5e27805 1311 }
2f2aa628 1312 }
47d67540 1313
f5e27805 1314 event.SetEventObject( win );
47d67540 1315
f5e27805 1316 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1317 {
f5e27805 1318 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" );
f03fc89f 1319 return TRUE;
034be888 1320 }
47d67540 1321
034be888 1322 return FALSE;
362c6693 1323}
c801d85f
KB
1324
1325//-----------------------------------------------------------------------------
2f2aa628
RR
1326// "motion_notify_event"
1327//-----------------------------------------------------------------------------
c801d85f 1328
2f2aa628 1329static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
47d67540 1330{
3ac8d3bc
RR
1331 DEBUG_MAIN_THREAD
1332
c50f1fb9 1333 if (g_isIdle)
a2053b27
RR
1334 wxapp_install_idle_handler();
1335
1336 if (!win->m_hasVMT) return FALSE;
034be888
RR
1337 if (g_blockEventsOnDrag) return FALSE;
1338 if (g_blockEventsOnScroll) return FALSE;
148cd9b6 1339
034be888
RR
1340 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1341
ff8bfdbb 1342 if (gdk_event->is_hint)
aae24d21 1343 {
f7a11f8c
RR
1344 int x = 0;
1345 int y = 0;
1346 GdkModifierType state;
1347 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
1348 gdk_event->x = x;
1349 gdk_event->y = y;
aae24d21 1350 }
ff8bfdbb 1351
c801d85f 1352/*
e380f72b
RR
1353 printf( "OnMotion from " );
1354 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1355 printf( win->GetClassInfo()->GetClassName() );
1356 printf( ".\n" );
aae24d21 1357*/
47d67540 1358
e380f72b 1359 wxMouseEvent event( wxEVT_MOTION );
d1367c3d 1360 event.SetTimestamp( gdk_event->time );
e380f72b
RR
1361 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1362 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1363 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1364 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1365 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1366 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1367 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
1368
13111b2a
VZ
1369 event.m_x = (wxCoord)gdk_event->x;
1370 event.m_y = (wxCoord)gdk_event->y;
e380f72b
RR
1371
1372 // Some control don't have their own X window and thus cannot get
1373 // any events.
1374
72195a0f 1375 if (!g_captureWindow)
2f2aa628 1376 {
b02da6b1
VZ
1377 wxCoord x = event.m_x;
1378 wxCoord y = event.m_y;
2f073eb2
RR
1379 if (win->m_wxwindow)
1380 {
da048e3d 1381 GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
b02da6b1
VZ
1382 x += pizza->xoffset;
1383 y += pizza->yoffset;
2f073eb2
RR
1384 }
1385
db1b4961 1386 wxNode *node = win->GetChildren().First();
e380f72b
RR
1387 while (node)
1388 {
1389 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb 1390
f96ac56a 1391 node = node->Next();
b02da6b1
VZ
1392 if (!child->IsShown())
1393 continue;
f96ac56a 1394
a2053b27 1395 if (child->m_isStaticBox)
ff8bfdbb
VZ
1396 {
1397 // wxStaticBox is transparent in the box itself
a2053b27
RR
1398 int xx1 = child->m_x;
1399 int yy1 = child->m_y;
1400 int xx2 = child->m_x + child->m_width;
1401 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1402
1403 // left
1404 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1405 // right
1406 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1407 // top
1408 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1409 // bottom
1410 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1411 {
1ecc4d80 1412 win = child;
a2053b27
RR
1413 event.m_x -= child->m_x;
1414 event.m_y -= child->m_y;
1ecc4d80 1415 break;
ff8bfdbb
VZ
1416 }
1417
1418 }
1419 else
1420 {
a2053b27 1421 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
2f073eb2
RR
1422 (child->m_x <= x) &&
1423 (child->m_y <= y) &&
1424 (child->m_x+child->m_width >= x) &&
1425 (child->m_y+child->m_height >= y))
1ecc4d80
RR
1426 {
1427 win = child;
a2053b27
RR
1428 event.m_x -= child->m_x;
1429 event.m_y -= child->m_y;
1ecc4d80 1430 break;
ff8bfdbb 1431 }
e380f72b 1432 }
e380f72b 1433 }
2f2aa628 1434 }
47d67540 1435
e380f72b 1436 event.SetEventObject( win );
47d67540 1437
e380f72b 1438 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1439 {
e380f72b 1440 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
f03fc89f 1441 return TRUE;
034be888 1442 }
47d67540 1443
034be888 1444 return FALSE;
362c6693 1445}
c801d85f
KB
1446
1447//-----------------------------------------------------------------------------
2f2aa628
RR
1448// "focus_in_event"
1449//-----------------------------------------------------------------------------
c801d85f 1450
2f2aa628 1451static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
c801d85f 1452{
3ac8d3bc
RR
1453 DEBUG_MAIN_THREAD
1454
c50f1fb9 1455 if (g_isIdle)
a2053b27
RR
1456 wxapp_install_idle_handler();
1457
1458 if (!win->m_hasVMT) return FALSE;
034be888 1459 if (g_blockEventsOnDrag) return FALSE;
ff8bfdbb 1460
148cd9b6
VZ
1461 switch ( g_sendActivateEvent )
1462 {
1463 case -1:
1464 // we've got focus from outside, synthtize wxActivateEvent
1465 g_sendActivateEvent = 1;
1466 break;
1467
1468 case 0:
1469 // another our window just lost focus, it was already ours before
1470 // - don't send any wxActivateEvent
1471 g_sendActivateEvent = -1;
1472 break;
1473 }
1474
b292e2f5 1475 g_focusWindow = win;
ff8bfdbb 1476
c801d85f 1477/*
f03fc89f 1478 printf( "OnSetFocus from " );
e380f72b 1479 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
f03fc89f
VZ
1480 printf( win->GetClassInfo()->GetClassName() );
1481 printf( " " );
1482 printf( WXSTRINGCAST win->GetLabel() );
1483 printf( ".\n" );
c801d85f 1484*/
47d67540 1485
3da17724
RR
1486 wxPanel *panel = wxDynamicCast(win->GetParent(), wxPanel);
1487 if (panel)
1488 {
1489 panel->SetLastFocus(win);
1490 }
148cd9b6 1491
b79395c5
RR
1492#ifdef HAVE_XIM
1493 if (win->m_ic)
1494 gdk_im_begin(win->m_ic, win->m_wxwindow->window);
1495#endif
1496
e380f72b
RR
1497 wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
1498 event.SetEventObject( win );
47d67540 1499
e380f72b 1500 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1501 {
e380f72b 1502 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
034be888
RR
1503 return TRUE;
1504 }
ca298c88 1505
034be888 1506 return FALSE;
362c6693 1507}
c801d85f
KB
1508
1509//-----------------------------------------------------------------------------
2f2aa628
RR
1510// "focus_out_event"
1511//-----------------------------------------------------------------------------
c801d85f 1512
2f2aa628 1513static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
c801d85f 1514{
3ac8d3bc
RR
1515 DEBUG_MAIN_THREAD
1516
c50f1fb9 1517 if (g_isIdle)
a2053b27
RR
1518 wxapp_install_idle_handler();
1519
1520 if (!win->m_hasVMT) return FALSE;
034be888 1521 if (g_blockEventsOnDrag) return FALSE;
ca298c88 1522
148cd9b6
VZ
1523 // if the focus goes out of our app alltogether, OnIdle() will send
1524 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1525 // g_sendActivateEvent to -1
1526 g_sendActivateEvent = 0;
1527
1528 g_focusWindow = (wxWindow *)NULL;
1529
c801d85f 1530/*
f03fc89f 1531 printf( "OnKillFocus from " );
e380f72b 1532 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
f03fc89f
VZ
1533 printf( win->GetClassInfo()->GetClassName() );
1534 printf( ".\n" );
c801d85f 1535*/
47d67540 1536
b79395c5
RR
1537#ifdef HAVE_XIM
1538 if (win->m_ic)
1539 gdk_im_end();
1540#endif
1541
e380f72b
RR
1542 wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
1543 event.SetEventObject( win );
47d67540 1544
e380f72b 1545 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1546 {
e380f72b 1547 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
034be888
RR
1548 return TRUE;
1549 }
ca298c88 1550
034be888 1551 return FALSE;
362c6693 1552}
c801d85f 1553
b4071e91
RR
1554//-----------------------------------------------------------------------------
1555// "enter_notify_event"
1556//-----------------------------------------------------------------------------
1557
1558static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1559{
3ac8d3bc
RR
1560 DEBUG_MAIN_THREAD
1561
c50f1fb9 1562 if (g_isIdle)
a2053b27 1563 wxapp_install_idle_handler();
ca298c88 1564
a2053b27
RR
1565 if (!win->m_hasVMT) return FALSE;
1566 if (g_blockEventsOnDrag) return FALSE;
47d67540 1567
a2053b27 1568 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
b292e2f5 1569
e380f72b 1570 wxMouseEvent event( wxEVT_ENTER_WINDOW );
6bc8a1c8 1571#if (GTK_MINOR_VERSION > 0)
d1367c3d 1572 event.SetTimestamp( gdk_event->time );
6bc8a1c8 1573#endif
e380f72b 1574 event.SetEventObject( win );
ff8bfdbb 1575
4a33eba6
RR
1576 int x = 0;
1577 int y = 0;
1578 GdkModifierType state = (GdkModifierType)0;
ff8bfdbb 1579
a2053b27 1580 gdk_window_get_pointer( widget->window, &x, &y, &state );
ff8bfdbb 1581
4a33eba6
RR
1582 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1583 event.m_controlDown = (state & GDK_CONTROL_MASK);
1584 event.m_altDown = (state & GDK_MOD1_MASK);
1585 event.m_metaDown = (state & GDK_MOD2_MASK);
1586 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1587 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1588 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1589
13111b2a
VZ
1590 event.m_x = x;
1591 event.m_y = y;
ff8bfdbb 1592
e380f72b 1593 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1594 {
e380f72b 1595 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "enter_notify_event" );
034be888
RR
1596 return TRUE;
1597 }
ca298c88 1598
034be888 1599 return FALSE;
b4071e91 1600}
47d67540 1601
b4071e91
RR
1602//-----------------------------------------------------------------------------
1603// "leave_notify_event"
1604//-----------------------------------------------------------------------------
1605
1606static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1607{
3ac8d3bc
RR
1608 DEBUG_MAIN_THREAD
1609
c50f1fb9 1610 if (g_isIdle)
a2053b27 1611 wxapp_install_idle_handler();
acfd422a 1612
a2053b27
RR
1613 if (!win->m_hasVMT) return FALSE;
1614 if (g_blockEventsOnDrag) return FALSE;
b292e2f5 1615
a2053b27 1616 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
c50f1fb9 1617
e380f72b 1618 wxMouseEvent event( wxEVT_LEAVE_WINDOW );
6bc8a1c8 1619#if (GTK_MINOR_VERSION > 0)
d1367c3d 1620 event.SetTimestamp( gdk_event->time );
6bc8a1c8 1621#endif
e380f72b 1622 event.SetEventObject( win );
47d67540 1623
4a33eba6
RR
1624 int x = 0;
1625 int y = 0;
1626 GdkModifierType state = (GdkModifierType)0;
ff8bfdbb 1627
4a33eba6 1628 gdk_window_get_pointer( widget->window, &x, &y, &state );
ff8bfdbb 1629
4a33eba6
RR
1630 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1631 event.m_controlDown = (state & GDK_CONTROL_MASK);
1632 event.m_altDown = (state & GDK_MOD1_MASK);
1633 event.m_metaDown = (state & GDK_MOD2_MASK);
1634 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1635 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1636 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1637
13111b2a
VZ
1638 event.m_x = x;
1639 event.m_y = y;
ff8bfdbb 1640
e380f72b 1641 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1642 {
e380f72b 1643 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "leave_notify_event" );
034be888
RR
1644 return TRUE;
1645 }
ca298c88 1646
034be888 1647 return FALSE;
b4071e91 1648}
47d67540 1649
c801d85f 1650//-----------------------------------------------------------------------------
2f2aa628
RR
1651// "value_changed" from m_vAdjust
1652//-----------------------------------------------------------------------------
c801d85f 1653
5e014a0c 1654static void gtk_window_vscroll_callback( GtkAdjustment *adjust, wxWindow *win )
c801d85f 1655{
3ac8d3bc
RR
1656 DEBUG_MAIN_THREAD
1657
c50f1fb9 1658 if (g_isIdle)
a2053b27 1659 wxapp_install_idle_handler();
c801d85f 1660
a2053b27 1661 if (g_blockEventsOnDrag) return;
47d67540 1662
a2053b27 1663 if (!win->m_hasVMT) return;
148cd9b6 1664
5e014a0c 1665 float diff = adjust->value - win->m_oldVerticalPos;
e380f72b 1666 if (fabs(diff) < 0.2) return;
148cd9b6 1667
5e014a0c 1668 win->m_oldVerticalPos = adjust->value;
47d67540 1669
5e014a0c
RR
1670 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
1671 GtkRange *range = GTK_RANGE( scrolledWindow->vscrollbar );
148cd9b6 1672
5e014a0c
RR
1673 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
1674 if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP;
1675 else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN;
1676 else if (range->scroll_type == GTK_SCROLL_PAGE_BACKWARD) command = wxEVT_SCROLLWIN_PAGEUP;
1677 else if (range->scroll_type == GTK_SCROLL_PAGE_FORWARD) command = wxEVT_SCROLLWIN_PAGEDOWN;
148cd9b6 1678
5e014a0c 1679 int value = (int)(adjust->value+0.5);
c801d85f 1680
c5b42c87 1681 wxScrollWinEvent event( command, value, wxVERTICAL );
e380f72b
RR
1682 event.SetEventObject( win );
1683 win->GetEventHandler()->ProcessEvent( event );
362c6693 1684}
c801d85f
KB
1685
1686//-----------------------------------------------------------------------------
2f2aa628
RR
1687// "value_changed" from m_hAdjust
1688//-----------------------------------------------------------------------------
c801d85f 1689
5e014a0c 1690static void gtk_window_hscroll_callback( GtkAdjustment *adjust, wxWindow *win )
47d67540 1691{
3ac8d3bc
RR
1692 DEBUG_MAIN_THREAD
1693
c50f1fb9 1694 if (g_isIdle)
a2053b27 1695 wxapp_install_idle_handler();
47d67540 1696
a2053b27
RR
1697 if (g_blockEventsOnDrag) return;
1698 if (!win->m_hasVMT) return;
47d67540 1699
5e014a0c 1700 float diff = adjust->value - win->m_oldHorizontalPos;
e380f72b 1701 if (fabs(diff) < 0.2) return;
148cd9b6 1702
5e014a0c 1703 win->m_oldHorizontalPos = adjust->value;
8bbe427f 1704
5e014a0c
RR
1705 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
1706 GtkRange *range = GTK_RANGE( scrolledWindow->hscrollbar );
148cd9b6 1707
5e014a0c
RR
1708 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
1709 if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP;
1710 else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN;
1711 else if (range->scroll_type == GTK_SCROLL_PAGE_BACKWARD) command = wxEVT_SCROLLWIN_PAGEUP;
1712 else if (range->scroll_type == GTK_SCROLL_PAGE_FORWARD) command = wxEVT_SCROLLWIN_PAGEDOWN;
148cd9b6 1713
5e014a0c 1714 int value = (int)(adjust->value+0.5);
47d67540 1715
c5b42c87 1716 wxScrollWinEvent event( command, value, wxHORIZONTAL );
e380f72b
RR
1717 event.SetEventObject( win );
1718 win->GetEventHandler()->ProcessEvent( event );
362c6693 1719}
c801d85f 1720
cb43b372
RR
1721//-----------------------------------------------------------------------------
1722// "button_press_event" from scrollbar
1723//-----------------------------------------------------------------------------
1724
2a23d363
RR
1725static gint gtk_scrollbar_button_press_callback( GtkRange *widget,
1726 GdkEventButton *gdk_event,
846e1424 1727 wxWindow *win)
cb43b372 1728{
3ac8d3bc
RR
1729 DEBUG_MAIN_THREAD
1730
c50f1fb9 1731 if (g_isIdle)
a2053b27
RR
1732 wxapp_install_idle_handler();
1733
d6d26e04 1734
5b8a521e 1735 g_blockEventsOnScroll = TRUE;
2a23d363 1736 win->m_isScrolling = (gdk_event->window == widget->slider);
47d67540 1737
e380f72b 1738 return FALSE;
cb43b372
RR
1739}
1740
1741//-----------------------------------------------------------------------------
1742// "button_release_event" from scrollbar
1743//-----------------------------------------------------------------------------
1744
88413fec 1745static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
8bbe427f 1746 GdkEventButton *WXUNUSED(gdk_event),
846e1424 1747 wxWindow *win)
cb43b372 1748{
3ac8d3bc
RR
1749 DEBUG_MAIN_THREAD
1750
1ecc4d80 1751// don't test here as we can release the mouse while being over
5e014a0c 1752// a different window than the slider
76ed8f8d
RR
1753//
1754// if (gdk_event->window != widget->slider) return FALSE;
cb43b372 1755
5b8a521e 1756 g_blockEventsOnScroll = FALSE;
47d67540 1757
2a23d363 1758 if (win->m_isScrolling)
88413fec 1759 {
d6d26e04 1760 wxEventType command = wxEVT_SCROLLWIN_THUMBRELEASE;
2a23d363
RR
1761 int value = -1;
1762 int dir = -1;
2daa0ce9 1763
2a23d363
RR
1764 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
1765 if (widget == GTK_RANGE(scrolledWindow->hscrollbar))
1766 {
1767 value = (int)(win->m_hAdjust->value+0.5);
1768 dir = wxHORIZONTAL;
1769 }
1770 if (widget == GTK_RANGE(scrolledWindow->vscrollbar))
1771 {
1772 value = (int)(win->m_vAdjust->value+0.5);
1773 dir = wxVERTICAL;
1774 }
2daa0ce9 1775
2a23d363 1776 wxScrollWinEvent event( command, value, dir );
2a23d363
RR
1777 event.SetEventObject( win );
1778 win->GetEventHandler()->ProcessEvent( event );
88413fec
RR
1779 }
1780
2a23d363 1781 win->m_isScrolling = FALSE;
2daa0ce9 1782
e380f72b 1783 return FALSE;
cb43b372
RR
1784}
1785
f03fc89f
VZ
1786// ----------------------------------------------------------------------------
1787// this wxWindowBase function is implemented here (in platform-specific file)
1788// because it is static and so couldn't be made virtual
1789// ----------------------------------------------------------------------------
2b07d713 1790
f03fc89f 1791wxWindow *wxWindowBase::FindFocus()
2b07d713 1792{
f03fc89f 1793 return g_focusWindow;
2b07d713 1794}
ca298c88 1795
a2053b27
RR
1796//-----------------------------------------------------------------------------
1797// "realize" from m_widget
1798//-----------------------------------------------------------------------------
1799
b79395c5
RR
1800/* We cannot set colours and fonts before the widget has
1801 been realized, so we do this directly after realization. */
a2053b27
RR
1802
1803static gint
63081513 1804gtk_window_realized_callback( GtkWidget *WXUNUSED(m_widget), wxWindow *win )
a2053b27 1805{
3ac8d3bc
RR
1806 DEBUG_MAIN_THREAD
1807
c50f1fb9 1808 if (g_isIdle)
a2053b27
RR
1809 wxapp_install_idle_handler();
1810
739730ca
RR
1811 if (win->m_delayedBackgroundColour)
1812 win->SetBackgroundColour( win->GetBackgroundColour() );
a2053b27 1813
739730ca
RR
1814 if (win->m_delayedForegroundColour)
1815 win->SetForegroundColour( win->GetForegroundColour() );
a2053b27 1816
3c679789
RR
1817 wxWindowCreateEvent event( win );
1818 event.SetEventObject( win );
1819 win->GetEventHandler()->ProcessEvent( event );
3d2d8da1 1820
a2053b27
RR
1821 return FALSE;
1822}
1823
b79395c5
RR
1824//-----------------------------------------------------------------------------
1825// "size_allocate"
1826//-----------------------------------------------------------------------------
1827
8f75cb6c 1828static
adc1999b
RR
1829void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
1830 GtkAllocation *WXUNUSED(alloc),
8f75cb6c
RR
1831 wxWindow *win )
1832{
1833 if (g_isIdle)
1834 wxapp_install_idle_handler();
2daa0ce9 1835
5b8a521e 1836 if (!win->m_hasScrolling) return;
2daa0ce9 1837
5b8a521e
RR
1838 int client_width = 0;
1839 int client_height = 0;
1840 win->GetClientSize( &client_width, &client_height );
1841 if ((client_width == win->m_oldClientWidth) && (client_height == win->m_oldClientHeight))
1842 return;
2daa0ce9 1843
5b8a521e
RR
1844 win->m_oldClientWidth = client_width;
1845 win->m_oldClientHeight = client_height;
2daa0ce9 1846
5b8a521e
RR
1847 if (!win->m_nativeSizeEvent)
1848 {
1849 wxSizeEvent event( win->GetSize(), win->GetId() );
1850 event.SetEventObject( win );
1851 win->GetEventHandler()->ProcessEvent( event );
1852 }
8f75cb6c
RR
1853}
1854
1855
3ed2e7ce
VZ
1856#ifdef HAVE_XIM
1857 #define WXUNUSED_UNLESS_XIM(param) param
1858#else
1859 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1860#endif
1861
b79395c5
RR
1862/* Resize XIM window */
1863
3ed2e7ce 1864static
8f75cb6c
RR
1865void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget),
1866 GtkAllocation* WXUNUSED_UNLESS_XIM(alloc),
1867 wxWindow* WXUNUSED_UNLESS_XIM(win) )
b79395c5
RR
1868{
1869 if (g_isIdle)
1870 wxapp_install_idle_handler();
2daa0ce9 1871
9a8c7620 1872#ifdef HAVE_XIM
b79395c5
RR
1873 if (!win->m_ic)
1874 return;
1875
b79395c5
RR
1876 if (gdk_ic_get_style (win->m_ic) & GDK_IM_PREEDIT_POSITION)
1877 {
1878 gint width, height;
1879
3ed2e7ce 1880 gdk_window_get_size (widget->window, &width, &height);
b79395c5
RR
1881 win->m_icattr->preedit_area.width = width;
1882 win->m_icattr->preedit_area.height = height;
1883 gdk_ic_set_attr (win->m_ic, win->m_icattr, GDK_IC_PREEDIT_AREA);
1884 }
9a8c7620 1885#endif // HAVE_XIM
b79395c5
RR
1886}
1887
63081513
RR
1888//-----------------------------------------------------------------------------
1889// "realize" from m_wxwindow
1890//-----------------------------------------------------------------------------
1891
1892/* Initialize XIM support */
1893
1894static gint
3ed2e7ce
VZ
1895gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
1896 wxWindow * WXUNUSED_UNLESS_XIM(win) )
63081513
RR
1897{
1898 if (g_isIdle)
1899 wxapp_install_idle_handler();
1900
d06800f1 1901#ifdef HAVE_XIM
63081513
RR
1902 if (win->m_ic) return FALSE;
1903 if (!widget) return FALSE;
1904 if (!gdk_im_ready()) return FALSE;
1905
1906 win->m_icattr = gdk_ic_attr_new();
1907 if (!win->m_icattr) return FALSE;
2daa0ce9 1908
63081513
RR
1909 gint width, height;
1910 GdkEventMask mask;
1911 GdkColormap *colormap;
1912 GdkICAttr *attr = win->m_icattr;
b58b1dfc 1913 unsigned attrmask = GDK_IC_ALL_REQ;
63081513 1914 GdkIMStyle style;
b79395c5
RR
1915 GdkIMStyle supported_style = (GdkIMStyle)
1916 (GDK_IM_PREEDIT_NONE |
63081513
RR
1917 GDK_IM_PREEDIT_NOTHING |
1918 GDK_IM_PREEDIT_POSITION |
1919 GDK_IM_STATUS_NONE |
b79395c5 1920 GDK_IM_STATUS_NOTHING);
63081513
RR
1921
1922 if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
b79395c5 1923 supported_style = (GdkIMStyle)(supported_style & ~GDK_IM_PREEDIT_POSITION);
63081513
RR
1924
1925 attr->style = style = gdk_im_decide_style (supported_style);
1926 attr->client_window = widget->window;
1927
1928 if ((colormap = gtk_widget_get_colormap (widget)) !=
1929 gtk_widget_get_default_colormap ())
1930 {
b420fb6a
RR
1931 attrmask |= GDK_IC_PREEDIT_COLORMAP;
1932 attr->preedit_colormap = colormap;
63081513 1933 }
2daa0ce9 1934
63081513
RR
1935 attrmask |= GDK_IC_PREEDIT_FOREGROUND;
1936 attrmask |= GDK_IC_PREEDIT_BACKGROUND;
1937 attr->preedit_foreground = widget->style->fg[GTK_STATE_NORMAL];
1938 attr->preedit_background = widget->style->base[GTK_STATE_NORMAL];
1939
1940 switch (style & GDK_IM_PREEDIT_MASK)
1941 {
1942 case GDK_IM_PREEDIT_POSITION:
1943 if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
1944 {
1945 g_warning ("over-the-spot style requires fontset");
1946 break;
1947 }
1948
1949 gdk_window_get_size (widget->window, &width, &height);
1950
1951 attrmask |= GDK_IC_PREEDIT_POSITION_REQ;
1952 attr->spot_location.x = 0;
1953 attr->spot_location.y = height;
1954 attr->preedit_area.x = 0;
1955 attr->preedit_area.y = 0;
1956 attr->preedit_area.width = width;
1957 attr->preedit_area.height = height;
1958 attr->preedit_fontset = widget->style->font;
1959
1960 break;
b79395c5 1961 }
2daa0ce9 1962
b58b1dfc 1963 win->m_ic = gdk_ic_new (attr, (GdkICAttributesType)attrmask);
2daa0ce9 1964
63081513
RR
1965 if (win->m_ic == NULL)
1966 g_warning ("Can't create input context.");
1967 else
1968 {
1969 mask = gdk_window_get_events (widget->window);
b79395c5 1970 mask = (GdkEventMask)(mask | gdk_ic_get_events (win->m_ic));
63081513
RR
1971 gdk_window_set_events (widget->window, mask);
1972
1973 if (GTK_WIDGET_HAS_FOCUS(widget))
1974 gdk_im_begin (win->m_ic, widget->window);
1975 }
63081513
RR
1976#endif
1977
1978 return FALSE;
1979}
1980
6ca41e57
RR
1981//-----------------------------------------------------------------------------
1982// InsertChild for wxWindow.
1983//-----------------------------------------------------------------------------
1984
b1170810
RR
1985/* Callback for wxWindow. This very strange beast has to be used because
1986 * C++ has no virtual methods in a constructor. We have to emulate a
1987 * virtual function here as wxNotebook requires a different way to insert
1988 * a child in it. I had opted for creating a wxNotebookPage window class
1989 * which would have made this superfluous (such in the MDI window system),
1990 * but no-one was listening to me... */
6ca41e57
RR
1991
1992static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
1993{
bf0c00c6
RR
1994 /* the window might have been scrolled already, do we
1995 have to adapt the position */
da048e3d
RR
1996 GtkPizza *pizza = GTK_PIZZA(parent->m_wxwindow);
1997 child->m_x += pizza->xoffset;
1998 child->m_y += pizza->yoffset;
148cd9b6 1999
da048e3d 2000 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
a2053b27
RR
2001 GTK_WIDGET(child->m_widget),
2002 child->m_x,
2003 child->m_y,
2004 child->m_width,
2005 child->m_height );
6ca41e57
RR
2006}
2007
bbe0af5b
RR
2008//-----------------------------------------------------------------------------
2009// global functions
2010//-----------------------------------------------------------------------------
2011
2012wxWindow* wxGetActiveWindow()
2013{
f03fc89f 2014 return g_focusWindow;
bbe0af5b
RR
2015}
2016
c801d85f 2017//-----------------------------------------------------------------------------
2f2aa628 2018// wxWindow
c801d85f
KB
2019//-----------------------------------------------------------------------------
2020
f03fc89f 2021IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
c801d85f 2022
68995f26 2023void wxWindow::Init()
c801d85f 2024{
f03fc89f
VZ
2025 // common init
2026 InitBase();
68995f26 2027
f03fc89f 2028 // GTK specific
a2053b27 2029 m_widget = (GtkWidget *) NULL;
e380f72b 2030 m_wxwindow = (GtkWidget *) NULL;
8bbe427f 2031
f03fc89f 2032 // position/size
a2053b27
RR
2033 m_x = 0;
2034 m_y = 0;
2035 m_width = 0;
e380f72b 2036 m_height = 0;
8bbe427f 2037
e380f72b
RR
2038 m_sizeSet = FALSE;
2039 m_hasVMT = FALSE;
2040 m_needParent = TRUE;
31c6b4fc 2041 m_isBeingDeleted = FALSE;
148cd9b6 2042
147bc491 2043 m_noExpose = FALSE;
30760ce7 2044 m_nativeSizeEvent = FALSE;
148cd9b6 2045
a2053b27 2046 m_hasScrolling = FALSE;
846e1424 2047 m_isScrolling = FALSE;
f03fc89f 2048
a2053b27 2049 m_hAdjust = (GtkAdjustment*) NULL;
e380f72b 2050 m_vAdjust = (GtkAdjustment*) NULL;
a2053b27 2051 m_oldHorizontalPos = 0.0;
e380f72b 2052 m_oldVerticalPos = 0.0;
8bbe427f 2053
e380f72b 2054 m_resizing = FALSE;
e380f72b 2055 m_widgetStyle = (GtkStyle*) NULL;
8bbe427f 2056
ddb6bc71 2057 m_insertCallback = (wxInsertChildFunction) NULL;
8bbe427f 2058
1ecc4d80 2059 m_isStaticBox = FALSE;
953704c1 2060 m_isRadioButton = FALSE;
54517652 2061 m_isFrame = FALSE;
b292e2f5 2062 m_acceptsFocus = FALSE;
148cd9b6 2063
b6fa52db
RR
2064 m_clipPaintRegion = FALSE;
2065 m_queuedFullRedraw = FALSE;
2066
5e014a0c 2067 m_cursor = *wxSTANDARD_CURSOR;
2daa0ce9 2068
63081513
RR
2069#ifdef HAVE_XIM
2070 m_ic = (GdkIC*) NULL;
2071 m_icattr = (GdkICAttr*) NULL;
2072#endif
362c6693 2073}
c801d85f 2074
68995f26
VZ
2075wxWindow::wxWindow()
2076{
2077 Init();
2078}
2079
6ca41e57 2080wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
e380f72b
RR
2081 const wxPoint &pos, const wxSize &size,
2082 long style, const wxString &name )
6ca41e57 2083{
68995f26
VZ
2084 Init();
2085
e380f72b 2086 Create( parent, id, pos, size, style, name );
6ca41e57 2087}
8bbe427f 2088
debe6624 2089bool wxWindow::Create( wxWindow *parent, wxWindowID id,
e380f72b
RR
2090 const wxPoint &pos, const wxSize &size,
2091 long style, const wxString &name )
c801d85f 2092{
4dcaf11a
RR
2093 if (!PreCreation( parent, pos, size ) ||
2094 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
2095 {
223d09f6 2096 wxFAIL_MSG( wxT("wxWindow creation failed") );
b02da6b1 2097 return FALSE;
4dcaf11a 2098 }
47d67540 2099
ddb6bc71 2100 m_insertCallback = wxInsertChildInWindow;
b6fa52db 2101
e380f72b 2102 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
38c7b3d3 2103 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
ff8bfdbb 2104
f03fc89f 2105 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
47d67540 2106
e380f72b
RR
2107 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
2108 scroll_class->scrollbar_spacing = 0;
47d67540 2109
f03fc89f 2110 gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
47d67540 2111
f03fc89f
VZ
2112 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->hscrollbar) );
2113 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->vscrollbar) );
47d67540 2114
da048e3d 2115 m_wxwindow = gtk_pizza_new();
38c7b3d3 2116
034be888 2117 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
58dea4b0 2118
034be888 2119#if (GTK_MINOR_VERSION > 0)
da048e3d 2120 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
b292e2f5 2121
f03fc89f 2122 if (HasFlag(wxRAISED_BORDER))
034be888 2123 {
da048e3d 2124 gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_OUT );
034be888 2125 }
f03fc89f 2126 else if (HasFlag(wxSUNKEN_BORDER))
034be888 2127 {
da048e3d 2128 gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_IN );
5e014a0c
RR
2129 }
2130 else if (HasFlag(wxSIMPLE_BORDER))
2131 {
da048e3d 2132 gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_THIN );
034be888
RR
2133 }
2134 else
2135 {
da048e3d 2136 gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_NONE );
034be888 2137 }
f03fc89f
VZ
2138#else // GTK_MINOR_VERSION == 0
2139 GtkViewport *viewport = GTK_VIEWPORT(scrolledWindow->viewport);
b292e2f5 2140
f03fc89f 2141 if (HasFlag(wxRAISED_BORDER))
e380f72b
RR
2142 {
2143 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
2144 }
f03fc89f 2145 else if (HasFlag(wxSUNKEN_BORDER))
e380f72b
RR
2146 {
2147 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
2148 }
2149 else
2150 {
2151 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
2152 }
f03fc89f 2153#endif // GTK_MINOR_VERSION
47d67540 2154
3da17724
RR
2155 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
2156 m_acceptsFocus = TRUE;
ca298c88 2157
034be888 2158#if (GTK_MINOR_VERSION == 0)
e380f72b
RR
2159 // shut the viewport up
2160 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2161 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
f03fc89f 2162#endif // GTK_MINOR_VERSION == 0
e380f72b
RR
2163
2164 // I _really_ don't want scrollbars in the beginning
a2053b27
RR
2165 m_vAdjust->lower = 0.0;
2166 m_vAdjust->upper = 1.0;
2167 m_vAdjust->value = 0.0;
2168 m_vAdjust->step_increment = 1.0;
2169 m_vAdjust->page_increment = 1.0;
2170 m_vAdjust->page_size = 5.0;
2171 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
2172 m_hAdjust->lower = 0.0;
2173 m_hAdjust->upper = 1.0;
2174 m_hAdjust->value = 0.0;
2175 m_hAdjust->step_increment = 1.0;
2176 m_hAdjust->page_increment = 1.0;
2177 m_hAdjust->page_size = 5.0;
2178 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
f03fc89f
VZ
2179
2180 // these handlers block mouse events to any window during scrolling such as
2181 // motion events and prevent GTK and wxWindows from fighting over where the
2182 // slider should be
2183
2184 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_press_event",
76ed8f8d
RR
2185 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
2186
f03fc89f 2187 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_press_event",
76ed8f8d
RR
2188 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
2189
f03fc89f 2190 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_release_event",
76ed8f8d
RR
2191 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
2192
f03fc89f 2193 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_release_event",
76ed8f8d 2194 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
8bbe427f 2195
034be888 2196 // these handlers get notified when screen updates are required either when
76ed8f8d
RR
2197 // scrolling or when the window size (and therefore scrollbar configuration)
2198 // has changed
2199
2200 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
2201 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
2202 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
2203 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
2204
f03fc89f 2205 gtk_widget_show( m_wxwindow );
47d67540 2206
f03fc89f
VZ
2207 if (m_parent)
2208 m_parent->DoAddChild( this );
8bbe427f 2209
e380f72b 2210 PostCreation();
8bbe427f 2211
e380f72b 2212 Show( TRUE );
c801d85f 2213
e380f72b 2214 return TRUE;
362c6693 2215}
c801d85f 2216
68dda785 2217wxWindow::~wxWindow()
c801d85f 2218{
31c6b4fc 2219 m_isBeingDeleted = TRUE;
43a18898 2220 m_hasVMT = FALSE;
47d67540 2221
f03fc89f
VZ
2222 if (m_widget)
2223 Show( FALSE );
8bbe427f 2224
a2053b27
RR
2225 DestroyChildren();
2226
f03fc89f
VZ
2227 if (m_parent)
2228 m_parent->RemoveChild( this );
c801d85f 2229
63081513
RR
2230#ifdef HAVE_XIM
2231 if (m_ic)
2232 gdk_ic_destroy (m_ic);
2233 if (m_icattr)
2234 gdk_ic_attr_destroy (m_icattr);
2235#endif
2236
f03fc89f 2237 if (m_widgetStyle)
a2053b27 2238 {
a56fcaaf 2239#if DISABLE_STYLE_IF_BROKEN_THEME
bce1406b
RR
2240 // don't delete if it's a pixmap theme style
2241 if (!m_widgetStyle->engine_data)
2242 gtk_style_unref( m_widgetStyle );
a56fcaaf 2243#endif
c50f1fb9 2244 m_widgetStyle = (GtkStyle*) NULL;
a2053b27 2245 }
c801d85f 2246
f03fc89f 2247 if (m_wxwindow)
a2053b27 2248 {
f03fc89f 2249 gtk_widget_destroy( m_wxwindow );
c50f1fb9 2250 m_wxwindow = (GtkWidget*) NULL;
a2053b27 2251 }
8bbe427f 2252
f03fc89f 2253 if (m_widget)
a2053b27 2254 {
f03fc89f 2255 gtk_widget_destroy( m_widget );
c50f1fb9 2256 m_widget = (GtkWidget*) NULL;
a2053b27 2257 }
362c6693 2258}
c801d85f 2259
4dcaf11a 2260bool wxWindow::PreCreation( wxWindow *parent, const wxPoint &pos, const wxSize &size )
c801d85f 2261{
223d09f6 2262 wxCHECK_MSG( !m_needParent || parent, FALSE, wxT("Need complete parent.") );
8bbe427f 2263
4dcaf11a
RR
2264 /* this turns -1 into 20 so that a minimal window is
2265 visible even although -1,-1 has been given as the
2266 size of the window. the same trick is used in other
2267 ports and should make debugging easier */
f03fc89f
VZ
2268 m_width = WidthDefault(size.x);
2269 m_height = HeightDefault(size.y);
8bbe427f 2270
43a18898
RR
2271 m_x = (int)pos.x;
2272 m_y = (int)pos.y;
8bbe427f 2273
4dcaf11a 2274 /* some reasonable defaults */
148cd9b6 2275 if (!parent)
6ca41e57 2276 {
43a18898
RR
2277 if (m_x == -1)
2278 {
2279 m_x = (gdk_screen_width () - m_width) / 2;
2280 if (m_x < 10) m_x = 10;
2281 }
2282 if (m_y == -1)
2283 {
2284 m_y = (gdk_screen_height () - m_height) / 2;
2285 if (m_y < 10) m_y = 10;
2286 }
6ca41e57 2287 }
148cd9b6 2288
4dcaf11a 2289 return TRUE;
c801d85f
KB
2290}
2291
68dda785 2292void wxWindow::PostCreation()
c801d85f 2293{
223d09f6 2294 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
ca298c88 2295
43a18898
RR
2296 if (m_wxwindow)
2297 {
147bc491 2298 if (!m_noExpose)
b02da6b1 2299 {
147bc491 2300 /* these get reported to wxWindows -> wxPaintEvent */
b420fb6a
RR
2301
2302 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow), TRUE );
2303
b6fa52db
RR
2304 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "event",
2305 GTK_SIGNAL_FUNC(gtk_window_event_event_callback), (gpointer)this );
2306
147bc491
RR
2307 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
2308 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
2309
2310 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
2311 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
b02da6b1 2312 }
148cd9b6 2313
ef47f9b3 2314#if (GTK_MINOR_VERSION > 0)
ed673c6a 2315 /* these are called when the "sunken" or "raised" borders are drawn */
034be888
RR
2316 gtk_signal_connect( GTK_OBJECT(m_widget), "expose_event",
2317 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback), (gpointer)this );
2318
2319 gtk_signal_connect( GTK_OBJECT(m_widget), "draw",
2320 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback), (gpointer)this );
ef47f9b3 2321#endif
43a18898 2322 }
47d67540 2323
63081513
RR
2324 if (m_wxwindow && m_needParent)
2325 {
2326 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "focus_in_event",
2327 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
2328
2329 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "focus_out_event",
2330 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
2331 }
2332 else
2333 {
2334 // For dialogs and frames, we are interested mainly in
2335 // m_widget's focus.
2daa0ce9 2336
63081513
RR
2337 gtk_signal_connect( GTK_OBJECT(m_widget), "focus_in_event",
2338 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
2339
2340 gtk_signal_connect( GTK_OBJECT(m_widget), "focus_out_event",
2341 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
2342 }
2343
a2053b27 2344 GtkWidget *connect_widget = GetConnectWidget();
f03fc89f 2345
a2053b27 2346 ConnectWidget( connect_widget );
47d67540 2347
63081513 2348 /* We cannot set colours, fonts and cursors before the widget has
a2053b27
RR
2349 been realized, so we do this directly after realization */
2350 gtk_signal_connect( GTK_OBJECT(connect_widget), "realize",
c50f1fb9 2351 GTK_SIGNAL_FUNC(gtk_window_realized_callback), (gpointer) this );
2daa0ce9 2352
63081513
RR
2353 if (m_wxwindow)
2354 {
8f75cb6c
RR
2355 /* Catch native resize events. */
2356 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
2357 GTK_SIGNAL_FUNC(gtk_window_size_callback), (gpointer)this );
2daa0ce9 2358
8f75cb6c 2359 /* Initialize XIM support. */
63081513
RR
2360 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
2361 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback), (gpointer) this );
8f75cb6c
RR
2362
2363 /* And resize XIM window. */
b79395c5
RR
2364 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
2365 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback), (gpointer)this );
63081513 2366 }
2daa0ce9 2367
43a18898 2368 m_hasVMT = TRUE;
b4071e91
RR
2369}
2370
2371void wxWindow::ConnectWidget( GtkWidget *widget )
2372{
43a18898
RR
2373 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
2374 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
c801d85f 2375
b666df2c
RR
2376 gtk_signal_connect( GTK_OBJECT(widget), "key_release_event",
2377 GTK_SIGNAL_FUNC(gtk_window_key_release_callback), (gpointer)this );
2378
43a18898
RR
2379 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
2380 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
47d67540 2381
43a18898
RR
2382 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
2383 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
47d67540 2384
43a18898
RR
2385 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
2386 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
47d67540 2387
43a18898
RR
2388 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
2389 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
47d67540 2390
43a18898
RR
2391 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
2392 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
362c6693 2393}
c801d85f 2394
68dda785 2395bool wxWindow::Destroy()
c801d85f 2396{
223d09f6 2397 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
47d67540 2398
43a18898 2399 m_hasVMT = FALSE;
c801d85f 2400
f03fc89f 2401 return wxWindowBase::Destroy();
362c6693 2402}
c801d85f 2403
23efdd02
RR
2404void wxWindow::DoMoveWindow(int x, int y, int width, int height)
2405{
b6fa52db
RR
2406 if (m_wxwindow && GTK_PIZZA(m_wxwindow)->bin_window)
2407 {
2408 /* Normally, GTK will send expose events only for the regions
2409 which actually got exposed. Sadly, wxMSW invalidates
2410 the whole window so we have to do that, too. We could
2411 simply add a complete refresh, but we would then get
2412 the normal GTK expose events in surplus, so we shut
2413 off the expose events and schedule a full redraw to
2414 be done in OnInternalIdle, where we restore the handling
2415 of expose events. */
2416
2417 m_queuedFullRedraw = TRUE;
2418
2419 GdkEventMask mask = gdk_window_get_events( GTK_PIZZA(m_wxwindow)->bin_window );
2420 mask = (GdkEventMask)(mask & ~GDK_EXPOSURE_MASK);
2421 gdk_window_set_events( GTK_PIZZA(m_wxwindow)->bin_window, mask );
2422 }
2423
23efdd02
RR
2424 gtk_pizza_set_size( GTK_PIZZA(m_parent->m_wxwindow), m_widget, x, y, width, height );
2425}
2daa0ce9 2426
bfc6fde4 2427void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
c801d85f 2428{
223d09f6
KB
2429 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
2430 wxASSERT_MSG( (m_parent != NULL), wxT("wxWindow::SetSize requires parent.\n") );
8bbe427f 2431
e27ce4e9 2432 if (m_resizing) return; /* I don't like recursions */
fb1585ae 2433 m_resizing = TRUE;
b6fa52db 2434
a2053b27 2435 if (m_parent->m_wxwindow == NULL) /* i.e. wxNotebook */
fb1585ae 2436 {
e27ce4e9 2437 /* don't set the size for children of wxNotebook, just take the values. */
fb1585ae
RR
2438 m_x = x;
2439 m_y = y;
2440 m_width = width;
ba4e3652 2441 m_height = height;
fb1585ae 2442 }
ba4e3652 2443 else
fb1585ae 2444 {
da048e3d 2445 GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
148cd9b6 2446
85ad5eb5 2447 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
ba4e3652 2448 {
da048e3d
RR
2449 if (x != -1) m_x = x + pizza->xoffset;
2450 if (y != -1) m_y = y + pizza->yoffset;
ba4e3652
RR
2451 if (width != -1) m_width = width;
2452 if (height != -1) m_height = height;
2453 }
2454 else
2455 {
da048e3d
RR
2456 m_x = x + pizza->xoffset;
2457 m_y = y + pizza->yoffset;
ba4e3652
RR
2458 m_width = width;
2459 m_height = height;
2460 }
47d67540 2461
ba4e3652
RR
2462 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
2463 {
2464 if (width == -1) m_width = 80;
2465 }
2466
2467 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
2468 {
2469 if (height == -1) m_height = 26;
2470 }
8bbe427f 2471
ba4e3652
RR
2472 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
2473 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
d3b4d113
RR
2474 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
2475 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
47d67540 2476
a2053b27 2477 int border = 0;
c50f1fb9 2478 int bottom_border = 0;
f03fc89f 2479
29f538ce 2480 if (GTK_WIDGET_CAN_DEFAULT(m_widget))
c50f1fb9
VZ
2481 {
2482 /* the default button has a border around it */
2483 border = 6;
2484 bottom_border = 5;
2485 }
2486
23efdd02
RR
2487 DoMoveWindow( m_x-border,
2488 m_y-border,
2489 m_width+2*border,
2490 m_height+border+bottom_border );
54517652 2491 }
148cd9b6 2492
5b8a521e
RR
2493 if (m_hasScrolling)
2494 {
b6fa52db
RR
2495 /* Sometimes the client area changes size without the
2496 whole windows's size changing, but if the whole
2497 windows's size doesn't change, no wxSizeEvent will
2498 normally be sent. Here we add an extra test if
2499 the client test has been changed and this will
2500 be used then. */
5b8a521e
RR
2501 GetClientSize( &m_oldClientWidth, &m_oldClientHeight );
2502 }
2503
54517652 2504/*
6d693bb4
RR
2505 wxPrintf( "OnSize sent from " );
2506 if (GetClassInfo() && GetClassInfo()->GetClassName())
2507 wxPrintf( GetClassInfo()->GetClassName() );
2508 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2509*/
2510
30760ce7
RR
2511 if (!m_nativeSizeEvent)
2512 {
2513 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
2514 event.SetEventObject( this );
2515 GetEventHandler()->ProcessEvent( event );
2516 }
6d693bb4 2517
fb1585ae 2518 m_resizing = FALSE;
362c6693 2519}
c801d85f 2520
9390a202
RR
2521void wxWindow::OnInternalIdle()
2522{
148cd9b6
VZ
2523 if ( g_sendActivateEvent != -1 )
2524 {
2525 bool activate = g_sendActivateEvent != 0;
2526
2527 // do it only once
2528 g_sendActivateEvent = -1;
2529
2530 wxActivateEvent event(wxEVT_ACTIVATE, activate, GetId());
2531 event.SetEventObject(this);
2532
2533 (void)GetEventHandler()->ProcessEvent(event);
2534 }
2535
9146082c
RR
2536 wxCursor cursor = m_cursor;
2537 if (g_globalCursor.Ok()) cursor = g_globalCursor;
c50f1fb9 2538
f7a11f8c 2539 if (cursor.Ok())
9146082c 2540 {
3017f78d 2541 /* I now set the cursor anew in every OnInternalIdle call
b02da6b1
VZ
2542 as setting the cursor in a parent window also effects the
2543 windows above so that checking for the current cursor is
2544 not possible. */
148cd9b6 2545
9146082c 2546 if (m_wxwindow)
6a008b33 2547 {
da048e3d 2548 GdkWindow *window = GTK_PIZZA(m_wxwindow)->bin_window;
6a008b33 2549 if (window)
c50f1fb9 2550 gdk_window_set_cursor( window, cursor.GetCursor() );
6a008b33
VZ
2551
2552 if (!g_globalCursor.Ok())
2553 cursor = *wxSTANDARD_CURSOR;
2554
2555 window = m_widget->window;
5e014a0c 2556 if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
9146082c 2557 gdk_window_set_cursor( window, cursor.GetCursor() );
5e014a0c 2558
6a008b33
VZ
2559 }
2560 else
2561 {
5e014a0c 2562
9146082c 2563 GdkWindow *window = m_widget->window;
5e014a0c 2564 if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
9146082c 2565 gdk_window_set_cursor( window, cursor.GetCursor() );
5e014a0c 2566
6a008b33 2567 }
9146082c 2568 }
6a008b33 2569
9390a202 2570 UpdateWindowUI();
b6fa52db
RR
2571
2572 if (m_queuedFullRedraw)
2573 {
2574 /* See also wxWindow::DoMoveWindow for explanation of this code. What
2575 we test here is if the requested size of the window is the same as
2576 the actual size of window, in which case all expose events that resulted
2577 from resizing the window have been sent (and discarded) and we can
2578 now do our full redraw and switch on expose event handling again. */
8cb9f0d0
RR
2579
2580 bool child_already_resized = FALSE;
2581 if (m_isFrame)
2582 child_already_resized = gtk_pizza_child_resized( GTK_PIZZA(m_wxwindow->parent), m_wxwindow );
2583 else
2584 child_already_resized = gtk_pizza_child_resized( GTK_PIZZA(m_widget->parent), m_widget );
2585
2586 if (child_already_resized)
b6fa52db
RR
2587 {
2588 m_queuedFullRedraw = FALSE;
2589 m_updateRegion.Clear();
2590 m_updateRegion.Union( 0,0,m_width,m_height );
2591 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
b420fb6a 2592
b6fa52db
RR
2593 GdkEventMask mask = gdk_window_get_events( GTK_PIZZA(m_wxwindow)->bin_window );
2594 mask = (GdkEventMask)(mask | GDK_EXPOSURE_MASK);
2595 gdk_window_set_events( GTK_PIZZA(m_wxwindow)->bin_window, mask );
2596 }
2597 }
9390a202
RR
2598}
2599
f03fc89f 2600void wxWindow::DoGetSize( int *width, int *height ) const
c801d85f 2601{
223d09f6 2602 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2603
fb1585ae
RR
2604 if (width) (*width) = m_width;
2605 if (height) (*height) = m_height;
362c6693 2606}
c801d85f 2607
bfc6fde4 2608void wxWindow::DoSetClientSize( int width, int height )
c801d85f 2609{
223d09f6 2610 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2611
1ecc4d80 2612 if (!m_wxwindow)
c801d85f 2613 {
1ecc4d80 2614 SetSize( width, height );
c801d85f
KB
2615 }
2616 else
2617 {
1ecc4d80
RR
2618 int dw = 0;
2619 int dh = 0;
2620
98d3fdbe
RR
2621 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2622 {
5e014a0c 2623 /* when using GTK 1.2 we set the shadow border size to 2 */
6a008b33 2624 dw += 2 * 2;
98d3fdbe
RR
2625 dh += 2 * 2;
2626 }
5e014a0c
RR
2627 if (HasFlag(wxSIMPLE_BORDER))
2628 {
2629 /* when using GTK 1.2 we set the simple border size to 1 */
2630 dw += 1 * 2;
2631 dh += 1 * 2;
2632 }
034be888 2633
5b8a521e 2634 if (m_hasScrolling)
98d3fdbe 2635 {
324dbfec 2636 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2daa0ce9 2637
9000c624
RR
2638 GtkRequisition vscroll_req;
2639 vscroll_req.width = 2;
2640 vscroll_req.height = 2;
2641 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->vscrollbar)->klass )->size_request )
2642 (scroll_window->vscrollbar, &vscroll_req );
2daa0ce9 2643
9000c624
RR
2644 GtkRequisition hscroll_req;
2645 hscroll_req.width = 2;
2646 hscroll_req.height = 2;
2647 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->hscrollbar)->klass )->size_request )
2648 (scroll_window->hscrollbar, &hscroll_req );
2649
324dbfec
RR
2650 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
2651
1ecc4d80
RR
2652 if (scroll_window->vscrollbar_visible)
2653 {
9000c624 2654 dw += vscroll_req.width;
1ecc4d80
RR
2655 dw += scroll_class->scrollbar_spacing;
2656 }
2657
2658 if (scroll_window->hscrollbar_visible)
2659 {
9000c624 2660 dh += hscroll_req.height;
63cc5d9d 2661 dh += scroll_class->scrollbar_spacing;
1ecc4d80 2662 }
9000c624 2663 }
1ecc4d80 2664
034be888 2665 SetSize( width+dw, height+dh );
1ecc4d80 2666 }
362c6693 2667}
c801d85f 2668
f03fc89f 2669void wxWindow::DoGetClientSize( int *width, int *height ) const
c801d85f 2670{
223d09f6 2671 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2672
1ecc4d80
RR
2673 if (!m_wxwindow)
2674 {
2675 if (width) (*width) = m_width;
2676 if (height) (*height) = m_height;
c801d85f
KB
2677 }
2678 else
2679 {
1ecc4d80
RR
2680 int dw = 0;
2681 int dh = 0;
2682
98d3fdbe
RR
2683 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2684 {
5e014a0c 2685 /* when using GTK 1.2 we set the shadow border size to 2 */
6a008b33 2686 dw += 2 * 2;
98d3fdbe
RR
2687 dh += 2 * 2;
2688 }
5e014a0c
RR
2689 if (HasFlag(wxSIMPLE_BORDER))
2690 {
2691 /* when using GTK 1.2 we set the simple border size to 1 */
2692 dw += 1 * 2;
2693 dh += 1 * 2;
2694 }
9000c624 2695
5b8a521e 2696 if (m_hasScrolling)
98d3fdbe 2697 {
6a008b33 2698 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2daa0ce9 2699
9000c624
RR
2700 GtkRequisition vscroll_req;
2701 vscroll_req.width = 2;
2702 vscroll_req.height = 2;
2703 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->vscrollbar)->klass )->size_request )
2704 (scroll_window->vscrollbar, &vscroll_req );
2daa0ce9 2705
9000c624
RR
2706 GtkRequisition hscroll_req;
2707 hscroll_req.width = 2;
2708 hscroll_req.height = 2;
2709 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->hscrollbar)->klass )->size_request )
2710 (scroll_window->hscrollbar, &hscroll_req );
2711
6a008b33
VZ
2712 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
2713
1ecc4d80
RR
2714 if (scroll_window->vscrollbar_visible)
2715 {
9000c624 2716 dw += vscroll_req.width;
1ecc4d80
RR
2717 dw += scroll_class->scrollbar_spacing;
2718 }
2719
2720 if (scroll_window->hscrollbar_visible)
2721 {
9000c624 2722 dh += hscroll_req.height;
1ecc4d80
RR
2723 dh += scroll_class->scrollbar_spacing;
2724 }
6a008b33 2725 }
47d67540 2726
1ecc4d80
RR
2727 if (width) (*width) = m_width - dw;
2728 if (height) (*height) = m_height - dh;
2729 }
362c6693 2730}
c801d85f 2731
f03fc89f 2732void wxWindow::DoGetPosition( int *x, int *y ) const
c801d85f 2733{
223d09f6 2734 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2735
bf0c00c6
RR
2736 int dx = 0;
2737 int dy = 0;
2738 if (m_parent && m_parent->m_wxwindow)
2739 {
da048e3d 2740 GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
b02da6b1
VZ
2741 dx = pizza->xoffset;
2742 dy = pizza->yoffset;
bf0c00c6
RR
2743 }
2744
2745 if (x) (*x) = m_x - dx;
2746 if (y) (*y) = m_y - dy;
362c6693 2747}
c801d85f 2748
dabc0cd5 2749void wxWindow::DoClientToScreen( int *x, int *y ) const
c801d85f 2750{
223d09f6 2751 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2752
a2053b27
RR
2753 if (!m_widget->window) return;
2754
43a18898
RR
2755 GdkWindow *source = (GdkWindow *) NULL;
2756 if (m_wxwindow)
da048e3d 2757 source = GTK_PIZZA(m_wxwindow)->bin_window;
43a18898
RR
2758 else
2759 source = m_widget->window;
47d67540 2760
43a18898
RR
2761 int org_x = 0;
2762 int org_y = 0;
2763 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2764
43a18898 2765 if (!m_wxwindow)
c801d85f 2766 {
43a18898
RR
2767 if (GTK_WIDGET_NO_WINDOW (m_widget))
2768 {
2769 org_x += m_widget->allocation.x;
2770 org_y += m_widget->allocation.y;
2771 }
362c6693 2772 }
47d67540 2773
43a18898
RR
2774 if (x) *x += org_x;
2775 if (y) *y += org_y;
362c6693 2776}
c801d85f 2777
dabc0cd5 2778void wxWindow::DoScreenToClient( int *x, int *y ) const
c801d85f 2779{
223d09f6 2780 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2781
a2053b27
RR
2782 if (!m_widget->window) return;
2783
1ecc4d80
RR
2784 GdkWindow *source = (GdkWindow *) NULL;
2785 if (m_wxwindow)
da048e3d 2786 source = GTK_PIZZA(m_wxwindow)->bin_window;
1ecc4d80
RR
2787 else
2788 source = m_widget->window;
47d67540 2789
1ecc4d80
RR
2790 int org_x = 0;
2791 int org_y = 0;
2792 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2793
1ecc4d80 2794 if (!m_wxwindow)
c801d85f 2795 {
1ecc4d80
RR
2796 if (GTK_WIDGET_NO_WINDOW (m_widget))
2797 {
2798 org_x += m_widget->allocation.x;
2799 org_y += m_widget->allocation.y;
2800 }
362c6693 2801 }
47d67540 2802
1ecc4d80
RR
2803 if (x) *x -= org_x;
2804 if (y) *y -= org_y;
362c6693 2805}
c801d85f 2806
f03fc89f 2807bool wxWindow::Show( bool show )
c801d85f 2808{
223d09f6 2809 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
47d67540 2810
739730ca
RR
2811 if (!wxWindowBase::Show(show))
2812 {
2813 // nothing to do
f03fc89f 2814 return FALSE;
739730ca 2815 }
8bbe427f 2816
f03fc89f
VZ
2817 if (show)
2818 gtk_widget_show( m_widget );
1ecc4d80 2819 else
f03fc89f 2820 gtk_widget_hide( m_widget );
8bbe427f 2821
f03fc89f 2822 return TRUE;
362c6693 2823}
c801d85f 2824
f03fc89f 2825bool wxWindow::Enable( bool enable )
c801d85f 2826{
223d09f6 2827 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
5e0aa05a 2828
739730ca
RR
2829 if (!wxWindowBase::Enable(enable))
2830 {
2831 // nothing to do
f03fc89f 2832 return FALSE;
739730ca 2833 }
1ecc4d80 2834
f03fc89f
VZ
2835 gtk_widget_set_sensitive( m_widget, enable );
2836 if ( m_wxwindow )
2837 gtk_widget_set_sensitive( m_wxwindow, enable );
ff8bfdbb 2838
f03fc89f 2839 return TRUE;
362c6693 2840}
c801d85f 2841
f03fc89f 2842int wxWindow::GetCharHeight() const
2f2aa628 2843{
223d09f6 2844 wxCHECK_MSG( (m_widget != NULL), 12, wxT("invalid window") );
47d67540 2845
223d09f6 2846 wxCHECK_MSG( m_font.Ok(), 12, wxT("invalid font") );
2f2aa628 2847
f03fc89f
VZ
2848 GdkFont *font = m_font.GetInternalFont( 1.0 );
2849
2850 return font->ascent + font->descent;
362c6693 2851}
c801d85f 2852
f03fc89f 2853int wxWindow::GetCharWidth() const
c33c4050 2854{
223d09f6 2855 wxCHECK_MSG( (m_widget != NULL), 8, wxT("invalid window") );
47d67540 2856
223d09f6 2857 wxCHECK_MSG( m_font.Ok(), 8, wxT("invalid font") );
47d67540 2858
463c1fa1 2859 GdkFont *font = m_font.GetInternalFont( 1.0 );
ff8bfdbb 2860
463c1fa1 2861 return gdk_string_width( font, "H" );
c33c4050
RR
2862}
2863
f03fc89f
VZ
2864void wxWindow::GetTextExtent( const wxString& string,
2865 int *x,
2866 int *y,
2867 int *descent,
2868 int *externalLeading,
2869 const wxFont *theFont ) const
c33c4050 2870{
463c1fa1
RR
2871 wxFont fontToUse = m_font;
2872 if (theFont) fontToUse = *theFont;
47d67540 2873
223d09f6 2874 wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
47d67540 2875
463c1fa1 2876 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
05939a81 2877 if (x) (*x) = gdk_string_width( font, string.mbc_str() );
463c1fa1
RR
2878 if (y) (*y) = font->ascent + font->descent;
2879 if (descent) (*descent) = font->descent;
2880 if (externalLeading) (*externalLeading) = 0; // ??
c33c4050
RR
2881}
2882
68dda785 2883void wxWindow::SetFocus()
c801d85f 2884{
223d09f6 2885 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2daa0ce9 2886
354aa1e3
RR
2887 if (m_wxwindow)
2888 {
173348db
RR
2889 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow))
2890 gtk_widget_grab_focus (m_wxwindow);
354aa1e3
RR
2891 return;
2892 }
2893
2894 if (m_widget)
c801d85f 2895 {
173348db 2896 if (GTK_WIDGET_CAN_FOCUS(m_widget) && !GTK_WIDGET_HAS_FOCUS (m_widget) )
463c1fa1 2897 {
354aa1e3 2898 gtk_widget_grab_focus (m_widget);
463c1fa1 2899 }
354aa1e3 2900 else if (GTK_IS_CONTAINER(m_widget))
ff8bfdbb 2901 {
354aa1e3 2902 gtk_container_focus( GTK_CONTAINER(m_widget), GTK_DIR_TAB_FORWARD );
ff8bfdbb
VZ
2903 }
2904 else
2905 {
b02da6b1 2906 // ?
ff8bfdbb 2907 }
362c6693 2908 }
362c6693 2909}
c801d85f 2910
b292e2f5
RR
2911bool wxWindow::AcceptsFocus() const
2912{
f03fc89f 2913 return m_acceptsFocus && wxWindowBase::AcceptsFocus();
b292e2f5
RR
2914}
2915
fdb7dadb 2916bool wxWindow::Reparent( wxWindowBase *newParentBase )
463c1fa1 2917{
223d09f6 2918 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
c50f1fb9 2919
fdb7dadb
VZ
2920 wxWindow *oldParent = m_parent,
2921 *newParent = (wxWindow *)newParentBase;
a2053b27 2922
5fd11f09
RR
2923 wxASSERT( GTK_IS_WIDGET(m_widget) );
2924
f03fc89f
VZ
2925 if ( !wxWindowBase::Reparent(newParent) )
2926 return FALSE;
8bbe427f 2927
5fd11f09
RR
2928 wxASSERT( GTK_IS_WIDGET(m_widget) );
2929
2930 /* prevent GTK from deleting the widget arbitrarily */
2931 gtk_widget_ref( m_widget );
2932
8ce63e9d
RR
2933 if (oldParent)
2934 {
3017f78d 2935 gtk_container_remove( GTK_CONTAINER(m_widget->parent), m_widget );
8ce63e9d 2936 }
c50f1fb9 2937
5fd11f09
RR
2938 wxASSERT( GTK_IS_WIDGET(m_widget) );
2939
8ce63e9d
RR
2940 if (newParent)
2941 {
2942 /* insert GTK representation */
2943 (*(newParent->m_insertCallback))(newParent, this);
2944 }
c50f1fb9 2945
5fd11f09
RR
2946 /* reverse: prevent GTK from deleting the widget arbitrarily */
2947 gtk_widget_unref( m_widget );
148cd9b6 2948
f03fc89f 2949 return TRUE;
362c6693 2950}
c801d85f 2951
c50f1fb9 2952void wxWindow::DoAddChild(wxWindow *child)
ddb6bc71 2953{
223d09f6 2954 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
ddb6bc71 2955
223d09f6 2956 wxASSERT_MSG( (child != NULL), wxT("invalid child window") );
ddb6bc71 2957
223d09f6 2958 wxASSERT_MSG( (m_insertCallback != NULL), wxT("invalid child insertion function") );
c50f1fb9 2959
ddb6bc71
RR
2960 /* add to list */
2961 AddChild( child );
c50f1fb9 2962
ddb6bc71
RR
2963 /* insert GTK representation */
2964 (*m_insertCallback)(this, child);
2965}
2966
68dda785 2967void wxWindow::Raise()
362c6693 2968{
223d09f6 2969 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2970
a2053b27
RR
2971 if (!m_widget->window) return;
2972
f03fc89f 2973 gdk_window_raise( m_widget->window );
362c6693
RR
2974}
2975
68dda785 2976void wxWindow::Lower()
362c6693 2977{
223d09f6 2978 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2979
a2053b27
RR
2980 if (!m_widget->window) return;
2981
f03fc89f 2982 gdk_window_lower( m_widget->window );
362c6693 2983}
c801d85f 2984
f03fc89f 2985bool wxWindow::SetCursor( const wxCursor &cursor )
86b29a61 2986{
223d09f6 2987 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
86b29a61 2988
5e014a0c 2989 return wxWindowBase::SetCursor( cursor );
362c6693 2990}
c801d85f 2991
85eb36c2 2992void wxWindow::WarpPointer( int x, int y )
4f22cf8d 2993{
223d09f6 2994 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
85eb36c2 2995
ed673c6a
RR
2996 /* we provide this function ourselves as it is
2997 missing in GDK (top of this file) */
148cd9b6 2998
ed673c6a
RR
2999 GdkWindow *window = (GdkWindow*) NULL;
3000 if (m_wxwindow)
da048e3d 3001 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3002 else
3003 window = GetConnectWidget()->window;
148cd9b6 3004
ed673c6a
RR
3005 if (window)
3006 gdk_window_warp_pointer( window, x, y );
4f22cf8d
RR
3007}
3008
debe6624 3009void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
c801d85f 3010{
f2593d0d 3011 if (!m_widget) return;
a2053b27
RR
3012 if (!m_widget->window) return;
3013
139adb6a 3014 if (eraseBackground && m_wxwindow && m_wxwindow->window)
c801d85f 3015 {
139adb6a
RR
3016 if (rect)
3017 {
da048e3d 3018 gdk_window_clear_area( GTK_PIZZA(m_wxwindow)->bin_window,
139adb6a 3019 rect->x, rect->y,
f234c60c 3020 rect->width, rect->height );
139adb6a
RR
3021 }
3022 else
3023 {
da048e3d 3024 gdk_window_clear( GTK_PIZZA(m_wxwindow)->bin_window );
139adb6a
RR
3025 }
3026 }
ff8bfdbb 3027
1b68e0b5 3028 /* there is no GTK equivalent of "draw only, don't clear" so we
da048e3d 3029 invent our own in the GtkPizza widget */
1b68e0b5 3030
139adb6a
RR
3031 if (!rect)
3032 {
3033 if (m_wxwindow)
b02da6b1 3034 {
b6fa52db
RR
3035
3036/*
b02da6b1
VZ
3037 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3038 gboolean old_clear = pizza->clear_on_draw;
3039 gtk_pizza_set_clear( pizza, FALSE );
1b68e0b5 3040 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
b02da6b1 3041 gtk_pizza_set_clear( pizza, old_clear );
b6fa52db
RR
3042*/
3043 GdkEventExpose gdk_event;
b4bee866
RR
3044 gdk_event.type = GDK_EXPOSE;
3045 gdk_event.window = GTK_PIZZA(m_wxwindow)->bin_window;
b6fa52db
RR
3046 gdk_event.count = 0;
3047 gdk_event.area.x = 0;
3048 gdk_event.area.y = 0;
3049 gdk_event.area.width = m_wxwindow->allocation.width;
3050 gdk_event.area.height = m_wxwindow->allocation.height;
3051 gtk_window_expose_callback( m_wxwindow, &gdk_event, this );
3052
b02da6b1 3053 }
ff8bfdbb 3054 else
b6fa52db 3055 {
139adb6a 3056 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
b6fa52db 3057 }
362c6693 3058 }
c801d85f 3059 else
139adb6a 3060 {
139adb6a
RR
3061
3062 if (m_wxwindow)
b02da6b1 3063 {
b6fa52db 3064/*
b02da6b1
VZ
3065 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3066 gboolean old_clear = pizza->clear_on_draw;
3067 gtk_pizza_set_clear( pizza, FALSE );
148cd9b6 3068
b6fa52db
RR
3069 GdkRectangle gdk_rect;
3070 gdk_rect.x = rect->x;
3071 gdk_rect.y = rect->y;
3072 gdk_rect.width = rect->width;
3073 gdk_rect.height = rect->height;
1b68e0b5 3074 gtk_widget_draw( m_wxwindow, &gdk_rect );
b6fa52db 3075 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
148cd9b6 3076
b02da6b1 3077 gtk_pizza_set_clear( pizza, old_clear );
b6fa52db
RR
3078*/
3079 GdkEventExpose gdk_event;
b4bee866
RR
3080 gdk_event.type = GDK_EXPOSE;
3081 gdk_event.window = GTK_PIZZA(m_wxwindow)->bin_window;
b6fa52db
RR
3082 gdk_event.count = 0;
3083 gdk_event.area.x = rect->x;
3084 gdk_event.area.y = rect->y;
3085 gdk_event.area.width = rect->width;
3086 gdk_event.area.height = rect->height;
3087 gtk_window_expose_callback( m_wxwindow, &gdk_event, this );
b02da6b1 3088 }
139adb6a 3089 else
b6fa52db
RR
3090 {
3091 GdkRectangle gdk_rect;
3092 gdk_rect.x = rect->x;
3093 gdk_rect.y = rect->y;
3094 gdk_rect.width = rect->width;
3095 gdk_rect.height = rect->height;
139adb6a 3096 gtk_widget_draw( m_widget, &gdk_rect );
b6fa52db 3097 }
139adb6a 3098 }
362c6693 3099}
c801d85f 3100
68dda785 3101void wxWindow::Clear()
c801d85f 3102{
223d09f6 3103 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3104
a2053b27
RR
3105 if (!m_widget->window) return;
3106
f234c60c
RR
3107 if (m_wxwindow && m_wxwindow->window)
3108 {
c916e13b 3109// gdk_window_clear( m_wxwindow->window );
f234c60c 3110 }
362c6693 3111}
c801d85f 3112
ff8bfdbb 3113#if wxUSE_TOOLTIPS
f03fc89f 3114void wxWindow::DoSetToolTip( wxToolTip *tip )
b1170810 3115{
f03fc89f 3116 wxWindowBase::DoSetToolTip(tip);
ff8bfdbb 3117
f03fc89f
VZ
3118 if (m_tooltip)
3119 m_tooltip->Apply( this );
b1170810
RR
3120}
3121
05939a81 3122void wxWindow::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
b1170810 3123{
dcf924a3 3124 gtk_tooltips_set_tip( tips, GetConnectWidget(), wxConvCurrent->cWX2MB(tip), (gchar*) NULL );
301cd871 3125}
ff8bfdbb 3126#endif // wxUSE_TOOLTIPS
b1170810 3127
f03fc89f 3128bool wxWindow::SetBackgroundColour( const wxColour &colour )
c801d85f 3129{
223d09f6 3130 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
8bbe427f 3131
739730ca
RR
3132 if (!wxWindowBase::SetBackgroundColour(colour))
3133 {
3134 // don't leave if the GTK widget has just
3135 // been realized
3136 if (!m_delayedBackgroundColour) return FALSE;
3137 }
c50f1fb9 3138
ed673c6a
RR
3139 GdkWindow *window = (GdkWindow*) NULL;
3140 if (m_wxwindow)
da048e3d 3141 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3142 else
3143 window = GetConnectWidget()->window;
148cd9b6 3144
ed673c6a 3145 if (!window)
739730ca
RR
3146 {
3147 // indicate that a new style has been set
c50f1fb9
VZ
3148 // but it couldn't get applied as the
3149 // widget hasn't been realized yet.
3150 m_delayedBackgroundColour = TRUE;
739730ca 3151 }
ca298c88 3152
0f2f4986 3153 if ((m_wxwindow) &&
103aab26 3154 (m_wxwindow->window) &&
0f2f4986 3155 (m_backgroundColour != wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE)))
3bc755fc 3156 {
a2053b27
RR
3157 /* wxMSW doesn't clear the window here. I don't do that either to
3158 provide compatibility. call Clear() to do the job. */
ca298c88 3159
ed673c6a
RR
3160 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
3161 gdk_window_set_background( window, m_backgroundColour.GetColor() );
3bc755fc 3162 }
8bbe427f 3163
0f2f4986 3164 ApplyWidgetStyle();
c801d85f 3165
f03fc89f 3166 return TRUE;
6de97a3b
RR
3167}
3168
f03fc89f 3169bool wxWindow::SetForegroundColour( const wxColour &colour )
6de97a3b 3170{
223d09f6 3171 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
8bbe427f 3172
739730ca
RR
3173 if (!wxWindowBase::SetForegroundColour(colour))
3174 {
3175 // don't leave if the GTK widget has just
3176 // been realized
3177 if (!m_delayedForegroundColour) return FALSE;
3178 }
c50f1fb9 3179
ed673c6a
RR
3180 GdkWindow *window = (GdkWindow*) NULL;
3181 if (m_wxwindow)
da048e3d 3182 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3183 else
3184 window = GetConnectWidget()->window;
148cd9b6 3185
ed673c6a 3186 if (!window)
739730ca
RR
3187 {
3188 // indicate that a new style has been set
c50f1fb9
VZ
3189 // but it couldn't get applied as the
3190 // widget hasn't been realized yet.
3191 m_delayedForegroundColour = TRUE;
739730ca 3192 }
2b07d713 3193
0f2f4986 3194 ApplyWidgetStyle();
f03fc89f
VZ
3195
3196 return TRUE;
58614078
RR
3197}
3198
3199GtkStyle *wxWindow::GetWidgetStyle()
3200{
103aab26
RR
3201 if (m_widgetStyle)
3202 {
3203 GtkStyle *remake = gtk_style_copy( m_widgetStyle );
3204 remake->klass = m_widgetStyle->klass;
2daa0ce9 3205
103aab26
RR
3206 gtk_style_unref( m_widgetStyle );
3207 m_widgetStyle = remake;
3208 }
3209 else
3210 {
3211 GtkStyle *def = gtk_rc_get_style( m_widget );
e6527f9d 3212
103aab26
RR
3213 if (!def)
3214 def = gtk_widget_get_default_style();
e6527f9d 3215
103aab26
RR
3216 m_widgetStyle = gtk_style_copy( def );
3217 m_widgetStyle->klass = def->klass;
3218 }
8bbe427f 3219
1ecc4d80 3220 return m_widgetStyle;
58614078
RR
3221}
3222
3223void wxWindow::SetWidgetStyle()
3224{
a56fcaaf 3225#if DISABLE_STYLE_IF_BROKEN_THEM
fb65642c
RR
3226 if (m_widget->style->engine_data)
3227 {
3228 static bool s_warningPrinted = FALSE;
3229 if (!s_warningPrinted)
3230 {
3231 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3232 s_warningPrinted = TRUE;
3233 }
3234 m_widgetStyle = m_widget->style;
3235 return;
3236 }
a56fcaaf 3237#endif
fb65642c 3238
1ecc4d80
RR
3239 GtkStyle *style = GetWidgetStyle();
3240
db434467
RR
3241 if (m_font != wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT ))
3242 {
3243 gdk_font_unref( style->font );
3244 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
3245 }
1ecc4d80
RR
3246
3247 if (m_foregroundColour.Ok())
3248 {
454e2a22 3249 m_foregroundColour.CalcPixel( gtk_widget_get_colormap( m_widget ) );
db434467
RR
3250 if (m_foregroundColour != wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT))
3251 {
3252 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
3253 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
3254 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
3255 }
1ecc4d80
RR
3256 }
3257
3258 if (m_backgroundColour.Ok())
3259 {
454e2a22 3260 m_backgroundColour.CalcPixel( gtk_widget_get_colormap( m_widget ) );
db434467
RR
3261 if (m_backgroundColour != wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE))
3262 {
3263 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
3264 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
3265 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
3266 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
3267 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
3268 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
3269 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
3270 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
3271 }
1ecc4d80 3272 }
a81258be
RR
3273}
3274
58614078 3275void wxWindow::ApplyWidgetStyle()
a81258be 3276{
6de97a3b
RR
3277}
3278
2259e007
RR
3279//-----------------------------------------------------------------------------
3280// Pop-up menu stuff
3281//-----------------------------------------------------------------------------
3282
3283static void gtk_pop_hide_callback( GtkWidget *WXUNUSED(widget), bool* is_waiting )
3284{
3285 *is_waiting = FALSE;
3286}
3287
30dea054
RR
3288static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
3289{
1ecc4d80 3290 menu->SetInvokingWindow( win );
1987af7e 3291 wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
1ecc4d80
RR
3292 while (node)
3293 {
1987af7e 3294 wxMenuItem *menuitem = node->GetData();
1ecc4d80
RR
3295 if (menuitem->IsSubMenu())
3296 {
ff8bfdbb
VZ
3297 SetInvokingWindow( menuitem->GetSubMenu(), win );
3298 }
1987af7e
VZ
3299
3300 node = node->GetNext();
1ecc4d80 3301 }
362c6693 3302}
30dea054 3303
0c77152e
RR
3304static gint gs_pop_x = 0;
3305static gint gs_pop_y = 0;
3306
a234a61a
VZ
3307static void pop_pos_callback( GtkMenu * WXUNUSED(menu),
3308 gint *x, gint *y,
3309 wxWindow *win )
0c77152e
RR
3310{
3311 win->ClientToScreen( &gs_pop_x, &gs_pop_y );
3312 *x = gs_pop_x;
3313 *y = gs_pop_y;
3314}
3315
a1665b22 3316bool wxWindow::DoPopupMenu( wxMenu *menu, int x, int y )
30dea054 3317{
223d09f6 3318 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
47d67540 3319
223d09f6 3320 wxCHECK_MSG( menu != NULL, FALSE, wxT("invalid popup-menu") );
8bbe427f 3321
1ecc4d80 3322 SetInvokingWindow( menu, this );
ff8bfdbb 3323
631f1bfe
JS
3324 menu->UpdateUI();
3325
0c77152e
RR
3326 gs_pop_x = x;
3327 gs_pop_y = y;
ff8bfdbb 3328
2259e007 3329 bool is_waiting = TRUE;
148cd9b6 3330
2259e007
RR
3331 gtk_signal_connect( GTK_OBJECT(menu->m_menu), "hide",
3332 GTK_SIGNAL_FUNC(gtk_pop_hide_callback), (gpointer)&is_waiting );
3333
1ecc4d80 3334 gtk_menu_popup(
47d67540 3335 GTK_MENU(menu->m_menu),
0c77152e
RR
3336 (GtkWidget *) NULL, // parent menu shell
3337 (GtkWidget *) NULL, // parent menu item
3338 (GtkMenuPositionFunc) pop_pos_callback,
3339 (gpointer) this, // client data
3340 0, // button used to activate it
54517652 3341 gs_timeLastClick // the time of activation
47d67540 3342 );
148cd9b6 3343
956dbab1
RR
3344 while (is_waiting)
3345 {
3346 while (gtk_events_pending())
3347 gtk_main_iteration();
3348 }
2259e007 3349
1ecc4d80 3350 return TRUE;
30dea054
RR
3351}
3352
06cfab17 3353#if wxUSE_DRAG_AND_DROP
ac57418f 3354
c801d85f
KB
3355void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
3356{
223d09f6 3357 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3358
1ecc4d80 3359 GtkWidget *dnd_widget = GetConnectWidget();
47d67540 3360
1ecc4d80 3361 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
47d67540 3362
1ecc4d80
RR
3363 if (m_dropTarget) delete m_dropTarget;
3364 m_dropTarget = dropTarget;
47d67540 3365
1ecc4d80 3366 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
362c6693 3367}
c801d85f 3368
f03fc89f 3369#endif // wxUSE_DRAG_AND_DROP
ac57418f 3370
68dda785 3371GtkWidget* wxWindow::GetConnectWidget()
e3e65dac 3372{
1ecc4d80
RR
3373 GtkWidget *connect_widget = m_widget;
3374 if (m_wxwindow) connect_widget = m_wxwindow;
47d67540 3375
1ecc4d80 3376 return connect_widget;
e3e65dac 3377}
47d67540 3378
903f689b
RR
3379bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
3380{
148cd9b6 3381 if (m_wxwindow)
da048e3d 3382 return (window == GTK_PIZZA(m_wxwindow)->bin_window);
148cd9b6 3383
1ecc4d80 3384 return (window == m_widget->window);
903f689b
RR
3385}
3386
f03fc89f 3387bool wxWindow::SetFont( const wxFont &font )
c801d85f 3388{
223d09f6 3389 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
c801d85f 3390
739730ca
RR
3391 if (!wxWindowBase::SetFont(font))
3392 {
454e2a22 3393 return FALSE;
739730ca 3394 }
9c288e4d 3395
ae0bdb01 3396 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
f03fc89f 3397 if ( sysbg == m_backgroundColour )
ae0bdb01
RR
3398 {
3399 m_backgroundColour = wxNullColour;
3400 ApplyWidgetStyle();
ff8bfdbb
VZ
3401 m_backgroundColour = sysbg;
3402 }
ae0bdb01
RR
3403 else
3404 {
3405 ApplyWidgetStyle();
3406 }
c801d85f 3407
f03fc89f 3408 return TRUE;
362c6693 3409}
c801d85f 3410
68dda785 3411void wxWindow::CaptureMouse()
c801d85f 3412{
223d09f6 3413 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3414
223d09f6 3415 wxCHECK_RET( g_captureWindow == NULL, wxT("CaptureMouse called twice") );
47d67540 3416
ed673c6a
RR
3417 GdkWindow *window = (GdkWindow*) NULL;
3418 if (m_wxwindow)
da048e3d 3419 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3420 else
3421 window = GetConnectWidget()->window;
148cd9b6 3422
ed673c6a 3423 if (!window) return;
c50f1fb9 3424
cca602ac
JS
3425 wxCursor* cursor = & m_cursor;
3426 if (!cursor->Ok())
3427 cursor = wxSTANDARD_CURSOR;
3428
ed673c6a 3429 gdk_pointer_grab( window, FALSE,
1ecc4d80
RR
3430 (GdkEventMask)
3431 (GDK_BUTTON_PRESS_MASK |
3432 GDK_BUTTON_RELEASE_MASK |
148cd9b6 3433 GDK_POINTER_MOTION_HINT_MASK |
1ecc4d80 3434 GDK_POINTER_MOTION_MASK),
ff8bfdbb 3435 (GdkWindow *) NULL,
cca602ac 3436 cursor->GetCursor(),
b02da6b1 3437 (guint32)GDK_CURRENT_TIME );
72195a0f 3438 g_captureWindow = this;
362c6693 3439}
c801d85f 3440
68dda785 3441void wxWindow::ReleaseMouse()
c801d85f 3442{
223d09f6 3443 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3444
223d09f6 3445 wxCHECK_RET( g_captureWindow, wxT("ReleaseMouse called twice") );
47d67540 3446
ed673c6a
RR
3447 GdkWindow *window = (GdkWindow*) NULL;
3448 if (m_wxwindow)
da048e3d 3449 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3450 else
3451 window = GetConnectWidget()->window;
148cd9b6 3452
b02da6b1
VZ
3453 if (!window)
3454 return;
c50f1fb9 3455
b02da6b1 3456 gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME );
72195a0f 3457 g_captureWindow = (wxWindow*) NULL;
362c6693 3458}
c801d85f 3459
f03fc89f 3460bool wxWindow::IsRetained() const
c801d85f 3461{
1ecc4d80 3462 return FALSE;
362c6693 3463}
c801d85f 3464
debe6624 3465void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
cb43b372 3466 int range, bool refresh )
c801d85f 3467{
223d09f6 3468 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
8bbe427f 3469
223d09f6 3470 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
c801d85f 3471
1ecc4d80 3472 m_hasScrolling = TRUE;
47d67540 3473
1ecc4d80 3474 if (orient == wxHORIZONTAL)
cb43b372 3475 {
1ecc4d80
RR
3476 float fpos = (float)pos;
3477 float frange = (float)range;
3478 float fthumb = (float)thumbVisible;
3479 if (fpos > frange-fthumb) fpos = frange-fthumb;
3480 if (fpos < 0.0) fpos = 0.0;
3481
3482 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
3483 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
3484 {
3485 SetScrollPos( orient, pos, refresh );
3486 return;
3487 }
47d67540 3488
1ecc4d80 3489 m_oldHorizontalPos = fpos;
47d67540 3490
1ecc4d80
RR
3491 m_hAdjust->lower = 0.0;
3492 m_hAdjust->upper = frange;
3493 m_hAdjust->value = fpos;
3494 m_hAdjust->step_increment = 1.0;
3495 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
3496 m_hAdjust->page_size = fthumb;
cb43b372 3497 }
1ecc4d80
RR
3498 else
3499 {
3500 float fpos = (float)pos;
3501 float frange = (float)range;
3502 float fthumb = (float)thumbVisible;
3503 if (fpos > frange-fthumb) fpos = frange-fthumb;
3504 if (fpos < 0.0) fpos = 0.0;
3505
3506 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
3507 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
3508 {
3509 SetScrollPos( orient, pos, refresh );
3510 return;
3511 }
47d67540 3512
1ecc4d80 3513 m_oldVerticalPos = fpos;
47d67540 3514
1ecc4d80
RR
3515 m_vAdjust->lower = 0.0;
3516 m_vAdjust->upper = frange;
3517 m_vAdjust->value = fpos;
3518 m_vAdjust->step_increment = 1.0;
3519 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
3520 m_vAdjust->page_size = fthumb;
3521 }
47d67540 3522
eb082a08
RR
3523 if (orient == wxHORIZONTAL)
3524 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
3525 else
3526 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
362c6693 3527}
c801d85f 3528
debe6624 3529void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
c801d85f 3530{
223d09f6 3531 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
1ecc4d80 3532
223d09f6 3533 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
1ecc4d80
RR
3534
3535 if (orient == wxHORIZONTAL)
3536 {
3537 float fpos = (float)pos;
3538 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
3539 if (fpos < 0.0) fpos = 0.0;
3540 m_oldHorizontalPos = fpos;
3541
3542 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
3543 m_hAdjust->value = fpos;
3544 }
3545 else
3546 {
3547 float fpos = (float)pos;
3548 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
3549 if (fpos < 0.0) fpos = 0.0;
3550 m_oldVerticalPos = fpos;
ff8bfdbb 3551
1ecc4d80
RR
3552 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
3553 m_vAdjust->value = fpos;
3554 }
47d67540 3555
5b8a521e 3556 if (m_wxwindow->window)
47d67540 3557 {
5b8a521e 3558 if (orient == wxHORIZONTAL)
473d087e
RR
3559 {
3560 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust),
3561 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
2daa0ce9 3562
5b8a521e 3563 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2daa0ce9 3564
473d087e
RR
3565 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
3566 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
3567 }
5b8a521e 3568 else
473d087e
RR
3569 {
3570 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust),
3571 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
2daa0ce9 3572
5b8a521e 3573 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
473d087e
RR
3574
3575 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
3576 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
3577 }
cb43b372 3578 }
362c6693 3579}
c801d85f 3580
debe6624 3581int wxWindow::GetScrollThumb( int orient ) const
c801d85f 3582{
223d09f6 3583 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 3584
223d09f6 3585 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
47d67540 3586
1ecc4d80
RR
3587 if (orient == wxHORIZONTAL)
3588 return (int)(m_hAdjust->page_size+0.5);
3589 else
3590 return (int)(m_vAdjust->page_size+0.5);
362c6693 3591}
c801d85f 3592
debe6624 3593int wxWindow::GetScrollPos( int orient ) const
c801d85f 3594{
223d09f6 3595 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 3596
223d09f6 3597 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
c801d85f 3598
1ecc4d80
RR
3599 if (orient == wxHORIZONTAL)
3600 return (int)(m_hAdjust->value+0.5);
3601 else
3602 return (int)(m_vAdjust->value+0.5);
362c6693 3603}
c801d85f 3604
debe6624 3605int wxWindow::GetScrollRange( int orient ) const
c801d85f 3606{
223d09f6 3607 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 3608
223d09f6 3609 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
c801d85f 3610
1ecc4d80
RR
3611 if (orient == wxHORIZONTAL)
3612 return (int)(m_hAdjust->upper+0.5);
3613 else
3614 return (int)(m_vAdjust->upper+0.5);
362c6693 3615}
c801d85f 3616
debe6624 3617void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
c801d85f 3618{
223d09f6 3619 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3620
223d09f6 3621 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
8e217128
RR
3622
3623 if ((dx == 0) && (dy == 0)) return;
c801d85f 3624
b6fa52db 3625 m_clipPaintRegion = TRUE;
da048e3d 3626 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
b6fa52db 3627 m_clipPaintRegion = FALSE;
8e217128
RR
3628
3629/*
3630 if (m_children.GetCount() > 0)
3631 {
3632 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3633 }
3634 else
3635 {
3636 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3637
3638 pizza->xoffset -= dx;
3639 pizza->yoffset -= dy;
3640
3641 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3642 gdk_gc_set_exposures( m_scrollGC, TRUE );
3643
3644 int cw = 0;
3645 int ch = 0;
3646 GetClientSize( &cw, &ch );
3647 int w = cw - abs(dx);
3648 int h = ch - abs(dy);
3649
3650 if ((h < 0) || (w < 0))
3651 {
3652 Refresh();
3653 }
3654 else
3655 {
3656 int s_x = 0;
3657 int s_y = 0;
3658 if (dx < 0) s_x = -dx;
3659 if (dy < 0) s_y = -dy;
3660 int d_x = 0;
3661 int d_y = 0;
3662 if (dx > 0) d_x = dx;
3663 if (dy > 0) d_y = dy;
3664
3665 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3666 pizza->bin_window, s_x, s_y, w, h );
3667
3668 wxRect rect;
3669 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3670 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3671 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3672 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3673
3674 Refresh( TRUE, &rect );
3675 }
3676
3677 gdk_gc_unref( m_scrollGC );
3678 }
3679*/
c801d85f 3680}