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