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