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