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