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