]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/window.cpp
Got a new idea to do cursors, including global
[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 #if (GTK_MINOR_VERSION == 0)
48 #include "gdk/gdkx.h"
49 #endif
50
51 //-----------------------------------------------------------------------------
52 // documentation on internals
53 //-----------------------------------------------------------------------------
54
55 /*
56 I have been asked several times about writing some documentation about
57 the GTK port of wxWindows, especially its internal structures. Obviously,
58 you cannot understand wxGTK without knowing a little about the GTK, but
59 some more information about what the wxWindow, which is the base class
60 for all other window classes, does seems required as well.
61
62 What does wxWindow do? It contains the common interface for the following
63 jobs of its descendants:
64
65 1) Define the rudimentary behaviour common to all window classes, such as
66 resizing, intercepting user input (so as to make it possible to use these
67 events for special purposes in a derived class), window names etc.
68
69 2) Provide the possibility to contain and manage children, if the derived
70 class is allowed to contain children, which holds true for those window
71 classes which do not display a native GTK widget. To name them, these
72 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
73 work classes are a special case and are handled a bit differently from
74 the rest. The same holds true for the wxNotebook class.
75
76 3) Provide the possibility to draw into a client area of a window. This,
77 too, only holds true for classes that do not display a native GTK widget
78 as above.
79
80 4) Provide the entire mechanism for scrolling widgets. This actual inter-
81 face for this is usually in wxScrolledWindow, but the GTK implementation
82 is in this class.
83
84 5) A multitude of helper or extra methods for special purposes, such as
85 Drag'n'Drop, managing validators etc.
86
87 Normally one might expect, that one wxWindows window would always correspond
88 to one GTK widget. Under GTK, there is no such allround widget that has all
89 the functionality. Moreover, the GTK defines a client area as a different
90 widget from the actual widget you are handling. Last but not least some
91 special classes (e.g. wxFrame) handle different categories of widgets and
92 still have the possibility to draw something in the client area.
93 It was therefore required to write a special purpose GTK widget, that would
94 represent a client area in the sense of wxWindows capable to do the jobs
95 2), 3) and 4). I have written this class and it resides in win_gtk.c of
96 this directory.
97
98 All windows must have a widget, with which they interact with other under-
99 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
100 thw wxWindow class has a member variable called m_widget which holds a
101 pointer to this widget. When the window class represents a GTK native widget,
102 this is (in most cases) the only GTK widget the class manages. E.g. the
103 wxStatitText class handles only a GtkLabel widget a pointer to which you
104 can find in m_widget (defined in wxWindow)
105
106 When the class has a client area for drawing into and for containing children
107 it has to handle the client area widget (of the type GtkMyFixed, defined in
108 win_gtk.c), but there could be any number of widgets, handled by a class
109 The common rule for all windows is only, that the widget that interacts with
110 the rest of GTK must be referenced in m_widget and all other widgets must be
111 children of this widget on the GTK level. The top-most widget, which also
112 represents the client area, must be in the m_wxwindow field and must be of
113 the type GtkMyFixed.
114
115 As I said, the window classes that display a GTK native widget only have
116 one widget, so in the case of e.g. the wxButton class m_widget holds a
117 pointer to a GtkButton widget. But windows with client areas (for drawing
118 and children) have a m_widget field that is a pointer to a GtkScrolled-
119 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
120 one is (in the GTK sense) a child of the GtkScrolledWindow.
121
122 If the m_wxwindow field is set, then all input to this widget is inter-
123 cepted and sent to the wxWindows class. If not, all input to the widget
124 that gets pointed to by m_widget gets intercepted and sent to the class.
125
126 */
127
128 //-----------------------------------------------------------------------------
129 // data
130 //-----------------------------------------------------------------------------
131
132 extern wxList wxPendingDelete;
133 extern bool g_blockEventsOnDrag;
134 extern bool g_blockEventsOnScroll;
135 extern wxCursor g_globalCursor;
136 static bool g_capturing = FALSE;
137 static wxWindow *g_focusWindow = (wxWindow*) NULL;
138
139 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
140 the last click here */
141 static guint32 gs_timeLastClick = 0;
142
143 //-----------------------------------------------------------------------------
144 // debug
145 //-----------------------------------------------------------------------------
146
147 #ifdef __WXDEBUG__
148
149 static gint gtk_debug_focus_in_callback( GtkWidget *WXUNUSED(widget),
150 GdkEvent *WXUNUSED(event),
151 const wxChar *name )
152 {
153 /*
154 static bool s_done = FALSE;
155 if ( !s_done )
156 {
157 wxLog::AddTraceMask("focus");
158 s_done = TRUE;
159 }
160 wxLogTrace(_T("FOCUS NOW AT: %s"), name);
161 */
162
163 return FALSE;
164 }
165
166 void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window )
167 {
168 wxString tmp = name;
169 tmp += _T(" FROM ");
170 tmp += window;
171
172 wxChar *s = new wxChar[tmp.Length()+1];
173
174 wxStrcpy( s, tmp );
175
176 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
177 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback), (gpointer)s );
178 }
179
180 #endif // Debug
181
182 //-----------------------------------------------------------------------------
183 // idle system
184 //-----------------------------------------------------------------------------
185
186 extern void wxapp_install_idle_handler();
187 extern bool g_isIdle;
188
189 //-----------------------------------------------------------------------------
190 // key event conversion routines
191 //-----------------------------------------------------------------------------
192
193 #if (GTK_MINOR_VERSION == 0)
194 static guint
195 gdk_keyval_to_upper (guint keyval)
196 {
197 if (keyval)
198 {
199 KeySym lower_val = 0;
200 KeySym upper_val = 0;
201
202 XConvertCase (keyval, &lower_val, &upper_val);
203 return upper_val;
204 }
205 return 0;
206 }
207 #endif
208
209 static long map_to_unmodified_wx_keysym( KeySym keysym )
210 {
211 guint key_code = 0;
212
213 switch (keysym)
214 {
215 case GDK_Shift_L:
216 case GDK_Shift_R: key_code = WXK_SHIFT; break;
217 case GDK_Control_L:
218 case GDK_Control_R: key_code = WXK_CONTROL; break;
219 case GDK_Menu: key_code = WXK_MENU; break;
220 case GDK_Help: key_code = WXK_HELP; break;
221 case GDK_BackSpace: key_code = WXK_BACK; break;
222 case GDK_ISO_Left_Tab:
223 case GDK_Tab: key_code = WXK_TAB; break;
224 case GDK_Linefeed: key_code = WXK_RETURN; break;
225 case GDK_Clear: key_code = WXK_CLEAR; break;
226 case GDK_Return: key_code = WXK_RETURN; break;
227 case GDK_Pause: key_code = WXK_PAUSE; break;
228 case GDK_Scroll_Lock: key_code = WXK_SCROLL; break;
229 case GDK_Escape: key_code = WXK_ESCAPE; break;
230 case GDK_Delete: key_code = WXK_DELETE; break;
231 case GDK_Home: key_code = WXK_HOME; break;
232 case GDK_Left: key_code = WXK_LEFT; break;
233 case GDK_Up: key_code = WXK_UP; break;
234 case GDK_Right: key_code = WXK_RIGHT; break;
235 case GDK_Down: key_code = WXK_DOWN; break;
236 case GDK_Prior: key_code = WXK_PRIOR; break;
237 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
238 case GDK_Next: key_code = WXK_NEXT; break;
239 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
240 case GDK_End: key_code = WXK_END; break;
241 case GDK_Begin: key_code = WXK_HOME; break;
242 case GDK_Select: key_code = WXK_SELECT; break;
243 case GDK_Print: key_code = WXK_PRINT; break;
244 case GDK_Execute: key_code = WXK_EXECUTE; break;
245 case GDK_Insert: key_code = WXK_INSERT; break;
246 case GDK_Num_Lock: key_code = WXK_NUMLOCK; break;
247
248 case GDK_KP_0: key_code = WXK_NUMPAD0; break;
249 case GDK_KP_1: key_code = WXK_NUMPAD1; break;
250 case GDK_KP_2: key_code = WXK_NUMPAD2; break;
251 case GDK_KP_3: key_code = WXK_NUMPAD3; break;
252 case GDK_KP_4: key_code = WXK_NUMPAD4; break;
253 case GDK_KP_5: key_code = WXK_NUMPAD5; break;
254 case GDK_KP_6: key_code = WXK_NUMPAD6; break;
255 case GDK_KP_7: key_code = WXK_NUMPAD7; break;
256 case GDK_KP_8: key_code = WXK_NUMPAD8; break;
257 case GDK_KP_9: key_code = WXK_NUMPAD9; break;
258 case GDK_KP_Space: key_code = WXK_NUMPAD_SPACE; break;
259 case GDK_KP_Tab: key_code = WXK_NUMPAD_TAB; break;
260 case GDK_KP_Enter: key_code = WXK_NUMPAD_ENTER; break;
261 case GDK_KP_F1: key_code = WXK_NUMPAD_F1; break;
262 case GDK_KP_F2: key_code = WXK_NUMPAD_F2; break;
263 case GDK_KP_F3: key_code = WXK_NUMPAD_F3; break;
264 case GDK_KP_F4: key_code = WXK_NUMPAD_F4; break;
265 case GDK_KP_Home: key_code = WXK_NUMPAD_HOME; break;
266 case GDK_KP_Left: key_code = WXK_NUMPAD_LEFT; break;
267 case GDK_KP_Up: key_code = WXK_NUMPAD_UP; break;
268 case GDK_KP_Right: key_code = WXK_NUMPAD_RIGHT; break;
269 case GDK_KP_Down: key_code = WXK_NUMPAD_DOWN; break;
270 case GDK_KP_Prior: key_code = WXK_NUMPAD_PRIOR; break;
271 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
272 case GDK_KP_Next: key_code = WXK_NUMPAD_NEXT; break;
273 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
274 case GDK_KP_End: key_code = WXK_NUMPAD_END; break;
275 case GDK_KP_Begin: key_code = WXK_NUMPAD_BEGIN; break;
276 case GDK_KP_Insert: key_code = WXK_NUMPAD_INSERT; break;
277 case GDK_KP_Delete: key_code = WXK_NUMPAD_DELETE; break;
278 case GDK_KP_Equal: key_code = WXK_NUMPAD_EQUAL; break;
279 case GDK_KP_Multiply: key_code = WXK_NUMPAD_MULTIPLY; break;
280 case GDK_KP_Add: key_code = WXK_NUMPAD_ADD; break;
281 case GDK_KP_Separator: key_code = WXK_NUMPAD_SEPARATOR; break;
282 case GDK_KP_Subtract: key_code = WXK_NUMPAD_SUBTRACT; break;
283 case GDK_KP_Decimal: key_code = WXK_NUMPAD_DECIMAL; break;
284 case GDK_KP_Divide: key_code = WXK_NUMPAD_DIVIDE; break;
285
286 case GDK_F1: key_code = WXK_F1; break;
287 case GDK_F2: key_code = WXK_F2; break;
288 case GDK_F3: key_code = WXK_F3; break;
289 case GDK_F4: key_code = WXK_F4; break;
290 case GDK_F5: key_code = WXK_F5; break;
291 case GDK_F6: key_code = WXK_F6; break;
292 case GDK_F7: key_code = WXK_F7; break;
293 case GDK_F8: key_code = WXK_F8; break;
294 case GDK_F9: key_code = WXK_F9; break;
295 case GDK_F10: key_code = WXK_F10; break;
296 case GDK_F11: key_code = WXK_F11; break;
297 case GDK_F12: key_code = WXK_F12; break;
298 default:
299 {
300 if (keysym <= 0xFF)
301 {
302 guint upper = gdk_keyval_to_upper( keysym );
303 keysym = (upper != 0 ? upper : keysym ); /* to be MSW compatible */
304 key_code = keysym;
305 }
306 }
307 }
308
309 return (key_code);
310 }
311
312 static long map_to_wx_keysym( KeySym keysym )
313 {
314 guint key_code = 0;
315
316 switch (keysym)
317 {
318 case GDK_Menu: key_code = WXK_MENU; break;
319 case GDK_Help: key_code = WXK_HELP; break;
320 case GDK_BackSpace: key_code = WXK_BACK; break;
321 case GDK_ISO_Left_Tab:
322 case GDK_Tab: key_code = WXK_TAB; break;
323 case GDK_Linefeed: key_code = WXK_RETURN; break;
324 case GDK_Clear: key_code = WXK_CLEAR; break;
325 case GDK_Return: key_code = WXK_RETURN; break;
326 case GDK_Pause: key_code = WXK_PAUSE; break;
327 case GDK_Scroll_Lock: key_code = WXK_SCROLL; break;
328 case GDK_Escape: key_code = WXK_ESCAPE; break;
329 case GDK_Delete: key_code = WXK_DELETE; break;
330 case GDK_Home: key_code = WXK_HOME; break;
331 case GDK_Left: key_code = WXK_LEFT; break;
332 case GDK_Up: key_code = WXK_UP; break;
333 case GDK_Right: key_code = WXK_RIGHT; break;
334 case GDK_Down: key_code = WXK_DOWN; break;
335 case GDK_Prior: key_code = WXK_PRIOR; break;
336 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
337 case GDK_Next: key_code = WXK_NEXT; break;
338 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
339 case GDK_End: key_code = WXK_END; break;
340 case GDK_Begin: key_code = WXK_HOME; break;
341 case GDK_Select: key_code = WXK_SELECT; break;
342 case GDK_Print: key_code = WXK_PRINT; break;
343 case GDK_Execute: key_code = WXK_EXECUTE; break;
344 case GDK_Insert: key_code = WXK_INSERT; break;
345 case GDK_Num_Lock: key_code = WXK_NUMLOCK; break;
346
347 case GDK_KP_0: key_code = '0'; break;
348 case GDK_KP_1: key_code = '1'; break;
349 case GDK_KP_2: key_code = '2'; break;
350 case GDK_KP_3: key_code = '3'; break;
351 case GDK_KP_4: key_code = '4'; break;
352 case GDK_KP_5: key_code = '5'; break;
353 case GDK_KP_6: key_code = '6'; break;
354 case GDK_KP_7: key_code = '7'; break;
355 case GDK_KP_8: key_code = '8'; break;
356 case GDK_KP_9: key_code = '9'; break;
357 case GDK_KP_Space: key_code = ' '; break;
358 case GDK_KP_Tab: key_code = WXK_TAB; break; /* or '\t' ??? */
359 case GDK_KP_Enter: key_code = WXK_RETURN; break; /* or '\r' ??? */
360 case GDK_KP_F1: key_code = WXK_NUMPAD_F1; break;
361 case GDK_KP_F2: key_code = WXK_NUMPAD_F2; break;
362 case GDK_KP_F3: key_code = WXK_NUMPAD_F3; break;
363 case GDK_KP_F4: key_code = WXK_NUMPAD_F4; break;
364 case GDK_KP_Home: key_code = WXK_HOME; break;
365 case GDK_KP_Left: key_code = WXK_LEFT; break;
366 case GDK_KP_Up: key_code = WXK_UP; break;
367 case GDK_KP_Right: key_code = WXK_RIGHT; break;
368 case GDK_KP_Down: key_code = WXK_DOWN; break;
369 case GDK_KP_Prior: key_code = WXK_PRIOR; break;
370 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
371 case GDK_KP_Next: key_code = WXK_NEXT; break;
372 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
373 case GDK_KP_End: key_code = WXK_END; break;
374 case GDK_KP_Begin: key_code = WXK_HOME; break;
375 case GDK_KP_Insert: key_code = WXK_INSERT; break;
376 case GDK_KP_Delete: key_code = WXK_DELETE; break;
377 case GDK_KP_Equal: key_code = '='; break;
378 case GDK_KP_Multiply: key_code = '*'; break;
379 case GDK_KP_Add: key_code = '+'; break;
380 case GDK_KP_Separator: key_code = ','; break;
381 case GDK_KP_Subtract: key_code = '-'; break;
382 case GDK_KP_Decimal: key_code = '.'; break;
383 case GDK_KP_Divide: key_code = '/'; break;
384
385 case GDK_F1: key_code = WXK_F1; break;
386 case GDK_F2: key_code = WXK_F2; break;
387 case GDK_F3: key_code = WXK_F3; break;
388 case GDK_F4: key_code = WXK_F4; break;
389 case GDK_F5: key_code = WXK_F5; break;
390 case GDK_F6: key_code = WXK_F6; break;
391 case GDK_F7: key_code = WXK_F7; break;
392 case GDK_F8: key_code = WXK_F8; break;
393 case GDK_F9: key_code = WXK_F9; break;
394 case GDK_F10: key_code = WXK_F10; break;
395 case GDK_F11: key_code = WXK_F11; break;
396 case GDK_F12: key_code = WXK_F12; break;
397 default:
398 {
399 if (keysym <= 0xFF)
400 {
401 key_code = keysym;
402 }
403 }
404 }
405
406 return (key_code);
407 }
408
409 //-----------------------------------------------------------------------------
410 // local code (see below)
411 //-----------------------------------------------------------------------------
412
413 #if (GTK_MINOR_VERSION > 0)
414
415 static void draw_frame( GtkWidget *widget, wxWindow *win )
416 {
417 if (!win->m_hasVMT)
418 return;
419
420 int dw = 0;
421 int dh = 0;
422
423 if (win->HasScrolling())
424 {
425 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(widget);
426 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget)->klass );
427
428 /*
429 GtkWidget *hscrollbar = scroll_window->hscrollbar;
430 GtkWidget *vscrollbar = scroll_window->vscrollbar;
431
432 we use this instead: range.slider_width = 11 + 2*2pts edge
433 */
434
435 if (scroll_window->vscrollbar_visible)
436 {
437 dw += 15; /* dw += vscrollbar->allocation.width; */
438 dw += scroll_class->scrollbar_spacing;
439 }
440
441 if (scroll_window->hscrollbar_visible)
442 {
443 dh += 15; /* dh += hscrollbar->allocation.height; */
444 dh += scroll_class->scrollbar_spacing;
445 }
446 }
447
448 int dx = 0;
449 int dy = 0;
450 if (GTK_WIDGET_NO_WINDOW (widget))
451 {
452 dx += widget->allocation.x;
453 dy += widget->allocation.y;
454 }
455
456 if (win->HasFlag(wxRAISED_BORDER))
457 {
458 gtk_draw_shadow( widget->style,
459 widget->window,
460 GTK_STATE_NORMAL,
461 GTK_SHADOW_OUT,
462 dx, dy,
463 win->m_width-dw, win->m_height-dh );
464 return;
465 }
466
467 if (win->HasFlag(wxSUNKEN_BORDER))
468 {
469 gtk_draw_shadow( widget->style,
470 widget->window,
471 GTK_STATE_NORMAL,
472 GTK_SHADOW_IN,
473 dx, dy,
474 win->m_width-dw, win->m_height-dh );
475 return;
476 }
477 }
478
479 //-----------------------------------------------------------------------------
480 // "expose_event" of m_widget
481 //-----------------------------------------------------------------------------
482
483 static void gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win )
484 {
485 if (gdk_event->count > 0) return;
486 draw_frame( widget, win );
487 }
488
489 //-----------------------------------------------------------------------------
490 // "draw" of m_wxwindow
491 //-----------------------------------------------------------------------------
492
493 static void gtk_window_own_draw_callback( GtkWidget *widget, GdkRectangle *WXUNUSED(rect), wxWindow *win )
494 {
495 draw_frame( widget, win );
496 }
497
498 #endif // GTK_MINOR_VERSION > 0
499
500 //-----------------------------------------------------------------------------
501 // "expose_event" of m_wxwindow
502 //-----------------------------------------------------------------------------
503
504 static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxWindow *win )
505 {
506 if ( !win->m_hasVMT )
507 return;
508
509 win->GetUpdateRegion().Union( gdk_event->area.x,
510 gdk_event->area.y,
511 gdk_event->area.width,
512 gdk_event->area.height );
513
514 if ( gdk_event->count > 0 )
515 return;
516
517 /*
518 printf( "OnExpose from " );
519 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
520 printf( win->GetClassInfo()->GetClassName() );
521 printf( ".\n" );
522 */
523
524 wxPaintEvent event( win->GetId() );
525 event.SetEventObject( win );
526 win->GetEventHandler()->ProcessEvent( event );
527
528 win->GetUpdateRegion().Clear();
529 }
530
531 //-----------------------------------------------------------------------------
532 // "draw" of m_wxwindow
533 //-----------------------------------------------------------------------------
534
535 static void gtk_window_draw_callback( GtkWidget *WXUNUSED(widget), GdkRectangle *rect, wxWindow *win )
536 {
537 if (g_isIdle)
538 wxapp_install_idle_handler();
539
540 if (!win->m_hasVMT)
541 return;
542
543 win->GetUpdateRegion().Union( rect->x, rect->y,
544 rect->width, rect->height );
545
546 wxPaintEvent event( win->GetId() );
547 event.SetEventObject( win );
548 win->GetEventHandler()->ProcessEvent( event );
549
550 win->GetUpdateRegion().Clear();
551 }
552
553 //-----------------------------------------------------------------------------
554 // "key_press_event" from any window
555 //-----------------------------------------------------------------------------
556
557 static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
558 {
559 if (g_isIdle)
560 wxapp_install_idle_handler();
561
562 if (!win->m_hasVMT) return FALSE;
563 if (g_blockEventsOnDrag) return FALSE;
564
565 /*
566 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
567 if (gdk_event->state & GDK_SHIFT_MASK)
568 printf( "ShiftDown.\n" );
569 else
570 printf( "ShiftUp.\n" );
571 if (gdk_event->state & GDK_CONTROL_MASK)
572 printf( "ControlDown.\n" );
573 else
574 printf( "ControlUp.\n" );
575 printf( "\n" );
576 */
577 int x = 0;
578 int y = 0;
579 GdkModifierType state;
580 if (gdk_event->window) gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
581
582 long key_code = map_to_unmodified_wx_keysym( gdk_event->keyval );
583
584 /* sending unknown key events doesn't really make sense */
585 if (key_code == 0) return FALSE;
586
587 bool ret = FALSE;
588
589 wxKeyEvent event( wxEVT_KEY_DOWN );
590 event.SetTimestamp( gdk_event->time );
591 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
592 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
593 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
594 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
595 event.m_keyCode = key_code;
596 event.m_scanCode = gdk_event->keyval;
597 event.m_x = x;
598 event.m_y = y;
599 event.SetEventObject( win );
600 ret = win->GetEventHandler()->ProcessEvent( event );
601
602 key_code = map_to_wx_keysym( gdk_event->keyval );
603
604 /* wxMSW doesn't send char events with Alt pressed */
605 if ((key_code != 0) &&
606 ((gdk_event->state & GDK_MOD1_MASK) == 0) &&
607 ((gdk_event->state & GDK_MOD1_MASK) == 0))
608 {
609 wxKeyEvent event2( wxEVT_CHAR );
610 event2.SetTimestamp( gdk_event->time );
611 event2.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
612 event2.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
613 // event2.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
614 // event2.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
615 event2.m_keyCode = key_code;
616 event2.m_scanCode = gdk_event->keyval;
617 event2.m_x = x;
618 event2.m_y = y;
619 event2.SetEventObject( win );
620 ret = (ret || win->GetEventHandler()->ProcessEvent( event2 ));
621 }
622
623 if (!ret)
624 {
625 wxWindow *ancestor = win;
626 while (ancestor)
627 {
628 int command = ancestor->GetAcceleratorTable()->GetCommand( event );
629 if (command != -1)
630 {
631 wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
632 ret = ancestor->GetEventHandler()->ProcessEvent( command_event );
633 break;
634 }
635 ancestor = ancestor->GetParent();
636 }
637 }
638
639 /* win is a control: tab can be propagated up */
640 if ( (!ret) &&
641 ((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
642 (win->HasFlag(wxTE_PROCESS_TAB) == 0))
643 {
644 wxNavigationKeyEvent new_event;
645 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
646 new_event.SetDirection( (gdk_event->keyval == GDK_Tab) );
647 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
648 new_event.SetWindowChange( (gdk_event->state & GDK_CONTROL_MASK) );
649 new_event.SetCurrentFocus( win );
650 ret = win->GetEventHandler()->ProcessEvent( new_event );
651 }
652
653 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
654 if ( (!ret) &&
655 (gdk_event->keyval == GDK_Escape) )
656 {
657 wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
658 new_event.SetEventObject( win );
659 ret = win->GetEventHandler()->ProcessEvent( new_event );
660 }
661
662 #if (GTK_MINOR_VERSION > 0)
663 /* pressing F10 will activate the menu bar of the top frame */
664 if ( (!ret) &&
665 (gdk_event->keyval == GDK_F10) )
666 {
667 wxWindow *ancestor = win;
668 while (ancestor)
669 {
670 if (wxIsKindOf(ancestor,wxFrame))
671 {
672 wxFrame *frame = (wxFrame*) ancestor;
673 wxMenuBar *menubar = frame->GetMenuBar();
674 if (menubar)
675 {
676 wxNode *node = menubar->GetMenus().First();
677 if (node)
678 {
679 wxMenu *firstMenu = (wxMenu*) node->Data();
680 // doesn't work correctly
681 // gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
682 // ret = TRUE;
683 break;
684 }
685 }
686 }
687 ancestor = ancestor->GetParent();
688 }
689 }
690 #endif
691
692 /*
693 Damn, I forgot why this didn't work, but it didn't work.
694
695 // win is a panel: up can be propagated to the panel
696 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
697 (gdk_event->keyval == GDK_Up))
698 {
699 win->m_parent->SetFocus();
700 ret = TRUE;
701 }
702
703 // win is a panel: left/right can be propagated to the panel
704 if ((!ret) && (win->m_wxwindow) &&
705 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
706 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
707 {
708 wxNavigationKeyEvent new_event;
709 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
710 new_event.SetCurrentFocus( win );
711 ret = win->GetEventHandler()->ProcessEvent( new_event );
712 }
713 */
714
715 if (ret)
716 {
717 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
718 return TRUE;
719 }
720
721 return FALSE;
722 }
723
724 //-----------------------------------------------------------------------------
725 // "key_release_event" from any window
726 //-----------------------------------------------------------------------------
727
728 static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
729 {
730 if (g_isIdle)
731 wxapp_install_idle_handler();
732
733 if (!win->m_hasVMT) return FALSE;
734 if (g_blockEventsOnDrag) return FALSE;
735
736 /*
737 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
738 if (gdk_event->state & GDK_SHIFT_MASK)
739 printf( "ShiftDown.\n" );
740 else
741 printf( "ShiftUp.\n" );
742 if (gdk_event->state & GDK_CONTROL_MASK)
743 printf( "ControlDown.\n" );
744 else
745 printf( "ControlUp.\n" );
746 printf( "\n" );
747 */
748
749 long key_code = map_to_unmodified_wx_keysym( gdk_event->keyval );
750
751 /* sending unknown key events doesn't really make sense */
752 if (key_code == 0) return FALSE;
753
754 int x = 0;
755 int y = 0;
756 GdkModifierType state;
757 if (gdk_event->window) gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
758
759 wxKeyEvent event( wxEVT_KEY_UP );
760 event.SetTimestamp( gdk_event->time );
761 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
762 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
763 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
764 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
765 event.m_keyCode = key_code;
766 event.m_scanCode = gdk_event->keyval;
767 event.m_x = x;
768 event.m_y = y;
769 event.SetEventObject( win );
770
771 if (win->GetEventHandler()->ProcessEvent( event ))
772 {
773 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_release_event" );
774 return TRUE;
775 }
776
777 return FALSE;
778 }
779
780 //-----------------------------------------------------------------------------
781 // "button_press_event"
782 //-----------------------------------------------------------------------------
783
784 static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
785 {
786 if (g_isIdle)
787 wxapp_install_idle_handler();
788
789 /*
790 wxPrintf( _T("1) OnButtonPress from ") );
791 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
792 wxPrintf( win->GetClassInfo()->GetClassName() );
793 wxPrintf( _T(".\n") );
794 */
795 if (!win->m_hasVMT) return FALSE;
796 if (g_blockEventsOnDrag) return TRUE;
797 if (g_blockEventsOnScroll) return TRUE;
798
799 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
800
801 if (win->m_wxwindow)
802 {
803 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow) && !GTK_WIDGET_HAS_FOCUS (win->m_wxwindow) )
804 {
805 gtk_widget_grab_focus (win->m_wxwindow);
806
807 /*
808 wxPrintf( _T("GrabFocus from ") );
809 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
810 wxPrintf( win->GetClassInfo()->GetClassName() );
811 wxPrintf( _T(".\n") );
812 */
813
814 }
815 }
816
817 /*
818 wxPrintf( _T("2) OnButtonPress from ") );
819 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
820 wxPrintf( win->GetClassInfo()->GetClassName() );
821 wxPrintf( _T(".\n") );
822 */
823
824 wxEventType event_type = wxEVT_LEFT_DOWN;
825
826 if (gdk_event->button == 1)
827 {
828 switch (gdk_event->type)
829 {
830 case GDK_BUTTON_PRESS: event_type = wxEVT_LEFT_DOWN; break;
831 case GDK_2BUTTON_PRESS: event_type = wxEVT_LEFT_DCLICK; break;
832 default: break;
833 }
834 }
835 else if (gdk_event->button == 2)
836 {
837 switch (gdk_event->type)
838 {
839 case GDK_BUTTON_PRESS: event_type = wxEVT_MIDDLE_DOWN; break;
840 case GDK_2BUTTON_PRESS: event_type = wxEVT_MIDDLE_DCLICK; break;
841 default: break;
842 }
843 }
844 else if (gdk_event->button == 3)
845 {
846 switch (gdk_event->type)
847 {
848 case GDK_BUTTON_PRESS: event_type = wxEVT_RIGHT_DOWN; break;
849 case GDK_2BUTTON_PRESS: event_type = wxEVT_RIGHT_DCLICK; break;
850 default: break;
851 }
852 }
853
854 wxMouseEvent event( event_type );
855 event.SetTimestamp( gdk_event->time );
856 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
857 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
858 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
859 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
860 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
861 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
862 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
863
864 event.m_x = (long)gdk_event->x;
865 event.m_y = (long)gdk_event->y;
866
867 // Some control don't have their own X window and thus cannot get
868 // any events.
869
870 if (!g_capturing)
871 {
872 wxNode *node = win->GetChildren().First();
873 while (node)
874 {
875 wxWindow *child = (wxWindow*)node->Data();
876
877 if (child->m_isStaticBox)
878 {
879 // wxStaticBox is transparent in the box itself
880 int x = event.m_x;
881 int y = event.m_y;
882 int xx1 = child->m_x;
883 int yy1 = child->m_y;
884 int xx2 = child->m_x + child->m_width;
885 int yy2 = child->m_x + child->m_height;
886
887 // left
888 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
889 // right
890 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
891 // top
892 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
893 // bottom
894 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
895 {
896 win = child;
897 event.m_x -= child->m_x;
898 event.m_y -= child->m_y;
899 break;
900 }
901
902 }
903 else
904 {
905 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
906 (child->m_x <= event.m_x) &&
907 (child->m_y <= event.m_y) &&
908 (child->m_x+child->m_width >= event.m_x) &&
909 (child->m_y+child->m_height >= event.m_y))
910 {
911 win = child;
912 event.m_x -= child->m_x;
913 event.m_y -= child->m_y;
914 break;
915 }
916 }
917 node = node->Next();
918 }
919 }
920
921 event.SetEventObject( win );
922
923 gs_timeLastClick = gdk_event->time;
924
925 if (win->GetEventHandler()->ProcessEvent( event ))
926 {
927 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
928 return TRUE;
929 }
930
931 return FALSE;
932 }
933
934 //-----------------------------------------------------------------------------
935 // "button_release_event"
936 //-----------------------------------------------------------------------------
937
938 static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
939 {
940 if (g_isIdle)
941 wxapp_install_idle_handler();
942
943 if (!win->m_hasVMT) return FALSE;
944 if (g_blockEventsOnDrag) return FALSE;
945 if (g_blockEventsOnScroll) return FALSE;
946
947 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
948
949 /*
950 printf( "OnButtonRelease from " );
951 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
952 printf( win->GetClassInfo()->GetClassName() );
953 printf( ".\n" );
954 */
955
956 wxEventType event_type = wxEVT_NULL;
957
958 switch (gdk_event->button)
959 {
960 case 1: event_type = wxEVT_LEFT_UP; break;
961 case 2: event_type = wxEVT_MIDDLE_UP; break;
962 case 3: event_type = wxEVT_RIGHT_UP; break;
963 }
964
965 wxMouseEvent event( event_type );
966 event.SetTimestamp( gdk_event->time );
967 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
968 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
969 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
970 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
971 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
972 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
973 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
974 event.m_x = (long)gdk_event->x;
975 event.m_y = (long)gdk_event->y;
976
977 // Some control don't have their own X window and thus cannot get
978 // any events.
979
980 if (!g_capturing)
981 {
982 wxNode *node = win->GetChildren().First();
983 while (node)
984 {
985 wxWindow *child = (wxWindow*)node->Data();
986
987 if (child->m_isStaticBox)
988 {
989 // wxStaticBox is transparent in the box itself
990 int x = event.m_x;
991 int y = event.m_y;
992 int xx1 = child->m_x;
993 int yy1 = child->m_y;
994 int xx2 = child->m_x + child->m_width;
995 int yy2 = child->m_x + child->m_height;
996
997 // left
998 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
999 // right
1000 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1001 // top
1002 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1003 // bottom
1004 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1005 {
1006 win = child;
1007 event.m_x -= child->m_x;
1008 event.m_y -= child->m_y;
1009 break;
1010 }
1011
1012 }
1013 else
1014 {
1015 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
1016 (child->m_x <= event.m_x) &&
1017 (child->m_y <= event.m_y) &&
1018 (child->m_x+child->m_width >= event.m_x) &&
1019 (child->m_y+child->m_height >= event.m_y))
1020 {
1021 win = child;
1022 event.m_x -= child->m_x;
1023 event.m_y -= child->m_y;
1024 break;
1025 }
1026 }
1027 node = node->Next();
1028 }
1029 }
1030
1031 event.SetEventObject( win );
1032
1033 if (win->GetEventHandler()->ProcessEvent( event ))
1034 {
1035 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" );
1036 return TRUE;
1037 }
1038
1039 return FALSE;
1040 }
1041
1042 //-----------------------------------------------------------------------------
1043 // "motion_notify_event"
1044 //-----------------------------------------------------------------------------
1045
1046 static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
1047 {
1048 if (g_isIdle)
1049 wxapp_install_idle_handler();
1050
1051 if (!win->m_hasVMT) return FALSE;
1052 if (g_blockEventsOnDrag) return FALSE;
1053 if (g_blockEventsOnScroll) return FALSE;
1054
1055 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1056
1057 if (gdk_event->is_hint)
1058 {
1059 int x = 0;
1060 int y = 0;
1061 GdkModifierType state;
1062 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
1063 gdk_event->x = x;
1064 gdk_event->y = y;
1065 gdk_event->state = state;
1066 }
1067
1068 /*
1069 printf( "OnMotion from " );
1070 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1071 printf( win->GetClassInfo()->GetClassName() );
1072 printf( ".\n" );
1073 */
1074
1075 wxMouseEvent event( wxEVT_MOTION );
1076 event.SetTimestamp( gdk_event->time );
1077 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1078 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1079 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1080 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1081 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1082 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1083 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
1084
1085 event.m_x = (long)gdk_event->x;
1086 event.m_y = (long)gdk_event->y;
1087
1088 // Some control don't have their own X window and thus cannot get
1089 // any events.
1090
1091 if (!g_capturing)
1092 {
1093 wxNode *node = win->GetChildren().First();
1094 while (node)
1095 {
1096 wxWindow *child = (wxWindow*)node->Data();
1097
1098 if (child->m_isStaticBox)
1099 {
1100 // wxStaticBox is transparent in the box itself
1101 int x = event.m_x;
1102 int y = event.m_y;
1103 int xx1 = child->m_x;
1104 int yy1 = child->m_y;
1105 int xx2 = child->m_x + child->m_width;
1106 int yy2 = child->m_x + child->m_height;
1107
1108 // left
1109 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1110 // right
1111 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1112 // top
1113 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1114 // bottom
1115 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1116 {
1117 win = child;
1118 event.m_x -= child->m_x;
1119 event.m_y -= child->m_y;
1120 break;
1121 }
1122
1123 }
1124 else
1125 {
1126 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
1127 (child->m_x <= event.m_x) &&
1128 (child->m_y <= event.m_y) &&
1129 (child->m_x+child->m_width >= event.m_x) &&
1130 (child->m_y+child->m_height >= event.m_y))
1131 {
1132 win = child;
1133 event.m_x -= child->m_x;
1134 event.m_y -= child->m_y;
1135 break;
1136 }
1137 }
1138 node = node->Next();
1139 }
1140 }
1141
1142 event.SetEventObject( win );
1143
1144 if (win->GetEventHandler()->ProcessEvent( event ))
1145 {
1146 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
1147 return TRUE;
1148 }
1149
1150 return FALSE;
1151 }
1152
1153 //-----------------------------------------------------------------------------
1154 // "focus_in_event"
1155 //-----------------------------------------------------------------------------
1156
1157 static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
1158 {
1159 if (g_isIdle)
1160 wxapp_install_idle_handler();
1161
1162 if (!win->m_hasVMT) return FALSE;
1163 if (g_blockEventsOnDrag) return FALSE;
1164
1165 g_focusWindow = win;
1166
1167 if (win->m_wxwindow)
1168 {
1169 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
1170 {
1171 GTK_WIDGET_SET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
1172 /*
1173 printf( "SetFocus flag from " );
1174 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1175 printf( win->GetClassInfo()->GetClassName() );
1176 printf( ".\n" );
1177 */
1178 }
1179 }
1180
1181
1182 /*
1183 printf( "OnSetFocus from " );
1184 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1185 printf( win->GetClassInfo()->GetClassName() );
1186 printf( " " );
1187 printf( WXSTRINGCAST win->GetLabel() );
1188 printf( ".\n" );
1189 */
1190
1191 wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
1192 event.SetEventObject( win );
1193
1194 if (win->GetEventHandler()->ProcessEvent( event ))
1195 {
1196 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
1197 return TRUE;
1198 }
1199
1200 return FALSE;
1201 }
1202
1203 //-----------------------------------------------------------------------------
1204 // "focus_out_event"
1205 //-----------------------------------------------------------------------------
1206
1207 static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
1208 {
1209 if (g_isIdle)
1210 wxapp_install_idle_handler();
1211
1212 if (!win->m_hasVMT) return FALSE;
1213 if (g_blockEventsOnDrag) return FALSE;
1214
1215 if (win->m_wxwindow)
1216 {
1217 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
1218 GTK_WIDGET_UNSET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
1219 }
1220
1221 /*
1222 printf( "OnKillFocus from " );
1223 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1224 printf( win->GetClassInfo()->GetClassName() );
1225 printf( ".\n" );
1226 */
1227
1228 wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
1229 event.SetEventObject( win );
1230
1231 if (win->GetEventHandler()->ProcessEvent( event ))
1232 {
1233 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
1234 return TRUE;
1235 }
1236
1237 return FALSE;
1238 }
1239
1240 //-----------------------------------------------------------------------------
1241 // "enter_notify_event"
1242 //-----------------------------------------------------------------------------
1243
1244 static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1245 {
1246 if (g_isIdle)
1247 wxapp_install_idle_handler();
1248
1249 if (!win->m_hasVMT) return FALSE;
1250 if (g_blockEventsOnDrag) return FALSE;
1251
1252 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1253
1254 wxMouseEvent event( wxEVT_ENTER_WINDOW );
1255 #if (GTK_MINOR_VERSION > 0)
1256 event.SetTimestamp( gdk_event->time );
1257 #endif
1258 event.SetEventObject( win );
1259
1260 int x = 0;
1261 int y = 0;
1262 GdkModifierType state = (GdkModifierType)0;
1263
1264 gdk_window_get_pointer( widget->window, &x, &y, &state );
1265
1266 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1267 event.m_controlDown = (state & GDK_CONTROL_MASK);
1268 event.m_altDown = (state & GDK_MOD1_MASK);
1269 event.m_metaDown = (state & GDK_MOD2_MASK);
1270 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1271 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1272 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1273
1274 event.m_x = (long)x;
1275 event.m_y = (long)y;
1276
1277 if (win->GetEventHandler()->ProcessEvent( event ))
1278 {
1279 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "enter_notify_event" );
1280 return TRUE;
1281 }
1282
1283 return FALSE;
1284 }
1285
1286 //-----------------------------------------------------------------------------
1287 // "leave_notify_event"
1288 //-----------------------------------------------------------------------------
1289
1290 static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1291 {
1292 if (g_isIdle)
1293 wxapp_install_idle_handler();
1294
1295 if (!win->m_hasVMT) return FALSE;
1296 if (g_blockEventsOnDrag) return FALSE;
1297
1298 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1299
1300 wxMouseEvent event( wxEVT_LEAVE_WINDOW );
1301 #if (GTK_MINOR_VERSION > 0)
1302 event.SetTimestamp( gdk_event->time );
1303 #endif
1304 event.SetEventObject( win );
1305
1306 int x = 0;
1307 int y = 0;
1308 GdkModifierType state = (GdkModifierType)0;
1309
1310 gdk_window_get_pointer( widget->window, &x, &y, &state );
1311
1312 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1313 event.m_controlDown = (state & GDK_CONTROL_MASK);
1314 event.m_altDown = (state & GDK_MOD1_MASK);
1315 event.m_metaDown = (state & GDK_MOD2_MASK);
1316 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1317 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1318 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1319
1320 event.m_x = (long)x;
1321 event.m_y = (long)y;
1322
1323 if (win->GetEventHandler()->ProcessEvent( event ))
1324 {
1325 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "leave_notify_event" );
1326 return TRUE;
1327 }
1328
1329 return FALSE;
1330 }
1331
1332 //-----------------------------------------------------------------------------
1333 // "value_changed" from m_vAdjust
1334 //-----------------------------------------------------------------------------
1335
1336 static void gtk_window_vscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
1337 {
1338 if (g_isIdle)
1339 wxapp_install_idle_handler();
1340
1341 if (g_blockEventsOnDrag) return;
1342
1343 if (!win->m_hasVMT) return;
1344
1345 float diff = win->m_vAdjust->value - win->m_oldVerticalPos;
1346 if (fabs(diff) < 0.2) return;
1347 win->m_oldVerticalPos = win->m_vAdjust->value;
1348
1349 wxEventType command = wxEVT_NULL;
1350
1351 float line_step = win->m_vAdjust->step_increment;
1352 float page_step = win->m_vAdjust->page_increment;
1353
1354 if (win->IsScrolling())
1355 {
1356 command = wxEVT_SCROLLWIN_THUMBTRACK;
1357 }
1358 else
1359 {
1360 if (fabs(win->m_vAdjust->value-win->m_vAdjust->lower) < 0.2) command = wxEVT_SCROLLWIN_BOTTOM;
1361 else if (fabs(win->m_vAdjust->value-win->m_vAdjust->upper) < 0.2) command = wxEVT_SCROLLWIN_TOP;
1362 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLLWIN_LINEDOWN;
1363 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLLWIN_LINEUP;
1364 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLLWIN_PAGEDOWN;
1365 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLLWIN_PAGEUP;
1366 else command = wxEVT_SCROLLWIN_THUMBTRACK;
1367 }
1368
1369 int value = (int)(win->m_vAdjust->value+0.5);
1370
1371 wxScrollWinEvent event( command, value, wxVERTICAL );
1372 event.SetEventObject( win );
1373 win->GetEventHandler()->ProcessEvent( event );
1374 }
1375
1376 //-----------------------------------------------------------------------------
1377 // "value_changed" from m_hAdjust
1378 //-----------------------------------------------------------------------------
1379
1380 static void gtk_window_hscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
1381 {
1382 if (g_isIdle)
1383 wxapp_install_idle_handler();
1384
1385 if (g_blockEventsOnDrag) return;
1386 if (!win->m_hasVMT) return;
1387
1388 float diff = win->m_hAdjust->value - win->m_oldHorizontalPos;
1389 if (fabs(diff) < 0.2) return;
1390 win->m_oldHorizontalPos = win->m_hAdjust->value;
1391
1392 wxEventType command = wxEVT_NULL;
1393
1394 float line_step = win->m_hAdjust->step_increment;
1395 float page_step = win->m_hAdjust->page_increment;
1396
1397 if (win->IsScrolling())
1398 {
1399 command = wxEVT_SCROLLWIN_THUMBTRACK;
1400 }
1401 else
1402 {
1403 if (fabs(win->m_hAdjust->value-win->m_hAdjust->lower) < 0.2) command = wxEVT_SCROLLWIN_BOTTOM;
1404 else if (fabs(win->m_hAdjust->value-win->m_hAdjust->upper) < 0.2) command = wxEVT_SCROLLWIN_TOP;
1405 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLLWIN_LINEDOWN;
1406 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLLWIN_LINEUP;
1407 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLLWIN_PAGEDOWN;
1408 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLLWIN_PAGEUP;
1409 else command = wxEVT_SCROLLWIN_THUMBTRACK;
1410 }
1411
1412 int value = (int)(win->m_hAdjust->value+0.5);
1413
1414 wxScrollWinEvent event( command, value, wxHORIZONTAL );
1415 event.SetEventObject( win );
1416 win->GetEventHandler()->ProcessEvent( event );
1417 }
1418
1419 //-----------------------------------------------------------------------------
1420 // "changed" from m_vAdjust
1421 //-----------------------------------------------------------------------------
1422
1423 static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
1424 {
1425 if (g_isIdle)
1426 wxapp_install_idle_handler();
1427
1428 if (g_blockEventsOnDrag) return;
1429 if (!win->m_hasVMT) return;
1430
1431 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
1432 int value = (int)(win->m_vAdjust->value+0.5);
1433
1434 wxScrollWinEvent event( command, value, wxVERTICAL );
1435 event.SetEventObject( win );
1436 win->GetEventHandler()->ProcessEvent( event );
1437 }
1438
1439 //-----------------------------------------------------------------------------
1440 // "changed" from m_hAdjust
1441 //-----------------------------------------------------------------------------
1442
1443 static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
1444 {
1445 if (g_isIdle)
1446 wxapp_install_idle_handler();
1447
1448 if (g_blockEventsOnDrag) return;
1449 if (!win->m_hasVMT) return;
1450
1451 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
1452 int value = (int)(win->m_hAdjust->value+0.5);
1453
1454 wxScrollWinEvent event( command, value, wxHORIZONTAL );
1455 event.SetEventObject( win );
1456 win->GetEventHandler()->ProcessEvent( event );
1457 }
1458
1459 //-----------------------------------------------------------------------------
1460 // "button_press_event" from scrollbar
1461 //-----------------------------------------------------------------------------
1462
1463 static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
1464 GdkEventButton *WXUNUSED(gdk_event),
1465 wxWindow *win )
1466 {
1467 if (g_isIdle)
1468 wxapp_install_idle_handler();
1469
1470 // don't test here as we can release the mouse while being over
1471 // a different window then the slider
1472 //
1473 // if (gdk_event->window != widget->slider) return FALSE;
1474
1475 win->SetScrolling( TRUE );
1476
1477 return FALSE;
1478 }
1479
1480 //-----------------------------------------------------------------------------
1481 // "button_release_event" from scrollbar
1482 //-----------------------------------------------------------------------------
1483
1484 static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
1485 GdkEventButton *WXUNUSED(gdk_event),
1486 wxWindow *win )
1487 {
1488
1489 // don't test here as we can release the mouse while being over
1490 // a different window then the slider
1491 //
1492 // if (gdk_event->window != widget->slider) return FALSE;
1493
1494 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
1495
1496 if (widget == GTK_RANGE(scrolledWindow->vscrollbar))
1497 gtk_signal_emit_by_name( GTK_OBJECT(win->m_hAdjust), "value_changed" );
1498 else
1499 gtk_signal_emit_by_name( GTK_OBJECT(win->m_vAdjust), "value_changed" );
1500
1501 win->SetScrolling( FALSE );
1502
1503 return FALSE;
1504 }
1505
1506 // ----------------------------------------------------------------------------
1507 // this wxWindowBase function is implemented here (in platform-specific file)
1508 // because it is static and so couldn't be made virtual
1509 // ----------------------------------------------------------------------------
1510
1511 wxWindow *wxWindowBase::FindFocus()
1512 {
1513 return g_focusWindow;
1514 }
1515
1516 //-----------------------------------------------------------------------------
1517 // "realize" from m_widget
1518 //-----------------------------------------------------------------------------
1519
1520 /* we cannot set colours, fonts and cursors before the widget has
1521 been realized, so we do this directly after realization */
1522
1523 static gint
1524 gtk_window_realized_callback( GtkWidget * WXUNUSED(widget), wxWindow *win )
1525 {
1526 if (g_isIdle)
1527 wxapp_install_idle_handler();
1528
1529 if (win->m_delayedFont)
1530 win->SetFont( win->GetFont() );
1531
1532 if (win->m_delayedBackgroundColour)
1533 win->SetBackgroundColour( win->GetBackgroundColour() );
1534
1535 if (win->m_delayedForegroundColour)
1536 win->SetForegroundColour( win->GetForegroundColour() );
1537
1538 win->SetCursor( win->GetCursor() );
1539
1540 wxWindowCreateEvent event( win );
1541 event.SetEventObject( win );
1542 win->GetEventHandler()->ProcessEvent( event );
1543
1544 return FALSE;
1545 }
1546
1547 //-----------------------------------------------------------------------------
1548 // InsertChild for wxWindow.
1549 //-----------------------------------------------------------------------------
1550
1551 /* Callback for wxWindow. This very strange beast has to be used because
1552 * C++ has no virtual methods in a constructor. We have to emulate a
1553 * virtual function here as wxNotebook requires a different way to insert
1554 * a child in it. I had opted for creating a wxNotebookPage window class
1555 * which would have made this superfluous (such in the MDI window system),
1556 * but no-one was listening to me... */
1557
1558 static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
1559 {
1560 gtk_myfixed_put( GTK_MYFIXED(parent->m_wxwindow),
1561 GTK_WIDGET(child->m_widget),
1562 child->m_x,
1563 child->m_y,
1564 child->m_width,
1565 child->m_height );
1566
1567 if (parent->HasFlag(wxTAB_TRAVERSAL))
1568 {
1569 /* we now allow a window to get the focus as long as it
1570 doesn't have any children. */
1571 GTK_WIDGET_UNSET_FLAGS( parent->m_wxwindow, GTK_CAN_FOCUS );
1572 }
1573 }
1574
1575 //-----------------------------------------------------------------------------
1576 // global functions
1577 //-----------------------------------------------------------------------------
1578
1579 wxWindow* wxGetActiveWindow()
1580 {
1581 return g_focusWindow;
1582 }
1583
1584 //-----------------------------------------------------------------------------
1585 // wxWindow
1586 //-----------------------------------------------------------------------------
1587
1588 IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
1589
1590 void wxWindow::Init()
1591 {
1592 // common init
1593 InitBase();
1594
1595 // GTK specific
1596 m_widget = (GtkWidget *) NULL;
1597 m_wxwindow = (GtkWidget *) NULL;
1598
1599 // position/size
1600 m_x = 0;
1601 m_y = 0;
1602 m_width = 0;
1603 m_height = 0;
1604
1605 m_sizeSet = FALSE;
1606 m_hasVMT = FALSE;
1607 m_needParent = TRUE;
1608 m_isBeingDeleted = FALSE;
1609
1610 m_hasScrolling = FALSE;
1611 m_isScrolling = FALSE;
1612
1613 m_hAdjust = (GtkAdjustment*) NULL;
1614 m_vAdjust = (GtkAdjustment*) NULL;
1615 m_oldHorizontalPos = 0.0;
1616 m_oldVerticalPos = 0.0;
1617
1618 m_resizing = FALSE;
1619 m_scrollGC = (GdkGC*) NULL;
1620 m_widgetStyle = (GtkStyle*) NULL;
1621
1622 m_insertCallback = wxInsertChildInWindow;
1623
1624 m_isStaticBox = FALSE;
1625 m_acceptsFocus = FALSE;
1626 }
1627
1628 wxWindow::wxWindow()
1629 {
1630 Init();
1631 }
1632
1633 wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
1634 const wxPoint &pos, const wxSize &size,
1635 long style, const wxString &name )
1636 {
1637 Init();
1638
1639 Create( parent, id, pos, size, style, name );
1640 }
1641
1642 bool wxWindow::Create( wxWindow *parent, wxWindowID id,
1643 const wxPoint &pos, const wxSize &size,
1644 long style, const wxString &name )
1645 {
1646 PreCreation( parent, id, pos, size, style, name );
1647
1648 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
1649 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
1650
1651 #ifdef __WXDEBUG__
1652 debug_focus_in( m_widget, _T("wxWindow::m_widget"), name );
1653 #endif
1654
1655 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
1656
1657 #ifdef __WXDEBUG__
1658 debug_focus_in( scrolledWindow->hscrollbar, _T("wxWindow::hsrcollbar"), name );
1659 debug_focus_in( scrolledWindow->vscrollbar, _T("wxWindow::vsrcollbar"), name );
1660 #endif
1661
1662 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1663 scroll_class->scrollbar_spacing = 0;
1664
1665 gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
1666
1667 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->hscrollbar) );
1668 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->vscrollbar) );
1669
1670 m_wxwindow = gtk_myfixed_new();
1671
1672 #ifdef __WXDEBUG__
1673 debug_focus_in( m_wxwindow, _T("wxWindow::m_wxwindow"), name );
1674 #endif
1675
1676 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
1677
1678 #if (GTK_MINOR_VERSION > 0)
1679 GtkMyFixed *myfixed = GTK_MYFIXED(m_wxwindow);
1680
1681 if (HasFlag(wxRAISED_BORDER))
1682 {
1683 gtk_myfixed_set_shadow_type( myfixed, GTK_SHADOW_OUT );
1684 }
1685 else if (HasFlag(wxSUNKEN_BORDER))
1686 {
1687 gtk_myfixed_set_shadow_type( myfixed, GTK_SHADOW_IN );
1688 }
1689 else
1690 {
1691 gtk_myfixed_set_shadow_type( myfixed, GTK_SHADOW_NONE );
1692 }
1693 #else // GTK_MINOR_VERSION == 0
1694 GtkViewport *viewport = GTK_VIEWPORT(scrolledWindow->viewport);
1695
1696 if (HasFlag(wxRAISED_BORDER))
1697 {
1698 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
1699 }
1700 else if (HasFlag(wxSUNKEN_BORDER))
1701 {
1702 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
1703 }
1704 else
1705 {
1706 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
1707 }
1708 #endif // GTK_MINOR_VERSION
1709
1710 if (HasFlag(wxTAB_TRAVERSAL))
1711 {
1712 /* we now allow a window to get the focus as long as it
1713 doesn't have any children. */
1714 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
1715 m_acceptsFocus = FALSE;
1716 }
1717 else
1718 {
1719 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
1720 m_acceptsFocus = TRUE;
1721 }
1722
1723 #if (GTK_MINOR_VERSION == 0)
1724 // shut the viewport up
1725 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1726 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1727 #endif // GTK_MINOR_VERSION == 0
1728
1729 // I _really_ don't want scrollbars in the beginning
1730 m_vAdjust->lower = 0.0;
1731 m_vAdjust->upper = 1.0;
1732 m_vAdjust->value = 0.0;
1733 m_vAdjust->step_increment = 1.0;
1734 m_vAdjust->page_increment = 1.0;
1735 m_vAdjust->page_size = 5.0;
1736 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1737 m_hAdjust->lower = 0.0;
1738 m_hAdjust->upper = 1.0;
1739 m_hAdjust->value = 0.0;
1740 m_hAdjust->step_increment = 1.0;
1741 m_hAdjust->page_increment = 1.0;
1742 m_hAdjust->page_size = 5.0;
1743 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
1744
1745 // these handlers block mouse events to any window during scrolling such as
1746 // motion events and prevent GTK and wxWindows from fighting over where the
1747 // slider should be
1748
1749 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_press_event",
1750 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1751
1752 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_press_event",
1753 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1754
1755 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_release_event",
1756 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1757
1758 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_release_event",
1759 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1760
1761 // these handlers get notified when screen updates are required either when
1762 // scrolling or when the window size (and therefore scrollbar configuration)
1763 // has changed
1764
1765 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
1766 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
1767 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
1768 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
1769
1770 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
1771 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
1772 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
1773 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
1774
1775 gtk_widget_show( m_wxwindow );
1776
1777 if (m_parent)
1778 m_parent->DoAddChild( this );
1779
1780 PostCreation();
1781
1782 Show( TRUE );
1783
1784 return TRUE;
1785 }
1786
1787 wxWindow::~wxWindow()
1788 {
1789 m_isBeingDeleted = TRUE;
1790 m_hasVMT = FALSE;
1791
1792 if (m_widget)
1793 Show( FALSE );
1794
1795 DestroyChildren();
1796
1797 if (m_parent)
1798 m_parent->RemoveChild( this );
1799
1800 if (m_widgetStyle)
1801 {
1802 gtk_style_unref( m_widgetStyle );
1803 m_widgetStyle = (GtkStyle*) NULL;
1804 }
1805
1806 if (m_scrollGC)
1807 {
1808 gdk_gc_unref( m_scrollGC );
1809 m_scrollGC = (GdkGC*) NULL;
1810 }
1811
1812 if (m_wxwindow)
1813 {
1814 gtk_widget_destroy( m_wxwindow );
1815 m_wxwindow = (GtkWidget*) NULL;
1816 }
1817
1818 if (m_widget)
1819 {
1820 gtk_widget_destroy( m_widget );
1821 m_widget = (GtkWidget*) NULL;
1822 }
1823 }
1824
1825 void wxWindow::PreCreation( wxWindow *parent,
1826 wxWindowID id,
1827 const wxPoint &pos,
1828 const wxSize &size,
1829 long style,
1830 const wxString &name )
1831 {
1832 wxASSERT_MSG( !m_needParent || parent, _T("Need complete parent.") );
1833
1834 if ( !CreateBase(parent, id, pos, size, style, name) )
1835 {
1836 wxFAIL_MSG(_T("window creation failed"));
1837 }
1838
1839 m_width = WidthDefault(size.x);
1840 m_height = HeightDefault(size.y);
1841
1842 m_x = (int)pos.x;
1843 m_y = (int)pos.y;
1844
1845 if (!parent) /* some reasonable defaults */
1846 {
1847 if (m_x == -1)
1848 {
1849 m_x = (gdk_screen_width () - m_width) / 2;
1850 if (m_x < 10) m_x = 10;
1851 }
1852 if (m_y == -1)
1853 {
1854 m_y = (gdk_screen_height () - m_height) / 2;
1855 if (m_y < 10) m_y = 10;
1856 }
1857 }
1858 }
1859
1860 void wxWindow::PostCreation()
1861 {
1862 wxASSERT_MSG( (m_widget != NULL), _T("invalid window") );
1863
1864 if (m_wxwindow)
1865 {
1866 /* these get reported to wxWindows -> wxPaintEvent */
1867 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
1868 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
1869
1870 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
1871 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
1872
1873 #if (GTK_MINOR_VERSION > 0)
1874 /* these are called when the "sunken" or "raised" borders are drawn */
1875 gtk_signal_connect( GTK_OBJECT(m_widget), "expose_event",
1876 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback), (gpointer)this );
1877
1878 gtk_signal_connect( GTK_OBJECT(m_widget), "draw",
1879 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback), (gpointer)this );
1880 #endif
1881 }
1882
1883 GtkWidget *connect_widget = GetConnectWidget();
1884
1885 ConnectWidget( connect_widget );
1886
1887 /* we cannot set colours, fonts and cursors before the widget has
1888 been realized, so we do this directly after realization */
1889 gtk_signal_connect( GTK_OBJECT(connect_widget), "realize",
1890 GTK_SIGNAL_FUNC(gtk_window_realized_callback), (gpointer) this );
1891
1892 m_hasVMT = TRUE;
1893 }
1894
1895 void wxWindow::ConnectWidget( GtkWidget *widget )
1896 {
1897 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
1898 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
1899
1900 gtk_signal_connect( GTK_OBJECT(widget), "key_release_event",
1901 GTK_SIGNAL_FUNC(gtk_window_key_release_callback), (gpointer)this );
1902
1903 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
1904 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
1905
1906 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
1907 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
1908
1909 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
1910 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
1911
1912 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
1913 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
1914
1915 gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
1916 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
1917
1918 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
1919 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
1920
1921 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
1922 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
1923 }
1924
1925 bool wxWindow::Destroy()
1926 {
1927 wxASSERT_MSG( (m_widget != NULL), _T("invalid window") );
1928
1929 m_hasVMT = FALSE;
1930
1931 return wxWindowBase::Destroy();
1932 }
1933
1934 void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
1935 {
1936 wxASSERT_MSG( (m_widget != NULL), _T("invalid window") );
1937 wxASSERT_MSG( (m_parent != NULL), _T("wxWindow::SetSize requires parent.\n") );
1938
1939 if (m_resizing) return; /* I don't like recursions */
1940 m_resizing = TRUE;
1941
1942 if (m_parent->m_wxwindow == NULL) /* i.e. wxNotebook */
1943 {
1944 /* don't set the size for children of wxNotebook, just take the values. */
1945 m_x = x;
1946 m_y = y;
1947 m_width = width;
1948 m_height = height;
1949 }
1950 else
1951 {
1952 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
1953 {
1954 if (x != -1) m_x = x;
1955 if (y != -1) m_y = y;
1956 if (width != -1) m_width = width;
1957 if (height != -1) m_height = height;
1958 }
1959 else
1960 {
1961 m_x = x;
1962 m_y = y;
1963 m_width = width;
1964 m_height = height;
1965 }
1966
1967 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
1968 {
1969 if (width == -1) m_width = 80;
1970 }
1971
1972 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
1973 {
1974 if (height == -1) m_height = 26;
1975 }
1976
1977 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
1978 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
1979 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
1980 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
1981
1982 int border = 0;
1983
1984 if (GTK_WIDGET_CAN_DEFAULT(m_widget))
1985 {
1986 /* the default button has a border around it */
1987 border = 5;
1988 }
1989
1990 /* this is the result of hours of debugging: the following code
1991 means that if we have a m_wxwindow and we set the size of
1992 m_widget, m_widget (which is a GtkScrolledWindow) does NOT
1993 automatically propagate its size down to its m_wxwindow,
1994 which is its client area. therefore, we have to tell the
1995 client area directly that it has to resize itself.
1996 this will lead to that m_widget (GtkScrolledWindow) will
1997 calculate how much size it needs for scrollbars etc and
1998 it will then call XXX_size_allocate of its child, which
1999 is m_wxwindow. m_wxwindow in turn will do the same with its
2000 children and so on. problems can arise if this happens
2001 before all the children have been realized as some widgets
2002 stupidy need to be realized during XXX_size_allocate (e.g.
2003 GtkNotebook) and they will segv if called otherwise. this
2004 emergency is tested in gtk_myfixed_size_allocate. Normally
2005 this shouldn't be needed and only gtk_widget_queue_resize()
2006 should be enough to provoke a resize at the next appropriate
2007 moment, but this seems to fail, e.g. when a wxNotebook contains
2008 a wxSplitterWindow: the splitter window's children won't
2009 show up properly resized then. */
2010
2011 gtk_myfixed_set_size( GTK_MYFIXED(m_parent->m_wxwindow),
2012 m_widget,
2013 m_x-border,
2014 m_y-border,
2015 m_width+2*border,
2016 m_height+2*border );
2017 }
2018
2019 m_sizeSet = TRUE;
2020
2021 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
2022 event.SetEventObject( this );
2023 GetEventHandler()->ProcessEvent( event );
2024
2025 m_resizing = FALSE;
2026 }
2027
2028 void wxWindow::OnInternalIdle()
2029 {
2030 GdkWindow *window = GetConnectWidget()->window;
2031 if (window)
2032 {
2033 if (g_globalCursor.Ok())
2034 gdk_window_set_cursor( window, g_globalCursor.GetCursor() );
2035 else
2036 gdk_window_set_cursor( window, m_cursor.GetCursor() );
2037 }
2038
2039 UpdateWindowUI();
2040 }
2041
2042 void wxWindow::DoGetSize( int *width, int *height ) const
2043 {
2044 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
2045
2046 if (width) (*width) = m_width;
2047 if (height) (*height) = m_height;
2048 }
2049
2050 void wxWindow::DoSetClientSize( int width, int height )
2051 {
2052 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
2053
2054 if (!m_wxwindow)
2055 {
2056 SetSize( width, height );
2057 }
2058 else
2059 {
2060 int dw = 0;
2061 int dh = 0;
2062
2063 if (!m_hasScrolling)
2064 {
2065 GtkStyleClass *window_class = m_wxwindow->style->klass;
2066
2067 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2068 {
2069 dw += 2 * window_class->xthickness;
2070 dh += 2 * window_class->ythickness;
2071 }
2072 }
2073 else
2074 {
2075 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2076 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
2077
2078 #if (GTK_MINOR_VERSION == 0)
2079 GtkWidget *viewport = scroll_window->viewport;
2080 GtkStyleClass *viewport_class = viewport->style->klass;
2081
2082 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2083 {
2084 dw += 2 * viewport_class->xthickness;
2085 dh += 2 * viewport_class->ythickness;
2086 }
2087 #endif
2088
2089 /*
2090 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2091 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2092
2093 we use this instead: range.slider_width = 11 + 2*2pts edge
2094 */
2095
2096 if (scroll_window->vscrollbar_visible)
2097 {
2098 dw += 15; /* dw += vscrollbar->allocation.width; */
2099 dw += scroll_class->scrollbar_spacing;
2100 }
2101
2102 if (scroll_window->hscrollbar_visible)
2103 {
2104 dh += 15; /* dh += hscrollbar->allocation.height; */
2105 dh += scroll_class->scrollbar_spacing;
2106 }
2107 }
2108
2109 SetSize( width+dw, height+dh );
2110 }
2111 }
2112
2113 void wxWindow::DoGetClientSize( int *width, int *height ) const
2114 {
2115 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
2116
2117 if (!m_wxwindow)
2118 {
2119 if (width) (*width) = m_width;
2120 if (height) (*height) = m_height;
2121 }
2122 else
2123 {
2124 int dw = 0;
2125 int dh = 0;
2126
2127 if (!m_hasScrolling)
2128 {
2129 GtkStyleClass *window_class = m_wxwindow->style->klass;
2130
2131 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2132 {
2133 dw += 2 * window_class->xthickness;
2134 dh += 2 * window_class->ythickness;
2135 }
2136 }
2137 else
2138 {
2139 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2140 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
2141
2142 #if (GTK_MINOR_VERSION == 0)
2143 GtkWidget *viewport = scroll_window->viewport;
2144 GtkStyleClass *viewport_class = viewport->style->klass;
2145
2146 if ( HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER) )
2147 {
2148 dw += 2 * viewport_class->xthickness;
2149 dh += 2 * viewport_class->ythickness;
2150 }
2151 #endif
2152 /*
2153 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2154 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2155
2156 we use this instead: range.slider_width = 11 + 2*2pts edge
2157 */
2158
2159 if (scroll_window->vscrollbar_visible)
2160 {
2161 dw += 15; /* dw += vscrollbar->allocation.width; */
2162 dw += scroll_class->scrollbar_spacing;
2163 }
2164
2165 if (scroll_window->hscrollbar_visible)
2166 {
2167 dh += 15; /* dh += hscrollbar->allocation.height; */
2168 dh += scroll_class->scrollbar_spacing;
2169 }
2170 }
2171
2172 if (width) (*width) = m_width - dw;
2173 if (height) (*height) = m_height - dh;
2174 }
2175 }
2176
2177 void wxWindow::DoGetPosition( int *x, int *y ) const
2178 {
2179 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
2180
2181 if (x) (*x) = m_x;
2182 if (y) (*y) = m_y;
2183 }
2184
2185 void wxWindow::DoClientToScreen( int *x, int *y ) const
2186 {
2187 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
2188
2189 if (!m_widget->window) return;
2190
2191 GdkWindow *source = (GdkWindow *) NULL;
2192 if (m_wxwindow)
2193 source = m_wxwindow->window;
2194 else
2195 source = m_widget->window;
2196
2197 int org_x = 0;
2198 int org_y = 0;
2199 gdk_window_get_origin( source, &org_x, &org_y );
2200
2201 if (!m_wxwindow)
2202 {
2203 if (GTK_WIDGET_NO_WINDOW (m_widget))
2204 {
2205 org_x += m_widget->allocation.x;
2206 org_y += m_widget->allocation.y;
2207 }
2208 }
2209
2210 if (x) *x += org_x;
2211 if (y) *y += org_y;
2212 }
2213
2214 void wxWindow::DoScreenToClient( int *x, int *y ) const
2215 {
2216 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
2217
2218 if (!m_widget->window) return;
2219
2220 GdkWindow *source = (GdkWindow *) NULL;
2221 if (m_wxwindow)
2222 source = m_wxwindow->window;
2223 else
2224 source = m_widget->window;
2225
2226 int org_x = 0;
2227 int org_y = 0;
2228 gdk_window_get_origin( source, &org_x, &org_y );
2229
2230 if (!m_wxwindow)
2231 {
2232 if (GTK_WIDGET_NO_WINDOW (m_widget))
2233 {
2234 org_x += m_widget->allocation.x;
2235 org_y += m_widget->allocation.y;
2236 }
2237 }
2238
2239 if (x) *x -= org_x;
2240 if (y) *y -= org_y;
2241 }
2242
2243 bool wxWindow::Show( bool show )
2244 {
2245 wxCHECK_MSG( (m_widget != NULL), FALSE, _T("invalid window") );
2246
2247 if (!wxWindowBase::Show(show))
2248 {
2249 // nothing to do
2250 return FALSE;
2251 }
2252
2253 if (show)
2254 gtk_widget_show( m_widget );
2255 else
2256 gtk_widget_hide( m_widget );
2257
2258 return TRUE;
2259 }
2260
2261 bool wxWindow::Enable( bool enable )
2262 {
2263 wxCHECK_MSG( (m_widget != NULL), FALSE, _T("invalid window") );
2264
2265 if (!wxWindowBase::Enable(enable))
2266 {
2267 // nothing to do
2268 return FALSE;
2269 }
2270
2271 gtk_widget_set_sensitive( m_widget, enable );
2272 if ( m_wxwindow )
2273 gtk_widget_set_sensitive( m_wxwindow, enable );
2274
2275 return TRUE;
2276 }
2277
2278 int wxWindow::GetCharHeight() const
2279 {
2280 wxCHECK_MSG( (m_widget != NULL), 12, _T("invalid window") );
2281
2282 wxCHECK_MSG( m_font.Ok(), 12, _T("invalid font") );
2283
2284 GdkFont *font = m_font.GetInternalFont( 1.0 );
2285
2286 return font->ascent + font->descent;
2287 }
2288
2289 int wxWindow::GetCharWidth() const
2290 {
2291 wxCHECK_MSG( (m_widget != NULL), 8, _T("invalid window") );
2292
2293 wxCHECK_MSG( m_font.Ok(), 8, _T("invalid font") );
2294
2295 GdkFont *font = m_font.GetInternalFont( 1.0 );
2296
2297 return gdk_string_width( font, "H" );
2298 }
2299
2300 void wxWindow::GetTextExtent( const wxString& string,
2301 int *x,
2302 int *y,
2303 int *descent,
2304 int *externalLeading,
2305 const wxFont *theFont ) const
2306 {
2307 wxFont fontToUse = m_font;
2308 if (theFont) fontToUse = *theFont;
2309
2310 wxCHECK_RET( fontToUse.Ok(), _T("invalid font") );
2311
2312 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
2313 if (x) (*x) = gdk_string_width( font, string.mbc_str() );
2314 if (y) (*y) = font->ascent + font->descent;
2315 if (descent) (*descent) = font->descent;
2316 if (externalLeading) (*externalLeading) = 0; // ??
2317 }
2318
2319 void wxWindow::SetFocus()
2320 {
2321 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
2322
2323 GtkWidget *connect_widget = GetConnectWidget();
2324 if (connect_widget)
2325 {
2326 if (GTK_WIDGET_CAN_FOCUS(connect_widget) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2327 {
2328 gtk_widget_grab_focus (connect_widget);
2329 }
2330 else if (GTK_IS_CONTAINER(connect_widget))
2331 {
2332 gtk_container_focus( GTK_CONTAINER(connect_widget), GTK_DIR_TAB_FORWARD );
2333 }
2334 else
2335 {
2336 }
2337 }
2338 }
2339
2340 bool wxWindow::AcceptsFocus() const
2341 {
2342 return m_acceptsFocus && wxWindowBase::AcceptsFocus();
2343 }
2344
2345 bool wxWindow::Reparent( wxWindow *newParent )
2346 {
2347 wxCHECK_MSG( (m_widget != NULL), (wxWindow*) NULL, _T("invalid window") );
2348
2349 gtk_widget_unparent( m_widget );
2350
2351 if ( !wxWindowBase::Reparent(newParent) )
2352 return FALSE;
2353
2354 return TRUE;
2355 }
2356
2357 void wxWindow::Raise()
2358 {
2359 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
2360
2361 if (!m_widget->window) return;
2362
2363 gdk_window_raise( m_widget->window );
2364 }
2365
2366 void wxWindow::Lower()
2367 {
2368 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
2369
2370 if (!m_widget->window) return;
2371
2372 gdk_window_lower( m_widget->window );
2373 }
2374
2375 bool wxWindow::SetCursor( const wxCursor &cursor )
2376 {
2377 wxCHECK_MSG( (m_widget != NULL), FALSE, _T("invalid window") );
2378
2379 if (!wxWindowBase::SetCursor(cursor))
2380 {
2381 // don't leave if the GTK widget has just
2382 // been realized
2383 if (!m_delayedCursor) return FALSE;
2384 }
2385
2386 GtkWidget *connect_widget = GetConnectWidget();
2387 if (!connect_widget->window)
2388 {
2389 // indicate that a new style has been set
2390 // but it couldn't get applied as the
2391 // widget hasn't been realized yet.
2392 m_delayedCursor = TRUE;
2393
2394 // pretend we have done something
2395 return TRUE;
2396 }
2397
2398 // gdk_window_set_cursor( connect_widget->window, GetCursor().GetCursor() );
2399
2400 // cursor was set
2401 return TRUE;
2402 }
2403
2404 void wxWindow::WarpPointer( int WXUNUSED(x), int WXUNUSED(y) )
2405 {
2406 // TODO
2407 }
2408
2409 void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
2410 {
2411 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
2412
2413 if (!m_widget->window) return;
2414
2415 if (eraseBackground && m_wxwindow && m_wxwindow->window)
2416 {
2417 if (rect)
2418 {
2419 gdk_window_clear_area( m_wxwindow->window,
2420 rect->x, rect->y,
2421 rect->width, rect->height );
2422 }
2423 else
2424 {
2425 gdk_window_clear( m_wxwindow->window );
2426 }
2427 }
2428
2429 if (!rect)
2430 {
2431 if (m_wxwindow)
2432 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
2433 else
2434 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
2435 }
2436 else
2437 {
2438 GdkRectangle gdk_rect;
2439 gdk_rect.x = rect->x;
2440 gdk_rect.y = rect->y;
2441 gdk_rect.width = rect->width;
2442 gdk_rect.height = rect->height;
2443
2444 if (m_wxwindow)
2445 gtk_widget_draw( m_wxwindow, &gdk_rect );
2446 else
2447 gtk_widget_draw( m_widget, &gdk_rect );
2448 }
2449 }
2450
2451 void wxWindow::Clear()
2452 {
2453 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
2454
2455 if (!m_widget->window) return;
2456
2457 if (m_wxwindow && m_wxwindow->window)
2458 {
2459 gdk_window_clear( m_wxwindow->window );
2460 }
2461 }
2462
2463 #if wxUSE_TOOLTIPS
2464 void wxWindow::DoSetToolTip( wxToolTip *tip )
2465 {
2466 wxWindowBase::DoSetToolTip(tip);
2467
2468 if (m_tooltip)
2469 m_tooltip->Apply( this );
2470 }
2471
2472 void wxWindow::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
2473 {
2474 gtk_tooltips_set_tip( tips, GetConnectWidget(), wxConv_current->cWX2MB(tip), (gchar*) NULL );
2475 }
2476 #endif // wxUSE_TOOLTIPS
2477
2478 bool wxWindow::SetBackgroundColour( const wxColour &colour )
2479 {
2480 wxCHECK_MSG( m_widget != NULL, FALSE, _T("invalid window") );
2481
2482 if (!wxWindowBase::SetBackgroundColour(colour))
2483 {
2484 // don't leave if the GTK widget has just
2485 // been realized
2486 if (!m_delayedBackgroundColour) return FALSE;
2487 }
2488
2489 GtkWidget *connect_widget = GetConnectWidget();
2490 if (!connect_widget->window)
2491 {
2492 // indicate that a new style has been set
2493 // but it couldn't get applied as the
2494 // widget hasn't been realized yet.
2495 m_delayedBackgroundColour = TRUE;
2496
2497 // pretend we have done something
2498 return TRUE;
2499 }
2500
2501 if (m_wxwindow && m_wxwindow->window)
2502 {
2503 /* wxMSW doesn't clear the window here. I don't do that either to
2504 provide compatibility. call Clear() to do the job. */
2505
2506 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_wxwindow->window ) );
2507 gdk_window_set_background( m_wxwindow->window, m_backgroundColour.GetColor() );
2508 }
2509
2510 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2511
2512 if (sysbg == m_backgroundColour)
2513 {
2514 m_backgroundColour = wxNullColour;
2515 ApplyWidgetStyle();
2516 m_backgroundColour = sysbg;
2517 }
2518 else
2519 {
2520 ApplyWidgetStyle();
2521 }
2522
2523 return TRUE;
2524 }
2525
2526 bool wxWindow::SetForegroundColour( const wxColour &colour )
2527 {
2528 wxCHECK_MSG( m_widget != NULL, FALSE, _T("invalid window") );
2529
2530 if (!wxWindowBase::SetForegroundColour(colour))
2531 {
2532 // don't leave if the GTK widget has just
2533 // been realized
2534 if (!m_delayedForegroundColour) return FALSE;
2535 }
2536
2537 GtkWidget *connect_widget = GetConnectWidget();
2538 if (!connect_widget->window)
2539 {
2540 // indicate that a new style has been set
2541 // but it couldn't get applied as the
2542 // widget hasn't been realized yet.
2543 m_delayedForegroundColour = TRUE;
2544
2545 // pretend we have done something
2546 return TRUE;
2547 }
2548
2549 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2550 if (sysbg == m_foregroundColour)
2551 {
2552 m_backgroundColour = wxNullColour;
2553 ApplyWidgetStyle();
2554 m_backgroundColour = sysbg;
2555 }
2556 else
2557 {
2558 ApplyWidgetStyle();
2559 }
2560
2561 return TRUE;
2562 }
2563
2564 GtkStyle *wxWindow::GetWidgetStyle()
2565 {
2566 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
2567
2568 m_widgetStyle = gtk_style_copy( gtk_widget_get_style( m_widget ) );
2569
2570 return m_widgetStyle;
2571 }
2572
2573 void wxWindow::SetWidgetStyle()
2574 {
2575 GtkStyle *style = GetWidgetStyle();
2576
2577 gdk_font_unref( style->font );
2578 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2579
2580 if (m_foregroundColour.Ok())
2581 {
2582 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2583 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2584 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2585 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2586 }
2587
2588 if (m_backgroundColour.Ok())
2589 {
2590 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2591 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2592 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2593 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2594 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2595 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2596 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2597 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2598 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2599 }
2600 }
2601
2602 void wxWindow::ApplyWidgetStyle()
2603 {
2604 }
2605
2606 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2607 {
2608 menu->SetInvokingWindow( win );
2609 wxNode *node = menu->GetItems().First();
2610 while (node)
2611 {
2612 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2613 if (menuitem->IsSubMenu())
2614 {
2615 SetInvokingWindow( menuitem->GetSubMenu(), win );
2616 }
2617 node = node->Next();
2618 }
2619 }
2620
2621 static gint gs_pop_x = 0;
2622 static gint gs_pop_y = 0;
2623
2624 static void pop_pos_callback( GtkMenu * WXUNUSED(menu),
2625 gint *x, gint *y,
2626 wxWindow *win )
2627 {
2628 win->ClientToScreen( &gs_pop_x, &gs_pop_y );
2629 *x = gs_pop_x;
2630 *y = gs_pop_y;
2631 }
2632
2633 bool wxWindow::PopupMenu( wxMenu *menu, int x, int y )
2634 {
2635 wxCHECK_MSG( m_widget != NULL, FALSE, _T("invalid window") );
2636
2637 wxCHECK_MSG( menu != NULL, FALSE, _T("invalid popup-menu") );
2638
2639 SetInvokingWindow( menu, this );
2640
2641 menu->UpdateUI();
2642
2643 gs_pop_x = x;
2644 gs_pop_y = y;
2645
2646 gtk_menu_popup(
2647 GTK_MENU(menu->m_menu),
2648 (GtkWidget *) NULL, // parent menu shell
2649 (GtkWidget *) NULL, // parent menu item
2650 (GtkMenuPositionFunc) pop_pos_callback,
2651 (gpointer) this, // client data
2652 0, // button used to activate it
2653 0 //gs_timeLastClick // the time of activation
2654 );
2655 return TRUE;
2656 }
2657
2658 #if wxUSE_DRAG_AND_DROP
2659
2660 void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2661 {
2662 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
2663
2664 GtkWidget *dnd_widget = GetConnectWidget();
2665
2666 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
2667
2668 if (m_dropTarget) delete m_dropTarget;
2669 m_dropTarget = dropTarget;
2670
2671 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
2672 }
2673
2674 #endif // wxUSE_DRAG_AND_DROP
2675
2676 GtkWidget* wxWindow::GetConnectWidget()
2677 {
2678 GtkWidget *connect_widget = m_widget;
2679 if (m_wxwindow) connect_widget = m_wxwindow;
2680
2681 return connect_widget;
2682 }
2683
2684 bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2685 {
2686 if (m_wxwindow) return (window == m_wxwindow->window);
2687 return (window == m_widget->window);
2688 }
2689
2690 bool wxWindow::SetFont( const wxFont &font )
2691 {
2692 wxCHECK_MSG( m_widget != NULL, FALSE, _T( "invalid window") );
2693
2694 if (!wxWindowBase::SetFont(font))
2695 {
2696 // don't leave if the GTK widget has just
2697 // been realized
2698 if (!m_delayedFont) return FALSE;
2699 }
2700
2701 GtkWidget *connect_widget = GetConnectWidget();
2702 if (!connect_widget->window)
2703 {
2704 // indicate that a new style has been set
2705 // but it couldn't get applied as the
2706 // widget hasn't been realized yet.
2707 m_delayedFont = TRUE;
2708
2709 // pretend we have done something
2710 return TRUE;
2711 }
2712
2713 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2714 if ( sysbg == m_backgroundColour )
2715 {
2716 m_backgroundColour = wxNullColour;
2717 ApplyWidgetStyle();
2718 m_backgroundColour = sysbg;
2719 }
2720 else
2721 {
2722 ApplyWidgetStyle();
2723 }
2724
2725 return TRUE;
2726 }
2727
2728 void wxWindow::CaptureMouse()
2729 {
2730 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
2731
2732 wxCHECK_RET( g_capturing == FALSE, _T("CaptureMouse called twice") );
2733
2734 GtkWidget *connect_widget = GetConnectWidget();
2735 if (!connect_widget->window) return;
2736
2737 gtk_grab_add( connect_widget );
2738 gdk_pointer_grab( connect_widget->window, FALSE,
2739 (GdkEventMask)
2740 (GDK_BUTTON_PRESS_MASK |
2741 GDK_BUTTON_RELEASE_MASK |
2742 GDK_POINTER_MOTION_MASK),
2743 (GdkWindow *) NULL,
2744 (GdkCursor *) NULL,
2745 GDK_CURRENT_TIME );
2746 g_capturing = TRUE;
2747 }
2748
2749 void wxWindow::ReleaseMouse()
2750 {
2751 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
2752
2753 wxCHECK_RET( g_capturing == TRUE, _T("ReleaseMouse called twice") );
2754
2755 GtkWidget *connect_widget = GetConnectWidget();
2756 if (!connect_widget->window) return;
2757
2758 gtk_grab_remove( connect_widget );
2759 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
2760 g_capturing = FALSE;
2761 }
2762
2763 bool wxWindow::IsRetained() const
2764 {
2765 return FALSE;
2766 }
2767
2768 void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
2769 int range, bool refresh )
2770 {
2771 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
2772
2773 wxCHECK_RET( m_wxwindow != NULL, _T("window needs client area for scrolling") );
2774
2775 m_hasScrolling = TRUE;
2776
2777 if (orient == wxHORIZONTAL)
2778 {
2779 float fpos = (float)pos;
2780 float frange = (float)range;
2781 float fthumb = (float)thumbVisible;
2782 if (fpos > frange-fthumb) fpos = frange-fthumb;
2783 if (fpos < 0.0) fpos = 0.0;
2784
2785 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
2786 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
2787 {
2788 SetScrollPos( orient, pos, refresh );
2789 return;
2790 }
2791
2792 m_oldHorizontalPos = fpos;
2793
2794 m_hAdjust->lower = 0.0;
2795 m_hAdjust->upper = frange;
2796 m_hAdjust->value = fpos;
2797 m_hAdjust->step_increment = 1.0;
2798 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
2799 m_hAdjust->page_size = fthumb;
2800 }
2801 else
2802 {
2803 float fpos = (float)pos;
2804 float frange = (float)range;
2805 float fthumb = (float)thumbVisible;
2806 if (fpos > frange-fthumb) fpos = frange-fthumb;
2807 if (fpos < 0.0) fpos = 0.0;
2808
2809 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
2810 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
2811 {
2812 SetScrollPos( orient, pos, refresh );
2813 return;
2814 }
2815
2816 m_oldVerticalPos = fpos;
2817
2818 m_vAdjust->lower = 0.0;
2819 m_vAdjust->upper = frange;
2820 m_vAdjust->value = fpos;
2821 m_vAdjust->step_increment = 1.0;
2822 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
2823 m_vAdjust->page_size = fthumb;
2824 }
2825
2826 if (orient == wxHORIZONTAL)
2827 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
2828 else
2829 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
2830 }
2831
2832 void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
2833 {
2834 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
2835
2836 wxCHECK_RET( m_wxwindow != NULL, _T("window needs client area for scrolling") );
2837
2838 if (orient == wxHORIZONTAL)
2839 {
2840 float fpos = (float)pos;
2841 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
2842 if (fpos < 0.0) fpos = 0.0;
2843 m_oldHorizontalPos = fpos;
2844
2845 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
2846 m_hAdjust->value = fpos;
2847 }
2848 else
2849 {
2850 float fpos = (float)pos;
2851 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
2852 if (fpos < 0.0) fpos = 0.0;
2853 m_oldVerticalPos = fpos;
2854
2855 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
2856 m_vAdjust->value = fpos;
2857 }
2858
2859 if (!m_isScrolling) /* prevent recursion */
2860 {
2861 if (m_wxwindow->window)
2862 {
2863 if (orient == wxHORIZONTAL)
2864 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2865 else
2866 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
2867 }
2868 }
2869 }
2870
2871 int wxWindow::GetScrollThumb( int orient ) const
2872 {
2873 wxCHECK_MSG( m_widget != NULL, 0, _T("invalid window") );
2874
2875 wxCHECK_MSG( m_wxwindow != NULL, 0, _T("window needs client area for scrolling") );
2876
2877 if (orient == wxHORIZONTAL)
2878 return (int)(m_hAdjust->page_size+0.5);
2879 else
2880 return (int)(m_vAdjust->page_size+0.5);
2881 }
2882
2883 int wxWindow::GetScrollPos( int orient ) const
2884 {
2885 wxCHECK_MSG( m_widget != NULL, 0, _T("invalid window") );
2886
2887 wxCHECK_MSG( m_wxwindow != NULL, 0, _T("window needs client area for scrolling") );
2888
2889 if (orient == wxHORIZONTAL)
2890 return (int)(m_hAdjust->value+0.5);
2891 else
2892 return (int)(m_vAdjust->value+0.5);
2893 }
2894
2895 int wxWindow::GetScrollRange( int orient ) const
2896 {
2897 wxCHECK_MSG( m_widget != NULL, 0, _T("invalid window") );
2898
2899 wxCHECK_MSG( m_wxwindow != NULL, 0, _T("window needs client area for scrolling") );
2900
2901 if (orient == wxHORIZONTAL)
2902 return (int)(m_hAdjust->upper+0.5);
2903 else
2904 return (int)(m_vAdjust->upper+0.5);
2905 }
2906
2907 void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
2908 {
2909 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
2910
2911 wxCHECK_RET( m_wxwindow != NULL, _T("window needs client area for scrolling") );
2912
2913 if (!m_scrollGC)
2914 {
2915 m_scrollGC = gdk_gc_new( m_wxwindow->window );
2916 gdk_gc_set_exposures( m_scrollGC, TRUE );
2917 }
2918
2919 wxNode *node = m_children.First();
2920 while (node)
2921 {
2922 wxWindow *child = (wxWindow*) node->Data();
2923 child->Move( child->m_x + dx, child->m_y + dy );
2924 node = node->Next();
2925 }
2926
2927 int cw = 0;
2928 int ch = 0;
2929 GetClientSize( &cw, &ch );
2930 int w = cw - abs(dx);
2931 int h = ch - abs(dy);
2932
2933 if ((h < 0) || (w < 0))
2934 {
2935 Refresh();
2936 }
2937 else
2938 {
2939 int s_x = 0;
2940 int s_y = 0;
2941 if (dx < 0) s_x = -dx;
2942 if (dy < 0) s_y = -dy;
2943 int d_x = 0;
2944 int d_y = 0;
2945 if (dx > 0) d_x = dx;
2946 if (dy > 0) d_y = dy;
2947
2948 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
2949 m_wxwindow->window, s_x, s_y, w, h );
2950
2951 wxRect rect;
2952 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
2953 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
2954 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
2955 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
2956
2957 Refresh( TRUE, &rect );
2958 }
2959 }
2960
2961 void wxWindow::SetScrolling(bool scroll)
2962 {
2963 m_isScrolling = g_blockEventsOnScroll = scroll;
2964 }