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