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