]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/window.cpp
compilation fixes for gcc 2.7.2.1 under FreeBSD
[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__
12#pragma implementation "window.h"
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"
06cfab17 24#if wxUSE_DRAG_AND_DROP
c801d85f 25#include "wx/dnd.h"
ac57418f 26#endif
cad880f5 27#if wxUSE_TOOLTIPS
b1170810 28#include "wx/tooltip.h"
cad880f5 29#endif
30dea054 30#include "wx/menu.h"
d4c99d6f 31#include "wx/statusbr.h"
b4071e91 32#include "wx/intl.h"
3bc755fc 33#include "wx/settings.h"
3069ac4e 34#include "wx/log.h"
b4071e91
RR
35
36#include <math.h>
c801d85f 37
83624f79
RR
38#include "gdk/gdk.h"
39#include "gtk/gtk.h"
40#include "gdk/gdkprivate.h"
41#include "gdk/gdkkeysyms.h"
42#include "wx/gtk/win_gtk.h"
43
868a2826
RR
44//-----------------------------------------------------------------------------
45// documentation on internals
46//-----------------------------------------------------------------------------
47
48/*
49 I have been asked several times about writing some documentation about
50 the GTK port of wxWindows, especially its internal structures. Obviously,
51 you cannot understand wxGTK without knowing a little about the GTK, but
47d67540 52 some more information about what the wxWindow, which is the base class
868a2826 53 for all other window classes, does seems required as well.
47d67540 54
868a2826 55 What does wxWindow do? It contains the common interface for the following
e380f72b 56 jobs of its descendants:
47d67540 57
868a2826 58 1) Define the rudimentary behaviour common to all window classes, such as
e380f72b
RR
59 resizing, intercepting user input (so as to make it possible to use these
60 events for special purposes in a derived class), window names etc.
868a2826
RR
61
62 2) Provide the possibility to contain and manage children, if the derived
63 class is allowed to contain children, which holds true for those window
e380f72b 64 classes which do not display a native GTK widget. To name them, these
868a2826 65 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
47d67540 66 work classes are a special case and are handled a bit differently from
e380f72b 67 the rest. The same holds true for the wxNotebook class.
47d67540 68
868a2826
RR
69 3) Provide the possibility to draw into a client area of a window. This,
70 too, only holds true for classes that do not display a native GTK widget
71 as above.
47d67540 72
e380f72b
RR
73 4) Provide the entire mechanism for scrolling widgets. This actual inter-
74 face for this is usually in wxScrolledWindow, but the GTK implementation
868a2826 75 is in this class.
47d67540 76
868a2826
RR
77 5) A multitude of helper or extra methods for special purposes, such as
78 Drag'n'Drop, managing validators etc.
47d67540 79
e380f72b
RR
80 Normally one might expect, that one wxWindows window would always correspond
81 to one GTK widget. Under GTK, there is no such allround widget that has all
868a2826
RR
82 the functionality. Moreover, the GTK defines a client area as a different
83 widget from the actual widget you are handling. Last but not least some
84 special classes (e.g. wxFrame) handle different categories of widgets and
85 still have the possibility to draw something in the client area.
86 It was therefore required to write a special purpose GTK widget, that would
87 represent a client area in the sense of wxWindows capable to do the jobs
88 2), 3) and 4). I have written this class and it resides in win_gtk.c of
89 this directory.
47d67540 90
868a2826 91 All windows must have a widget, with which they interact with other under-
e380f72b 92 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
868a2826 93 thw wxWindow class has a member variable called m_widget which holds a
e380f72b
RR
94 pointer to this widget. When the window class represents a GTK native widget,
95 this is (in most cases) the only GTK widget the class manages. E.g. the
96 wxStatitText class handles only a GtkLabel widget a pointer to which you
97 can find in m_widget (defined in wxWindow)
8bbe427f 98
e380f72b 99 When the class has a client area for drawing into and for containing children
8bbe427f
VZ
100 it has to handle the client area widget (of the type GtkMyFixed, defined in
101 win_gtk.c), but there could be any number of widgets, handled by a class
102 The common rule for all windows is only, that the widget that interacts with
103 the rest of GTK must be referenced in m_widget and all other widgets must be
104 children of this widget on the GTK level. The top-most widget, which also
105 represents the client area, must be in the m_wxwindow field and must be of
e380f72b 106 the type GtkMyFixed.
47d67540 107
868a2826
RR
108 As I said, the window classes that display a GTK native widget only have
109 one widget, so in the case of e.g. the wxButton class m_widget holds a
110 pointer to a GtkButton widget. But windows with client areas (for drawing
111 and children) have a m_widget field that is a pointer to a GtkScrolled-
112 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
113 one is (in the GTK sense) a child of the GtkScrolledWindow.
47d67540 114
868a2826
RR
115 If the m_wxwindow field is set, then all input to this widget is inter-
116 cepted and sent to the wxWindows class. If not, all input to the widget
117 that gets pointed to by m_widget gets intercepted and sent to the class.
118
119*/
120
38c7b3d3
RR
121//-------------------------------------------------------------------------
122// conditional compilation
123//-------------------------------------------------------------------------
124
125#if (GTK_MINOR_VERSION == 1)
126#if (GTK_MICRO_VERSION >= 5)
127#define NEW_GTK_SCROLL_CODE
128#endif
129#endif
130
b292e2f5
RR
131//-----------------------------------------------------------------------------
132// (debug)
133//-----------------------------------------------------------------------------
134
135#ifdef __WXDEBUG__
136
ff8bfdbb
VZ
137static gint gtk_debug_focus_in_callback( GtkWidget *WXUNUSED(widget),
138 GdkEvent *WXUNUSED(event),
139 const char *name )
b292e2f5
RR
140{
141 printf( "FOCUS NOW AT: " );
142 printf( name );
143 printf( "\n" );
ff8bfdbb 144
b292e2f5
RR
145 return FALSE;
146}
147
148void debug_focus_in( GtkWidget* widget, const char* name, const char *window )
149{
150 return;
151
152 wxString tmp = name;
153 tmp += " FROM ";
154 tmp += window;
ff8bfdbb 155
b292e2f5 156 char *s = new char[tmp.Length()+1];
ff8bfdbb 157
b292e2f5
RR
158 strcpy( s, WXSTRINGCAST tmp );
159
160 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
161 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback), (gpointer)s );
162}
163
164#endif
165
c801d85f
KB
166//-----------------------------------------------------------------------------
167// data
168//-----------------------------------------------------------------------------
169
b292e2f5
RR
170extern wxList wxPendingDelete;
171extern wxList wxTopLevelWindows;
172extern bool g_blockEventsOnDrag;
173extern bool g_blockEventsOnScroll;
174static bool g_capturing = FALSE;
175static wxWindow *g_focusWindow = (wxWindow*) NULL;
47d67540
VZ
176
177// hack: we need something to pass to gtk_menu_popup, so we store the time of
178// the last click here
179static guint32 gs_timeLastClick = 0;
c801d85f
KB
180
181//-----------------------------------------------------------------------------
2f2aa628 182// "expose_event" (of m_wxwindow, not of m_widget)
c801d85f
KB
183//-----------------------------------------------------------------------------
184
2f2aa628 185static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxWindow *win )
47d67540 186{
f5e27805 187 if (!win->HasVMT()) return;
47d67540 188
f5e27805
RR
189 win->m_updateRegion.Union( gdk_event->area.x,
190 gdk_event->area.y,
191 gdk_event->area.width,
192 gdk_event->area.height );
47d67540 193
f5e27805 194 if (gdk_event->count > 0) return;
c801d85f 195
d8c83875 196/*
f5e27805
RR
197 printf( "OnExpose from " );
198 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
199 printf( win->GetClassInfo()->GetClassName() );
200 printf( ".\n" );
d8c83875
RR
201*/
202
f5e27805
RR
203 wxPaintEvent event( win->GetId() );
204 event.SetEventObject( win );
205 win->GetEventHandler()->ProcessEvent( event );
47d67540 206
f5e27805 207 win->m_updateRegion.Clear();
362c6693 208}
c801d85f
KB
209
210//-----------------------------------------------------------------------------
2f2aa628
RR
211// "draw" (of m_wxwindow, not of m_widget)
212//-----------------------------------------------------------------------------
c801d85f 213
2f2aa628 214static void gtk_window_draw_callback( GtkWidget *WXUNUSED(widget), GdkRectangle *rect, wxWindow *win )
47d67540 215{
f5e27805 216 if (!win->HasVMT()) return;
47d67540 217
f5e27805 218 win->m_updateRegion.Union( rect->x, rect->y, rect->width, rect->height );
47d67540 219
f5e27805
RR
220 wxPaintEvent event( win->GetId() );
221 event.SetEventObject( win );
222 win->GetEventHandler()->ProcessEvent( event );
47d67540 223
f5e27805 224 win->m_updateRegion.Clear();
362c6693 225}
c801d85f
KB
226
227//-----------------------------------------------------------------------------
b292e2f5 228// "key_press_event" from any window
c801d85f 229//-----------------------------------------------------------------------------
c801d85f 230
2f2aa628 231static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
47d67540 232{
f5e27805
RR
233 if (!win->HasVMT()) return FALSE;
234 if (g_blockEventsOnDrag) return FALSE;
c801d85f 235
7be4c594 236/*
f5e27805
RR
237 printf( "OnKeyPress from " );
238 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
239 printf( win->GetClassInfo()->GetClassName() );
240 printf( ".\n" );
7be4c594 241*/
c801d85f 242
f5e27805
RR
243 long key_code = 0;
244 switch (gdk_event->keyval)
c801d85f 245 {
f5e27805
RR
246 case GDK_BackSpace: key_code = WXK_BACK; break;
247 case GDK_Tab: key_code = WXK_TAB; break;
248 case GDK_Linefeed: key_code = WXK_RETURN; break;
249 case GDK_Clear: key_code = WXK_CLEAR; break;
250 case GDK_Return: key_code = WXK_RETURN; break;
251 case GDK_Pause: key_code = WXK_PAUSE; break;
252 case GDK_Scroll_Lock: key_code = WXK_SCROLL; break;
253 case GDK_Escape: key_code = WXK_ESCAPE; break;
254 case GDK_Delete: key_code = WXK_DELETE; break;
255 case GDK_Home: key_code = WXK_HOME; break;
256 case GDK_Left: key_code = WXK_LEFT; break;
257 case GDK_Up: key_code = WXK_UP; break;
258 case GDK_Right: key_code = WXK_RIGHT; break;
259 case GDK_Down: key_code = WXK_DOWN; break;
260 case GDK_Prior: key_code = WXK_PRIOR; break;
261// case GDK_Page_Up: key_code = WXK_PAGEUP; break;
262 case GDK_Next: key_code = WXK_NEXT; break;
263// case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
264 case GDK_End: key_code = WXK_END; break;
265 case GDK_Begin: key_code = WXK_HOME; break;
266 case GDK_Select: key_code = WXK_SELECT; break;
267 case GDK_Print: key_code = WXK_PRINT; break;
268 case GDK_Execute: key_code = WXK_EXECUTE; break;
269 case GDK_Insert: key_code = WXK_INSERT; break;
270 case GDK_Num_Lock: key_code = WXK_NUMLOCK; break;
271 case GDK_KP_Tab: key_code = WXK_TAB; break;
272 case GDK_KP_Enter: key_code = WXK_RETURN; break;
273 case GDK_KP_Home: key_code = WXK_HOME; break;
274 case GDK_KP_Left: key_code = WXK_LEFT; break;
275 case GDK_KP_Up: key_code = WXK_UP; break;
276 case GDK_KP_Right: key_code = WXK_RIGHT; break;
277 case GDK_KP_Down: key_code = WXK_DOWN; break;
278 case GDK_KP_Prior: key_code = WXK_PRIOR; break;
279// case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
280 case GDK_KP_Next: key_code = WXK_NEXT; break;
281// case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
282 case GDK_KP_End: key_code = WXK_END; break;
283 case GDK_KP_Begin: key_code = WXK_HOME; break;
284 case GDK_KP_Insert: key_code = WXK_INSERT; break;
285 case GDK_KP_Delete: key_code = WXK_DELETE; break;
286 case GDK_KP_Multiply: key_code = WXK_MULTIPLY; break;
287 case GDK_KP_Add: key_code = WXK_ADD; break;
288 case GDK_KP_Separator: key_code = WXK_SEPARATOR; break;
289 case GDK_KP_Subtract: key_code = WXK_SUBTRACT; break;
290 case GDK_KP_Decimal: key_code = WXK_DECIMAL; break;
291 case GDK_KP_Divide: key_code = WXK_DIVIDE; break;
292 case GDK_KP_0: key_code = WXK_NUMPAD0; break;
293 case GDK_KP_1: key_code = WXK_NUMPAD1; break;
294 case GDK_KP_2: key_code = WXK_NUMPAD2; break;
295 case GDK_KP_3: key_code = WXK_NUMPAD3; break;
296 case GDK_KP_4: key_code = WXK_NUMPAD4; break;
297 case GDK_KP_5: key_code = WXK_NUMPAD5; break;
298 case GDK_KP_6: key_code = WXK_NUMPAD6; break;
299 case GDK_KP_7: key_code = WXK_NUMPAD7; break;
300 case GDK_KP_8: key_code = WXK_NUMPAD7; break;
301 case GDK_KP_9: key_code = WXK_NUMPAD9; break;
302 case GDK_F1: key_code = WXK_F1; break;
303 case GDK_F2: key_code = WXK_F2; break;
304 case GDK_F3: key_code = WXK_F3; break;
305 case GDK_F4: key_code = WXK_F4; break;
306 case GDK_F5: key_code = WXK_F5; break;
307 case GDK_F6: key_code = WXK_F6; break;
308 case GDK_F7: key_code = WXK_F7; break;
309 case GDK_F8: key_code = WXK_F8; break;
310 case GDK_F9: key_code = WXK_F9; break;
311 case GDK_F10: key_code = WXK_F10; break;
312 case GDK_F11: key_code = WXK_F11; break;
313 case GDK_F12: key_code = WXK_F12; break;
314 default:
315 {
316 if ((gdk_event->keyval >= 0x20) && (gdk_event->keyval <= 0xFF))
317 key_code = gdk_event->keyval;
318 }
362c6693 319 }
c801d85f 320
f5e27805 321 if (!key_code) return FALSE;
47d67540 322
b666df2c 323 wxKeyEvent event( wxEVT_KEY_DOWN );
f5e27805
RR
324 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
325 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
326 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
327 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
328 event.m_keyCode = key_code;
329 event.m_x = 0;
330 event.m_y = 0;
331 event.SetEventObject( win );
47d67540 332
f5e27805 333 bool ret = win->GetEventHandler()->ProcessEvent( event );
47d67540 334
f5e27805 335 if (!ret)
47d67540 336 {
f5e27805
RR
337 wxWindow *ancestor = win;
338 while (ancestor)
339 {
340 int command = ancestor->GetAcceleratorTable()->GetCommand( event );
341 if (command != -1)
342 {
343 wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
344 ret = ancestor->GetEventHandler()->ProcessEvent( command_event );
345 break;
346 }
347 ancestor = ancestor->GetParent();
348 }
bcf1fa6b 349 }
ff8bfdbb 350
b292e2f5 351 // win is a control: tab can be propagated up
291a8f20 352 if ((!ret) && (gdk_event->keyval == GDK_Tab) && ((win->m_windowStyle & wxTE_PROCESS_TAB) == 0))
b292e2f5
RR
353 {
354 wxNavigationKeyEvent new_event;
355 new_event.SetDirection( !(gdk_event->state & GDK_SHIFT_MASK) );
ff8bfdbb 356 new_event.SetWindowChange( FALSE );
b292e2f5 357 new_event.SetCurrentFocus( win );
ff8bfdbb 358 ret = win->GetEventHandler()->ProcessEvent( new_event );
b292e2f5 359 }
ff8bfdbb 360
b292e2f5
RR
361/*
362 // win is a panel: up can be propagated to the panel
363 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
364 (gdk_event->keyval == GDK_Up))
365 {
366 win->m_parent->SetFocus();
ff8bfdbb 367 ret = TRUE;
b292e2f5 368 }
ff8bfdbb 369
b292e2f5 370 // win is a panel: left/right can be propagated to the panel
ff8bfdbb
VZ
371 if ((!ret) && (win->m_wxwindow) &&
372 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
b292e2f5
RR
373 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
374 {
375 wxNavigationKeyEvent new_event;
376 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
377 new_event.SetCurrentFocus( win );
ff8bfdbb 378 ret = win->GetEventHandler()->ProcessEvent( new_event );
b292e2f5
RR
379 }
380*/
ff8bfdbb 381
f5e27805
RR
382 if (ret)
383 {
b292e2f5 384 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
f5e27805 385 }
47d67540 386
f5e27805 387 return ret;
362c6693 388}
c801d85f 389
b666df2c
RR
390//-----------------------------------------------------------------------------
391// "key_release_event" from any window
392//-----------------------------------------------------------------------------
393
394static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
395{
396 if (!win->HasVMT()) return FALSE;
397 if (g_blockEventsOnDrag) return FALSE;
398
399/*
400 printf( "OnKeyRelease from " );
401 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
402 printf( win->GetClassInfo()->GetClassName() );
403 printf( ".\n" );
404*/
405
406 long key_code = 0;
407 switch (gdk_event->keyval)
408 {
409 case GDK_BackSpace: key_code = WXK_BACK; break;
410 case GDK_Tab: key_code = WXK_TAB; break;
411 case GDK_Linefeed: key_code = WXK_RETURN; break;
412 case GDK_Clear: key_code = WXK_CLEAR; break;
413 case GDK_Return: key_code = WXK_RETURN; break;
414 case GDK_Pause: key_code = WXK_PAUSE; break;
415 case GDK_Scroll_Lock: key_code = WXK_SCROLL; break;
416 case GDK_Escape: key_code = WXK_ESCAPE; break;
417 case GDK_Delete: key_code = WXK_DELETE; break;
418 case GDK_Home: key_code = WXK_HOME; break;
419 case GDK_Left: key_code = WXK_LEFT; break;
420 case GDK_Up: key_code = WXK_UP; break;
421 case GDK_Right: key_code = WXK_RIGHT; break;
422 case GDK_Down: key_code = WXK_DOWN; break;
423 case GDK_Prior: key_code = WXK_PRIOR; break;
424// case GDK_Page_Up: key_code = WXK_PAGEUP; break;
425 case GDK_Next: key_code = WXK_NEXT; break;
426// case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
427 case GDK_End: key_code = WXK_END; break;
428 case GDK_Begin: key_code = WXK_HOME; break;
429 case GDK_Select: key_code = WXK_SELECT; break;
430 case GDK_Print: key_code = WXK_PRINT; break;
431 case GDK_Execute: key_code = WXK_EXECUTE; break;
432 case GDK_Insert: key_code = WXK_INSERT; break;
433 case GDK_Num_Lock: key_code = WXK_NUMLOCK; break;
434 case GDK_KP_Tab: key_code = WXK_TAB; break;
435 case GDK_KP_Enter: key_code = WXK_RETURN; break;
436 case GDK_KP_Home: key_code = WXK_HOME; break;
437 case GDK_KP_Left: key_code = WXK_LEFT; break;
438 case GDK_KP_Up: key_code = WXK_UP; break;
439 case GDK_KP_Right: key_code = WXK_RIGHT; break;
440 case GDK_KP_Down: key_code = WXK_DOWN; break;
441 case GDK_KP_Prior: key_code = WXK_PRIOR; break;
442// case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
443 case GDK_KP_Next: key_code = WXK_NEXT; break;
444// case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
445 case GDK_KP_End: key_code = WXK_END; break;
446 case GDK_KP_Begin: key_code = WXK_HOME; break;
447 case GDK_KP_Insert: key_code = WXK_INSERT; break;
448 case GDK_KP_Delete: key_code = WXK_DELETE; break;
449 case GDK_KP_Multiply: key_code = WXK_MULTIPLY; break;
450 case GDK_KP_Add: key_code = WXK_ADD; break;
451 case GDK_KP_Separator: key_code = WXK_SEPARATOR; break;
452 case GDK_KP_Subtract: key_code = WXK_SUBTRACT; break;
453 case GDK_KP_Decimal: key_code = WXK_DECIMAL; break;
454 case GDK_KP_Divide: key_code = WXK_DIVIDE; break;
455 case GDK_KP_0: key_code = WXK_NUMPAD0; break;
456 case GDK_KP_1: key_code = WXK_NUMPAD1; break;
457 case GDK_KP_2: key_code = WXK_NUMPAD2; break;
458 case GDK_KP_3: key_code = WXK_NUMPAD3; break;
459 case GDK_KP_4: key_code = WXK_NUMPAD4; break;
460 case GDK_KP_5: key_code = WXK_NUMPAD5; break;
461 case GDK_KP_6: key_code = WXK_NUMPAD6; break;
462 case GDK_KP_7: key_code = WXK_NUMPAD7; break;
463 case GDK_KP_8: key_code = WXK_NUMPAD7; break;
464 case GDK_KP_9: key_code = WXK_NUMPAD9; break;
465 case GDK_F1: key_code = WXK_F1; break;
466 case GDK_F2: key_code = WXK_F2; break;
467 case GDK_F3: key_code = WXK_F3; break;
468 case GDK_F4: key_code = WXK_F4; break;
469 case GDK_F5: key_code = WXK_F5; break;
470 case GDK_F6: key_code = WXK_F6; break;
471 case GDK_F7: key_code = WXK_F7; break;
472 case GDK_F8: key_code = WXK_F8; break;
473 case GDK_F9: key_code = WXK_F9; break;
474 case GDK_F10: key_code = WXK_F10; break;
475 case GDK_F11: key_code = WXK_F11; break;
476 case GDK_F12: key_code = WXK_F12; break;
477 default:
478 {
479 if ((gdk_event->keyval >= 0x20) && (gdk_event->keyval <= 0xFF))
480 key_code = gdk_event->keyval;
481 }
482 }
483
484 if (!key_code) return FALSE;
485
486 wxKeyEvent event( wxEVT_KEY_UP );
487 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
488 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
489 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
490 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
491 event.m_keyCode = key_code;
492 event.m_x = 0;
493 event.m_y = 0;
494 event.SetEventObject( win );
495
496 bool ret = win->GetEventHandler()->ProcessEvent( event );
497
498 if (ret)
499 {
500 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
501 }
502
503 return ret;
504}
505
c801d85f 506//-----------------------------------------------------------------------------
2f2aa628
RR
507// "button_press_event"
508//-----------------------------------------------------------------------------
c801d85f 509
2f2aa628 510static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
903f689b 511{
f5e27805 512 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
47d67540 513
f5e27805 514 if (g_blockEventsOnDrag) return TRUE;
76ed8f8d 515 if (g_blockEventsOnScroll) return TRUE;
c801d85f 516
f5e27805 517 if (win->m_wxwindow)
c801d85f 518 {
f5e27805
RR
519 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow) && !GTK_WIDGET_HAS_FOCUS (win->m_wxwindow) )
520 {
521 gtk_widget_grab_focus (win->m_wxwindow);
47d67540 522
c801d85f 523/*
f5e27805
RR
524 printf( "GrabFocus from " );
525 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
526 printf( win->GetClassInfo()->GetClassName() );
527 printf( ".\n" );
c801d85f 528*/
47d67540 529
f5e27805 530 }
362c6693 531 }
47d67540 532
f5e27805 533 if (!win->HasVMT()) return TRUE;
97b3455a 534
8429bec1 535/*
f5e27805
RR
536 printf( "OnButtonPress from " );
537 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
538 printf( win->GetClassInfo()->GetClassName() );
539 printf( ".\n" );
8429bec1 540*/
30dea054 541
f5e27805 542 wxEventType event_type = wxEVT_LEFT_DOWN;
47d67540 543
f5e27805 544 if (gdk_event->button == 1)
c801d85f 545 {
f5e27805
RR
546 switch (gdk_event->type)
547 {
548 case GDK_BUTTON_PRESS: event_type = wxEVT_LEFT_DOWN; break;
549 case GDK_2BUTTON_PRESS: event_type = wxEVT_LEFT_DCLICK; break;
550 default: break;
551 }
362c6693 552 }
f5e27805 553 else if (gdk_event->button == 2)
c801d85f 554 {
f5e27805
RR
555 switch (gdk_event->type)
556 {
557 case GDK_BUTTON_PRESS: event_type = wxEVT_MIDDLE_DOWN; break;
558 case GDK_2BUTTON_PRESS: event_type = wxEVT_MIDDLE_DCLICK; break;
559 default: break;
560 }
362c6693 561 }
f5e27805 562 else if (gdk_event->button == 3)
c801d85f 563 {
f5e27805
RR
564 switch (gdk_event->type)
565 {
566 case GDK_BUTTON_PRESS: event_type = wxEVT_RIGHT_DOWN; break;
567 case GDK_2BUTTON_PRESS: event_type = wxEVT_RIGHT_DCLICK; break;
568 default: break;
569 }
362c6693 570 }
47d67540 571
f5e27805
RR
572 wxMouseEvent event( event_type );
573 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
574 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
575 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
576 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
577 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
578 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
579 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
47d67540 580
f5e27805
RR
581 event.m_x = (long)gdk_event->x;
582 event.m_y = (long)gdk_event->y;
47d67540 583
f5e27805
RR
584 // Some control don't have their own X window and thus cannot get
585 // any events.
47d67540 586
f5e27805 587 if (!g_capturing)
2f2aa628 588 {
db1b4961 589 wxNode *node = win->GetChildren().First();
f5e27805
RR
590 while (node)
591 {
592 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb
VZ
593
594 if (child->m_isStaticBox)
595 {
596 // wxStaticBox is transparent in the box itself
597 int x = event.m_x;
598 int y = event.m_y;
599 int xx1 = child->m_x;
600 int yy1 = child->m_y;
601 int xx2 = child->m_x + child->m_width;
602 int yy2 = child->m_x + child->m_height;
603
604 // left
605 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
606 // right
607 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
608 // top
609 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
610 // bottom
611 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
612 {
1ecc4d80
RR
613 win = child;
614 event.m_x -= child->m_x;
615 event.m_y -= child->m_y;
616 break;
ff8bfdbb
VZ
617 }
618
619 }
620 else
621 {
1ecc4d80 622 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
ff8bfdbb 623 (child->m_x <= event.m_x) &&
1ecc4d80
RR
624 (child->m_y <= event.m_y) &&
625 (child->m_x+child->m_width >= event.m_x) &&
626 (child->m_y+child->m_height >= event.m_y))
627 {
628 win = child;
629 event.m_x -= child->m_x;
630 event.m_y -= child->m_y;
631 break;
ff8bfdbb 632 }
f5e27805
RR
633 }
634 node = node->Next();
635 }
2f2aa628 636 }
ff8bfdbb 637
0c77152e
RR
638 wxPoint pt(win->GetClientAreaOrigin());
639 event.m_x -= pt.x;
640 event.m_y -= pt.y;
47d67540 641
f5e27805 642 event.SetEventObject( win );
47d67540 643
f5e27805 644 gs_timeLastClick = gdk_event->time;
47d67540 645
f5e27805
RR
646 if (win->GetEventHandler()->ProcessEvent( event ))
647 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
47d67540 648
f5e27805 649 return TRUE;
362c6693 650}
c801d85f
KB
651
652//-----------------------------------------------------------------------------
97b3455a 653// "button_release_event"
2f2aa628 654//-----------------------------------------------------------------------------
c801d85f 655
2f2aa628 656static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
47d67540 657{
f5e27805 658 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
47d67540 659
f5e27805 660 if (g_blockEventsOnDrag) return TRUE;
76ed8f8d 661 if (g_blockEventsOnScroll) return TRUE;
c801d85f 662
f5e27805 663 if (!win->HasVMT()) return TRUE;
47d67540 664
c801d85f 665/*
f5e27805
RR
666 printf( "OnButtonRelease from " );
667 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
668 printf( win->GetClassInfo()->GetClassName() );
669 printf( ".\n" );
c801d85f 670*/
47d67540 671
f5e27805 672 wxEventType event_type = wxEVT_NULL;
47d67540 673
f5e27805
RR
674 switch (gdk_event->button)
675 {
676 case 1: event_type = wxEVT_LEFT_UP; break;
677 case 2: event_type = wxEVT_MIDDLE_UP; break;
678 case 3: event_type = wxEVT_RIGHT_UP; break;
679 }
47d67540 680
f5e27805
RR
681 wxMouseEvent event( event_type );
682 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
683 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
684 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
685 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
686 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
687 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
688 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
689 event.m_x = (long)gdk_event->x;
690 event.m_y = (long)gdk_event->y;
691
692 // Some control don't have their own X window and thus cannot get
693 // any events.
694
695 if (!g_capturing)
2f2aa628 696 {
db1b4961 697 wxNode *node = win->GetChildren().First();
f5e27805
RR
698 while (node)
699 {
700 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb
VZ
701
702 if (child->m_isStaticBox)
703 {
704 // wxStaticBox is transparent in the box itself
705 int x = event.m_x;
706 int y = event.m_y;
707 int xx1 = child->m_x;
708 int yy1 = child->m_y;
709 int xx2 = child->m_x + child->m_width;
710 int yy2 = child->m_x + child->m_height;
711
712 // left
713 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
714 // right
715 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
716 // top
717 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
718 // bottom
719 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
720 {
1ecc4d80
RR
721 win = child;
722 event.m_x -= child->m_x;
723 event.m_y -= child->m_y;
724 break;
ff8bfdbb
VZ
725 }
726
727 }
728 else
729 {
1ecc4d80 730 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
ff8bfdbb 731 (child->m_x <= event.m_x) &&
1ecc4d80
RR
732 (child->m_y <= event.m_y) &&
733 (child->m_x+child->m_width >= event.m_x) &&
734 (child->m_y+child->m_height >= event.m_y))
735 {
736 win = child;
737 event.m_x -= child->m_x;
738 event.m_y -= child->m_y;
739 break;
ff8bfdbb 740 }
f5e27805
RR
741 }
742 node = node->Next();
743 }
2f2aa628 744 }
47d67540 745
0c77152e
RR
746 wxPoint pt(win->GetClientAreaOrigin());
747 event.m_x -= pt.x;
748 event.m_y -= pt.y;
749
f5e27805 750 event.SetEventObject( win );
47d67540 751
f5e27805
RR
752 if (win->GetEventHandler()->ProcessEvent( event ))
753 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" );
47d67540 754
f5e27805 755 return TRUE;
362c6693 756}
c801d85f
KB
757
758//-----------------------------------------------------------------------------
2f2aa628
RR
759// "motion_notify_event"
760//-----------------------------------------------------------------------------
c801d85f 761
2f2aa628 762static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
47d67540 763{
ff8bfdbb 764 if (gdk_event->is_hint)
aae24d21
RR
765 {
766 int x = 0;
767 int y = 0;
768 GdkModifierType state;
769 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
770 gdk_event->x = x;
771 gdk_event->y = y;
772 gdk_event->state = state;
773 }
ff8bfdbb 774
e380f72b 775 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
47d67540 776
e380f72b 777 if (g_blockEventsOnDrag) return TRUE;
76ed8f8d 778 if (g_blockEventsOnScroll) return TRUE;
8bbe427f 779
e380f72b 780 if (!win->HasVMT()) return TRUE;
47d67540 781
c801d85f 782/*
e380f72b
RR
783 printf( "OnMotion from " );
784 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
785 printf( win->GetClassInfo()->GetClassName() );
786 printf( ".\n" );
aae24d21 787*/
47d67540 788
e380f72b
RR
789 wxMouseEvent event( wxEVT_MOTION );
790 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
791 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
792 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
793 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
794 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
795 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
796 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
797
798 event.m_x = (long)gdk_event->x;
799 event.m_y = (long)gdk_event->y;
800
801 // Some control don't have their own X window and thus cannot get
802 // any events.
803
804 if (!g_capturing)
2f2aa628 805 {
db1b4961 806 wxNode *node = win->GetChildren().First();
e380f72b
RR
807 while (node)
808 {
809 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb
VZ
810
811 if (child->m_isStaticBox)
812 {
813 // wxStaticBox is transparent in the box itself
814 int x = event.m_x;
815 int y = event.m_y;
816 int xx1 = child->m_x;
817 int yy1 = child->m_y;
818 int xx2 = child->m_x + child->m_width;
819 int yy2 = child->m_x + child->m_height;
820
821 // left
822 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
823 // right
824 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
825 // top
826 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
827 // bottom
828 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
829 {
1ecc4d80
RR
830 win = child;
831 event.m_x -= child->m_x;
832 event.m_y -= child->m_y;
833 break;
ff8bfdbb
VZ
834 }
835
836 }
837 else
838 {
1ecc4d80 839 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
ff8bfdbb 840 (child->m_x <= event.m_x) &&
1ecc4d80
RR
841 (child->m_y <= event.m_y) &&
842 (child->m_x+child->m_width >= event.m_x) &&
843 (child->m_y+child->m_height >= event.m_y))
844 {
845 win = child;
846 event.m_x -= child->m_x;
847 event.m_y -= child->m_y;
848 break;
ff8bfdbb 849 }
e380f72b
RR
850 }
851 node = node->Next();
852 }
2f2aa628 853 }
47d67540 854
0c77152e
RR
855 wxPoint pt(win->GetClientAreaOrigin());
856 event.m_x -= pt.x;
857 event.m_y -= pt.y;
858
e380f72b 859 event.SetEventObject( win );
47d67540 860
e380f72b
RR
861 if (win->GetEventHandler()->ProcessEvent( event ))
862 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
47d67540 863
e380f72b 864 return TRUE;
362c6693 865}
c801d85f
KB
866
867//-----------------------------------------------------------------------------
2f2aa628
RR
868// "focus_in_event"
869//-----------------------------------------------------------------------------
c801d85f 870
2f2aa628 871static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
c801d85f 872{
e380f72b 873 if (g_blockEventsOnDrag) return TRUE;
ff8bfdbb 874
b292e2f5 875 g_focusWindow = win;
ff8bfdbb 876
e380f72b 877 if (win->m_wxwindow)
c801d85f 878 {
e380f72b
RR
879 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
880 {
881 GTK_WIDGET_SET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
47d67540 882/*
e380f72b
RR
883 printf( "SetFocus flag from " );
884 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
885 printf( win->GetClassInfo()->GetClassName() );
886 printf( ".\n" );
c801d85f 887*/
e380f72b 888 }
362c6693 889 }
47d67540 890
e380f72b 891 if (!win->HasVMT()) return TRUE;
47d67540 892
c801d85f 893/*
e380f72b
RR
894 printf( "OnSetFocus from " );
895 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
896 printf( win->GetClassInfo()->GetClassName() );
897 printf( " " );
898 printf( WXSTRINGCAST win->GetLabel() );
899 printf( ".\n" );
c801d85f 900*/
47d67540 901
e380f72b
RR
902 wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
903 event.SetEventObject( win );
47d67540 904
e380f72b
RR
905 if (win->GetEventHandler()->ProcessEvent( event ))
906 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
47d67540 907
e380f72b 908 return TRUE;
362c6693 909}
c801d85f
KB
910
911//-----------------------------------------------------------------------------
2f2aa628
RR
912// "focus_out_event"
913//-----------------------------------------------------------------------------
c801d85f 914
2f2aa628 915static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
c801d85f 916{
e380f72b
RR
917 if (g_blockEventsOnDrag) return TRUE;
918 if (win->m_wxwindow)
919 {
920 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
921 GTK_WIDGET_UNSET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
922 }
47d67540 923
e380f72b 924 if (!win->HasVMT()) return TRUE;
47d67540 925
c801d85f 926/*
e380f72b
RR
927 printf( "OnKillFocus from " );
928 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
929 printf( win->GetClassInfo()->GetClassName() );
930 printf( ".\n" );
c801d85f 931*/
47d67540 932
e380f72b
RR
933 wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
934 event.SetEventObject( win );
47d67540 935
e380f72b
RR
936 if (win->GetEventHandler()->ProcessEvent( event ))
937 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
2f2aa628 938
e380f72b 939 return TRUE;
362c6693 940}
c801d85f 941
b4071e91
RR
942//-----------------------------------------------------------------------------
943// "enter_notify_event"
944//-----------------------------------------------------------------------------
945
946static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
947{
e380f72b 948 if (g_blockEventsOnDrag) return TRUE;
47d67540 949
b292e2f5
RR
950 if ((widget->window) && (win->m_cursor))
951 gdk_window_set_cursor( widget->window, win->m_cursor->GetCursor() );
952
953 if (widget->window != gdk_event->window) return TRUE;
954
e380f72b 955 if (!win->HasVMT()) return TRUE;
47d67540 956
d8c83875 957/*
e380f72b
RR
958 printf( "OnEnter from " );
959 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
960 printf( win->GetClassInfo()->GetClassName() );
961 printf( ".\n" );
d8c83875 962*/
47d67540 963
e380f72b
RR
964 wxMouseEvent event( wxEVT_ENTER_WINDOW );
965 event.SetEventObject( win );
ff8bfdbb 966
4a33eba6
RR
967 int x = 0;
968 int y = 0;
969 GdkModifierType state = (GdkModifierType)0;
ff8bfdbb 970
4a33eba6 971 gdk_window_get_pointer( widget->window, &x, &y, &state );
ff8bfdbb 972
4a33eba6
RR
973 event.m_shiftDown = (state & GDK_SHIFT_MASK);
974 event.m_controlDown = (state & GDK_CONTROL_MASK);
975 event.m_altDown = (state & GDK_MOD1_MASK);
976 event.m_metaDown = (state & GDK_MOD2_MASK);
977 event.m_leftDown = (state & GDK_BUTTON1_MASK);
978 event.m_middleDown = (state & GDK_BUTTON2_MASK);
979 event.m_rightDown = (state & GDK_BUTTON3_MASK);
980
981 event.m_x = (long)x;
982 event.m_y = (long)y;
ff8bfdbb 983
0c77152e
RR
984 wxPoint pt(win->GetClientAreaOrigin());
985 event.m_x -= pt.x;
986 event.m_y -= pt.y;
987
e380f72b
RR
988 if (win->GetEventHandler()->ProcessEvent( event ))
989 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "enter_notify_event" );
47d67540 990
e380f72b 991 return TRUE;
b4071e91 992}
47d67540 993
b4071e91
RR
994//-----------------------------------------------------------------------------
995// "leave_notify_event"
996//-----------------------------------------------------------------------------
997
998static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
999{
e380f72b 1000 if (g_blockEventsOnDrag) return TRUE;
47d67540 1001
b292e2f5
RR
1002 if ((widget->window) && (win->m_cursor))
1003 gdk_window_set_cursor( widget->window, wxSTANDARD_CURSOR->GetCursor() );
1004
1005 if (widget->window != gdk_event->window) return TRUE;
1006
e380f72b 1007 if (!win->HasVMT()) return TRUE;
47d67540 1008
d8c83875 1009/*
e380f72b
RR
1010 printf( "OnLeave from " );
1011 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1012 printf( win->GetClassInfo()->GetClassName() );
1013 printf( ".\n" );
d8c83875 1014*/
47d67540 1015
e380f72b
RR
1016 wxMouseEvent event( wxEVT_LEAVE_WINDOW );
1017 event.SetEventObject( win );
47d67540 1018
4a33eba6
RR
1019 int x = 0;
1020 int y = 0;
1021 GdkModifierType state = (GdkModifierType)0;
ff8bfdbb 1022
4a33eba6 1023 gdk_window_get_pointer( widget->window, &x, &y, &state );
ff8bfdbb 1024
4a33eba6
RR
1025 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1026 event.m_controlDown = (state & GDK_CONTROL_MASK);
1027 event.m_altDown = (state & GDK_MOD1_MASK);
1028 event.m_metaDown = (state & GDK_MOD2_MASK);
1029 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1030 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1031 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1032
1033 event.m_x = (long)x;
1034 event.m_y = (long)y;
ff8bfdbb 1035
0c77152e
RR
1036 wxPoint pt(win->GetClientAreaOrigin());
1037 event.m_x -= pt.x;
1038 event.m_y -= pt.y;
1039
e380f72b
RR
1040 if (win->GetEventHandler()->ProcessEvent( event ))
1041 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "leave_notify_event" );
47d67540 1042
e380f72b 1043 return TRUE;
b4071e91 1044}
47d67540 1045
c801d85f 1046//-----------------------------------------------------------------------------
2f2aa628
RR
1047// "value_changed" from m_vAdjust
1048//-----------------------------------------------------------------------------
c801d85f 1049
2f2aa628 1050static void gtk_window_vscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
c801d85f 1051{
e380f72b 1052 if (g_blockEventsOnDrag) return;
c801d85f
KB
1053
1054/*
e380f72b
RR
1055 printf( "OnVScroll from " );
1056 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1057 printf( win->GetClassInfo()->GetClassName() );
1058 printf( ".\n" );
c801d85f 1059*/
47d67540 1060
e380f72b 1061 if (!win->HasVMT()) return;
47d67540 1062
e380f72b
RR
1063 float diff = win->m_vAdjust->value - win->m_oldVerticalPos;
1064 if (fabs(diff) < 0.2) return;
47d67540 1065
e380f72b 1066 wxEventType command = wxEVT_NULL;
47d67540 1067
e380f72b
RR
1068 float line_step = win->m_vAdjust->step_increment;
1069 float page_step = win->m_vAdjust->page_increment;
47d67540 1070
76ed8f8d
RR
1071 if (win->m_isScrolling)
1072 {
1073 command = wxEVT_SCROLL_THUMBTRACK;
1074 }
1075 else
1076 {
1077 if (fabs(win->m_vAdjust->value-win->m_vAdjust->lower) < 0.2) command = wxEVT_SCROLL_BOTTOM;
1078 else if (fabs(win->m_vAdjust->value-win->m_vAdjust->upper) < 0.2) command = wxEVT_SCROLL_TOP;
1079 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLL_LINEDOWN;
1080 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLL_LINEUP;
1081 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLL_PAGEDOWN;
1082 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLL_PAGEUP;
1083 else command = wxEVT_SCROLL_THUMBTRACK;
1084 }
47d67540 1085
e380f72b 1086 int value = (int)(win->m_vAdjust->value+0.5);
c801d85f 1087
e380f72b
RR
1088 wxScrollEvent event( command, win->GetId(), value, wxVERTICAL );
1089 event.SetEventObject( win );
1090 win->GetEventHandler()->ProcessEvent( event );
362c6693 1091}
c801d85f
KB
1092
1093//-----------------------------------------------------------------------------
2f2aa628
RR
1094// "value_changed" from m_hAdjust
1095//-----------------------------------------------------------------------------
c801d85f 1096
2f2aa628 1097static void gtk_window_hscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
47d67540 1098{
e380f72b 1099 if (g_blockEventsOnDrag) return;
47d67540 1100
c801d85f 1101/*
e380f72b
RR
1102 printf( "OnHScroll from " );
1103 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1104 printf( win->GetClassInfo()->GetClassName() );
1105 printf( ".\n" );
c801d85f 1106*/
47d67540 1107
e380f72b 1108 if (!win->HasVMT()) return;
47d67540 1109
e380f72b
RR
1110 float diff = win->m_hAdjust->value - win->m_oldHorizontalPos;
1111 if (fabs(diff) < 0.2) return;
47d67540 1112
e380f72b 1113 wxEventType command = wxEVT_NULL;
47d67540 1114
e380f72b
RR
1115 float line_step = win->m_hAdjust->step_increment;
1116 float page_step = win->m_hAdjust->page_increment;
8bbe427f 1117
76ed8f8d
RR
1118 if (win->m_isScrolling)
1119 {
1120 command = wxEVT_SCROLL_THUMBTRACK;
1121 }
1122 else
1123 {
1124 if (fabs(win->m_hAdjust->value-win->m_hAdjust->lower) < 0.2) command = wxEVT_SCROLL_BOTTOM;
1125 else if (fabs(win->m_hAdjust->value-win->m_hAdjust->upper) < 0.2) command = wxEVT_SCROLL_TOP;
1126 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLL_LINEDOWN;
1127 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLL_LINEUP;
1128 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLL_PAGEDOWN;
1129 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLL_PAGEUP;
1130 else command = wxEVT_SCROLL_THUMBTRACK;
1131 }
c801d85f 1132
e380f72b 1133 int value = (int)(win->m_hAdjust->value+0.5);
47d67540 1134
e380f72b
RR
1135 wxScrollEvent event( command, win->GetId(), value, wxHORIZONTAL );
1136 event.SetEventObject( win );
1137 win->GetEventHandler()->ProcessEvent( event );
362c6693 1138}
c801d85f
KB
1139
1140//-----------------------------------------------------------------------------
2f2aa628
RR
1141// "changed" from m_vAdjust
1142//-----------------------------------------------------------------------------
c801d85f 1143
2f2aa628 1144static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
c801d85f 1145{
e380f72b 1146 if (g_blockEventsOnDrag) return;
c801d85f
KB
1147
1148/*
e380f72b
RR
1149 printf( "OnVScroll change from " );
1150 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1151 printf( win->GetClassInfo()->GetClassName() );
1152 printf( ".\n" );
c801d85f 1153*/
47d67540 1154
e380f72b 1155 if (!win->HasVMT()) return;
47d67540 1156
e380f72b
RR
1157 wxEventType command = wxEVT_SCROLL_THUMBTRACK;
1158 int value = (int)(win->m_vAdjust->value+0.5);
c801d85f 1159
e380f72b
RR
1160 wxScrollEvent event( command, win->GetId(), value, wxVERTICAL );
1161 event.SetEventObject( win );
1162 win->GetEventHandler()->ProcessEvent( event );
362c6693 1163}
c801d85f
KB
1164
1165//-----------------------------------------------------------------------------
2f2aa628
RR
1166// "changed" from m_hAdjust
1167//-----------------------------------------------------------------------------
c801d85f 1168
2f2aa628 1169static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
47d67540 1170{
e380f72b 1171 if (g_blockEventsOnDrag) return;
47d67540 1172
c801d85f 1173/*
e380f72b
RR
1174 printf( "OnHScroll change from " );
1175 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1176 printf( win->GetClassInfo()->GetClassName() );
1177 printf( ".\n" );
c801d85f 1178*/
47d67540 1179
e380f72b 1180 if (!win->HasVMT()) return;
47d67540 1181
e380f72b
RR
1182 wxEventType command = wxEVT_SCROLL_THUMBTRACK;
1183 int value = (int)(win->m_hAdjust->value+0.5);
47d67540 1184
e380f72b
RR
1185 wxScrollEvent event( command, win->GetId(), value, wxHORIZONTAL );
1186 event.SetEventObject( win );
1187 win->GetEventHandler()->ProcessEvent( event );
362c6693 1188}
c801d85f 1189
cb43b372
RR
1190//-----------------------------------------------------------------------------
1191// "button_press_event" from scrollbar
1192//-----------------------------------------------------------------------------
1193
8bbe427f
VZ
1194static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
1195 GdkEventButton *WXUNUSED(gdk_event),
ff8bfdbb 1196 wxWindow *win )
cb43b372 1197{
1ecc4d80
RR
1198// don't test here as we can release the mouse while being over
1199// a different window then the slider
1200//
76ed8f8d 1201// if (gdk_event->window != widget->slider) return FALSE;
8bbe427f 1202
e380f72b 1203 win->m_isScrolling = TRUE;
76ed8f8d 1204 g_blockEventsOnScroll = TRUE;
47d67540 1205
e380f72b 1206 return FALSE;
cb43b372
RR
1207}
1208
1209//-----------------------------------------------------------------------------
1210// "button_release_event" from scrollbar
1211//-----------------------------------------------------------------------------
1212
8bbe427f
VZ
1213static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
1214 GdkEventButton *WXUNUSED(gdk_event),
ff8bfdbb 1215 wxWindow *win )
cb43b372 1216{
76ed8f8d 1217
1ecc4d80 1218// don't test here as we can release the mouse while being over
76ed8f8d
RR
1219// a different window then the slider
1220//
1221// if (gdk_event->window != widget->slider) return FALSE;
cb43b372 1222
e380f72b 1223 GtkScrolledWindow *s_window = GTK_SCROLLED_WINDOW(win->m_widget);
47d67540 1224
e380f72b
RR
1225 if (widget == GTK_RANGE(s_window->vscrollbar))
1226 gtk_signal_emit_by_name( GTK_OBJECT(win->m_hAdjust), "value_changed" );
1227 else
1228 gtk_signal_emit_by_name( GTK_OBJECT(win->m_vAdjust), "value_changed" );
47d67540 1229
e380f72b 1230 win->m_isScrolling = FALSE;
76ed8f8d 1231 g_blockEventsOnScroll = FALSE;
47d67540 1232
e380f72b 1233 return FALSE;
cb43b372
RR
1234}
1235
6ca41e57
RR
1236//-----------------------------------------------------------------------------
1237// InsertChild for wxWindow.
1238//-----------------------------------------------------------------------------
1239
b1170810
RR
1240/* Callback for wxWindow. This very strange beast has to be used because
1241 * C++ has no virtual methods in a constructor. We have to emulate a
1242 * virtual function here as wxNotebook requires a different way to insert
1243 * a child in it. I had opted for creating a wxNotebookPage window class
1244 * which would have made this superfluous (such in the MDI window system),
1245 * but no-one was listening to me... */
6ca41e57
RR
1246
1247static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
1248{
8bbe427f
VZ
1249 gtk_myfixed_put( GTK_MYFIXED(parent->m_wxwindow),
1250 GTK_WIDGET(child->m_widget),
ff8bfdbb
VZ
1251 child->m_x,
1252 child->m_y );
6ca41e57 1253
8bbe427f
VZ
1254 gtk_widget_set_usize( GTK_WIDGET(child->m_widget),
1255 child->m_width,
ff8bfdbb
VZ
1256 child->m_height );
1257
5b077d48
RR
1258 if (wxIS_KIND_OF(parent,wxFrame))
1259 {
1260 parent->m_sizeSet = FALSE;
1261 }
ff8bfdbb 1262
3e61c765
RR
1263 if (parent->m_windowStyle & wxTAB_TRAVERSAL)
1264 {
1265 /* we now allow a window to get the focus as long as it
ff8bfdbb
VZ
1266 doesn't have any children. */
1267 GTK_WIDGET_UNSET_FLAGS( parent->m_wxwindow, GTK_CAN_FOCUS );
3e61c765 1268 }
6ca41e57
RR
1269}
1270
bbe0af5b
RR
1271//-----------------------------------------------------------------------------
1272// global functions
1273//-----------------------------------------------------------------------------
1274
1275wxWindow* wxGetActiveWindow()
1276{
1277 return g_focusWindow;
1278}
1279
c801d85f 1280//-----------------------------------------------------------------------------
2f2aa628 1281// wxWindow
c801d85f
KB
1282//-----------------------------------------------------------------------------
1283
1284IMPLEMENT_DYNAMIC_CLASS(wxWindow,wxEvtHandler)
1285
1286BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler)
e380f72b
RR
1287 EVT_SIZE(wxWindow::OnSize)
1288 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
1289 EVT_INIT_DIALOG(wxWindow::OnInitDialog)
b666df2c 1290 EVT_KEY_DOWN(wxWindow::OnKeyDown)
c801d85f
KB
1291END_EVENT_TABLE()
1292
1293wxWindow::wxWindow()
1294{
e380f72b
RR
1295 m_widget = (GtkWidget *) NULL;
1296 m_wxwindow = (GtkWidget *) NULL;
1297 m_parent = (wxWindow *) NULL;
1298 m_children.DeleteContents( FALSE );
8bbe427f 1299
e380f72b
RR
1300 m_x = 0;
1301 m_y = 0;
1302 m_width = 0;
1303 m_height = 0;
1304 m_minWidth = -1;
1305 m_minHeight = -1;
1306 m_maxWidth = -1;
1307 m_maxHeight = -1;
8bbe427f 1308
e380f72b 1309 m_retCode = 0;
8bbe427f 1310
e380f72b
RR
1311 m_eventHandler = this;
1312 m_windowValidator = (wxValidator *) NULL;
8bbe427f 1313
e380f72b 1314 m_windowId = -1;
8bbe427f 1315
e380f72b
RR
1316 m_cursor = (wxCursor *) NULL;
1317 m_font = *wxSWISS_FONT;
1318 m_windowStyle = 0;
1319 m_windowName = "noname";
8bbe427f 1320
e380f72b
RR
1321 m_constraints = (wxLayoutConstraints *) NULL;
1322 m_constraintsInvolvedIn = (wxList *) NULL;
1323 m_windowSizer = (wxSizer *) NULL;
1324 m_sizerParent = (wxWindow *) NULL;
1325 m_autoLayout = FALSE;
8bbe427f 1326
e380f72b
RR
1327 m_sizeSet = FALSE;
1328 m_hasVMT = FALSE;
1329 m_needParent = TRUE;
8bbe427f 1330
e380f72b
RR
1331 m_hasScrolling = FALSE;
1332 m_isScrolling = FALSE;
1333 m_hAdjust = (GtkAdjustment*) NULL;
1334 m_vAdjust = (GtkAdjustment*) NULL;
1335 m_oldHorizontalPos = 0.0;
1336 m_oldVerticalPos = 0.0;
8bbe427f 1337
e380f72b
RR
1338 m_isShown = FALSE;
1339 m_isEnabled = TRUE;
8bbe427f 1340
06cfab17 1341#if wxUSE_DRAG_AND_DROP
e380f72b 1342 m_dropTarget = (wxDropTarget*) NULL;
ac57418f 1343#endif
e380f72b
RR
1344 m_resizing = FALSE;
1345 m_scrollGC = (GdkGC*) NULL;
1346 m_widgetStyle = (GtkStyle*) NULL;
8bbe427f 1347
e380f72b 1348 m_insertCallback = wxInsertChildInWindow;
8bbe427f 1349
e380f72b
RR
1350 m_clientObject = (wxClientData*) NULL;
1351 m_clientData = NULL;
ff8bfdbb 1352
1ecc4d80 1353 m_isStaticBox = FALSE;
b292e2f5 1354 m_acceptsFocus = FALSE;
ff8bfdbb
VZ
1355
1356#if wxUSE_TOOLTIPS
b1170810 1357 m_toolTip = (wxToolTip*) NULL;
ff8bfdbb 1358#endif // wxUSE_TOOLTIPS
362c6693 1359}
c801d85f 1360
6ca41e57 1361wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
e380f72b
RR
1362 const wxPoint &pos, const wxSize &size,
1363 long style, const wxString &name )
6ca41e57 1364{
e380f72b
RR
1365 m_insertCallback = wxInsertChildInWindow;
1366 Create( parent, id, pos, size, style, name );
6ca41e57 1367}
8bbe427f 1368
debe6624 1369bool wxWindow::Create( wxWindow *parent, wxWindowID id,
e380f72b
RR
1370 const wxPoint &pos, const wxSize &size,
1371 long style, const wxString &name )
c801d85f 1372{
e380f72b
RR
1373 m_isShown = FALSE;
1374 m_isEnabled = TRUE;
1375 m_needParent = TRUE;
47d67540 1376
e380f72b 1377 PreCreation( parent, id, pos, size, style, name );
47d67540 1378
e380f72b 1379 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
38c7b3d3 1380 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
ff8bfdbb 1381
b292e2f5
RR
1382#ifdef __WXDEBUG__
1383 debug_focus_in( m_widget, "wxWindow::m_widget", name );
1384#endif
47d67540 1385
e380f72b 1386 GtkScrolledWindow *s_window = GTK_SCROLLED_WINDOW(m_widget);
47d67540 1387
b292e2f5
RR
1388#ifdef __WXDEBUG__
1389 debug_focus_in( s_window->hscrollbar, "wxWindow::hsrcollbar", name );
1390 debug_focus_in( s_window->vscrollbar, "wxWindow::vsrcollbar", name );
1391#endif
1392
e380f72b
RR
1393 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1394 scroll_class->scrollbar_spacing = 0;
47d67540 1395
e380f72b 1396 gtk_scrolled_window_set_policy( s_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
47d67540 1397
e380f72b
RR
1398 m_oldHorizontalPos = 0.0;
1399 m_oldVerticalPos = 0.0;
47d67540 1400
e380f72b
RR
1401 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->hscrollbar) );
1402 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->vscrollbar) );
47d67540 1403
38c7b3d3
RR
1404 m_wxwindow = gtk_myfixed_new();
1405
b292e2f5
RR
1406#ifdef __WXDEBUG__
1407 debug_focus_in( m_wxwindow, "wxWindow::m_wxwindow", name );
1408#endif
1409
38c7b3d3
RR
1410#ifdef NEW_GTK_SCROLL_CODE
1411 gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(m_widget), m_wxwindow );
1412 GtkViewport *viewport = GTK_VIEWPORT(s_window->child);
1413#else
1414 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
e380f72b 1415 GtkViewport *viewport = GTK_VIEWPORT(s_window->viewport);
38c7b3d3 1416#endif
47d67540 1417
b292e2f5
RR
1418#ifdef __WXDEBUG__
1419 debug_focus_in( GTK_WIDGET(viewport), "wxWindow::viewport", name );
1420#endif
1421
e380f72b
RR
1422 if (m_windowStyle & wxRAISED_BORDER)
1423 {
1424 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
1425 }
1426 else if (m_windowStyle & wxSUNKEN_BORDER)
1427 {
1428 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
1429 }
1430 else
1431 {
1432 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
1433 }
47d67540 1434
3e61c765 1435 if (m_windowStyle & wxTAB_TRAVERSAL)
b292e2f5 1436 {
3e61c765 1437 /* we now allow a window to get the focus as long as it
ff8bfdbb
VZ
1438 doesn't have any children. */
1439 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
b292e2f5
RR
1440 m_acceptsFocus = FALSE;
1441 }
e380f72b 1442 else
b292e2f5 1443 {
e380f72b 1444 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
b292e2f5
RR
1445 m_acceptsFocus = TRUE;
1446 }
e380f72b 1447
e380f72b
RR
1448 // shut the viewport up
1449 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1450 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1451
1452 // I _really_ don't want scrollbars in the beginning
1453 m_vAdjust->lower = 0.0;
1454 m_vAdjust->upper = 1.0;
1455 m_vAdjust->value = 0.0;
1456 m_vAdjust->step_increment = 1.0;
1457 m_vAdjust->page_increment = 1.0;
1458 m_vAdjust->page_size = 5.0;
1459 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1460 m_hAdjust->lower = 0.0;
1461 m_hAdjust->upper = 1.0;
1462 m_hAdjust->value = 0.0;
1463 m_hAdjust->step_increment = 1.0;
1464 m_hAdjust->page_increment = 1.0;
1465 m_hAdjust->page_size = 5.0;
1466 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
1467
76ed8f8d
RR
1468 // these handlers block mouse events to any window during scrolling
1469 // such as motion events and prevent GTK and wxWindows from fighting
1470 // over where the slider should be
8bbe427f 1471
76ed8f8d
RR
1472 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_press_event",
1473 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1474
1475 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_press_event",
1476 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1477
1478 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_release_event",
1479 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1480
1481 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_release_event",
1482 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
8bbe427f 1483
76ed8f8d
RR
1484 // these handers het notified when screen updates are required either when
1485 // scrolling or when the window size (and therefore scrollbar configuration)
1486 // has changed
1487
1488 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
1489 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
1490 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
1491 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
1492
1493 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
1494 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
1495 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
1496 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
1497
e380f72b 1498 gtk_widget_show( m_wxwindow );
8bbe427f 1499
e380f72b 1500 if (m_parent) m_parent->AddChild( this );
47d67540 1501
e380f72b 1502 (m_parent->m_insertCallback)( m_parent, this );
8bbe427f 1503
e380f72b 1504 PostCreation();
8bbe427f 1505
e380f72b 1506 Show( TRUE );
c801d85f 1507
e380f72b 1508 return TRUE;
362c6693 1509}
c801d85f 1510
68dda785 1511wxWindow::~wxWindow()
c801d85f 1512{
1f916a19
JS
1513 // Remove potential dangling pointer
1514 if (GetParent() && GetParent()->IsKindOf(CLASSINFO(wxPanel)))
1515 {
1516 wxPanel* panel = (wxPanel*) GetParent();
1517 if (panel->GetLastFocus() == this)
1518 panel->SetLastFocus((wxWindow*) NULL);
1519 }
1520
43a18898 1521 m_hasVMT = FALSE;
47d67540 1522
06cfab17 1523#if wxUSE_DRAG_AND_DROP
ff8bfdbb 1524 wxDELETE(m_dropTarget);
ac57418f 1525#endif
47d67540 1526
ff8bfdbb
VZ
1527#if wxUSE_TOOLTIPS
1528 wxDELETE(m_toolTip);
1529#endif // wxUSE_TOOLTIPS
b1170810 1530
43a18898
RR
1531 if (m_parent) m_parent->RemoveChild( this );
1532 if (m_widget) Show( FALSE );
c801d85f 1533
43a18898 1534 DestroyChildren();
47d67540 1535
43a18898 1536 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
8bbe427f 1537
43a18898 1538 if (m_scrollGC) gdk_gc_unref( m_scrollGC );
8bbe427f 1539
43a18898 1540 if (m_wxwindow) gtk_widget_destroy( m_wxwindow );
47d67540 1541
43a18898 1542 if (m_widget) gtk_widget_destroy( m_widget );
8bbe427f 1543
43a18898 1544 if (m_cursor) delete m_cursor;
c801d85f 1545
43a18898
RR
1546 DeleteRelatedConstraints();
1547 if (m_constraints)
1548 {
1549 // This removes any dangling pointers to this window
1550 // in other windows' constraintsInvolvedIn lists.
1551 UnsetConstraints(m_constraints);
1552 delete m_constraints;
1553 m_constraints = (wxLayoutConstraints *) NULL;
1554 }
1555 if (m_windowSizer)
1556 {
1557 delete m_windowSizer;
1558 m_windowSizer = (wxSizer *) NULL;
1559 }
1560 // If this is a child of a sizer, remove self from parent
1561 if (m_sizerParent) m_sizerParent->RemoveChild((wxWindow *)this);
c801d85f 1562
43a18898
RR
1563 // Just in case the window has been Closed, but
1564 // we're then deleting immediately: don't leave
1565 // dangling pointers.
1566 wxPendingDelete.DeleteObject(this);
c801d85f 1567
43a18898
RR
1568 // Just in case we've loaded a top-level window via
1569 // wxWindow::LoadNativeDialog but we weren't a dialog
1570 // class
1571 wxTopLevelWindows.DeleteObject(this);
47d67540 1572
43a18898 1573 if (m_windowValidator) delete m_windowValidator;
8bbe427f 1574
43a18898 1575 if (m_clientObject) delete m_clientObject;
362c6693 1576}
c801d85f 1577
debe6624
JS
1578void wxWindow::PreCreation( wxWindow *parent, wxWindowID id,
1579 const wxPoint &pos, const wxSize &size,
1580 long style, const wxString &name )
c801d85f 1581{
3069ac4e 1582 wxASSERT_MSG( (!m_needParent) || (parent), "Need complete parent." );
8bbe427f 1583
43a18898
RR
1584 m_widget = (GtkWidget*) NULL;
1585 m_wxwindow = (GtkWidget*) NULL;
1586 m_hasVMT = FALSE;
1587 m_parent = parent;
1588 m_children.DeleteContents( FALSE );
8bbe427f 1589
43a18898
RR
1590 m_width = size.x;
1591 if (m_width == -1) m_width = 20;
1592 m_height = size.y;
1593 if (m_height == -1) m_height = 20;
8bbe427f 1594
43a18898
RR
1595 m_x = (int)pos.x;
1596 m_y = (int)pos.y;
8bbe427f 1597
43a18898 1598 if (!m_needParent) // some reasonable defaults
6ca41e57 1599 {
43a18898
RR
1600 if (m_x == -1)
1601 {
1602 m_x = (gdk_screen_width () - m_width) / 2;
1603 if (m_x < 10) m_x = 10;
1604 }
1605 if (m_y == -1)
1606 {
1607 m_y = (gdk_screen_height () - m_height) / 2;
1608 if (m_y < 10) m_y = 10;
1609 }
6ca41e57 1610 }
8bbe427f 1611
43a18898
RR
1612 m_minWidth = -1;
1613 m_minHeight = -1;
1614 m_maxWidth = -1;
1615 m_maxHeight = -1;
8bbe427f 1616
43a18898 1617 m_retCode = 0;
8bbe427f 1618
43a18898 1619 m_eventHandler = this;
8bbe427f 1620
b749747d 1621 m_windowId = id == -1 ? wxNewId() : id;
8bbe427f 1622
43a18898 1623 m_sizeSet = FALSE;
8bbe427f 1624
43a18898
RR
1625 m_cursor = new wxCursor( wxCURSOR_ARROW );
1626 m_font = *wxSWISS_FONT;
1ecc4d80
RR
1627 m_backgroundColour = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
1628 m_foregroundColour = *wxBLACK;
43a18898
RR
1629 m_windowStyle = style;
1630 m_windowName = name;
8bbe427f 1631
43a18898
RR
1632 m_constraints = (wxLayoutConstraints *) NULL;
1633 m_constraintsInvolvedIn = (wxList *) NULL;
1634 m_windowSizer = (wxSizer *) NULL;
1635 m_sizerParent = (wxWindow *) NULL;
1636 m_autoLayout = FALSE;
8bbe427f 1637
43a18898
RR
1638 m_hasScrolling = FALSE;
1639 m_isScrolling = FALSE;
1640 m_hAdjust = (GtkAdjustment *) NULL;
1641 m_vAdjust = (GtkAdjustment *) NULL;
1642 m_oldHorizontalPos = 0.0;
1643 m_oldVerticalPos = 0.0;
8bbe427f 1644
43a18898
RR
1645 m_isShown = FALSE;
1646 m_isEnabled = TRUE;
8bbe427f 1647
06cfab17 1648#if wxUSE_DRAG_AND_DROP
43a18898 1649 m_dropTarget = (wxDropTarget *) NULL;
ac57418f 1650#endif
43a18898
RR
1651 m_resizing = FALSE;
1652 m_windowValidator = (wxValidator *) NULL;
1653 m_scrollGC = (GdkGC*) NULL;
1654 m_widgetStyle = (GtkStyle*) NULL;
8bbe427f 1655
43a18898
RR
1656 m_clientObject = (wxClientData*)NULL;
1657 m_clientData = NULL;
ff8bfdbb 1658
1ecc4d80 1659 m_isStaticBox = FALSE;
ff8bfdbb
VZ
1660
1661#if wxUSE_TOOLTIPS
b1170810 1662 m_toolTip = (wxToolTip*) NULL;
ff8bfdbb 1663#endif // wxUSE_TOOLTIPS
c801d85f
KB
1664}
1665
68dda785 1666void wxWindow::PostCreation()
c801d85f 1667{
43a18898
RR
1668 if (m_wxwindow)
1669 {
1670 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
1671 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
47d67540 1672
43a18898
RR
1673 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
1674 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
1675 }
47d67540 1676
43a18898 1677 ConnectWidget( GetConnectWidget() );
47d67540 1678
43a18898 1679 if (m_widget && m_parent) gtk_widget_realize( m_widget );
47d67540 1680
43a18898 1681 if (m_wxwindow) gtk_widget_realize( m_wxwindow );
47d67540 1682
43a18898 1683 SetCursor( *wxSTANDARD_CURSOR );
47d67540 1684
43a18898 1685 m_hasVMT = TRUE;
b4071e91
RR
1686}
1687
1688void wxWindow::ConnectWidget( GtkWidget *widget )
1689{
43a18898
RR
1690 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
1691 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
c801d85f 1692
b666df2c
RR
1693 gtk_signal_connect( GTK_OBJECT(widget), "key_release_event",
1694 GTK_SIGNAL_FUNC(gtk_window_key_release_callback), (gpointer)this );
1695
43a18898
RR
1696 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
1697 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
47d67540 1698
43a18898
RR
1699 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
1700 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
47d67540 1701
43a18898
RR
1702 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
1703 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
47d67540 1704
43a18898
RR
1705 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
1706 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
c801d85f 1707
43a18898
RR
1708 gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
1709 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
c801d85f 1710
43a18898
RR
1711 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
1712 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
47d67540 1713
43a18898
RR
1714 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
1715 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
362c6693 1716}
c801d85f 1717
68dda785 1718bool wxWindow::HasVMT()
c801d85f 1719{
43a18898 1720 return m_hasVMT;
362c6693 1721}
c801d85f 1722
debe6624 1723bool wxWindow::Close( bool force )
c801d85f 1724{
43a18898 1725 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
47d67540 1726
43a18898
RR
1727 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
1728 event.SetEventObject(this);
2b854a32 1729 event.SetCanVeto(!force);
c801d85f 1730
fe4e9e6c
VZ
1731 // return FALSE if window wasn't closed because the application vetoed the
1732 // close event
1733 return GetEventHandler()->ProcessEvent(event) && !event.GetVeto();
362c6693 1734}
c801d85f 1735
68dda785 1736bool wxWindow::Destroy()
c801d85f 1737{
43a18898 1738 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
47d67540 1739
43a18898
RR
1740 m_hasVMT = FALSE;
1741 delete this;
1742 return TRUE;
362c6693 1743}
c801d85f 1744
68dda785 1745bool wxWindow::DestroyChildren()
c801d85f 1746{
db1b4961
RR
1747 wxNode *node;
1748 while ((node = m_children.First()) != (wxNode *)NULL)
c801d85f 1749 {
db1b4961
RR
1750 wxWindow *child;
1751 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL)
43a18898 1752 {
db1b4961
RR
1753 delete child;
1754 if (m_children.Member(child)) delete node;
43a18898 1755 }
362c6693 1756 }
43a18898 1757 return TRUE;
362c6693 1758}
c801d85f
KB
1759
1760void wxWindow::PrepareDC( wxDC &WXUNUSED(dc) )
1761{
43a18898 1762 // are we to set fonts here ?
362c6693 1763}
c801d85f 1764
6ca41e57
RR
1765wxPoint wxWindow::GetClientAreaOrigin() const
1766{
43a18898 1767 return wxPoint(0,0);
6ca41e57
RR
1768}
1769
1770void wxWindow::AdjustForParentClientOrigin( int& x, int& y, int sizeFlags )
1771{
43a18898
RR
1772 if (((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent())
1773 {
1774 wxPoint pt(GetParent()->GetClientAreaOrigin());
8bbe427f 1775 x += pt.x;
43a18898
RR
1776 y += pt.y;
1777 }
6ca41e57
RR
1778}
1779
debe6624 1780void wxWindow::SetSize( int x, int y, int width, int height, int sizeFlags )
c801d85f 1781{
fb1585ae
RR
1782 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1783 wxASSERT_MSG( (m_parent != NULL), "wxWindow::SetSize requires parent.\n" );
8bbe427f 1784
fb1585ae
RR
1785 if (m_resizing) return; // I don't like recursions
1786 m_resizing = TRUE;
47d67540 1787
ba4e3652 1788 if (m_parent->m_wxwindow == NULL) // i.e. wxNotebook
fb1585ae 1789 {
ba4e3652 1790 // don't set the size for children of wxNotebook, just take the values.
fb1585ae
RR
1791 m_x = x;
1792 m_y = y;
1793 m_width = width;
ba4e3652 1794 m_height = height;
fb1585ae 1795 }
ba4e3652 1796 else
fb1585ae 1797 {
ba4e3652
RR
1798 int old_width = m_width;
1799 int old_height = m_height;
8bbe427f 1800
ba4e3652
RR
1801 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
1802 {
1803 if (x != -1) m_x = x;
1804 if (y != -1) m_y = y;
1805 if (width != -1) m_width = width;
1806 if (height != -1) m_height = height;
1807 }
1808 else
1809 {
1810 m_x = x;
1811 m_y = y;
1812 m_width = width;
1813 m_height = height;
1814 }
47d67540 1815
ba4e3652
RR
1816 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
1817 {
1818 if (width == -1) m_width = 80;
1819 }
1820
1821 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
1822 {
1823 if (height == -1) m_height = 26;
1824 }
8bbe427f 1825
ba4e3652
RR
1826 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
1827 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
d3b4d113
RR
1828 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
1829 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
47d67540 1830
3502e687
RR
1831 if (GTK_WIDGET_HAS_DEFAULT(m_widget))
1832 {
1833 /* the default button has a border around it */
1834 int border = 5;
1835
1836 wxPoint pt( m_parent->GetClientAreaOrigin() );
1837 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x+pt.x-border, m_y+pt.y-border );
1838
1839 gtk_widget_set_usize( m_widget, m_width+2*border, m_height+2*border );
1840 }
1841 else
1842 {
1843 wxPoint pt( m_parent->GetClientAreaOrigin() );
1844 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x+pt.x, m_y+pt.y );
1845
1846 if ((old_width != m_width) || (old_height != m_height))
1847 gtk_widget_set_usize( m_widget, m_width, m_height );
1848 }
ba4e3652 1849 }
8bbe427f 1850
fb1585ae 1851 m_sizeSet = TRUE;
47d67540 1852
fb1585ae
RR
1853 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
1854 event.SetEventObject( this );
ba4e3652 1855 GetEventHandler()->ProcessEvent( event );
47d67540 1856
fb1585ae 1857 m_resizing = FALSE;
362c6693 1858}
c801d85f 1859
9390a202
RR
1860void wxWindow::OnInternalIdle()
1861{
1862 UpdateWindowUI();
1863}
1864
debe6624 1865void wxWindow::SetSize( int width, int height )
c801d85f 1866{
fb1585ae 1867 SetSize( -1, -1, width, height, wxSIZE_USE_EXISTING );
362c6693 1868}
c801d85f 1869
debe6624 1870void wxWindow::Move( int x, int y )
c801d85f 1871{
fb1585ae 1872 SetSize( x, y, -1, -1, wxSIZE_USE_EXISTING );
362c6693 1873}
c801d85f
KB
1874
1875void wxWindow::GetSize( int *width, int *height ) const
1876{
1ecc4d80 1877 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 1878
fb1585ae
RR
1879 if (width) (*width) = m_width;
1880 if (height) (*height) = m_height;
362c6693 1881}
c801d85f 1882
debe6624 1883void wxWindow::SetClientSize( int width, int height )
c801d85f 1884{
1ecc4d80 1885 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 1886
1ecc4d80 1887 if (!m_wxwindow)
c801d85f 1888 {
1ecc4d80 1889 SetSize( width, height );
c801d85f
KB
1890 }
1891 else
1892 {
1ecc4d80
RR
1893 int dw = 0;
1894 int dh = 0;
1895
1896 if (!m_hasScrolling)
1897 {
1898 GtkStyleClass *window_class = m_wxwindow->style->klass;
1899
1900 if ((m_windowStyle & wxRAISED_BORDER) ||
1901 (m_windowStyle & wxSUNKEN_BORDER))
1902 {
1903 dw += 2 * window_class->xthickness;
1904 dh += 2 * window_class->ythickness;
1905 }
1906 }
1907 else
1908 {
1909 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1910 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
47d67540 1911
38c7b3d3 1912#ifdef NEW_GTK_SCROLL_CODE
1ecc4d80 1913 GtkWidget *viewport = scroll_window->child;
8bbe427f 1914#else
1ecc4d80 1915 GtkWidget *viewport = scroll_window->viewport;
38c7b3d3
RR
1916#endif
1917
1ecc4d80
RR
1918 GtkStyleClass *viewport_class = viewport->style->klass;
1919
1920 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1921 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1922
1923 if ((m_windowStyle & wxRAISED_BORDER) ||
1924 (m_windowStyle & wxSUNKEN_BORDER))
1925 {
1926 dw += 2 * viewport_class->xthickness;
1927 dh += 2 * viewport_class->ythickness;
1928 }
47d67540 1929
1ecc4d80
RR
1930 if (scroll_window->vscrollbar_visible)
1931 {
1932 dw += vscrollbar->allocation.width;
1933 dw += scroll_class->scrollbar_spacing;
1934 }
1935
1936 if (scroll_window->hscrollbar_visible)
1937 {
1938 dh += hscrollbar->allocation.height;
1939 dw += scroll_class->scrollbar_spacing;
1940 }
1941 }
1942
1943 SetSize( width+dw, height+dh );
1944 }
362c6693 1945}
c801d85f
KB
1946
1947void wxWindow::GetClientSize( int *width, int *height ) const
1948{
1ecc4d80 1949 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 1950
1ecc4d80
RR
1951 if (!m_wxwindow)
1952 {
1953 if (width) (*width) = m_width;
1954 if (height) (*height) = m_height;
c801d85f
KB
1955 }
1956 else
1957 {
1ecc4d80
RR
1958 int dw = 0;
1959 int dh = 0;
1960
1961 if (!m_hasScrolling)
1962 {
1963 GtkStyleClass *window_class = m_wxwindow->style->klass;
1964
1965 if ((m_windowStyle & wxRAISED_BORDER) ||
1966 (m_windowStyle & wxSUNKEN_BORDER))
1967 {
1968 dw += 2 * window_class->xthickness;
1969 dh += 2 * window_class->ythickness;
1970 }
1971 }
1972 else
1973 {
1974 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1975 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
47d67540 1976
38c7b3d3 1977#ifdef NEW_GTK_SCROLL_CODE
1ecc4d80 1978 GtkWidget *viewport = scroll_window->child;
8bbe427f 1979#else
1ecc4d80 1980 GtkWidget *viewport = scroll_window->viewport;
38c7b3d3
RR
1981#endif
1982
1ecc4d80
RR
1983 GtkStyleClass *viewport_class = viewport->style->klass;
1984
1985 if ((m_windowStyle & wxRAISED_BORDER) ||
1986 (m_windowStyle & wxSUNKEN_BORDER))
1987 {
1988 dw += 2 * viewport_class->xthickness;
1989 dh += 2 * viewport_class->ythickness;
1990 }
1991
1992 if (scroll_window->vscrollbar_visible)
1993 {
1994// dw += vscrollbar->allocation.width;
1995 dw += 15; // range.slider_width = 11 + 2*2pts edge
1996 dw += scroll_class->scrollbar_spacing;
1997 }
1998
1999 if (scroll_window->hscrollbar_visible)
2000 {
2001// dh += hscrollbar->allocation.height;
2002 dh += 15;
2003 dh += scroll_class->scrollbar_spacing;
2004 }
2005 }
47d67540 2006
1ecc4d80
RR
2007 if (width) (*width) = m_width - dw;
2008 if (height) (*height) = m_height - dh;
2009 }
362c6693 2010}
c801d85f
KB
2011
2012void wxWindow::GetPosition( int *x, int *y ) const
2013{
1ecc4d80 2014 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2015
43a18898
RR
2016 if (x) (*x) = m_x;
2017 if (y) (*y) = m_y;
362c6693 2018}
c801d85f
KB
2019
2020void wxWindow::ClientToScreen( int *x, int *y )
2021{
1ecc4d80 2022 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2023
43a18898
RR
2024 GdkWindow *source = (GdkWindow *) NULL;
2025 if (m_wxwindow)
2026 source = m_wxwindow->window;
2027 else
2028 source = m_widget->window;
47d67540 2029
43a18898
RR
2030 int org_x = 0;
2031 int org_y = 0;
2032 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2033
43a18898 2034 if (!m_wxwindow)
c801d85f 2035 {
43a18898
RR
2036 if (GTK_WIDGET_NO_WINDOW (m_widget))
2037 {
2038 org_x += m_widget->allocation.x;
2039 org_y += m_widget->allocation.y;
2040 }
362c6693 2041 }
47d67540 2042
43a18898
RR
2043 wxPoint pt(GetClientAreaOrigin());
2044 org_x += pt.x;
2045 org_y += pt.y;
8bbe427f 2046
43a18898
RR
2047 if (x) *x += org_x;
2048 if (y) *y += org_y;
362c6693 2049}
c801d85f
KB
2050
2051void wxWindow::ScreenToClient( int *x, int *y )
2052{
1ecc4d80 2053 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2054
1ecc4d80
RR
2055 GdkWindow *source = (GdkWindow *) NULL;
2056 if (m_wxwindow)
2057 source = m_wxwindow->window;
2058 else
2059 source = m_widget->window;
47d67540 2060
1ecc4d80
RR
2061 int org_x = 0;
2062 int org_y = 0;
2063 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2064
1ecc4d80 2065 if (!m_wxwindow)
c801d85f 2066 {
1ecc4d80
RR
2067 if (GTK_WIDGET_NO_WINDOW (m_widget))
2068 {
2069 org_x += m_widget->allocation.x;
2070 org_y += m_widget->allocation.y;
2071 }
362c6693 2072 }
47d67540 2073
1ecc4d80
RR
2074 wxPoint pt(GetClientAreaOrigin());
2075 org_x -= pt.x;
2076 org_y -= pt.y;
8bbe427f 2077
1ecc4d80
RR
2078 if (x) *x -= org_x;
2079 if (y) *y -= org_y;
362c6693 2080}
c801d85f 2081
debe6624 2082void wxWindow::Centre( int direction )
c801d85f 2083{
1ecc4d80 2084 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2085
1ecc4d80
RR
2086 int x = m_x;
2087 int y = m_y;
8bbe427f 2088
1ecc4d80
RR
2089 if (m_parent)
2090 {
2091 int p_w = 0;
2092 int p_h = 0;
2093 m_parent->GetSize( &p_w, &p_h );
2094 if (direction & wxHORIZONTAL == wxHORIZONTAL) x = (p_w - m_width) / 2;
2095 if (direction & wxVERTICAL == wxVERTICAL) y = (p_h - m_height) / 2;
2096 }
2097 else
2098 {
2099 if (direction & wxHORIZONTAL == wxHORIZONTAL) x = (gdk_screen_width () - m_width) / 2;
2100 if (direction & wxVERTICAL == wxVERTICAL) y = (gdk_screen_height () - m_height) / 2;
2101 }
8bbe427f 2102
1ecc4d80 2103 Move( x, y );
362c6693 2104}
c801d85f 2105
68dda785 2106void wxWindow::Fit()
c801d85f 2107{
1ecc4d80 2108 wxCHECK_RET( (m_widget != NULL), "invalid window" );
5e0aa05a 2109
1ecc4d80
RR
2110 int maxX = 0;
2111 int maxY = 0;
2112 wxNode *node = m_children.First();
2113 while (node)
2114 {
2115 wxWindow *win = (wxWindow *)node->Data();
2116 int wx, wy, ww, wh;
2117 win->GetPosition(&wx, &wy);
2118 win->GetSize(&ww, &wh);
2119 if (wx + ww > maxX) maxX = wx + ww;
2120 if (wy + wh > maxY) maxY = wy + wh;
2121
2122 node = node->Next();
2123 }
ff8bfdbb 2124
1ecc4d80 2125 SetClientSize(maxX + 7, maxY + 14);
362c6693 2126}
c801d85f 2127
2f2aa628
RR
2128void wxWindow::SetSizeHints( int minW, int minH, int maxW, int maxH, int WXUNUSED(incW), int WXUNUSED(incH) )
2129{
1ecc4d80 2130 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2131
1ecc4d80
RR
2132 m_minWidth = minW;
2133 m_minHeight = minH;
2134 m_maxWidth = maxW;
2135 m_maxHeight = maxH;
2f2aa628
RR
2136}
2137
c801d85f
KB
2138void wxWindow::OnSize( wxSizeEvent &WXUNUSED(event) )
2139{
f04371f0 2140// if (GetAutoLayout()) Layout();
362c6693 2141}
c801d85f 2142
debe6624 2143bool wxWindow::Show( bool show )
c801d85f 2144{
1ecc4d80 2145 wxCHECK_MSG( (m_widget != NULL), FALSE, "invalid window" );
47d67540 2146
1ecc4d80
RR
2147 if (show)
2148 gtk_widget_show( m_widget );
2149 else
2150 gtk_widget_hide( m_widget );
ff8bfdbb 2151
1ecc4d80 2152 m_isShown = show;
ff8bfdbb 2153
1ecc4d80 2154 return TRUE;
362c6693 2155}
c801d85f 2156
debe6624 2157void wxWindow::Enable( bool enable )
c801d85f 2158{
1ecc4d80 2159 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2160
1ecc4d80 2161 m_isEnabled = enable;
ff8bfdbb 2162
1ecc4d80
RR
2163 gtk_widget_set_sensitive( m_widget, enable );
2164 if (m_wxwindow) gtk_widget_set_sensitive( m_wxwindow, enable );
362c6693 2165}
c801d85f 2166
68dda785 2167int wxWindow::GetCharHeight() const
c33c4050 2168{
1ecc4d80 2169 wxCHECK_MSG( (m_widget != NULL), 12, "invalid window" );
47d67540 2170
1ecc4d80 2171 wxCHECK_MSG( m_font.Ok(), 12, "invalid font" );
47d67540 2172
1ecc4d80 2173 GdkFont *font = m_font.GetInternalFont( 1.0 );
ff8bfdbb 2174
1ecc4d80 2175 return font->ascent + font->descent;
c33c4050
RR
2176}
2177
68dda785 2178int wxWindow::GetCharWidth() const
c33c4050 2179{
1ecc4d80 2180 wxCHECK_MSG( (m_widget != NULL), 8, "invalid window" );
47d67540 2181
1ecc4d80 2182 wxCHECK_MSG( m_font.Ok(), 8, "invalid font" );
47d67540 2183
463c1fa1 2184 GdkFont *font = m_font.GetInternalFont( 1.0 );
ff8bfdbb 2185
463c1fa1 2186 return gdk_string_width( font, "H" );
c33c4050
RR
2187}
2188
2189void wxWindow::GetTextExtent( const wxString& string, int *x, int *y,
2190 int *descent, int *externalLeading, const wxFont *theFont, bool WXUNUSED(use16) ) const
2191{
463c1fa1
RR
2192 wxFont fontToUse = m_font;
2193 if (theFont) fontToUse = *theFont;
47d67540 2194
1ecc4d80 2195 wxCHECK_RET( fontToUse.Ok(), "invalid font" );
47d67540 2196
463c1fa1
RR
2197 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
2198 if (x) (*x) = gdk_string_width( font, string );
2199 if (y) (*y) = font->ascent + font->descent;
2200 if (descent) (*descent) = font->descent;
2201 if (externalLeading) (*externalLeading) = 0; // ??
c33c4050
RR
2202}
2203
debe6624 2204void wxWindow::MakeModal( bool modal )
c801d85f 2205{
1ecc4d80 2206 return;
ff8bfdbb 2207
1ecc4d80
RR
2208 // Disable all other windows
2209 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
c801d85f 2210 {
1ecc4d80
RR
2211 wxNode *node = wxTopLevelWindows.First();
2212 while (node)
2213 {
2214 wxWindow *win = (wxWindow *)node->Data();
2215 if (win != this) win->Enable(!modal);
c801d85f 2216
1ecc4d80
RR
2217 node = node->Next();
2218 }
c801d85f 2219 }
c801d85f
KB
2220}
2221
b666df2c
RR
2222void wxWindow::OnKeyDown( wxKeyEvent &event )
2223{
2224 event.SetEventType( wxEVT_CHAR );
ff8bfdbb 2225
b666df2c
RR
2226 if (!GetEventHandler()->ProcessEvent( event ))
2227 {
2228 event.Skip();
2229 }
2230}
2231
68dda785 2232void wxWindow::SetFocus()
c801d85f 2233{
1ecc4d80 2234 wxCHECK_RET( (m_widget != NULL), "invalid window" );
ff8bfdbb 2235
463c1fa1
RR
2236 GtkWidget *connect_widget = GetConnectWidget();
2237 if (connect_widget)
c801d85f 2238 {
b292e2f5 2239 if (GTK_WIDGET_CAN_FOCUS(connect_widget) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
463c1fa1
RR
2240 {
2241 gtk_widget_grab_focus (connect_widget);
2242 }
ff8bfdbb
VZ
2243 else if (GTK_IS_CONTAINER(connect_widget))
2244 {
2245 gtk_container_focus( GTK_CONTAINER(connect_widget), GTK_DIR_TAB_FORWARD );
2246 }
2247 else
2248 {
2249 }
362c6693 2250 }
362c6693 2251}
c801d85f 2252
b292e2f5
RR
2253wxWindow *wxWindow::FindFocus()
2254{
2255 return g_focusWindow;
2256}
2257
2258bool wxWindow::AcceptsFocus() const
2259{
2260 return IsEnabled() && IsShown() && m_acceptsFocus;
2261}
2262
c801d85f
KB
2263void wxWindow::AddChild( wxWindow *child )
2264{
1ecc4d80
RR
2265 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2266 wxCHECK_RET( (child != NULL), "invalid child" );
47d67540 2267
463c1fa1 2268 m_children.Append( child );
362c6693 2269}
c801d85f 2270
463c1fa1
RR
2271wxWindow *wxWindow::ReParent( wxWindow *newParent )
2272{
1ecc4d80 2273 wxCHECK_MSG( (m_widget != NULL), (wxWindow*) NULL, "invalid window" );
ff8bfdbb 2274
1ecc4d80 2275 wxWindow *oldParent = GetParent();
8bbe427f 2276
1ecc4d80 2277 if (oldParent) oldParent->RemoveChild( this );
8bbe427f 2278
1ecc4d80 2279 gtk_widget_unparent( m_widget );
8bbe427f 2280
1ecc4d80
RR
2281 if (newParent)
2282 {
2283 newParent->AddChild( this );
2284 (newParent->m_insertCallback)( newParent, this );
2285 }
8bbe427f 2286
1ecc4d80 2287 return oldParent;
362c6693 2288}
c801d85f
KB
2289
2290void wxWindow::RemoveChild( wxWindow *child )
2291{
db1b4961 2292 m_children.DeleteObject( child );
463c1fa1 2293 child->m_parent = (wxWindow *) NULL;
362c6693 2294}
c801d85f
KB
2295
2296void wxWindow::SetReturnCode( int retCode )
2297{
463c1fa1 2298 m_retCode = retCode;
362c6693 2299}
c801d85f 2300
68dda785 2301int wxWindow::GetReturnCode()
c801d85f 2302{
463c1fa1 2303 return m_retCode;
362c6693 2304}
c801d85f 2305
68dda785 2306void wxWindow::Raise()
362c6693 2307{
1ecc4d80 2308 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2309
463c1fa1 2310 if (m_widget) gdk_window_raise( m_widget->window );
362c6693
RR
2311}
2312
68dda785 2313void wxWindow::Lower()
362c6693 2314{
1ecc4d80 2315 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2316
463c1fa1 2317 if (m_widget) gdk_window_lower( m_widget->window );
362c6693 2318}
c801d85f 2319
8bbe427f 2320wxEvtHandler *wxWindow::GetEventHandler() const
c801d85f 2321{
463c1fa1 2322 return m_eventHandler;
362c6693 2323}
c801d85f 2324
86b29a61 2325void wxWindow::SetEventHandler( wxEvtHandler *handler )
c801d85f 2326{
463c1fa1 2327 m_eventHandler = handler;
362c6693 2328}
c801d85f 2329
86b29a61
RR
2330void wxWindow::PushEventHandler(wxEvtHandler *handler)
2331{
463c1fa1
RR
2332 handler->SetNextHandler(GetEventHandler());
2333 SetEventHandler(handler);
86b29a61
RR
2334}
2335
2336wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
2337{
463c1fa1 2338 if (GetEventHandler())
e55ad60e 2339 {
463c1fa1
RR
2340 wxEvtHandler *handlerA = GetEventHandler();
2341 wxEvtHandler *handlerB = handlerA->GetNextHandler();
2342 handlerA->SetNextHandler((wxEvtHandler *) NULL);
2343 SetEventHandler(handlerB);
2344 if (deleteHandler)
2345 {
2346 delete handlerA;
2347 return (wxEvtHandler*) NULL;
2348 }
2349 else
2350 return handlerA;
2351 }
2352 else
2353 return (wxEvtHandler *) NULL;
86b29a61
RR
2354}
2355
68dda785 2356wxValidator *wxWindow::GetValidator()
c801d85f 2357{
463c1fa1 2358 return m_windowValidator;
362c6693 2359}
c801d85f 2360
6de97a3b 2361void wxWindow::SetValidator( const wxValidator& validator )
c801d85f 2362{
1ecc4d80
RR
2363 if (m_windowValidator) delete m_windowValidator;
2364 m_windowValidator = validator.Clone();
2365 if (m_windowValidator) m_windowValidator->SetWindow(this);
362c6693 2366}
c801d85f 2367
fd0eed64
RR
2368void wxWindow::SetClientObject( wxClientData *data )
2369{
1ecc4d80
RR
2370 if (m_clientObject) delete m_clientObject;
2371 m_clientObject = data;
fd0eed64
RR
2372}
2373
2374wxClientData *wxWindow::GetClientObject()
2375{
1ecc4d80 2376 return m_clientObject;
fd0eed64
RR
2377}
2378
2379void wxWindow::SetClientData( void *data )
2380{
1ecc4d80 2381 m_clientData = data;
fd0eed64
RR
2382}
2383
2384void *wxWindow::GetClientData()
2385{
1ecc4d80 2386 return m_clientData;
fd0eed64
RR
2387}
2388
68dda785 2389bool wxWindow::IsBeingDeleted()
c801d85f 2390{
1ecc4d80 2391 return FALSE;
362c6693 2392}
c801d85f
KB
2393
2394void wxWindow::SetId( wxWindowID id )
2395{
1ecc4d80 2396 m_windowId = id;
362c6693 2397}
c801d85f 2398
8bbe427f 2399wxWindowID wxWindow::GetId() const
c801d85f 2400{
1ecc4d80 2401 return m_windowId;
362c6693 2402}
c801d85f
KB
2403
2404void wxWindow::SetCursor( const wxCursor &cursor )
2405{
1ecc4d80 2406 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2407
1ecc4d80
RR
2408 if (cursor.Ok())
2409 {
2410 if (cursor == *m_cursor) return;
2411 *m_cursor = cursor;
2412 }
2413 else
2414 {
2415 *m_cursor = *wxSTANDARD_CURSOR;
2416 }
a3622daa 2417
1ecc4d80
RR
2418 if ((m_widget) && (m_widget->window))
2419 gdk_window_set_cursor( m_widget->window, m_cursor->GetCursor() );
47d67540 2420
1ecc4d80
RR
2421 if ((m_wxwindow) && (m_wxwindow->window))
2422 gdk_window_set_cursor( m_wxwindow->window, m_cursor->GetCursor() );
362c6693 2423}
c801d85f 2424
4f22cf8d
RR
2425void wxWindow::WarpPointer( int WXUNUSED(x), int WXUNUSED(y) )
2426{
2427 // TODO
2428}
2429
debe6624 2430void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
c801d85f 2431{
139adb6a 2432 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2433
139adb6a 2434 if (eraseBackground && m_wxwindow && m_wxwindow->window)
c801d85f 2435 {
139adb6a
RR
2436 if (rect)
2437 {
2438 gdk_window_clear_area( m_wxwindow->window,
2439 rect->x, rect->y,
f234c60c 2440 rect->width, rect->height );
139adb6a
RR
2441 }
2442 else
2443 {
f234c60c 2444 gdk_window_clear( m_wxwindow->window );
139adb6a
RR
2445 }
2446 }
ff8bfdbb 2447
139adb6a
RR
2448 if (!rect)
2449 {
2450 if (m_wxwindow)
2451 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
ff8bfdbb 2452 else
139adb6a 2453 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
362c6693 2454 }
c801d85f 2455 else
139adb6a
RR
2456 {
2457 GdkRectangle gdk_rect;
2458 gdk_rect.x = rect->x;
2459 gdk_rect.y = rect->y;
2460 gdk_rect.width = rect->width;
2461 gdk_rect.height = rect->height;
2462
2463 if (m_wxwindow)
2464 gtk_widget_draw( m_wxwindow, &gdk_rect );
2465 else
2466 gtk_widget_draw( m_widget, &gdk_rect );
2467 }
362c6693 2468}
c801d85f 2469
8429bec1
RR
2470wxRegion wxWindow::GetUpdateRegion() const
2471{
2472 return m_updateRegion;
2473}
2474
2475bool wxWindow::IsExposed( int x, int y) const
c801d85f 2476{
1ecc4d80 2477 return (m_updateRegion.Contains( x, y ) != wxOutRegion );
362c6693 2478}
c801d85f 2479
8429bec1
RR
2480bool wxWindow::IsExposed( int x, int y, int w, int h ) const
2481{
1ecc4d80 2482 return (m_updateRegion.Contains( x, y, w, h ) != wxOutRegion );
8429bec1
RR
2483}
2484
2485bool wxWindow::IsExposed( const wxPoint& pt ) const
2486{
1ecc4d80 2487 return (m_updateRegion.Contains( pt.x, pt.y ) != wxOutRegion );
8429bec1
RR
2488}
2489
2490bool wxWindow::IsExposed( const wxRect& rect ) const
c801d85f 2491{
1ecc4d80 2492 return (m_updateRegion.Contains( rect.x, rect.y, rect.width, rect.height ) != wxOutRegion );
362c6693 2493}
c801d85f 2494
68dda785 2495void wxWindow::Clear()
c801d85f 2496{
3bc755fc 2497 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2498
f234c60c
RR
2499 if (m_wxwindow && m_wxwindow->window)
2500 {
2501 gdk_window_clear( m_wxwindow->window );
2502 }
362c6693 2503}
c801d85f 2504
ff8bfdbb 2505#if wxUSE_TOOLTIPS
b1170810
RR
2506void wxWindow::SetToolTip( const wxString &tip )
2507{
301cd871
RR
2508 if (m_toolTip)
2509 {
2510 m_toolTip->SetTip( tip );
2511 }
2512 else
2513 {
ff8bfdbb 2514 SetToolTip( new wxToolTip( tip ) );
301cd871 2515 }
ff8bfdbb
VZ
2516
2517 // setting empty tooltip text does not remove the tooltip any more for
2518 // wxMSW compatibility - use SetToolTip((wxToolTip *)NULL) for this
b1170810
RR
2519}
2520
2521void wxWindow::SetToolTip( wxToolTip *tip )
2522{
301cd871
RR
2523 if (m_toolTip)
2524 {
2525 m_toolTip->SetTip( (char*) NULL );
2526 delete m_toolTip;
2527 }
ff8bfdbb 2528
b1170810 2529 m_toolTip = tip;
ff8bfdbb
VZ
2530
2531 if (m_toolTip)
2532 m_toolTip->Apply( this );
b1170810
RR
2533}
2534
301cd871 2535void wxWindow::ApplyToolTip( GtkTooltips *tips, const char *tip )
b1170810 2536{
301cd871
RR
2537 gtk_tooltips_set_tip( tips, GetConnectWidget(), tip, (gchar*) NULL );
2538}
ff8bfdbb 2539#endif // wxUSE_TOOLTIPS
b1170810 2540
68dda785 2541wxColour wxWindow::GetBackgroundColour() const
c801d85f 2542{
3bc755fc 2543 return m_backgroundColour;
362c6693 2544}
c801d85f
KB
2545
2546void wxWindow::SetBackgroundColour( const wxColour &colour )
2547{
3bc755fc 2548 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2549
3bc755fc 2550 if (m_backgroundColour == colour) return;
8bbe427f 2551
3bc755fc
RR
2552 m_backgroundColour = colour;
2553 if (!m_backgroundColour.Ok()) return;
8bbe427f 2554
f234c60c 2555 if (m_wxwindow && m_wxwindow->window)
3bc755fc 2556 {
f234c60c
RR
2557 /* wxMSW doesn't clear the window here. I don't do that
2558 either to provide compatibility. call Clear() to do
2559 the job. */
2560
2561 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_wxwindow->window ) );
2562 gdk_window_set_background( m_wxwindow->window, m_backgroundColour.GetColor() );
3bc755fc 2563 }
8bbe427f 2564
ae0bdb01 2565 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
f234c60c 2566
ff8bfdbb
VZ
2567 if (sysbg.Red() == colour.Red() &&
2568 sysbg.Green() == colour.Green() &&
ae0bdb01
RR
2569 sysbg.Blue() == colour.Blue())
2570 {
2571 m_backgroundColour = wxNullColour;
2572 ApplyWidgetStyle();
ff8bfdbb
VZ
2573 m_backgroundColour = sysbg;
2574 }
ae0bdb01
RR
2575 else
2576 {
2577 ApplyWidgetStyle();
2578 }
362c6693 2579}
c801d85f 2580
68dda785 2581wxColour wxWindow::GetForegroundColour() const
6de97a3b 2582{
3bc755fc 2583 return m_foregroundColour;
6de97a3b
RR
2584}
2585
2586void wxWindow::SetForegroundColour( const wxColour &colour )
2587{
3bc755fc 2588 wxCHECK_RET( m_widget != NULL, "invalid window" );
a81258be 2589
3bc755fc 2590 if (m_foregroundColour == colour) return;
8bbe427f 2591
3bc755fc
RR
2592 m_foregroundColour = colour;
2593 if (!m_foregroundColour.Ok()) return;
8bbe427f 2594
ae0bdb01 2595 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
ff8bfdbb
VZ
2596 if (sysbg.Red() == colour.Red() &&
2597 sysbg.Green() == colour.Green() &&
ae0bdb01
RR
2598 sysbg.Blue() == colour.Blue())
2599 {
2600 m_backgroundColour = wxNullColour;
2601 ApplyWidgetStyle();
ff8bfdbb
VZ
2602 m_backgroundColour = sysbg;
2603 }
ae0bdb01
RR
2604 else
2605 {
2606 ApplyWidgetStyle();
2607 }
58614078
RR
2608}
2609
2610GtkStyle *wxWindow::GetWidgetStyle()
2611{
1ecc4d80 2612 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
8bbe427f 2613
1ecc4d80
RR
2614 m_widgetStyle =
2615 gtk_style_copy(
2616 gtk_widget_get_style( m_widget ) );
8bbe427f 2617
1ecc4d80 2618 return m_widgetStyle;
58614078
RR
2619}
2620
2621void wxWindow::SetWidgetStyle()
2622{
1ecc4d80
RR
2623 GtkStyle *style = GetWidgetStyle();
2624
2625 gdk_font_unref( style->font );
2626 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2627
2628 if (m_foregroundColour.Ok())
2629 {
2630 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2631 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2632 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2633 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2634 }
2635
2636 if (m_backgroundColour.Ok())
2637 {
2638 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2639 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2640 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2641 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2642 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2643 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2644 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2645 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2646 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2647 }
a81258be
RR
2648}
2649
58614078 2650void wxWindow::ApplyWidgetStyle()
a81258be 2651{
6de97a3b
RR
2652}
2653
68dda785 2654bool wxWindow::Validate()
c801d85f 2655{
1ecc4d80 2656 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
47d67540 2657
1ecc4d80
RR
2658 wxNode *node = m_children.First();
2659 while (node)
2660 {
2661 wxWindow *child = (wxWindow *)node->Data();
2662 if (child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this))
ff8bfdbb
VZ
2663 {
2664 return FALSE;
2665 }
1ecc4d80
RR
2666 node = node->Next();
2667 }
2668 return TRUE;
362c6693 2669}
c801d85f 2670
68dda785 2671bool wxWindow::TransferDataToWindow()
c801d85f 2672{
1ecc4d80 2673 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
47d67540 2674
1ecc4d80
RR
2675 wxNode *node = m_children.First();
2676 while (node)
c801d85f 2677 {
1ecc4d80
RR
2678 wxWindow *child = (wxWindow *)node->Data();
2679 if (child->GetValidator() && /* child->GetValidator()->Ok() && */
2680 !child->GetValidator()->TransferToWindow() )
2681 {
2682 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK|wxICON_EXCLAMATION );
2683 return FALSE;
2684 }
2685 node = node->Next();
362c6693 2686 }
1ecc4d80 2687 return TRUE;
362c6693 2688}
c801d85f 2689
68dda785 2690bool wxWindow::TransferDataFromWindow()
c801d85f 2691{
1ecc4d80 2692 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
47d67540 2693
1ecc4d80
RR
2694 wxNode *node = m_children.First();
2695 while (node)
2696 {
2697 wxWindow *child = (wxWindow *)node->Data();
2698 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->TransferFromWindow() )
ff8bfdbb
VZ
2699 {
2700 return FALSE;
2701 }
1ecc4d80
RR
2702 node = node->Next();
2703 }
2704 return TRUE;
362c6693 2705}
c801d85f 2706
bcf1fa6b
RR
2707void wxWindow::SetAcceleratorTable( const wxAcceleratorTable& accel )
2708{
1ecc4d80 2709 m_acceleratorTable = accel;
bcf1fa6b
RR
2710}
2711
c801d85f
KB
2712void wxWindow::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
2713{
1ecc4d80 2714 TransferDataToWindow();
362c6693 2715}
c801d85f 2716
68dda785 2717void wxWindow::InitDialog()
c801d85f 2718{
1ecc4d80 2719 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2720
1ecc4d80
RR
2721 wxInitDialogEvent event(GetId());
2722 event.SetEventObject( this );
2723 GetEventHandler()->ProcessEvent(event);
362c6693 2724}
c801d85f 2725
30dea054
RR
2726static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2727{
1ecc4d80
RR
2728 menu->SetInvokingWindow( win );
2729 wxNode *node = menu->m_items.First();
2730 while (node)
2731 {
2732 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2733 if (menuitem->IsSubMenu())
2734 {
ff8bfdbb
VZ
2735 SetInvokingWindow( menuitem->GetSubMenu(), win );
2736 }
1ecc4d80
RR
2737 node = node->Next();
2738 }
362c6693 2739}
30dea054 2740
0c77152e
RR
2741static gint gs_pop_x = 0;
2742static gint gs_pop_y = 0;
2743
2744static void pop_pos_callback( GtkMenu *menu, gint *x, gint *y, wxWindow *win )
2745{
2746 win->ClientToScreen( &gs_pop_x, &gs_pop_y );
2747 *x = gs_pop_x;
2748 *y = gs_pop_y;
2749}
2750
2751bool wxWindow::PopupMenu( wxMenu *menu, int x, int y )
30dea054 2752{
1ecc4d80 2753 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
47d67540 2754
1ecc4d80 2755 wxCHECK_MSG( menu != NULL, FALSE, "invalid popup-menu" );
8bbe427f 2756
1ecc4d80 2757 SetInvokingWindow( menu, this );
ff8bfdbb 2758
631f1bfe
JS
2759 menu->UpdateUI();
2760
0c77152e
RR
2761 gs_pop_x = x;
2762 gs_pop_y = y;
ff8bfdbb 2763
1ecc4d80 2764 gtk_menu_popup(
47d67540 2765 GTK_MENU(menu->m_menu),
0c77152e
RR
2766 (GtkWidget *) NULL, // parent menu shell
2767 (GtkWidget *) NULL, // parent menu item
2768 (GtkMenuPositionFunc) pop_pos_callback,
2769 (gpointer) this, // client data
2770 0, // button used to activate it
2771 0 //gs_timeLastClick // the time of activation
47d67540 2772 );
1ecc4d80 2773 return TRUE;
30dea054
RR
2774}
2775
06cfab17 2776#if wxUSE_DRAG_AND_DROP
ac57418f 2777
c801d85f
KB
2778void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2779{
1ecc4d80 2780 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2781
1ecc4d80 2782 GtkWidget *dnd_widget = GetConnectWidget();
47d67540 2783
1ecc4d80 2784 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
47d67540 2785
1ecc4d80
RR
2786 if (m_dropTarget) delete m_dropTarget;
2787 m_dropTarget = dropTarget;
47d67540 2788
1ecc4d80 2789 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
362c6693 2790}
c801d85f
KB
2791
2792wxDropTarget *wxWindow::GetDropTarget() const
2793{
1ecc4d80 2794 return m_dropTarget;
362c6693 2795}
c801d85f 2796
ac57418f
RR
2797#endif
2798
68dda785 2799GtkWidget* wxWindow::GetConnectWidget()
e3e65dac 2800{
1ecc4d80
RR
2801 GtkWidget *connect_widget = m_widget;
2802 if (m_wxwindow) connect_widget = m_wxwindow;
47d67540 2803
1ecc4d80 2804 return connect_widget;
e3e65dac 2805}
47d67540 2806
903f689b
RR
2807bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2808{
1ecc4d80
RR
2809 if (m_wxwindow) return (window == m_wxwindow->window);
2810 return (window == m_widget->window);
903f689b
RR
2811}
2812
c801d85f
KB
2813void wxWindow::SetFont( const wxFont &font )
2814{
1ecc4d80 2815 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2816
1ecc4d80
RR
2817 if (((wxFont*)&font)->Ok())
2818 m_font = font;
2819 else
2820 m_font = *wxSWISS_FONT;
c801d85f 2821
ae0bdb01 2822 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
ff8bfdbb
VZ
2823 if (sysbg.Red() == m_backgroundColour.Red() &&
2824 sysbg.Green() == m_backgroundColour.Green() &&
ae0bdb01
RR
2825 sysbg.Blue() == m_backgroundColour.Blue())
2826 {
2827 m_backgroundColour = wxNullColour;
2828 ApplyWidgetStyle();
ff8bfdbb
VZ
2829 m_backgroundColour = sysbg;
2830 }
ae0bdb01
RR
2831 else
2832 {
2833 ApplyWidgetStyle();
2834 }
362c6693 2835}
c801d85f
KB
2836
2837void wxWindow::SetWindowStyleFlag( long flag )
2838{
1ecc4d80 2839 m_windowStyle = flag;
362c6693 2840}
c801d85f 2841
68dda785 2842long wxWindow::GetWindowStyleFlag() const
c801d85f 2843{
1ecc4d80 2844 return m_windowStyle;
362c6693 2845}
c801d85f 2846
68dda785 2847void wxWindow::CaptureMouse()
c801d85f 2848{
1ecc4d80 2849 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2850
1ecc4d80 2851 wxCHECK_RET( g_capturing == FALSE, "CaptureMouse called twice" );
47d67540 2852
1ecc4d80
RR
2853 GtkWidget *connect_widget = GetConnectWidget();
2854 gtk_grab_add( connect_widget );
2855 gdk_pointer_grab( connect_widget->window, FALSE,
2856 (GdkEventMask)
2857 (GDK_BUTTON_PRESS_MASK |
2858 GDK_BUTTON_RELEASE_MASK |
2859 GDK_POINTER_MOTION_MASK),
ff8bfdbb
VZ
2860 (GdkWindow *) NULL,
2861 (GdkCursor *) NULL,
2862 GDK_CURRENT_TIME );
1ecc4d80 2863 g_capturing = TRUE;
362c6693 2864}
c801d85f 2865
68dda785 2866void wxWindow::ReleaseMouse()
c801d85f 2867{
1ecc4d80 2868 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2869
1ecc4d80 2870 wxCHECK_RET( g_capturing == TRUE, "ReleaseMouse called twice" );
47d67540 2871
1ecc4d80
RR
2872 GtkWidget *connect_widget = GetConnectWidget();
2873 gtk_grab_remove( connect_widget );
2874 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
2875 g_capturing = FALSE;
362c6693 2876}
c801d85f
KB
2877
2878void wxWindow::SetTitle( const wxString &WXUNUSED(title) )
2879{
362c6693 2880}
c801d85f 2881
68dda785 2882wxString wxWindow::GetTitle() const
c801d85f 2883{
1ecc4d80 2884 return (wxString&)m_windowName;
362c6693 2885}
c801d85f 2886
68dda785 2887wxString wxWindow::GetLabel() const
c801d85f 2888{
1ecc4d80 2889 return GetTitle();
362c6693 2890}
c801d85f
KB
2891
2892void wxWindow::SetName( const wxString &name )
2893{
1ecc4d80 2894 m_windowName = name;
362c6693 2895}
c801d85f 2896
68dda785 2897wxString wxWindow::GetName() const
c801d85f 2898{
1ecc4d80 2899 return (wxString&)m_windowName;
362c6693 2900}
c801d85f 2901
68dda785 2902bool wxWindow::IsShown() const
c801d85f 2903{
1ecc4d80 2904 return m_isShown;
362c6693 2905}
c801d85f 2906
68dda785 2907bool wxWindow::IsRetained()
c801d85f 2908{
1ecc4d80 2909 return FALSE;
362c6693 2910}
c801d85f 2911
debe6624 2912wxWindow *wxWindow::FindWindow( long id )
c801d85f 2913{
1ecc4d80
RR
2914 if (id == m_windowId) return this;
2915 wxNode *node = m_children.First();
2916 while (node)
2917 {
2918 wxWindow *child = (wxWindow*)node->Data();
2919 wxWindow *res = child->FindWindow( id );
2920 if (res) return res;
2921 node = node->Next();
2922 }
2923 return (wxWindow *) NULL;
362c6693 2924}
c801d85f
KB
2925
2926wxWindow *wxWindow::FindWindow( const wxString& name )
2927{
1ecc4d80
RR
2928 if (name == m_windowName) return this;
2929 wxNode *node = m_children.First();
2930 while (node)
2931 {
2932 wxWindow *child = (wxWindow*)node->Data();
2933 wxWindow *res = child->FindWindow( name );
2934 if (res) return res;
2935 node = node->Next();
2936 }
2937 return (wxWindow *) NULL;
362c6693 2938}
c801d85f 2939
debe6624 2940void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
cb43b372 2941 int range, bool refresh )
c801d85f 2942{
1ecc4d80 2943 wxCHECK_RET( m_widget != NULL, "invalid window" );
8bbe427f 2944
1ecc4d80 2945 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
c801d85f 2946
1ecc4d80 2947 m_hasScrolling = TRUE;
47d67540 2948
1ecc4d80 2949 if (orient == wxHORIZONTAL)
cb43b372 2950 {
1ecc4d80
RR
2951 float fpos = (float)pos;
2952 float frange = (float)range;
2953 float fthumb = (float)thumbVisible;
2954 if (fpos > frange-fthumb) fpos = frange-fthumb;
2955 if (fpos < 0.0) fpos = 0.0;
2956
2957 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
2958 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
2959 {
2960 SetScrollPos( orient, pos, refresh );
2961 return;
2962 }
47d67540 2963
1ecc4d80 2964 m_oldHorizontalPos = fpos;
47d67540 2965
1ecc4d80
RR
2966 m_hAdjust->lower = 0.0;
2967 m_hAdjust->upper = frange;
2968 m_hAdjust->value = fpos;
2969 m_hAdjust->step_increment = 1.0;
2970 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
2971 m_hAdjust->page_size = fthumb;
cb43b372 2972 }
1ecc4d80
RR
2973 else
2974 {
2975 float fpos = (float)pos;
2976 float frange = (float)range;
2977 float fthumb = (float)thumbVisible;
2978 if (fpos > frange-fthumb) fpos = frange-fthumb;
2979 if (fpos < 0.0) fpos = 0.0;
2980
2981 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
2982 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
2983 {
2984 SetScrollPos( orient, pos, refresh );
2985 return;
2986 }
47d67540 2987
1ecc4d80 2988 m_oldVerticalPos = fpos;
47d67540 2989
1ecc4d80
RR
2990 m_vAdjust->lower = 0.0;
2991 m_vAdjust->upper = frange;
2992 m_vAdjust->value = fpos;
2993 m_vAdjust->step_increment = 1.0;
2994 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
2995 m_vAdjust->page_size = fthumb;
2996 }
47d67540 2997
1ecc4d80
RR
2998 if (m_wxwindow->window)
2999 {
3000 if (orient == wxHORIZONTAL)
3001 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
3002 else
3003 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
47d67540 3004
1ecc4d80
RR
3005 gtk_widget_set_usize( m_widget, m_width, m_height );
3006 }
362c6693 3007}
c801d85f 3008
debe6624 3009void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
c801d85f 3010{
1ecc4d80
RR
3011 wxCHECK_RET( m_widget != NULL, "invalid window" );
3012
3013 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
3014
3015 if (orient == wxHORIZONTAL)
3016 {
3017 float fpos = (float)pos;
3018 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
3019 if (fpos < 0.0) fpos = 0.0;
3020 m_oldHorizontalPos = fpos;
3021
3022 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
3023 m_hAdjust->value = fpos;
3024 }
3025 else
3026 {
3027 float fpos = (float)pos;
3028 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
3029 if (fpos < 0.0) fpos = 0.0;
3030 m_oldVerticalPos = fpos;
ff8bfdbb 3031
1ecc4d80
RR
3032 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
3033 m_vAdjust->value = fpos;
3034 }
47d67540 3035
1ecc4d80 3036 if (!m_isScrolling)
47d67540 3037 {
1ecc4d80
RR
3038 if (m_wxwindow->window)
3039 {
3040 if (orient == wxHORIZONTAL)
3041 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
3042 else
3043 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
3044 }
cb43b372 3045 }
362c6693 3046}
c801d85f 3047
debe6624 3048int wxWindow::GetScrollThumb( int orient ) const
c801d85f 3049{
1ecc4d80 3050 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
47d67540 3051
1ecc4d80 3052 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
47d67540 3053
1ecc4d80
RR
3054 if (orient == wxHORIZONTAL)
3055 return (int)(m_hAdjust->page_size+0.5);
3056 else
3057 return (int)(m_vAdjust->page_size+0.5);
362c6693 3058}
c801d85f 3059
debe6624 3060int wxWindow::GetScrollPos( int orient ) const
c801d85f 3061{
1ecc4d80 3062 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
47d67540 3063
1ecc4d80 3064 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
c801d85f 3065
1ecc4d80
RR
3066 if (orient == wxHORIZONTAL)
3067 return (int)(m_hAdjust->value+0.5);
3068 else
3069 return (int)(m_vAdjust->value+0.5);
362c6693 3070}
c801d85f 3071
debe6624 3072int wxWindow::GetScrollRange( int orient ) const
c801d85f 3073{
1ecc4d80 3074 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
47d67540 3075
1ecc4d80 3076 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
c801d85f 3077
1ecc4d80
RR
3078 if (orient == wxHORIZONTAL)
3079 return (int)(m_hAdjust->upper+0.5);
3080 else
3081 return (int)(m_vAdjust->upper+0.5);
362c6693 3082}
c801d85f 3083
debe6624 3084void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
c801d85f 3085{
1ecc4d80 3086 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 3087
1ecc4d80 3088 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
c801d85f
KB
3089
3090 int cw = 0;
3091 int ch = 0;
3092 GetClientSize( &cw, &ch );
47d67540 3093
c801d85f
KB
3094 int w = cw - abs(dx);
3095 int h = ch - abs(dy);
3096 if ((h < 0) || (w < 0))
3097 {
1ecc4d80
RR
3098 Refresh();
3099 return;
362c6693 3100 }
c801d85f
KB
3101 int s_x = 0;
3102 int s_y = 0;
3103 if (dx < 0) s_x = -dx;
3104 if (dy < 0) s_y = -dy;
3105 int d_x = 0;
3106 int d_y = 0;
3107 if (dx > 0) d_x = dx;
3108 if (dy > 0) d_y = dy;
8bbe427f 3109
32e9da8b
RR
3110 if (!m_scrollGC)
3111 {
1ecc4d80
RR
3112 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3113 gdk_gc_set_exposures( m_scrollGC, TRUE );
32e9da8b 3114 }
8bbe427f 3115
32e9da8b 3116 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
1ecc4d80 3117 m_wxwindow->window, s_x, s_y, w, h );
47d67540 3118
c801d85f
KB
3119 wxRect rect;
3120 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3121 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3122 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3123 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
47d67540 3124
c801d85f 3125 Refresh( TRUE, &rect );
362c6693 3126}
c801d85f
KB
3127
3128//-------------------------------------------------------------------------------------
3129// Layout
3130//-------------------------------------------------------------------------------------
3131
68dda785 3132wxLayoutConstraints *wxWindow::GetConstraints() const
c801d85f
KB
3133{
3134 return m_constraints;
362c6693 3135}
c801d85f
KB
3136
3137void wxWindow::SetConstraints( wxLayoutConstraints *constraints )
3138{
3139 if (m_constraints)
3140 {
3141 UnsetConstraints(m_constraints);
3142 delete m_constraints;
3143 }
3144 m_constraints = constraints;
3145 if (m_constraints)
3146 {
3147 // Make sure other windows know they're part of a 'meaningful relationship'
3148 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
3149 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3150 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
3151 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3152 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
3153 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3154 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
3155 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3156 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
3157 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3158 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
3159 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3160 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
3161 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3162 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
3163 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3164 }
3165;
3166}
3167;
3168
debe6624 3169void wxWindow::SetAutoLayout( bool autoLayout )
c801d85f
KB
3170{
3171 m_autoLayout = autoLayout;
362c6693 3172}
c801d85f 3173
68dda785 3174bool wxWindow::GetAutoLayout() const
c801d85f
KB
3175{
3176 return m_autoLayout;
362c6693 3177}
c801d85f 3178
68dda785 3179wxSizer *wxWindow::GetSizer() const
c801d85f
KB
3180{
3181 return m_windowSizer;
362c6693 3182}
c801d85f
KB
3183
3184void wxWindow::SetSizerParent( wxWindow *win )
3185{
3186 m_sizerParent = win;
362c6693 3187}
c801d85f 3188
68dda785 3189wxWindow *wxWindow::GetSizerParent() const
c801d85f
KB
3190{
3191 return m_sizerParent;
362c6693 3192}
c801d85f
KB
3193
3194// This removes any dangling pointers to this window
3195// in other windows' constraintsInvolvedIn lists.
3196void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
3197{
3198 if (c)
3199 {
3200 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
3201 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3202 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
3203 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3204 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
3205 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3206 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
3207 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3208 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
3209 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3210 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
3211 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3212 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
3213 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3214 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
3215 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3216 }
3217}
3218
3219// Back-pointer to other windows we're involved with, so if we delete
3220// this window, we must delete any constraints we're involved with.
3221void wxWindow::AddConstraintReference(wxWindow *otherWin)
3222{
3223 if (!m_constraintsInvolvedIn)
3224 m_constraintsInvolvedIn = new wxList;
3225 if (!m_constraintsInvolvedIn->Member(otherWin))
3226 m_constraintsInvolvedIn->Append(otherWin);
3227}
3228
3229// REMOVE back-pointer to other windows we're involved with.
3230void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
3231{
3232 if (m_constraintsInvolvedIn)
3233 m_constraintsInvolvedIn->DeleteObject(otherWin);
3234}
3235
3236// Reset any constraints that mention this window
68dda785 3237void wxWindow::DeleteRelatedConstraints()
c801d85f
KB
3238{
3239 if (m_constraintsInvolvedIn)
3240 {
3241 wxNode *node = m_constraintsInvolvedIn->First();
3242 while (node)
3243 {
3244 wxWindow *win = (wxWindow *)node->Data();
3245 wxNode *next = node->Next();
3246 wxLayoutConstraints *constr = win->GetConstraints();
3247
3248 // Reset any constraints involving this window
3249 if (constr)
3250 {
3251 constr->left.ResetIfWin((wxWindow *)this);
3252 constr->top.ResetIfWin((wxWindow *)this);
3253 constr->right.ResetIfWin((wxWindow *)this);
3254 constr->bottom.ResetIfWin((wxWindow *)this);
3255 constr->width.ResetIfWin((wxWindow *)this);
3256 constr->height.ResetIfWin((wxWindow *)this);
3257 constr->centreX.ResetIfWin((wxWindow *)this);
3258 constr->centreY.ResetIfWin((wxWindow *)this);
3259 }
3260 delete node;
3261 node = next;
3262 }
3263 delete m_constraintsInvolvedIn;
c67daf87 3264 m_constraintsInvolvedIn = (wxList *) NULL;
c801d85f
KB
3265 }
3266}
3267
3268void wxWindow::SetSizer(wxSizer *sizer)
3269{
3270 m_windowSizer = sizer;
3271 if (sizer)
3272 sizer->SetSizerParent((wxWindow *)this);
3273}
3274
3275/*
3276 * New version
3277 */
3278
68dda785 3279bool wxWindow::Layout()
c801d85f
KB
3280{
3281 if (GetConstraints())
3282 {
3283 int w, h;
3284 GetClientSize(&w, &h);
3285 GetConstraints()->width.SetValue(w);
3286 GetConstraints()->height.SetValue(h);
3287 }
47d67540 3288
c801d85f
KB
3289 // If top level (one sizer), evaluate the sizer's constraints.
3290 if (GetSizer())
3291 {
3292 int noChanges;
3293 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
3294 GetSizer()->LayoutPhase1(&noChanges);
3295 GetSizer()->LayoutPhase2(&noChanges);
3296 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
3297 return TRUE;
3298 }
3299 else
3300 {
3301 // Otherwise, evaluate child constraints
3302 ResetConstraints(); // Mark all constraints as unevaluated
3303 DoPhase(1); // Just one phase need if no sizers involved
3304 DoPhase(2);
3305 SetConstraintSizes(); // Recursively set the real window sizes
3306 }
3307 return TRUE;
3308}
3309
3310
3311// Do a phase of evaluating constraints:
3312// the default behaviour. wxSizers may do a similar
3313// thing, but also impose their own 'constraints'
3314// and order the evaluation differently.
3315bool wxWindow::LayoutPhase1(int *noChanges)
3316{
3317 wxLayoutConstraints *constr = GetConstraints();
3318 if (constr)
3319 {
3320 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
3321 }
3322 else
3323 return TRUE;
3324}
3325
3326bool wxWindow::LayoutPhase2(int *noChanges)
3327{
3328 *noChanges = 0;
47d67540 3329
c801d85f
KB
3330 // Layout children
3331 DoPhase(1);
3332 DoPhase(2);
3333 return TRUE;
3334}
3335
3336// Do a phase of evaluating child constraints
debe6624 3337bool wxWindow::DoPhase(int phase)
c801d85f
KB
3338{
3339 int noIterations = 0;
3340 int maxIterations = 500;
3341 int noChanges = 1;
3342 int noFailures = 0;
3343 wxList succeeded;
3344 while ((noChanges > 0) && (noIterations < maxIterations))
3345 {
3346 noChanges = 0;
3347 noFailures = 0;
8bbe427f 3348 wxNode *node = m_children.First();
c801d85f
KB
3349 while (node)
3350 {
3351 wxWindow *child = (wxWindow *)node->Data();
3352 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
3353 {
3354 wxLayoutConstraints *constr = child->GetConstraints();
3355 if (constr)
3356 {
3357 if (succeeded.Member(child))
3358 {
3359 }
3360 else
3361 {
3362 int tempNoChanges = 0;
3363 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
3364 noChanges += tempNoChanges;
3365 if (success)
3366 {
3367 succeeded.Append(child);
3368 }
3369 }
3370 }
3371 }
3372 node = node->Next();
3373 }
3374 noIterations ++;
3375 }
3376 return TRUE;
3377}
3378
68dda785 3379void wxWindow::ResetConstraints()
c801d85f
KB
3380{
3381 wxLayoutConstraints *constr = GetConstraints();
3382 if (constr)
3383 {
3384 constr->left.SetDone(FALSE);
3385 constr->top.SetDone(FALSE);
3386 constr->right.SetDone(FALSE);
3387 constr->bottom.SetDone(FALSE);
3388 constr->width.SetDone(FALSE);
3389 constr->height.SetDone(FALSE);
3390 constr->centreX.SetDone(FALSE);
3391 constr->centreY.SetDone(FALSE);
3392 }
db1b4961 3393 wxNode *node = m_children.First();
c801d85f
KB
3394 while (node)
3395 {
3396 wxWindow *win = (wxWindow *)node->Data();
3397 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
3398 win->ResetConstraints();
3399 node = node->Next();
3400 }
3401}
3402
3403// Need to distinguish between setting the 'fake' size for
3404// windows and sizers, and setting the real values.
debe6624 3405void wxWindow::SetConstraintSizes(bool recurse)
c801d85f
KB
3406{
3407 wxLayoutConstraints *constr = GetConstraints();
3408 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
3409 constr->width.GetDone() && constr->height.GetDone())
3410 {
3411 int x = constr->left.GetValue();
3412 int y = constr->top.GetValue();
3413 int w = constr->width.GetValue();
3414 int h = constr->height.GetValue();
3415
3416 // If we don't want to resize this window, just move it...
3417 if ((constr->width.GetRelationship() != wxAsIs) ||
3418 (constr->height.GetRelationship() != wxAsIs))
3419 {
3420 // Calls Layout() recursively. AAAGH. How can we stop that.
3421 // Simply take Layout() out of non-top level OnSizes.
3422 SizerSetSize(x, y, w, h);
3423 }
3424 else
3425 {
3426 SizerMove(x, y);
3427 }
3428 }
3429 else if (constr)
3430 {
3431 char *windowClass = this->GetClassInfo()->GetClassName();
3432
3433 wxString winName;
5e0aa05a 3434 if (GetName() == "")
3069ac4e 3435 winName = "unnamed";
5e0aa05a
VZ
3436 else
3437 winName = GetName();
ff8bfdbb
VZ
3438 wxLogDebug( "Constraint(s) not satisfied for window of type %s, name %s:\n",
3439 (const char *)windowClass,
3440 (const char *)winName);
3069ac4e
RR
3441 if (!constr->left.GetDone()) wxLogDebug( " unsatisfied 'left' constraint.\n" );
3442 if (!constr->right.GetDone()) wxLogDebug( " unsatisfied 'right' constraint.\n" );
3443 if (!constr->width.GetDone()) wxLogDebug( " unsatisfied 'width' constraint.\n" );
3444 if (!constr->height.GetDone()) wxLogDebug( " unsatisfied 'height' constraint.\n" );
3445 wxLogDebug( "Please check constraints: try adding AsIs() constraints.\n" );
c801d85f
KB
3446 }
3447
3448 if (recurse)
3449 {
db1b4961 3450 wxNode *node = m_children.First();
c801d85f
KB
3451 while (node)
3452 {
3453 wxWindow *win = (wxWindow *)node->Data();
3454 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
3455 win->SetConstraintSizes();
3456 node = node->Next();
3457 }
3458 }
3459}
3460
3461// This assumes that all sizers are 'on' the same
3462// window, i.e. the parent of this window.
3463void wxWindow::TransformSizerToActual(int *x, int *y) const
3464{
3465 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
5e0aa05a 3466 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
c801d85f 3467 return;
47d67540 3468
c801d85f
KB
3469 int xp, yp;
3470 m_sizerParent->GetPosition(&xp, &yp);
3471 m_sizerParent->TransformSizerToActual(&xp, &yp);
3472 *x += xp;
3473 *y += yp;
3474}
3475
debe6624 3476void wxWindow::SizerSetSize(int x, int y, int w, int h)
c801d85f 3477{
5e0aa05a
VZ
3478 int xx = x;
3479 int yy = y;
c801d85f
KB
3480 TransformSizerToActual(&xx, &yy);
3481 SetSize(xx, yy, w, h);
3482}
3483
debe6624 3484void wxWindow::SizerMove(int x, int y)
c801d85f 3485{
5e0aa05a
VZ
3486 int xx = x;
3487 int yy = y;
c801d85f
KB
3488 TransformSizerToActual(&xx, &yy);
3489 Move(xx, yy);
3490}
3491
3492// Only set the size/position of the constraint (if any)
debe6624 3493void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
c801d85f
KB
3494{
3495 wxLayoutConstraints *constr = GetConstraints();
3496 if (constr)
3497 {
3498 if (x != -1)
3499 {
3500 constr->left.SetValue(x);
3501 constr->left.SetDone(TRUE);
3502 }
3503 if (y != -1)
3504 {
3505 constr->top.SetValue(y);
3506 constr->top.SetDone(TRUE);
3507 }
3508 if (w != -1)
3509 {
3510 constr->width.SetValue(w);
3511 constr->width.SetDone(TRUE);
3512 }
3513 if (h != -1)
3514 {
3515 constr->height.SetValue(h);
3516 constr->height.SetDone(TRUE);
3517 }
3518 }
3519}
3520
debe6624 3521void wxWindow::MoveConstraint(int x, int y)
c801d85f
KB
3522{
3523 wxLayoutConstraints *constr = GetConstraints();
3524 if (constr)
3525 {
3526 if (x != -1)
3527 {
3528 constr->left.SetValue(x);
3529 constr->left.SetDone(TRUE);
3530 }
3531 if (y != -1)
3532 {
3533 constr->top.SetValue(y);
3534 constr->top.SetDone(TRUE);
3535 }
3536 }
3537}
3538
3539void wxWindow::GetSizeConstraint(int *w, int *h) const
3540{
3541 wxLayoutConstraints *constr = GetConstraints();
3542 if (constr)
3543 {
3544 *w = constr->width.GetValue();
3545 *h = constr->height.GetValue();
3546 }
3547 else
3548 GetSize(w, h);
3549}
3550
3551void wxWindow::GetClientSizeConstraint(int *w, int *h) const
3552{
3553 wxLayoutConstraints *constr = GetConstraints();
3554 if (constr)
3555 {
3556 *w = constr->width.GetValue();
3557 *h = constr->height.GetValue();
3558 }
3559 else
3560 GetClientSize(w, h);
3561}
3562
3563void wxWindow::GetPositionConstraint(int *x, int *y) const
3564{
b292e2f5
RR
3565 wxLayoutConstraints *constr = GetConstraints();
3566 if (constr)
c801d85f
KB
3567 {
3568 *x = constr->left.GetValue();
3569 *y = constr->top.GetValue();
3570 }
3571 else
3572 GetPosition(x, y);
3573}
3574