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