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