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