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