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