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