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