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