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