]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/window.cpp
wxCheckListBox fixes: crash/memory leak when items are dynamically
[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;
47d67540 1084
e380f72b 1085 wxEventType command = wxEVT_NULL;
47d67540 1086
e380f72b
RR
1087 float line_step = win->m_vAdjust->step_increment;
1088 float page_step = win->m_vAdjust->page_increment;
47d67540 1089
76ed8f8d
RR
1090 if (win->m_isScrolling)
1091 {
1092 command = wxEVT_SCROLL_THUMBTRACK;
1093 }
1094 else
1095 {
1096 if (fabs(win->m_vAdjust->value-win->m_vAdjust->lower) < 0.2) command = wxEVT_SCROLL_BOTTOM;
1097 else if (fabs(win->m_vAdjust->value-win->m_vAdjust->upper) < 0.2) command = wxEVT_SCROLL_TOP;
1098 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLL_LINEDOWN;
1099 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLL_LINEUP;
1100 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLL_PAGEDOWN;
1101 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLL_PAGEUP;
1102 else command = wxEVT_SCROLL_THUMBTRACK;
1103 }
47d67540 1104
e380f72b 1105 int value = (int)(win->m_vAdjust->value+0.5);
c801d85f 1106
e380f72b
RR
1107 wxScrollEvent event( command, win->GetId(), value, wxVERTICAL );
1108 event.SetEventObject( win );
1109 win->GetEventHandler()->ProcessEvent( event );
362c6693 1110}
c801d85f
KB
1111
1112//-----------------------------------------------------------------------------
2f2aa628
RR
1113// "value_changed" from m_hAdjust
1114//-----------------------------------------------------------------------------
c801d85f 1115
2f2aa628 1116static void gtk_window_hscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
47d67540 1117{
e380f72b 1118 if (g_blockEventsOnDrag) return;
47d67540 1119
c801d85f 1120/*
e380f72b
RR
1121 printf( "OnHScroll from " );
1122 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1123 printf( win->GetClassInfo()->GetClassName() );
1124 printf( ".\n" );
c801d85f 1125*/
47d67540 1126
e380f72b 1127 if (!win->HasVMT()) return;
47d67540 1128
e380f72b
RR
1129 float diff = win->m_hAdjust->value - win->m_oldHorizontalPos;
1130 if (fabs(diff) < 0.2) return;
47d67540 1131
e380f72b 1132 wxEventType command = wxEVT_NULL;
47d67540 1133
e380f72b
RR
1134 float line_step = win->m_hAdjust->step_increment;
1135 float page_step = win->m_hAdjust->page_increment;
8bbe427f 1136
76ed8f8d
RR
1137 if (win->m_isScrolling)
1138 {
1139 command = wxEVT_SCROLL_THUMBTRACK;
1140 }
1141 else
1142 {
1143 if (fabs(win->m_hAdjust->value-win->m_hAdjust->lower) < 0.2) command = wxEVT_SCROLL_BOTTOM;
1144 else if (fabs(win->m_hAdjust->value-win->m_hAdjust->upper) < 0.2) command = wxEVT_SCROLL_TOP;
1145 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLL_LINEDOWN;
1146 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLL_LINEUP;
1147 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLL_PAGEDOWN;
1148 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLL_PAGEUP;
1149 else command = wxEVT_SCROLL_THUMBTRACK;
1150 }
c801d85f 1151
e380f72b 1152 int value = (int)(win->m_hAdjust->value+0.5);
47d67540 1153
e380f72b
RR
1154 wxScrollEvent event( command, win->GetId(), value, wxHORIZONTAL );
1155 event.SetEventObject( win );
1156 win->GetEventHandler()->ProcessEvent( event );
362c6693 1157}
c801d85f
KB
1158
1159//-----------------------------------------------------------------------------
2f2aa628
RR
1160// "changed" from m_vAdjust
1161//-----------------------------------------------------------------------------
c801d85f 1162
2f2aa628 1163static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
c801d85f 1164{
e380f72b 1165 if (g_blockEventsOnDrag) return;
c801d85f
KB
1166
1167/*
e380f72b
RR
1168 printf( "OnVScroll change from " );
1169 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1170 printf( win->GetClassInfo()->GetClassName() );
1171 printf( ".\n" );
c801d85f 1172*/
47d67540 1173
e380f72b 1174 if (!win->HasVMT()) return;
47d67540 1175
e380f72b
RR
1176 wxEventType command = wxEVT_SCROLL_THUMBTRACK;
1177 int value = (int)(win->m_vAdjust->value+0.5);
c801d85f 1178
e380f72b
RR
1179 wxScrollEvent event( command, win->GetId(), value, wxVERTICAL );
1180 event.SetEventObject( win );
1181 win->GetEventHandler()->ProcessEvent( event );
362c6693 1182}
c801d85f
KB
1183
1184//-----------------------------------------------------------------------------
2f2aa628
RR
1185// "changed" from m_hAdjust
1186//-----------------------------------------------------------------------------
c801d85f 1187
2f2aa628 1188static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
47d67540 1189{
e380f72b 1190 if (g_blockEventsOnDrag) return;
47d67540 1191
c801d85f 1192/*
e380f72b
RR
1193 printf( "OnHScroll change from " );
1194 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1195 printf( win->GetClassInfo()->GetClassName() );
1196 printf( ".\n" );
c801d85f 1197*/
47d67540 1198
e380f72b 1199 if (!win->HasVMT()) return;
47d67540 1200
e380f72b
RR
1201 wxEventType command = wxEVT_SCROLL_THUMBTRACK;
1202 int value = (int)(win->m_hAdjust->value+0.5);
47d67540 1203
e380f72b
RR
1204 wxScrollEvent event( command, win->GetId(), value, wxHORIZONTAL );
1205 event.SetEventObject( win );
1206 win->GetEventHandler()->ProcessEvent( event );
362c6693 1207}
c801d85f 1208
cb43b372
RR
1209//-----------------------------------------------------------------------------
1210// "button_press_event" from scrollbar
1211//-----------------------------------------------------------------------------
1212
8bbe427f
VZ
1213static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
1214 GdkEventButton *WXUNUSED(gdk_event),
ff8bfdbb 1215 wxWindow *win )
cb43b372 1216{
1ecc4d80
RR
1217// don't test here as we can release the mouse while being over
1218// a different window then the slider
1219//
76ed8f8d 1220// if (gdk_event->window != widget->slider) return FALSE;
8bbe427f 1221
e380f72b 1222 win->m_isScrolling = TRUE;
76ed8f8d 1223 g_blockEventsOnScroll = TRUE;
47d67540 1224
e380f72b 1225 return FALSE;
cb43b372
RR
1226}
1227
1228//-----------------------------------------------------------------------------
1229// "button_release_event" from scrollbar
1230//-----------------------------------------------------------------------------
1231
8bbe427f
VZ
1232static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
1233 GdkEventButton *WXUNUSED(gdk_event),
ff8bfdbb 1234 wxWindow *win )
cb43b372 1235{
76ed8f8d 1236
1ecc4d80 1237// don't test here as we can release the mouse while being over
76ed8f8d
RR
1238// a different window then the slider
1239//
1240// if (gdk_event->window != widget->slider) return FALSE;
cb43b372 1241
e380f72b 1242 GtkScrolledWindow *s_window = GTK_SCROLLED_WINDOW(win->m_widget);
47d67540 1243
e380f72b
RR
1244 if (widget == GTK_RANGE(s_window->vscrollbar))
1245 gtk_signal_emit_by_name( GTK_OBJECT(win->m_hAdjust), "value_changed" );
1246 else
1247 gtk_signal_emit_by_name( GTK_OBJECT(win->m_vAdjust), "value_changed" );
47d67540 1248
e380f72b 1249 win->m_isScrolling = FALSE;
76ed8f8d 1250 g_blockEventsOnScroll = FALSE;
47d67540 1251
e380f72b 1252 return FALSE;
cb43b372
RR
1253}
1254
6ca41e57
RR
1255//-----------------------------------------------------------------------------
1256// InsertChild for wxWindow.
1257//-----------------------------------------------------------------------------
1258
b1170810
RR
1259/* Callback for wxWindow. This very strange beast has to be used because
1260 * C++ has no virtual methods in a constructor. We have to emulate a
1261 * virtual function here as wxNotebook requires a different way to insert
1262 * a child in it. I had opted for creating a wxNotebookPage window class
1263 * which would have made this superfluous (such in the MDI window system),
1264 * but no-one was listening to me... */
6ca41e57
RR
1265
1266static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
1267{
8bbe427f
VZ
1268 gtk_myfixed_put( GTK_MYFIXED(parent->m_wxwindow),
1269 GTK_WIDGET(child->m_widget),
ff8bfdbb
VZ
1270 child->m_x,
1271 child->m_y );
6ca41e57 1272
8bbe427f
VZ
1273 gtk_widget_set_usize( GTK_WIDGET(child->m_widget),
1274 child->m_width,
ff8bfdbb
VZ
1275 child->m_height );
1276
5b077d48
RR
1277 if (wxIS_KIND_OF(parent,wxFrame))
1278 {
1279 parent->m_sizeSet = FALSE;
1280 }
ff8bfdbb 1281
3e61c765
RR
1282 if (parent->m_windowStyle & wxTAB_TRAVERSAL)
1283 {
1284 /* we now allow a window to get the focus as long as it
ff8bfdbb
VZ
1285 doesn't have any children. */
1286 GTK_WIDGET_UNSET_FLAGS( parent->m_wxwindow, GTK_CAN_FOCUS );
3e61c765 1287 }
6ca41e57
RR
1288}
1289
bbe0af5b
RR
1290//-----------------------------------------------------------------------------
1291// global functions
1292//-----------------------------------------------------------------------------
1293
1294wxWindow* wxGetActiveWindow()
1295{
1296 return g_focusWindow;
1297}
1298
c801d85f 1299//-----------------------------------------------------------------------------
2f2aa628 1300// wxWindow
c801d85f
KB
1301//-----------------------------------------------------------------------------
1302
1303IMPLEMENT_DYNAMIC_CLASS(wxWindow,wxEvtHandler)
1304
1305BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler)
e380f72b
RR
1306 EVT_SIZE(wxWindow::OnSize)
1307 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
1308 EVT_INIT_DIALOG(wxWindow::OnInitDialog)
b666df2c 1309 EVT_KEY_DOWN(wxWindow::OnKeyDown)
c801d85f
KB
1310END_EVENT_TABLE()
1311
68995f26 1312void wxWindow::Init()
c801d85f 1313{
68995f26
VZ
1314 m_isWindow = TRUE;
1315
e380f72b
RR
1316 m_widget = (GtkWidget *) NULL;
1317 m_wxwindow = (GtkWidget *) NULL;
1318 m_parent = (wxWindow *) NULL;
1319 m_children.DeleteContents( FALSE );
8bbe427f 1320
e380f72b
RR
1321 m_x = 0;
1322 m_y = 0;
1323 m_width = 0;
1324 m_height = 0;
1325 m_minWidth = -1;
1326 m_minHeight = -1;
1327 m_maxWidth = -1;
1328 m_maxHeight = -1;
8bbe427f 1329
e380f72b 1330 m_retCode = 0;
8bbe427f 1331
e380f72b
RR
1332 m_eventHandler = this;
1333 m_windowValidator = (wxValidator *) NULL;
8bbe427f 1334
e380f72b 1335 m_windowId = -1;
8bbe427f 1336
e380f72b
RR
1337 m_cursor = (wxCursor *) NULL;
1338 m_font = *wxSWISS_FONT;
1339 m_windowStyle = 0;
1340 m_windowName = "noname";
8bbe427f 1341
e380f72b
RR
1342 m_constraints = (wxLayoutConstraints *) NULL;
1343 m_constraintsInvolvedIn = (wxList *) NULL;
1344 m_windowSizer = (wxSizer *) NULL;
1345 m_sizerParent = (wxWindow *) NULL;
1346 m_autoLayout = FALSE;
8bbe427f 1347
e380f72b
RR
1348 m_sizeSet = FALSE;
1349 m_hasVMT = FALSE;
1350 m_needParent = TRUE;
8bbe427f 1351
e380f72b
RR
1352 m_hasScrolling = FALSE;
1353 m_isScrolling = FALSE;
1354 m_hAdjust = (GtkAdjustment*) NULL;
1355 m_vAdjust = (GtkAdjustment*) NULL;
1356 m_oldHorizontalPos = 0.0;
1357 m_oldVerticalPos = 0.0;
8bbe427f 1358
e380f72b
RR
1359 m_isShown = FALSE;
1360 m_isEnabled = TRUE;
8bbe427f 1361
06cfab17 1362#if wxUSE_DRAG_AND_DROP
e380f72b 1363 m_dropTarget = (wxDropTarget*) NULL;
ac57418f 1364#endif
e380f72b
RR
1365 m_resizing = FALSE;
1366 m_scrollGC = (GdkGC*) NULL;
1367 m_widgetStyle = (GtkStyle*) NULL;
8bbe427f 1368
e380f72b 1369 m_insertCallback = wxInsertChildInWindow;
8bbe427f 1370
e380f72b
RR
1371 m_clientObject = (wxClientData*) NULL;
1372 m_clientData = NULL;
ff8bfdbb 1373
1ecc4d80 1374 m_isStaticBox = FALSE;
b292e2f5 1375 m_acceptsFocus = FALSE;
ff8bfdbb
VZ
1376
1377#if wxUSE_TOOLTIPS
b1170810 1378 m_toolTip = (wxToolTip*) NULL;
ff8bfdbb 1379#endif // wxUSE_TOOLTIPS
362c6693 1380}
c801d85f 1381
68995f26
VZ
1382wxWindow::wxWindow()
1383{
1384 Init();
1385}
1386
6ca41e57 1387wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
e380f72b
RR
1388 const wxPoint &pos, const wxSize &size,
1389 long style, const wxString &name )
6ca41e57 1390{
68995f26
VZ
1391 Init();
1392
e380f72b 1393 Create( parent, id, pos, size, style, name );
6ca41e57 1394}
8bbe427f 1395
debe6624 1396bool wxWindow::Create( wxWindow *parent, wxWindowID id,
e380f72b
RR
1397 const wxPoint &pos, const wxSize &size,
1398 long style, const wxString &name )
c801d85f 1399{
68995f26 1400 wxASSERT_MSG( m_isWindow, "Init() must have been called before!" );
47d67540 1401
e380f72b 1402 PreCreation( parent, id, pos, size, style, name );
47d67540 1403
e380f72b 1404 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
38c7b3d3 1405 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
ff8bfdbb 1406
b292e2f5
RR
1407#ifdef __WXDEBUG__
1408 debug_focus_in( m_widget, "wxWindow::m_widget", name );
1409#endif
47d67540 1410
e380f72b 1411 GtkScrolledWindow *s_window = GTK_SCROLLED_WINDOW(m_widget);
47d67540 1412
b292e2f5
RR
1413#ifdef __WXDEBUG__
1414 debug_focus_in( s_window->hscrollbar, "wxWindow::hsrcollbar", name );
1415 debug_focus_in( s_window->vscrollbar, "wxWindow::vsrcollbar", name );
1416#endif
1417
e380f72b
RR
1418 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1419 scroll_class->scrollbar_spacing = 0;
47d67540 1420
e380f72b 1421 gtk_scrolled_window_set_policy( s_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
47d67540 1422
e380f72b
RR
1423 m_oldHorizontalPos = 0.0;
1424 m_oldVerticalPos = 0.0;
47d67540 1425
e380f72b
RR
1426 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->hscrollbar) );
1427 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->vscrollbar) );
47d67540 1428
38c7b3d3
RR
1429 m_wxwindow = gtk_myfixed_new();
1430
b292e2f5
RR
1431#ifdef __WXDEBUG__
1432 debug_focus_in( m_wxwindow, "wxWindow::m_wxwindow", name );
1433#endif
1434
38c7b3d3
RR
1435#ifdef NEW_GTK_SCROLL_CODE
1436 gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(m_widget), m_wxwindow );
1437 GtkViewport *viewport = GTK_VIEWPORT(s_window->child);
1438#else
1439 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
e380f72b 1440 GtkViewport *viewport = GTK_VIEWPORT(s_window->viewport);
38c7b3d3 1441#endif
47d67540 1442
b292e2f5
RR
1443#ifdef __WXDEBUG__
1444 debug_focus_in( GTK_WIDGET(viewport), "wxWindow::viewport", name );
1445#endif
1446
e380f72b
RR
1447 if (m_windowStyle & wxRAISED_BORDER)
1448 {
1449 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
1450 }
1451 else if (m_windowStyle & wxSUNKEN_BORDER)
1452 {
1453 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
1454 }
1455 else
1456 {
1457 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
1458 }
47d67540 1459
3e61c765 1460 if (m_windowStyle & wxTAB_TRAVERSAL)
b292e2f5 1461 {
3e61c765 1462 /* we now allow a window to get the focus as long as it
ff8bfdbb
VZ
1463 doesn't have any children. */
1464 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
b292e2f5
RR
1465 m_acceptsFocus = FALSE;
1466 }
e380f72b 1467 else
b292e2f5 1468 {
e380f72b 1469 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
b292e2f5
RR
1470 m_acceptsFocus = TRUE;
1471 }
e380f72b 1472
e380f72b
RR
1473 // shut the viewport up
1474 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1475 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1476
1477 // I _really_ don't want scrollbars in the beginning
1478 m_vAdjust->lower = 0.0;
1479 m_vAdjust->upper = 1.0;
1480 m_vAdjust->value = 0.0;
1481 m_vAdjust->step_increment = 1.0;
1482 m_vAdjust->page_increment = 1.0;
1483 m_vAdjust->page_size = 5.0;
1484 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1485 m_hAdjust->lower = 0.0;
1486 m_hAdjust->upper = 1.0;
1487 m_hAdjust->value = 0.0;
1488 m_hAdjust->step_increment = 1.0;
1489 m_hAdjust->page_increment = 1.0;
1490 m_hAdjust->page_size = 5.0;
1491 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
1492
76ed8f8d
RR
1493 // these handlers block mouse events to any window during scrolling
1494 // such as motion events and prevent GTK and wxWindows from fighting
1495 // over where the slider should be
8bbe427f 1496
76ed8f8d
RR
1497 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_press_event",
1498 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1499
1500 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_press_event",
1501 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1502
1503 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_release_event",
1504 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1505
1506 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_release_event",
1507 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
8bbe427f 1508
76ed8f8d
RR
1509 // these handers het notified when screen updates are required either when
1510 // scrolling or when the window size (and therefore scrollbar configuration)
1511 // has changed
1512
1513 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
1514 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
1515 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
1516 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
1517
1518 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
1519 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
1520 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
1521 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
1522
e380f72b 1523 gtk_widget_show( m_wxwindow );
8bbe427f 1524
e380f72b 1525 if (m_parent) m_parent->AddChild( this );
47d67540 1526
e380f72b 1527 (m_parent->m_insertCallback)( m_parent, this );
8bbe427f 1528
e380f72b 1529 PostCreation();
8bbe427f 1530
e380f72b 1531 Show( TRUE );
c801d85f 1532
e380f72b 1533 return TRUE;
362c6693 1534}
c801d85f 1535
68dda785 1536wxWindow::~wxWindow()
c801d85f 1537{
43a18898 1538 m_hasVMT = FALSE;
47d67540 1539
06cfab17 1540#if wxUSE_DRAG_AND_DROP
e27ce4e9
RR
1541 if (m_dropTarget)
1542 {
1543 delete m_dropTarget;
1544 m_dropTarget = (wxDropTarget*) NULL;
1545 }
ac57418f 1546#endif
47d67540 1547
ff8bfdbb 1548#if wxUSE_TOOLTIPS
e27ce4e9
RR
1549 if (m_toolTip)
1550 {
1551 delete m_toolTip;
1552 m_toolTip = (wxToolTip*) NULL;
1553 }
ff8bfdbb 1554#endif // wxUSE_TOOLTIPS
b1170810 1555
43a18898 1556 if (m_widget) Show( FALSE );
c801d85f 1557
43a18898 1558 DestroyChildren();
47d67540 1559
e27ce4e9
RR
1560 if (m_parent) m_parent->RemoveChild( this );
1561
43a18898 1562 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
8bbe427f 1563
43a18898 1564 if (m_scrollGC) gdk_gc_unref( m_scrollGC );
8bbe427f 1565
43a18898 1566 if (m_wxwindow) gtk_widget_destroy( m_wxwindow );
47d67540 1567
43a18898 1568 if (m_widget) gtk_widget_destroy( m_widget );
8bbe427f 1569
43a18898 1570 if (m_cursor) delete m_cursor;
c801d85f 1571
43a18898
RR
1572 DeleteRelatedConstraints();
1573 if (m_constraints)
1574 {
e27ce4e9
RR
1575 /* This removes any dangling pointers to this window
1576 * in other windows' constraintsInvolvedIn lists. */
43a18898
RR
1577 UnsetConstraints(m_constraints);
1578 delete m_constraints;
1579 m_constraints = (wxLayoutConstraints *) NULL;
1580 }
e27ce4e9 1581
43a18898
RR
1582 if (m_windowSizer)
1583 {
1584 delete m_windowSizer;
1585 m_windowSizer = (wxSizer *) NULL;
1586 }
e27ce4e9 1587 /* If this is a child of a sizer, remove self from parent */
43a18898 1588 if (m_sizerParent) m_sizerParent->RemoveChild((wxWindow *)this);
c801d85f 1589
e27ce4e9
RR
1590 /* Just in case the window has been Closed, but
1591 * we're then deleting immediately: don't leave
1592 * dangling pointers. */
43a18898 1593 wxPendingDelete.DeleteObject(this);
c801d85f 1594
e27ce4e9
RR
1595 /* Just in case we've loaded a top-level window via
1596 * wxWindow::LoadNativeDialog but we weren't a dialog
1597 * class */
43a18898 1598 wxTopLevelWindows.DeleteObject(this);
47d67540 1599
43a18898 1600 if (m_windowValidator) delete m_windowValidator;
8bbe427f 1601
43a18898 1602 if (m_clientObject) delete m_clientObject;
362c6693 1603}
c801d85f 1604
debe6624
JS
1605void wxWindow::PreCreation( wxWindow *parent, wxWindowID id,
1606 const wxPoint &pos, const wxSize &size,
1607 long style, const wxString &name )
c801d85f 1608{
3069ac4e 1609 wxASSERT_MSG( (!m_needParent) || (parent), "Need complete parent." );
8bbe427f 1610
43a18898
RR
1611 m_widget = (GtkWidget*) NULL;
1612 m_wxwindow = (GtkWidget*) NULL;
1613 m_hasVMT = FALSE;
1614 m_parent = parent;
1615 m_children.DeleteContents( FALSE );
8bbe427f 1616
43a18898
RR
1617 m_width = size.x;
1618 if (m_width == -1) m_width = 20;
1619 m_height = size.y;
1620 if (m_height == -1) m_height = 20;
8bbe427f 1621
43a18898
RR
1622 m_x = (int)pos.x;
1623 m_y = (int)pos.y;
8bbe427f 1624
e27ce4e9 1625 if (!m_needParent) /* some reasonable defaults */
6ca41e57 1626 {
43a18898
RR
1627 if (m_x == -1)
1628 {
1629 m_x = (gdk_screen_width () - m_width) / 2;
1630 if (m_x < 10) m_x = 10;
1631 }
1632 if (m_y == -1)
1633 {
1634 m_y = (gdk_screen_height () - m_height) / 2;
1635 if (m_y < 10) m_y = 10;
1636 }
6ca41e57 1637 }
8bbe427f 1638
43a18898
RR
1639 m_minWidth = -1;
1640 m_minHeight = -1;
1641 m_maxWidth = -1;
1642 m_maxHeight = -1;
8bbe427f 1643
43a18898 1644 m_retCode = 0;
8bbe427f 1645
43a18898 1646 m_eventHandler = this;
8bbe427f 1647
b749747d 1648 m_windowId = id == -1 ? wxNewId() : id;
8bbe427f 1649
43a18898 1650 m_sizeSet = FALSE;
8bbe427f 1651
43a18898
RR
1652 m_cursor = new wxCursor( wxCURSOR_ARROW );
1653 m_font = *wxSWISS_FONT;
1ecc4d80
RR
1654 m_backgroundColour = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
1655 m_foregroundColour = *wxBLACK;
43a18898
RR
1656 m_windowStyle = style;
1657 m_windowName = name;
8bbe427f 1658
43a18898
RR
1659 m_constraints = (wxLayoutConstraints *) NULL;
1660 m_constraintsInvolvedIn = (wxList *) NULL;
1661 m_windowSizer = (wxSizer *) NULL;
1662 m_sizerParent = (wxWindow *) NULL;
1663 m_autoLayout = FALSE;
8bbe427f 1664
43a18898
RR
1665 m_hasScrolling = FALSE;
1666 m_isScrolling = FALSE;
1667 m_hAdjust = (GtkAdjustment *) NULL;
1668 m_vAdjust = (GtkAdjustment *) NULL;
1669 m_oldHorizontalPos = 0.0;
1670 m_oldVerticalPos = 0.0;
8bbe427f 1671
43a18898
RR
1672 m_isShown = FALSE;
1673 m_isEnabled = TRUE;
8bbe427f 1674
06cfab17 1675#if wxUSE_DRAG_AND_DROP
43a18898 1676 m_dropTarget = (wxDropTarget *) NULL;
ac57418f 1677#endif
43a18898
RR
1678 m_resizing = FALSE;
1679 m_windowValidator = (wxValidator *) NULL;
1680 m_scrollGC = (GdkGC*) NULL;
1681 m_widgetStyle = (GtkStyle*) NULL;
8bbe427f 1682
43a18898
RR
1683 m_clientObject = (wxClientData*)NULL;
1684 m_clientData = NULL;
ff8bfdbb 1685
1ecc4d80 1686 m_isStaticBox = FALSE;
ff8bfdbb
VZ
1687
1688#if wxUSE_TOOLTIPS
b1170810 1689 m_toolTip = (wxToolTip*) NULL;
ff8bfdbb 1690#endif // wxUSE_TOOLTIPS
c801d85f
KB
1691}
1692
68dda785 1693void wxWindow::PostCreation()
c801d85f 1694{
de8113d9
RR
1695 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1696
43a18898
RR
1697 if (m_wxwindow)
1698 {
20239453
RR
1699 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
1700 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
47d67540 1701
20239453
RR
1702 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
1703 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
43a18898 1704 }
47d67540 1705
43a18898 1706 ConnectWidget( GetConnectWidget() );
47d67540 1707
de8113d9
RR
1708 /* we force the creation of wxFrame and wxDialog in the respective code */
1709 if (m_parent) gtk_widget_realize( m_widget );
47d67540 1710
43a18898 1711 if (m_wxwindow) gtk_widget_realize( m_wxwindow );
47d67540 1712
43a18898 1713 SetCursor( *wxSTANDARD_CURSOR );
47d67540 1714
43a18898 1715 m_hasVMT = TRUE;
b4071e91
RR
1716}
1717
1718void wxWindow::ConnectWidget( GtkWidget *widget )
1719{
43a18898
RR
1720 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
1721 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
c801d85f 1722
b666df2c
RR
1723 gtk_signal_connect( GTK_OBJECT(widget), "key_release_event",
1724 GTK_SIGNAL_FUNC(gtk_window_key_release_callback), (gpointer)this );
1725
43a18898
RR
1726 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
1727 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
47d67540 1728
43a18898
RR
1729 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
1730 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
47d67540 1731
43a18898
RR
1732 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
1733 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
47d67540 1734
43a18898
RR
1735 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
1736 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
c801d85f 1737
43a18898
RR
1738 gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
1739 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
c801d85f 1740
43a18898
RR
1741 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
1742 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
47d67540 1743
43a18898
RR
1744 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
1745 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
362c6693 1746}
c801d85f 1747
68dda785 1748bool wxWindow::HasVMT()
c801d85f 1749{
43a18898 1750 return m_hasVMT;
362c6693 1751}
c801d85f 1752
debe6624 1753bool wxWindow::Close( bool force )
c801d85f 1754{
43a18898 1755 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
47d67540 1756
43a18898
RR
1757 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
1758 event.SetEventObject(this);
2b854a32 1759 event.SetCanVeto(!force);
c801d85f 1760
e27ce4e9
RR
1761 /* return FALSE if window wasn't closed because the application vetoed the
1762 * close event */
fe4e9e6c 1763 return GetEventHandler()->ProcessEvent(event) && !event.GetVeto();
362c6693 1764}
c801d85f 1765
68dda785 1766bool wxWindow::Destroy()
c801d85f 1767{
43a18898 1768 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
47d67540 1769
43a18898
RR
1770 m_hasVMT = FALSE;
1771 delete this;
1772 return TRUE;
362c6693 1773}
c801d85f 1774
68dda785 1775bool wxWindow::DestroyChildren()
c801d85f 1776{
db1b4961
RR
1777 wxNode *node;
1778 while ((node = m_children.First()) != (wxNode *)NULL)
c801d85f 1779 {
db1b4961
RR
1780 wxWindow *child;
1781 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL)
43a18898 1782 {
db1b4961
RR
1783 delete child;
1784 if (m_children.Member(child)) delete node;
43a18898 1785 }
362c6693 1786 }
43a18898 1787 return TRUE;
362c6693 1788}
c801d85f
KB
1789
1790void wxWindow::PrepareDC( wxDC &WXUNUSED(dc) )
1791{
43a18898 1792 // are we to set fonts here ?
362c6693 1793}
c801d85f 1794
6ca41e57
RR
1795wxPoint wxWindow::GetClientAreaOrigin() const
1796{
43a18898 1797 return wxPoint(0,0);
6ca41e57
RR
1798}
1799
1800void wxWindow::AdjustForParentClientOrigin( int& x, int& y, int sizeFlags )
1801{
43a18898
RR
1802 if (((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent())
1803 {
1804 wxPoint pt(GetParent()->GetClientAreaOrigin());
8bbe427f 1805 x += pt.x;
43a18898
RR
1806 y += pt.y;
1807 }
6ca41e57
RR
1808}
1809
bfc6fde4 1810void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
c801d85f 1811{
fb1585ae
RR
1812 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1813 wxASSERT_MSG( (m_parent != NULL), "wxWindow::SetSize requires parent.\n" );
8bbe427f 1814
e27ce4e9 1815 if (m_resizing) return; /* I don't like recursions */
fb1585ae 1816 m_resizing = TRUE;
47d67540 1817
e27ce4e9 1818 if (m_parent->m_wxwindow == NULL) /* i.e. wxNotebook */
fb1585ae 1819 {
e27ce4e9 1820 /* don't set the size for children of wxNotebook, just take the values. */
fb1585ae
RR
1821 m_x = x;
1822 m_y = y;
1823 m_width = width;
ba4e3652 1824 m_height = height;
fb1585ae 1825 }
ba4e3652 1826 else
fb1585ae 1827 {
ba4e3652
RR
1828 int old_width = m_width;
1829 int old_height = m_height;
8bbe427f 1830
ba4e3652
RR
1831 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
1832 {
1833 if (x != -1) m_x = x;
1834 if (y != -1) m_y = y;
1835 if (width != -1) m_width = width;
1836 if (height != -1) m_height = height;
1837 }
1838 else
1839 {
1840 m_x = x;
1841 m_y = y;
1842 m_width = width;
1843 m_height = height;
1844 }
47d67540 1845
ba4e3652
RR
1846 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
1847 {
1848 if (width == -1) m_width = 80;
1849 }
1850
1851 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
1852 {
1853 if (height == -1) m_height = 26;
1854 }
8bbe427f 1855
ba4e3652
RR
1856 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
1857 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
d3b4d113
RR
1858 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
1859 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
47d67540 1860
3502e687
RR
1861 if (GTK_WIDGET_HAS_DEFAULT(m_widget))
1862 {
1863 /* the default button has a border around it */
1864 int border = 5;
1865
1866 wxPoint pt( m_parent->GetClientAreaOrigin() );
1867 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x+pt.x-border, m_y+pt.y-border );
1868
1869 gtk_widget_set_usize( m_widget, m_width+2*border, m_height+2*border );
1870 }
1871 else
1872 {
1873 wxPoint pt( m_parent->GetClientAreaOrigin() );
1874 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x+pt.x, m_y+pt.y );
1875
1876 if ((old_width != m_width) || (old_height != m_height))
1877 gtk_widget_set_usize( m_widget, m_width, m_height );
1878 }
ba4e3652 1879 }
8bbe427f 1880
fb1585ae 1881 m_sizeSet = TRUE;
47d67540 1882
fb1585ae
RR
1883 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
1884 event.SetEventObject( this );
ba4e3652 1885 GetEventHandler()->ProcessEvent( event );
47d67540 1886
fb1585ae 1887 m_resizing = FALSE;
362c6693 1888}
c801d85f 1889
9390a202
RR
1890void wxWindow::OnInternalIdle()
1891{
1892 UpdateWindowUI();
1893}
1894
c801d85f
KB
1895void wxWindow::GetSize( int *width, int *height ) const
1896{
1ecc4d80 1897 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 1898
fb1585ae
RR
1899 if (width) (*width) = m_width;
1900 if (height) (*height) = m_height;
362c6693 1901}
c801d85f 1902
bfc6fde4 1903void wxWindow::DoSetClientSize( int width, int height )
c801d85f 1904{
1ecc4d80 1905 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 1906
1ecc4d80 1907 if (!m_wxwindow)
c801d85f 1908 {
1ecc4d80 1909 SetSize( width, height );
c801d85f
KB
1910 }
1911 else
1912 {
1ecc4d80
RR
1913 int dw = 0;
1914 int dh = 0;
1915
1916 if (!m_hasScrolling)
1917 {
1918 GtkStyleClass *window_class = m_wxwindow->style->klass;
1919
1920 if ((m_windowStyle & wxRAISED_BORDER) ||
1921 (m_windowStyle & wxSUNKEN_BORDER))
1922 {
1923 dw += 2 * window_class->xthickness;
1924 dh += 2 * window_class->ythickness;
1925 }
1926 }
1927 else
1928 {
1929 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1930 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
47d67540 1931
38c7b3d3 1932#ifdef NEW_GTK_SCROLL_CODE
1ecc4d80 1933 GtkWidget *viewport = scroll_window->child;
8bbe427f 1934#else
1ecc4d80 1935 GtkWidget *viewport = scroll_window->viewport;
38c7b3d3
RR
1936#endif
1937
1ecc4d80
RR
1938 GtkStyleClass *viewport_class = viewport->style->klass;
1939
1940 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1941 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1942
1943 if ((m_windowStyle & wxRAISED_BORDER) ||
1944 (m_windowStyle & wxSUNKEN_BORDER))
1945 {
1946 dw += 2 * viewport_class->xthickness;
1947 dh += 2 * viewport_class->ythickness;
1948 }
47d67540 1949
1ecc4d80
RR
1950 if (scroll_window->vscrollbar_visible)
1951 {
1952 dw += vscrollbar->allocation.width;
1953 dw += scroll_class->scrollbar_spacing;
1954 }
1955
1956 if (scroll_window->hscrollbar_visible)
1957 {
1958 dh += hscrollbar->allocation.height;
1959 dw += scroll_class->scrollbar_spacing;
1960 }
1961 }
1962
1963 SetSize( width+dw, height+dh );
1964 }
362c6693 1965}
c801d85f
KB
1966
1967void wxWindow::GetClientSize( int *width, int *height ) const
1968{
1ecc4d80 1969 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 1970
1ecc4d80
RR
1971 if (!m_wxwindow)
1972 {
1973 if (width) (*width) = m_width;
1974 if (height) (*height) = m_height;
c801d85f
KB
1975 }
1976 else
1977 {
1ecc4d80
RR
1978 int dw = 0;
1979 int dh = 0;
1980
1981 if (!m_hasScrolling)
1982 {
1983 GtkStyleClass *window_class = m_wxwindow->style->klass;
1984
1985 if ((m_windowStyle & wxRAISED_BORDER) ||
1986 (m_windowStyle & wxSUNKEN_BORDER))
1987 {
1988 dw += 2 * window_class->xthickness;
1989 dh += 2 * window_class->ythickness;
1990 }
1991 }
1992 else
1993 {
1994 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1995 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
47d67540 1996
38c7b3d3 1997#ifdef NEW_GTK_SCROLL_CODE
1ecc4d80 1998 GtkWidget *viewport = scroll_window->child;
8bbe427f 1999#else
1ecc4d80 2000 GtkWidget *viewport = scroll_window->viewport;
38c7b3d3
RR
2001#endif
2002
1ecc4d80
RR
2003 GtkStyleClass *viewport_class = viewport->style->klass;
2004
2005 if ((m_windowStyle & wxRAISED_BORDER) ||
2006 (m_windowStyle & wxSUNKEN_BORDER))
2007 {
2008 dw += 2 * viewport_class->xthickness;
2009 dh += 2 * viewport_class->ythickness;
2010 }
2011
2012 if (scroll_window->vscrollbar_visible)
2013 {
2014// dw += vscrollbar->allocation.width;
2015 dw += 15; // range.slider_width = 11 + 2*2pts edge
2016 dw += scroll_class->scrollbar_spacing;
2017 }
2018
2019 if (scroll_window->hscrollbar_visible)
2020 {
2021// dh += hscrollbar->allocation.height;
2022 dh += 15;
2023 dh += scroll_class->scrollbar_spacing;
2024 }
2025 }
47d67540 2026
1ecc4d80
RR
2027 if (width) (*width) = m_width - dw;
2028 if (height) (*height) = m_height - dh;
2029 }
362c6693 2030}
c801d85f
KB
2031
2032void wxWindow::GetPosition( int *x, int *y ) const
2033{
1ecc4d80 2034 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2035
43a18898
RR
2036 if (x) (*x) = m_x;
2037 if (y) (*y) = m_y;
362c6693 2038}
c801d85f
KB
2039
2040void wxWindow::ClientToScreen( int *x, int *y )
2041{
1ecc4d80 2042 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2043
43a18898
RR
2044 GdkWindow *source = (GdkWindow *) NULL;
2045 if (m_wxwindow)
2046 source = m_wxwindow->window;
2047 else
2048 source = m_widget->window;
47d67540 2049
43a18898
RR
2050 int org_x = 0;
2051 int org_y = 0;
2052 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2053
43a18898 2054 if (!m_wxwindow)
c801d85f 2055 {
43a18898
RR
2056 if (GTK_WIDGET_NO_WINDOW (m_widget))
2057 {
2058 org_x += m_widget->allocation.x;
2059 org_y += m_widget->allocation.y;
2060 }
362c6693 2061 }
47d67540 2062
43a18898
RR
2063 wxPoint pt(GetClientAreaOrigin());
2064 org_x += pt.x;
2065 org_y += pt.y;
8bbe427f 2066
43a18898
RR
2067 if (x) *x += org_x;
2068 if (y) *y += org_y;
362c6693 2069}
c801d85f
KB
2070
2071void wxWindow::ScreenToClient( int *x, int *y )
2072{
1ecc4d80 2073 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2074
1ecc4d80
RR
2075 GdkWindow *source = (GdkWindow *) NULL;
2076 if (m_wxwindow)
2077 source = m_wxwindow->window;
2078 else
2079 source = m_widget->window;
47d67540 2080
1ecc4d80
RR
2081 int org_x = 0;
2082 int org_y = 0;
2083 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2084
1ecc4d80 2085 if (!m_wxwindow)
c801d85f 2086 {
1ecc4d80
RR
2087 if (GTK_WIDGET_NO_WINDOW (m_widget))
2088 {
2089 org_x += m_widget->allocation.x;
2090 org_y += m_widget->allocation.y;
2091 }
362c6693 2092 }
47d67540 2093
1ecc4d80
RR
2094 wxPoint pt(GetClientAreaOrigin());
2095 org_x -= pt.x;
2096 org_y -= pt.y;
8bbe427f 2097
1ecc4d80
RR
2098 if (x) *x -= org_x;
2099 if (y) *y -= org_y;
362c6693 2100}
c801d85f 2101
debe6624 2102void wxWindow::Centre( int direction )
c801d85f 2103{
1ecc4d80 2104 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2105
1ecc4d80
RR
2106 int x = m_x;
2107 int y = m_y;
8bbe427f 2108
1ecc4d80
RR
2109 if (m_parent)
2110 {
2111 int p_w = 0;
2112 int p_h = 0;
2113 m_parent->GetSize( &p_w, &p_h );
2114 if (direction & wxHORIZONTAL == wxHORIZONTAL) x = (p_w - m_width) / 2;
2115 if (direction & wxVERTICAL == wxVERTICAL) y = (p_h - m_height) / 2;
2116 }
2117 else
2118 {
2119 if (direction & wxHORIZONTAL == wxHORIZONTAL) x = (gdk_screen_width () - m_width) / 2;
2120 if (direction & wxVERTICAL == wxVERTICAL) y = (gdk_screen_height () - m_height) / 2;
2121 }
8bbe427f 2122
1ecc4d80 2123 Move( x, y );
362c6693 2124}
c801d85f 2125
68dda785 2126void wxWindow::Fit()
c801d85f 2127{
1ecc4d80 2128 wxCHECK_RET( (m_widget != NULL), "invalid window" );
5e0aa05a 2129
1ecc4d80
RR
2130 int maxX = 0;
2131 int maxY = 0;
2132 wxNode *node = m_children.First();
2133 while (node)
2134 {
2135 wxWindow *win = (wxWindow *)node->Data();
2136 int wx, wy, ww, wh;
2137 win->GetPosition(&wx, &wy);
2138 win->GetSize(&ww, &wh);
2139 if (wx + ww > maxX) maxX = wx + ww;
2140 if (wy + wh > maxY) maxY = wy + wh;
2141
2142 node = node->Next();
2143 }
ff8bfdbb 2144
1ecc4d80 2145 SetClientSize(maxX + 7, maxY + 14);
362c6693 2146}
c801d85f 2147
2f2aa628
RR
2148void wxWindow::SetSizeHints( int minW, int minH, int maxW, int maxH, int WXUNUSED(incW), int WXUNUSED(incH) )
2149{
1ecc4d80 2150 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2151
1ecc4d80
RR
2152 m_minWidth = minW;
2153 m_minHeight = minH;
2154 m_maxWidth = maxW;
2155 m_maxHeight = maxH;
2f2aa628
RR
2156}
2157
c801d85f
KB
2158void wxWindow::OnSize( wxSizeEvent &WXUNUSED(event) )
2159{
f04371f0 2160// if (GetAutoLayout()) Layout();
362c6693 2161}
c801d85f 2162
debe6624 2163bool wxWindow::Show( bool show )
c801d85f 2164{
1ecc4d80 2165 wxCHECK_MSG( (m_widget != NULL), FALSE, "invalid window" );
47d67540 2166
e27ce4e9
RR
2167 if (show == m_isShown) return TRUE;
2168
1ecc4d80
RR
2169 if (show)
2170 gtk_widget_show( m_widget );
2171 else
2172 gtk_widget_hide( m_widget );
ff8bfdbb 2173
1ecc4d80 2174 m_isShown = show;
ff8bfdbb 2175
1ecc4d80 2176 return TRUE;
362c6693 2177}
c801d85f 2178
debe6624 2179void wxWindow::Enable( bool enable )
c801d85f 2180{
1ecc4d80 2181 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2182
1ecc4d80 2183 m_isEnabled = enable;
ff8bfdbb 2184
1ecc4d80
RR
2185 gtk_widget_set_sensitive( m_widget, enable );
2186 if (m_wxwindow) gtk_widget_set_sensitive( m_wxwindow, enable );
362c6693 2187}
c801d85f 2188
68dda785 2189int wxWindow::GetCharHeight() const
c33c4050 2190{
1ecc4d80 2191 wxCHECK_MSG( (m_widget != NULL), 12, "invalid window" );
47d67540 2192
1ecc4d80 2193 wxCHECK_MSG( m_font.Ok(), 12, "invalid font" );
47d67540 2194
1ecc4d80 2195 GdkFont *font = m_font.GetInternalFont( 1.0 );
ff8bfdbb 2196
1ecc4d80 2197 return font->ascent + font->descent;
c33c4050
RR
2198}
2199
68dda785 2200int wxWindow::GetCharWidth() const
c33c4050 2201{
1ecc4d80 2202 wxCHECK_MSG( (m_widget != NULL), 8, "invalid window" );
47d67540 2203
1ecc4d80 2204 wxCHECK_MSG( m_font.Ok(), 8, "invalid font" );
47d67540 2205
463c1fa1 2206 GdkFont *font = m_font.GetInternalFont( 1.0 );
ff8bfdbb 2207
463c1fa1 2208 return gdk_string_width( font, "H" );
c33c4050
RR
2209}
2210
2211void wxWindow::GetTextExtent( const wxString& string, int *x, int *y,
2212 int *descent, int *externalLeading, const wxFont *theFont, bool WXUNUSED(use16) ) const
2213{
463c1fa1
RR
2214 wxFont fontToUse = m_font;
2215 if (theFont) fontToUse = *theFont;
47d67540 2216
1ecc4d80 2217 wxCHECK_RET( fontToUse.Ok(), "invalid font" );
47d67540 2218
463c1fa1
RR
2219 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
2220 if (x) (*x) = gdk_string_width( font, string );
2221 if (y) (*y) = font->ascent + font->descent;
2222 if (descent) (*descent) = font->descent;
2223 if (externalLeading) (*externalLeading) = 0; // ??
c33c4050
RR
2224}
2225
debe6624 2226void wxWindow::MakeModal( bool modal )
c801d85f 2227{
1ecc4d80 2228 return;
ff8bfdbb 2229
1ecc4d80
RR
2230 // Disable all other windows
2231 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
c801d85f 2232 {
1ecc4d80
RR
2233 wxNode *node = wxTopLevelWindows.First();
2234 while (node)
2235 {
2236 wxWindow *win = (wxWindow *)node->Data();
2237 if (win != this) win->Enable(!modal);
c801d85f 2238
1ecc4d80
RR
2239 node = node->Next();
2240 }
c801d85f 2241 }
c801d85f
KB
2242}
2243
b666df2c
RR
2244void wxWindow::OnKeyDown( wxKeyEvent &event )
2245{
2246 event.SetEventType( wxEVT_CHAR );
ff8bfdbb 2247
b666df2c
RR
2248 if (!GetEventHandler()->ProcessEvent( event ))
2249 {
2250 event.Skip();
2251 }
2252}
2253
68dda785 2254void wxWindow::SetFocus()
c801d85f 2255{
1ecc4d80 2256 wxCHECK_RET( (m_widget != NULL), "invalid window" );
ff8bfdbb 2257
463c1fa1
RR
2258 GtkWidget *connect_widget = GetConnectWidget();
2259 if (connect_widget)
c801d85f 2260 {
b292e2f5 2261 if (GTK_WIDGET_CAN_FOCUS(connect_widget) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
463c1fa1
RR
2262 {
2263 gtk_widget_grab_focus (connect_widget);
2264 }
ff8bfdbb
VZ
2265 else if (GTK_IS_CONTAINER(connect_widget))
2266 {
2267 gtk_container_focus( GTK_CONTAINER(connect_widget), GTK_DIR_TAB_FORWARD );
2268 }
2269 else
2270 {
2271 }
362c6693 2272 }
362c6693 2273}
c801d85f 2274
b292e2f5
RR
2275wxWindow *wxWindow::FindFocus()
2276{
2277 return g_focusWindow;
2278}
2279
2280bool wxWindow::AcceptsFocus() const
2281{
2282 return IsEnabled() && IsShown() && m_acceptsFocus;
2283}
2284
c801d85f
KB
2285void wxWindow::AddChild( wxWindow *child )
2286{
1ecc4d80
RR
2287 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2288 wxCHECK_RET( (child != NULL), "invalid child" );
47d67540 2289
463c1fa1 2290 m_children.Append( child );
362c6693 2291}
c801d85f 2292
463c1fa1
RR
2293wxWindow *wxWindow::ReParent( wxWindow *newParent )
2294{
1ecc4d80 2295 wxCHECK_MSG( (m_widget != NULL), (wxWindow*) NULL, "invalid window" );
ff8bfdbb 2296
1ecc4d80 2297 wxWindow *oldParent = GetParent();
8bbe427f 2298
1ecc4d80 2299 if (oldParent) oldParent->RemoveChild( this );
8bbe427f 2300
1ecc4d80 2301 gtk_widget_unparent( m_widget );
8bbe427f 2302
1ecc4d80
RR
2303 if (newParent)
2304 {
2305 newParent->AddChild( this );
2306 (newParent->m_insertCallback)( newParent, this );
2307 }
8bbe427f 2308
1ecc4d80 2309 return oldParent;
362c6693 2310}
c801d85f
KB
2311
2312void wxWindow::RemoveChild( wxWindow *child )
2313{
db1b4961 2314 m_children.DeleteObject( child );
463c1fa1 2315 child->m_parent = (wxWindow *) NULL;
362c6693 2316}
c801d85f
KB
2317
2318void wxWindow::SetReturnCode( int retCode )
2319{
463c1fa1 2320 m_retCode = retCode;
362c6693 2321}
c801d85f 2322
68dda785 2323int wxWindow::GetReturnCode()
c801d85f 2324{
463c1fa1 2325 return m_retCode;
362c6693 2326}
c801d85f 2327
68dda785 2328void wxWindow::Raise()
362c6693 2329{
1ecc4d80 2330 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2331
463c1fa1 2332 if (m_widget) gdk_window_raise( m_widget->window );
362c6693
RR
2333}
2334
68dda785 2335void wxWindow::Lower()
362c6693 2336{
1ecc4d80 2337 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2338
463c1fa1 2339 if (m_widget) gdk_window_lower( m_widget->window );
362c6693 2340}
c801d85f 2341
8bbe427f 2342wxEvtHandler *wxWindow::GetEventHandler() const
c801d85f 2343{
463c1fa1 2344 return m_eventHandler;
362c6693 2345}
c801d85f 2346
86b29a61 2347void wxWindow::SetEventHandler( wxEvtHandler *handler )
c801d85f 2348{
463c1fa1 2349 m_eventHandler = handler;
362c6693 2350}
c801d85f 2351
86b29a61
RR
2352void wxWindow::PushEventHandler(wxEvtHandler *handler)
2353{
463c1fa1
RR
2354 handler->SetNextHandler(GetEventHandler());
2355 SetEventHandler(handler);
86b29a61
RR
2356}
2357
2358wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
2359{
463c1fa1 2360 if (GetEventHandler())
e55ad60e 2361 {
463c1fa1
RR
2362 wxEvtHandler *handlerA = GetEventHandler();
2363 wxEvtHandler *handlerB = handlerA->GetNextHandler();
2364 handlerA->SetNextHandler((wxEvtHandler *) NULL);
2365 SetEventHandler(handlerB);
2366 if (deleteHandler)
2367 {
2368 delete handlerA;
2369 return (wxEvtHandler*) NULL;
2370 }
2371 else
2372 return handlerA;
2373 }
2374 else
2375 return (wxEvtHandler *) NULL;
86b29a61
RR
2376}
2377
68dda785 2378wxValidator *wxWindow::GetValidator()
c801d85f 2379{
463c1fa1 2380 return m_windowValidator;
362c6693 2381}
c801d85f 2382
6de97a3b 2383void wxWindow::SetValidator( const wxValidator& validator )
c801d85f 2384{
1ecc4d80
RR
2385 if (m_windowValidator) delete m_windowValidator;
2386 m_windowValidator = validator.Clone();
2387 if (m_windowValidator) m_windowValidator->SetWindow(this);
362c6693 2388}
c801d85f 2389
fd0eed64
RR
2390void wxWindow::SetClientObject( wxClientData *data )
2391{
1ecc4d80
RR
2392 if (m_clientObject) delete m_clientObject;
2393 m_clientObject = data;
fd0eed64
RR
2394}
2395
2396wxClientData *wxWindow::GetClientObject()
2397{
1ecc4d80 2398 return m_clientObject;
fd0eed64
RR
2399}
2400
2401void wxWindow::SetClientData( void *data )
2402{
1ecc4d80 2403 m_clientData = data;
fd0eed64
RR
2404}
2405
2406void *wxWindow::GetClientData()
2407{
1ecc4d80 2408 return m_clientData;
fd0eed64
RR
2409}
2410
68dda785 2411bool wxWindow::IsBeingDeleted()
c801d85f 2412{
1ecc4d80 2413 return FALSE;
362c6693 2414}
c801d85f
KB
2415
2416void wxWindow::SetId( wxWindowID id )
2417{
1ecc4d80 2418 m_windowId = id;
362c6693 2419}
c801d85f 2420
8bbe427f 2421wxWindowID wxWindow::GetId() const
c801d85f 2422{
1ecc4d80 2423 return m_windowId;
362c6693 2424}
c801d85f
KB
2425
2426void wxWindow::SetCursor( const wxCursor &cursor )
2427{
1ecc4d80 2428 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2429
1ecc4d80
RR
2430 if (cursor.Ok())
2431 {
2432 if (cursor == *m_cursor) return;
2433 *m_cursor = cursor;
2434 }
2435 else
2436 {
2437 *m_cursor = *wxSTANDARD_CURSOR;
2438 }
a3622daa 2439
1ecc4d80
RR
2440 if ((m_widget) && (m_widget->window))
2441 gdk_window_set_cursor( m_widget->window, m_cursor->GetCursor() );
47d67540 2442
1ecc4d80
RR
2443 if ((m_wxwindow) && (m_wxwindow->window))
2444 gdk_window_set_cursor( m_wxwindow->window, m_cursor->GetCursor() );
362c6693 2445}
c801d85f 2446
4f22cf8d
RR
2447void wxWindow::WarpPointer( int WXUNUSED(x), int WXUNUSED(y) )
2448{
2449 // TODO
2450}
2451
debe6624 2452void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
c801d85f 2453{
139adb6a 2454 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2455
139adb6a 2456 if (eraseBackground && m_wxwindow && m_wxwindow->window)
c801d85f 2457 {
139adb6a
RR
2458 if (rect)
2459 {
2460 gdk_window_clear_area( m_wxwindow->window,
2461 rect->x, rect->y,
f234c60c 2462 rect->width, rect->height );
139adb6a
RR
2463 }
2464 else
2465 {
f234c60c 2466 gdk_window_clear( m_wxwindow->window );
139adb6a
RR
2467 }
2468 }
ff8bfdbb 2469
139adb6a
RR
2470 if (!rect)
2471 {
2472 if (m_wxwindow)
2473 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
ff8bfdbb 2474 else
139adb6a 2475 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
362c6693 2476 }
c801d85f 2477 else
139adb6a
RR
2478 {
2479 GdkRectangle gdk_rect;
2480 gdk_rect.x = rect->x;
2481 gdk_rect.y = rect->y;
2482 gdk_rect.width = rect->width;
2483 gdk_rect.height = rect->height;
2484
2485 if (m_wxwindow)
2486 gtk_widget_draw( m_wxwindow, &gdk_rect );
2487 else
2488 gtk_widget_draw( m_widget, &gdk_rect );
2489 }
362c6693 2490}
c801d85f 2491
8429bec1
RR
2492wxRegion wxWindow::GetUpdateRegion() const
2493{
2494 return m_updateRegion;
2495}
2496
2497bool wxWindow::IsExposed( int x, int y) const
c801d85f 2498{
1ecc4d80 2499 return (m_updateRegion.Contains( x, y ) != wxOutRegion );
362c6693 2500}
c801d85f 2501
8429bec1
RR
2502bool wxWindow::IsExposed( int x, int y, int w, int h ) const
2503{
1ecc4d80 2504 return (m_updateRegion.Contains( x, y, w, h ) != wxOutRegion );
8429bec1
RR
2505}
2506
2507bool wxWindow::IsExposed( const wxPoint& pt ) const
2508{
1ecc4d80 2509 return (m_updateRegion.Contains( pt.x, pt.y ) != wxOutRegion );
8429bec1
RR
2510}
2511
2512bool wxWindow::IsExposed( const wxRect& rect ) const
c801d85f 2513{
1ecc4d80 2514 return (m_updateRegion.Contains( rect.x, rect.y, rect.width, rect.height ) != wxOutRegion );
362c6693 2515}
c801d85f 2516
68dda785 2517void wxWindow::Clear()
c801d85f 2518{
3bc755fc 2519 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2520
f234c60c
RR
2521 if (m_wxwindow && m_wxwindow->window)
2522 {
2523 gdk_window_clear( m_wxwindow->window );
2524 }
362c6693 2525}
c801d85f 2526
ff8bfdbb 2527#if wxUSE_TOOLTIPS
b1170810
RR
2528void wxWindow::SetToolTip( const wxString &tip )
2529{
301cd871
RR
2530 if (m_toolTip)
2531 {
2532 m_toolTip->SetTip( tip );
2533 }
2534 else
2535 {
ff8bfdbb 2536 SetToolTip( new wxToolTip( tip ) );
301cd871 2537 }
ff8bfdbb
VZ
2538
2539 // setting empty tooltip text does not remove the tooltip any more for
2540 // wxMSW compatibility - use SetToolTip((wxToolTip *)NULL) for this
b1170810
RR
2541}
2542
2543void wxWindow::SetToolTip( wxToolTip *tip )
2544{
301cd871
RR
2545 if (m_toolTip)
2546 {
2547 m_toolTip->SetTip( (char*) NULL );
2548 delete m_toolTip;
2549 }
ff8bfdbb 2550
b1170810 2551 m_toolTip = tip;
ff8bfdbb
VZ
2552
2553 if (m_toolTip)
2554 m_toolTip->Apply( this );
b1170810
RR
2555}
2556
301cd871 2557void wxWindow::ApplyToolTip( GtkTooltips *tips, const char *tip )
b1170810 2558{
301cd871
RR
2559 gtk_tooltips_set_tip( tips, GetConnectWidget(), tip, (gchar*) NULL );
2560}
ff8bfdbb 2561#endif // wxUSE_TOOLTIPS
b1170810 2562
68dda785 2563wxColour wxWindow::GetBackgroundColour() const
c801d85f 2564{
3bc755fc 2565 return m_backgroundColour;
362c6693 2566}
c801d85f
KB
2567
2568void wxWindow::SetBackgroundColour( const wxColour &colour )
2569{
3bc755fc 2570 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2571
3bc755fc 2572 if (m_backgroundColour == colour) return;
8bbe427f 2573
3bc755fc
RR
2574 m_backgroundColour = colour;
2575 if (!m_backgroundColour.Ok()) return;
8bbe427f 2576
f234c60c 2577 if (m_wxwindow && m_wxwindow->window)
3bc755fc 2578 {
f234c60c
RR
2579 /* wxMSW doesn't clear the window here. I don't do that
2580 either to provide compatibility. call Clear() to do
2581 the job. */
2582
2583 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_wxwindow->window ) );
2584 gdk_window_set_background( m_wxwindow->window, m_backgroundColour.GetColor() );
3bc755fc 2585 }
8bbe427f 2586
ae0bdb01 2587 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
f234c60c 2588
ff8bfdbb
VZ
2589 if (sysbg.Red() == colour.Red() &&
2590 sysbg.Green() == colour.Green() &&
ae0bdb01
RR
2591 sysbg.Blue() == colour.Blue())
2592 {
2593 m_backgroundColour = wxNullColour;
2594 ApplyWidgetStyle();
ff8bfdbb
VZ
2595 m_backgroundColour = sysbg;
2596 }
ae0bdb01
RR
2597 else
2598 {
2599 ApplyWidgetStyle();
2600 }
362c6693 2601}
c801d85f 2602
68dda785 2603wxColour wxWindow::GetForegroundColour() const
6de97a3b 2604{
3bc755fc 2605 return m_foregroundColour;
6de97a3b
RR
2606}
2607
2608void wxWindow::SetForegroundColour( const wxColour &colour )
2609{
3bc755fc 2610 wxCHECK_RET( m_widget != NULL, "invalid window" );
a81258be 2611
3bc755fc 2612 if (m_foregroundColour == colour) return;
8bbe427f 2613
3bc755fc
RR
2614 m_foregroundColour = colour;
2615 if (!m_foregroundColour.Ok()) return;
8bbe427f 2616
ae0bdb01 2617 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
ff8bfdbb
VZ
2618 if (sysbg.Red() == colour.Red() &&
2619 sysbg.Green() == colour.Green() &&
ae0bdb01
RR
2620 sysbg.Blue() == colour.Blue())
2621 {
2622 m_backgroundColour = wxNullColour;
2623 ApplyWidgetStyle();
ff8bfdbb
VZ
2624 m_backgroundColour = sysbg;
2625 }
ae0bdb01
RR
2626 else
2627 {
2628 ApplyWidgetStyle();
2629 }
58614078
RR
2630}
2631
2632GtkStyle *wxWindow::GetWidgetStyle()
2633{
1ecc4d80 2634 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
8bbe427f 2635
1ecc4d80
RR
2636 m_widgetStyle =
2637 gtk_style_copy(
2638 gtk_widget_get_style( m_widget ) );
8bbe427f 2639
1ecc4d80 2640 return m_widgetStyle;
58614078
RR
2641}
2642
2643void wxWindow::SetWidgetStyle()
2644{
1ecc4d80
RR
2645 GtkStyle *style = GetWidgetStyle();
2646
2647 gdk_font_unref( style->font );
2648 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2649
2650 if (m_foregroundColour.Ok())
2651 {
2652 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2653 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2654 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2655 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2656 }
2657
2658 if (m_backgroundColour.Ok())
2659 {
2660 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2661 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2662 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2663 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2664 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2665 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2666 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2667 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2668 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2669 }
a81258be
RR
2670}
2671
58614078 2672void wxWindow::ApplyWidgetStyle()
a81258be 2673{
6de97a3b
RR
2674}
2675
68dda785 2676bool wxWindow::Validate()
c801d85f 2677{
1ecc4d80 2678 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
47d67540 2679
1ecc4d80
RR
2680 wxNode *node = m_children.First();
2681 while (node)
2682 {
2683 wxWindow *child = (wxWindow *)node->Data();
2684 if (child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this))
ff8bfdbb
VZ
2685 {
2686 return FALSE;
2687 }
1ecc4d80
RR
2688 node = node->Next();
2689 }
2690 return TRUE;
362c6693 2691}
c801d85f 2692
68dda785 2693bool wxWindow::TransferDataToWindow()
c801d85f 2694{
1ecc4d80 2695 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
47d67540 2696
1ecc4d80
RR
2697 wxNode *node = m_children.First();
2698 while (node)
c801d85f 2699 {
1ecc4d80
RR
2700 wxWindow *child = (wxWindow *)node->Data();
2701 if (child->GetValidator() && /* child->GetValidator()->Ok() && */
2702 !child->GetValidator()->TransferToWindow() )
2703 {
2704 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK|wxICON_EXCLAMATION );
2705 return FALSE;
2706 }
2707 node = node->Next();
362c6693 2708 }
1ecc4d80 2709 return TRUE;
362c6693 2710}
c801d85f 2711
68dda785 2712bool wxWindow::TransferDataFromWindow()
c801d85f 2713{
1ecc4d80 2714 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
47d67540 2715
1ecc4d80
RR
2716 wxNode *node = m_children.First();
2717 while (node)
2718 {
2719 wxWindow *child = (wxWindow *)node->Data();
2720 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->TransferFromWindow() )
ff8bfdbb
VZ
2721 {
2722 return FALSE;
2723 }
1ecc4d80
RR
2724 node = node->Next();
2725 }
2726 return TRUE;
362c6693 2727}
c801d85f 2728
bcf1fa6b
RR
2729void wxWindow::SetAcceleratorTable( const wxAcceleratorTable& accel )
2730{
1ecc4d80 2731 m_acceleratorTable = accel;
bcf1fa6b
RR
2732}
2733
c801d85f
KB
2734void wxWindow::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
2735{
1ecc4d80 2736 TransferDataToWindow();
362c6693 2737}
c801d85f 2738
68dda785 2739void wxWindow::InitDialog()
c801d85f 2740{
1ecc4d80 2741 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2742
1ecc4d80
RR
2743 wxInitDialogEvent event(GetId());
2744 event.SetEventObject( this );
2745 GetEventHandler()->ProcessEvent(event);
362c6693 2746}
c801d85f 2747
30dea054
RR
2748static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2749{
1ecc4d80
RR
2750 menu->SetInvokingWindow( win );
2751 wxNode *node = menu->m_items.First();
2752 while (node)
2753 {
2754 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2755 if (menuitem->IsSubMenu())
2756 {
ff8bfdbb
VZ
2757 SetInvokingWindow( menuitem->GetSubMenu(), win );
2758 }
1ecc4d80
RR
2759 node = node->Next();
2760 }
362c6693 2761}
30dea054 2762
0c77152e
RR
2763static gint gs_pop_x = 0;
2764static gint gs_pop_y = 0;
2765
2766static void pop_pos_callback( GtkMenu *menu, gint *x, gint *y, wxWindow *win )
2767{
2768 win->ClientToScreen( &gs_pop_x, &gs_pop_y );
2769 *x = gs_pop_x;
2770 *y = gs_pop_y;
2771}
2772
2773bool wxWindow::PopupMenu( wxMenu *menu, int x, int y )
30dea054 2774{
1ecc4d80 2775 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
47d67540 2776
1ecc4d80 2777 wxCHECK_MSG( menu != NULL, FALSE, "invalid popup-menu" );
8bbe427f 2778
1ecc4d80 2779 SetInvokingWindow( menu, this );
ff8bfdbb 2780
631f1bfe
JS
2781 menu->UpdateUI();
2782
0c77152e
RR
2783 gs_pop_x = x;
2784 gs_pop_y = y;
ff8bfdbb 2785
1ecc4d80 2786 gtk_menu_popup(
47d67540 2787 GTK_MENU(menu->m_menu),
0c77152e
RR
2788 (GtkWidget *) NULL, // parent menu shell
2789 (GtkWidget *) NULL, // parent menu item
2790 (GtkMenuPositionFunc) pop_pos_callback,
2791 (gpointer) this, // client data
2792 0, // button used to activate it
2793 0 //gs_timeLastClick // the time of activation
47d67540 2794 );
1ecc4d80 2795 return TRUE;
30dea054
RR
2796}
2797
06cfab17 2798#if wxUSE_DRAG_AND_DROP
ac57418f 2799
c801d85f
KB
2800void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2801{
1ecc4d80 2802 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2803
1ecc4d80 2804 GtkWidget *dnd_widget = GetConnectWidget();
47d67540 2805
1ecc4d80 2806 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
47d67540 2807
1ecc4d80
RR
2808 if (m_dropTarget) delete m_dropTarget;
2809 m_dropTarget = dropTarget;
47d67540 2810
1ecc4d80 2811 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
362c6693 2812}
c801d85f
KB
2813
2814wxDropTarget *wxWindow::GetDropTarget() const
2815{
1ecc4d80 2816 return m_dropTarget;
362c6693 2817}
c801d85f 2818
ac57418f
RR
2819#endif
2820
68dda785 2821GtkWidget* wxWindow::GetConnectWidget()
e3e65dac 2822{
1ecc4d80
RR
2823 GtkWidget *connect_widget = m_widget;
2824 if (m_wxwindow) connect_widget = m_wxwindow;
47d67540 2825
1ecc4d80 2826 return connect_widget;
e3e65dac 2827}
47d67540 2828
903f689b
RR
2829bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2830{
1ecc4d80
RR
2831 if (m_wxwindow) return (window == m_wxwindow->window);
2832 return (window == m_widget->window);
903f689b
RR
2833}
2834
c801d85f
KB
2835void wxWindow::SetFont( const wxFont &font )
2836{
1ecc4d80 2837 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2838
1ecc4d80
RR
2839 if (((wxFont*)&font)->Ok())
2840 m_font = font;
2841 else
2842 m_font = *wxSWISS_FONT;
c801d85f 2843
ae0bdb01 2844 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
ff8bfdbb
VZ
2845 if (sysbg.Red() == m_backgroundColour.Red() &&
2846 sysbg.Green() == m_backgroundColour.Green() &&
ae0bdb01
RR
2847 sysbg.Blue() == m_backgroundColour.Blue())
2848 {
2849 m_backgroundColour = wxNullColour;
2850 ApplyWidgetStyle();
ff8bfdbb
VZ
2851 m_backgroundColour = sysbg;
2852 }
ae0bdb01
RR
2853 else
2854 {
2855 ApplyWidgetStyle();
2856 }
362c6693 2857}
c801d85f
KB
2858
2859void wxWindow::SetWindowStyleFlag( long flag )
2860{
1ecc4d80 2861 m_windowStyle = flag;
362c6693 2862}
c801d85f 2863
68dda785 2864long wxWindow::GetWindowStyleFlag() const
c801d85f 2865{
1ecc4d80 2866 return m_windowStyle;
362c6693 2867}
c801d85f 2868
68dda785 2869void wxWindow::CaptureMouse()
c801d85f 2870{
1ecc4d80 2871 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2872
1ecc4d80 2873 wxCHECK_RET( g_capturing == FALSE, "CaptureMouse called twice" );
47d67540 2874
1ecc4d80
RR
2875 GtkWidget *connect_widget = GetConnectWidget();
2876 gtk_grab_add( connect_widget );
2877 gdk_pointer_grab( connect_widget->window, FALSE,
2878 (GdkEventMask)
2879 (GDK_BUTTON_PRESS_MASK |
2880 GDK_BUTTON_RELEASE_MASK |
2881 GDK_POINTER_MOTION_MASK),
ff8bfdbb
VZ
2882 (GdkWindow *) NULL,
2883 (GdkCursor *) NULL,
2884 GDK_CURRENT_TIME );
1ecc4d80 2885 g_capturing = TRUE;
362c6693 2886}
c801d85f 2887
68dda785 2888void wxWindow::ReleaseMouse()
c801d85f 2889{
1ecc4d80 2890 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2891
1ecc4d80 2892 wxCHECK_RET( g_capturing == TRUE, "ReleaseMouse called twice" );
47d67540 2893
1ecc4d80
RR
2894 GtkWidget *connect_widget = GetConnectWidget();
2895 gtk_grab_remove( connect_widget );
2896 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
2897 g_capturing = FALSE;
362c6693 2898}
c801d85f
KB
2899
2900void wxWindow::SetTitle( const wxString &WXUNUSED(title) )
2901{
362c6693 2902}
c801d85f 2903
68dda785 2904wxString wxWindow::GetTitle() const
c801d85f 2905{
1ecc4d80 2906 return (wxString&)m_windowName;
362c6693 2907}
c801d85f 2908
68dda785 2909wxString wxWindow::GetLabel() const
c801d85f 2910{
1ecc4d80 2911 return GetTitle();
362c6693 2912}
c801d85f
KB
2913
2914void wxWindow::SetName( const wxString &name )
2915{
1ecc4d80 2916 m_windowName = name;
362c6693 2917}
c801d85f 2918
68dda785 2919wxString wxWindow::GetName() const
c801d85f 2920{
1ecc4d80 2921 return (wxString&)m_windowName;
362c6693 2922}
c801d85f 2923
68dda785 2924bool wxWindow::IsShown() const
c801d85f 2925{
1ecc4d80 2926 return m_isShown;
362c6693 2927}
c801d85f 2928
68dda785 2929bool wxWindow::IsRetained()
c801d85f 2930{
1ecc4d80 2931 return FALSE;
362c6693 2932}
c801d85f 2933
debe6624 2934wxWindow *wxWindow::FindWindow( long id )
c801d85f 2935{
1ecc4d80
RR
2936 if (id == m_windowId) return this;
2937 wxNode *node = m_children.First();
2938 while (node)
2939 {
2940 wxWindow *child = (wxWindow*)node->Data();
2941 wxWindow *res = child->FindWindow( id );
2942 if (res) return res;
2943 node = node->Next();
2944 }
2945 return (wxWindow *) NULL;
362c6693 2946}
c801d85f
KB
2947
2948wxWindow *wxWindow::FindWindow( const wxString& name )
2949{
1ecc4d80
RR
2950 if (name == m_windowName) return this;
2951 wxNode *node = m_children.First();
2952 while (node)
2953 {
2954 wxWindow *child = (wxWindow*)node->Data();
2955 wxWindow *res = child->FindWindow( name );
2956 if (res) return res;
2957 node = node->Next();
2958 }
2959 return (wxWindow *) NULL;
362c6693 2960}
c801d85f 2961
debe6624 2962void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
cb43b372 2963 int range, bool refresh )
c801d85f 2964{
1ecc4d80 2965 wxCHECK_RET( m_widget != NULL, "invalid window" );
8bbe427f 2966
1ecc4d80 2967 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
c801d85f 2968
1ecc4d80 2969 m_hasScrolling = TRUE;
47d67540 2970
1ecc4d80 2971 if (orient == wxHORIZONTAL)
cb43b372 2972 {
1ecc4d80
RR
2973 float fpos = (float)pos;
2974 float frange = (float)range;
2975 float fthumb = (float)thumbVisible;
2976 if (fpos > frange-fthumb) fpos = frange-fthumb;
2977 if (fpos < 0.0) fpos = 0.0;
2978
2979 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
2980 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
2981 {
2982 SetScrollPos( orient, pos, refresh );
2983 return;
2984 }
47d67540 2985
1ecc4d80 2986 m_oldHorizontalPos = fpos;
47d67540 2987
1ecc4d80
RR
2988 m_hAdjust->lower = 0.0;
2989 m_hAdjust->upper = frange;
2990 m_hAdjust->value = fpos;
2991 m_hAdjust->step_increment = 1.0;
2992 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
2993 m_hAdjust->page_size = fthumb;
cb43b372 2994 }
1ecc4d80
RR
2995 else
2996 {
2997 float fpos = (float)pos;
2998 float frange = (float)range;
2999 float fthumb = (float)thumbVisible;
3000 if (fpos > frange-fthumb) fpos = frange-fthumb;
3001 if (fpos < 0.0) fpos = 0.0;
3002
3003 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
3004 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
3005 {
3006 SetScrollPos( orient, pos, refresh );
3007 return;
3008 }
47d67540 3009
1ecc4d80 3010 m_oldVerticalPos = fpos;
47d67540 3011
1ecc4d80
RR
3012 m_vAdjust->lower = 0.0;
3013 m_vAdjust->upper = frange;
3014 m_vAdjust->value = fpos;
3015 m_vAdjust->step_increment = 1.0;
3016 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
3017 m_vAdjust->page_size = fthumb;
3018 }
47d67540 3019
1ecc4d80
RR
3020 if (m_wxwindow->window)
3021 {
3022 if (orient == wxHORIZONTAL)
3023 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
3024 else
3025 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
47d67540 3026
1ecc4d80
RR
3027 gtk_widget_set_usize( m_widget, m_width, m_height );
3028 }
362c6693 3029}
c801d85f 3030
debe6624 3031void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
c801d85f 3032{
1ecc4d80
RR
3033 wxCHECK_RET( m_widget != NULL, "invalid window" );
3034
3035 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
3036
3037 if (orient == wxHORIZONTAL)
3038 {
3039 float fpos = (float)pos;
3040 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
3041 if (fpos < 0.0) fpos = 0.0;
3042 m_oldHorizontalPos = fpos;
3043
3044 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
3045 m_hAdjust->value = fpos;
3046 }
3047 else
3048 {
3049 float fpos = (float)pos;
3050 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
3051 if (fpos < 0.0) fpos = 0.0;
3052 m_oldVerticalPos = fpos;
ff8bfdbb 3053
1ecc4d80
RR
3054 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
3055 m_vAdjust->value = fpos;
3056 }
47d67540 3057
1ecc4d80 3058 if (!m_isScrolling)
47d67540 3059 {
1ecc4d80
RR
3060 if (m_wxwindow->window)
3061 {
3062 if (orient == wxHORIZONTAL)
3063 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
3064 else
3065 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
3066 }
cb43b372 3067 }
362c6693 3068}
c801d85f 3069
debe6624 3070int wxWindow::GetScrollThumb( int orient ) const
c801d85f 3071{
1ecc4d80 3072 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
47d67540 3073
1ecc4d80 3074 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
47d67540 3075
1ecc4d80
RR
3076 if (orient == wxHORIZONTAL)
3077 return (int)(m_hAdjust->page_size+0.5);
3078 else
3079 return (int)(m_vAdjust->page_size+0.5);
362c6693 3080}
c801d85f 3081
debe6624 3082int wxWindow::GetScrollPos( int orient ) const
c801d85f 3083{
1ecc4d80 3084 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
47d67540 3085
1ecc4d80 3086 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
c801d85f 3087
1ecc4d80
RR
3088 if (orient == wxHORIZONTAL)
3089 return (int)(m_hAdjust->value+0.5);
3090 else
3091 return (int)(m_vAdjust->value+0.5);
362c6693 3092}
c801d85f 3093
debe6624 3094int wxWindow::GetScrollRange( int orient ) const
c801d85f 3095{
1ecc4d80 3096 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
47d67540 3097
1ecc4d80 3098 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
c801d85f 3099
1ecc4d80
RR
3100 if (orient == wxHORIZONTAL)
3101 return (int)(m_hAdjust->upper+0.5);
3102 else
3103 return (int)(m_vAdjust->upper+0.5);
362c6693 3104}
c801d85f 3105
debe6624 3106void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
c801d85f 3107{
1ecc4d80 3108 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 3109
1ecc4d80 3110 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
c801d85f
KB
3111
3112 int cw = 0;
3113 int ch = 0;
3114 GetClientSize( &cw, &ch );
47d67540 3115
c801d85f
KB
3116 int w = cw - abs(dx);
3117 int h = ch - abs(dy);
3118 if ((h < 0) || (w < 0))
3119 {
1ecc4d80
RR
3120 Refresh();
3121 return;
362c6693 3122 }
c801d85f
KB
3123 int s_x = 0;
3124 int s_y = 0;
3125 if (dx < 0) s_x = -dx;
3126 if (dy < 0) s_y = -dy;
3127 int d_x = 0;
3128 int d_y = 0;
3129 if (dx > 0) d_x = dx;
3130 if (dy > 0) d_y = dy;
8bbe427f 3131
32e9da8b
RR
3132 if (!m_scrollGC)
3133 {
1ecc4d80
RR
3134 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3135 gdk_gc_set_exposures( m_scrollGC, TRUE );
32e9da8b 3136 }
8bbe427f 3137
32e9da8b 3138 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
1ecc4d80 3139 m_wxwindow->window, s_x, s_y, w, h );
47d67540 3140
c801d85f
KB
3141 wxRect rect;
3142 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3143 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3144 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3145 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
47d67540 3146
c801d85f 3147 Refresh( TRUE, &rect );
362c6693 3148}
c801d85f
KB
3149
3150//-------------------------------------------------------------------------------------
3151// Layout
3152//-------------------------------------------------------------------------------------
3153
68dda785 3154wxLayoutConstraints *wxWindow::GetConstraints() const
c801d85f
KB
3155{
3156 return m_constraints;
362c6693 3157}
c801d85f
KB
3158
3159void wxWindow::SetConstraints( wxLayoutConstraints *constraints )
3160{
3161 if (m_constraints)
3162 {
3163 UnsetConstraints(m_constraints);
3164 delete m_constraints;
3165 }
3166 m_constraints = constraints;
3167 if (m_constraints)
3168 {
3169 // Make sure other windows know they're part of a 'meaningful relationship'
3170 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
3171 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3172 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
3173 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3174 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
3175 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3176 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
3177 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3178 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
3179 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3180 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
3181 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3182 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
3183 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3184 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
3185 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3186 }
3187;
3188}
3189;
3190
debe6624 3191void wxWindow::SetAutoLayout( bool autoLayout )
c801d85f
KB
3192{
3193 m_autoLayout = autoLayout;
362c6693 3194}
c801d85f 3195
68dda785 3196bool wxWindow::GetAutoLayout() const
c801d85f
KB
3197{
3198 return m_autoLayout;
362c6693 3199}
c801d85f 3200
68dda785 3201wxSizer *wxWindow::GetSizer() const
c801d85f
KB
3202{
3203 return m_windowSizer;
362c6693 3204}
c801d85f
KB
3205
3206void wxWindow::SetSizerParent( wxWindow *win )
3207{
3208 m_sizerParent = win;
362c6693 3209}
c801d85f 3210
68dda785 3211wxWindow *wxWindow::GetSizerParent() const
c801d85f
KB
3212{
3213 return m_sizerParent;
362c6693 3214}
c801d85f
KB
3215
3216// This removes any dangling pointers to this window
3217// in other windows' constraintsInvolvedIn lists.
3218void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
3219{
3220 if (c)
3221 {
3222 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
3223 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3224 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
3225 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3226 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
3227 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3228 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
3229 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3230 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
3231 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3232 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
3233 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3234 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
3235 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3236 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
3237 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3238 }
3239}
3240
3241// Back-pointer to other windows we're involved with, so if we delete
3242// this window, we must delete any constraints we're involved with.
3243void wxWindow::AddConstraintReference(wxWindow *otherWin)
3244{
3245 if (!m_constraintsInvolvedIn)
3246 m_constraintsInvolvedIn = new wxList;
3247 if (!m_constraintsInvolvedIn->Member(otherWin))
3248 m_constraintsInvolvedIn->Append(otherWin);
3249}
3250
3251// REMOVE back-pointer to other windows we're involved with.
3252void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
3253{
3254 if (m_constraintsInvolvedIn)
3255 m_constraintsInvolvedIn->DeleteObject(otherWin);
3256}
3257
3258// Reset any constraints that mention this window
68dda785 3259void wxWindow::DeleteRelatedConstraints()
c801d85f
KB
3260{
3261 if (m_constraintsInvolvedIn)
3262 {
3263 wxNode *node = m_constraintsInvolvedIn->First();
3264 while (node)
3265 {
3266 wxWindow *win = (wxWindow *)node->Data();
3267 wxNode *next = node->Next();
3268 wxLayoutConstraints *constr = win->GetConstraints();
3269
3270 // Reset any constraints involving this window
3271 if (constr)
3272 {
3273 constr->left.ResetIfWin((wxWindow *)this);
3274 constr->top.ResetIfWin((wxWindow *)this);
3275 constr->right.ResetIfWin((wxWindow *)this);
3276 constr->bottom.ResetIfWin((wxWindow *)this);
3277 constr->width.ResetIfWin((wxWindow *)this);
3278 constr->height.ResetIfWin((wxWindow *)this);
3279 constr->centreX.ResetIfWin((wxWindow *)this);
3280 constr->centreY.ResetIfWin((wxWindow *)this);
3281 }
3282 delete node;
3283 node = next;
3284 }
3285 delete m_constraintsInvolvedIn;
c67daf87 3286 m_constraintsInvolvedIn = (wxList *) NULL;
c801d85f
KB
3287 }
3288}
3289
3290void wxWindow::SetSizer(wxSizer *sizer)
3291{
3292 m_windowSizer = sizer;
3293 if (sizer)
3294 sizer->SetSizerParent((wxWindow *)this);
3295}
3296
3297/*
3298 * New version
3299 */
3300
68dda785 3301bool wxWindow::Layout()
c801d85f
KB
3302{
3303 if (GetConstraints())
3304 {
3305 int w, h;
3306 GetClientSize(&w, &h);
3307 GetConstraints()->width.SetValue(w);
3308 GetConstraints()->height.SetValue(h);
3309 }
47d67540 3310
c801d85f
KB
3311 // If top level (one sizer), evaluate the sizer's constraints.
3312 if (GetSizer())
3313 {
3314 int noChanges;
3315 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
3316 GetSizer()->LayoutPhase1(&noChanges);
3317 GetSizer()->LayoutPhase2(&noChanges);
3318 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
3319 return TRUE;
3320 }
3321 else
3322 {
3323 // Otherwise, evaluate child constraints
3324 ResetConstraints(); // Mark all constraints as unevaluated
3325 DoPhase(1); // Just one phase need if no sizers involved
3326 DoPhase(2);
3327 SetConstraintSizes(); // Recursively set the real window sizes
3328 }
3329 return TRUE;
3330}
3331
3332
3333// Do a phase of evaluating constraints:
3334// the default behaviour. wxSizers may do a similar
3335// thing, but also impose their own 'constraints'
3336// and order the evaluation differently.
3337bool wxWindow::LayoutPhase1(int *noChanges)
3338{
3339 wxLayoutConstraints *constr = GetConstraints();
3340 if (constr)
3341 {
3342 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
3343 }
3344 else
3345 return TRUE;
3346}
3347
3348bool wxWindow::LayoutPhase2(int *noChanges)
3349{
3350 *noChanges = 0;
47d67540 3351
c801d85f
KB
3352 // Layout children
3353 DoPhase(1);
3354 DoPhase(2);
3355 return TRUE;
3356}
3357
3358// Do a phase of evaluating child constraints
debe6624 3359bool wxWindow::DoPhase(int phase)
c801d85f
KB
3360{
3361 int noIterations = 0;
3362 int maxIterations = 500;
3363 int noChanges = 1;
3364 int noFailures = 0;
3365 wxList succeeded;
3366 while ((noChanges > 0) && (noIterations < maxIterations))
3367 {
3368 noChanges = 0;
3369 noFailures = 0;
8bbe427f 3370 wxNode *node = m_children.First();
c801d85f
KB
3371 while (node)
3372 {
3373 wxWindow *child = (wxWindow *)node->Data();
3374 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
3375 {
3376 wxLayoutConstraints *constr = child->GetConstraints();
3377 if (constr)
3378 {
3379 if (succeeded.Member(child))
3380 {
3381 }
3382 else
3383 {
3384 int tempNoChanges = 0;
3385 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
3386 noChanges += tempNoChanges;
3387 if (success)
3388 {
3389 succeeded.Append(child);
3390 }
3391 }
3392 }
3393 }
3394 node = node->Next();
3395 }
3396 noIterations ++;
3397 }
3398 return TRUE;
3399}
3400
68dda785 3401void wxWindow::ResetConstraints()
c801d85f
KB
3402{
3403 wxLayoutConstraints *constr = GetConstraints();
3404 if (constr)
3405 {
3406 constr->left.SetDone(FALSE);
3407 constr->top.SetDone(FALSE);
3408 constr->right.SetDone(FALSE);
3409 constr->bottom.SetDone(FALSE);
3410 constr->width.SetDone(FALSE);
3411 constr->height.SetDone(FALSE);
3412 constr->centreX.SetDone(FALSE);
3413 constr->centreY.SetDone(FALSE);
3414 }
db1b4961 3415 wxNode *node = m_children.First();
c801d85f
KB
3416 while (node)
3417 {
3418 wxWindow *win = (wxWindow *)node->Data();
3419 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
3420 win->ResetConstraints();
3421 node = node->Next();
3422 }
3423}
3424
3425// Need to distinguish between setting the 'fake' size for
3426// windows and sizers, and setting the real values.
debe6624 3427void wxWindow::SetConstraintSizes(bool recurse)
c801d85f
KB
3428{
3429 wxLayoutConstraints *constr = GetConstraints();
3430 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
3431 constr->width.GetDone() && constr->height.GetDone())
3432 {
3433 int x = constr->left.GetValue();
3434 int y = constr->top.GetValue();
3435 int w = constr->width.GetValue();
3436 int h = constr->height.GetValue();
3437
3438 // If we don't want to resize this window, just move it...
3439 if ((constr->width.GetRelationship() != wxAsIs) ||
3440 (constr->height.GetRelationship() != wxAsIs))
3441 {
3442 // Calls Layout() recursively. AAAGH. How can we stop that.
3443 // Simply take Layout() out of non-top level OnSizes.
3444 SizerSetSize(x, y, w, h);
3445 }
3446 else
3447 {
3448 SizerMove(x, y);
3449 }
3450 }
3451 else if (constr)
3452 {
3453 char *windowClass = this->GetClassInfo()->GetClassName();
3454
3455 wxString winName;
5e0aa05a 3456 if (GetName() == "")
3069ac4e 3457 winName = "unnamed";
5e0aa05a
VZ
3458 else
3459 winName = GetName();
ff8bfdbb
VZ
3460 wxLogDebug( "Constraint(s) not satisfied for window of type %s, name %s:\n",
3461 (const char *)windowClass,
3462 (const char *)winName);
3069ac4e
RR
3463 if (!constr->left.GetDone()) wxLogDebug( " unsatisfied 'left' constraint.\n" );
3464 if (!constr->right.GetDone()) wxLogDebug( " unsatisfied 'right' constraint.\n" );
3465 if (!constr->width.GetDone()) wxLogDebug( " unsatisfied 'width' constraint.\n" );
3466 if (!constr->height.GetDone()) wxLogDebug( " unsatisfied 'height' constraint.\n" );
3467 wxLogDebug( "Please check constraints: try adding AsIs() constraints.\n" );
c801d85f
KB
3468 }
3469
3470 if (recurse)
3471 {
db1b4961 3472 wxNode *node = m_children.First();
c801d85f
KB
3473 while (node)
3474 {
3475 wxWindow *win = (wxWindow *)node->Data();
3476 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
3477 win->SetConstraintSizes();
3478 node = node->Next();
3479 }
3480 }
3481}
3482
3483// This assumes that all sizers are 'on' the same
3484// window, i.e. the parent of this window.
3485void wxWindow::TransformSizerToActual(int *x, int *y) const
3486{
3487 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
5e0aa05a 3488 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
c801d85f 3489 return;
47d67540 3490
c801d85f
KB
3491 int xp, yp;
3492 m_sizerParent->GetPosition(&xp, &yp);
3493 m_sizerParent->TransformSizerToActual(&xp, &yp);
3494 *x += xp;
3495 *y += yp;
3496}
3497
debe6624 3498void wxWindow::SizerSetSize(int x, int y, int w, int h)
c801d85f 3499{
5e0aa05a
VZ
3500 int xx = x;
3501 int yy = y;
c801d85f
KB
3502 TransformSizerToActual(&xx, &yy);
3503 SetSize(xx, yy, w, h);
3504}
3505
debe6624 3506void wxWindow::SizerMove(int x, int y)
c801d85f 3507{
5e0aa05a
VZ
3508 int xx = x;
3509 int yy = y;
c801d85f
KB
3510 TransformSizerToActual(&xx, &yy);
3511 Move(xx, yy);
3512}
3513
3514// Only set the size/position of the constraint (if any)
debe6624 3515void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
c801d85f
KB
3516{
3517 wxLayoutConstraints *constr = GetConstraints();
3518 if (constr)
3519 {
3520 if (x != -1)
3521 {
3522 constr->left.SetValue(x);
3523 constr->left.SetDone(TRUE);
3524 }
3525 if (y != -1)
3526 {
3527 constr->top.SetValue(y);
3528 constr->top.SetDone(TRUE);
3529 }
3530 if (w != -1)
3531 {
3532 constr->width.SetValue(w);
3533 constr->width.SetDone(TRUE);
3534 }
3535 if (h != -1)
3536 {
3537 constr->height.SetValue(h);
3538 constr->height.SetDone(TRUE);
3539 }
3540 }
3541}
3542
debe6624 3543void wxWindow::MoveConstraint(int x, int y)
c801d85f
KB
3544{
3545 wxLayoutConstraints *constr = GetConstraints();
3546 if (constr)
3547 {
3548 if (x != -1)
3549 {
3550 constr->left.SetValue(x);
3551 constr->left.SetDone(TRUE);
3552 }
3553 if (y != -1)
3554 {
3555 constr->top.SetValue(y);
3556 constr->top.SetDone(TRUE);
3557 }
3558 }
3559}
3560
3561void wxWindow::GetSizeConstraint(int *w, int *h) const
3562{
3563 wxLayoutConstraints *constr = GetConstraints();
3564 if (constr)
3565 {
3566 *w = constr->width.GetValue();
3567 *h = constr->height.GetValue();
3568 }
3569 else
3570 GetSize(w, h);
3571}
3572
3573void wxWindow::GetClientSizeConstraint(int *w, int *h) const
3574{
3575 wxLayoutConstraints *constr = GetConstraints();
3576 if (constr)
3577 {
3578 *w = constr->width.GetValue();
3579 *h = constr->height.GetValue();
3580 }
3581 else
3582 GetClientSize(w, h);
3583}
3584
3585void wxWindow::GetPositionConstraint(int *x, int *y) const
3586{
b292e2f5
RR
3587 wxLayoutConstraints *constr = GetConstraints();
3588 if (constr)
c801d85f
KB
3589 {
3590 *x = constr->left.GetValue();
3591 *y = constr->top.GetValue();
3592 }
3593 else
3594 GetPosition(x, y);
3595}
3596