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