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