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