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