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