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