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