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