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