1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #include "wx/window.h"
20 #include "wx/layout.h"
22 #include "wx/dialog.h"
23 #include "wx/msgdlg.h"
25 #if wxUSE_DRAG_AND_DROP
30 #include "wx/tooltip.h"
34 #include "wx/statusbr.h"
36 #include "wx/settings.h"
43 #include "gdk/gdkprivate.h"
44 #include "gdk/gdkkeysyms.h"
46 #include "wx/gtk/win_gtk.h"
48 //-----------------------------------------------------------------------------
49 // documentation on internals
50 //-----------------------------------------------------------------------------
53 I have been asked several times about writing some documentation about
54 the GTK port of wxWindows, especially its internal structures. Obviously,
55 you cannot understand wxGTK without knowing a little about the GTK, but
56 some more information about what the wxWindow, which is the base class
57 for all other window classes, does seems required as well.
59 What does wxWindow do? It contains the common interface for the following
60 jobs of its descendants:
62 1) Define the rudimentary behaviour common to all window classes, such as
63 resizing, intercepting user input (so as to make it possible to use these
64 events for special purposes in a derived class), window names etc.
66 2) Provide the possibility to contain and manage children, if the derived
67 class is allowed to contain children, which holds true for those window
68 classes which do not display a native GTK widget. To name them, these
69 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
70 work classes are a special case and are handled a bit differently from
71 the rest. The same holds true for the wxNotebook class.
73 3) Provide the possibility to draw into a client area of a window. This,
74 too, only holds true for classes that do not display a native GTK widget
77 4) Provide the entire mechanism for scrolling widgets. This actual inter-
78 face for this is usually in wxScrolledWindow, but the GTK implementation
81 5) A multitude of helper or extra methods for special purposes, such as
82 Drag'n'Drop, managing validators etc.
84 Normally one might expect, that one wxWindows window would always correspond
85 to one GTK widget. Under GTK, there is no such allround widget that has all
86 the functionality. Moreover, the GTK defines a client area as a different
87 widget from the actual widget you are handling. Last but not least some
88 special classes (e.g. wxFrame) handle different categories of widgets and
89 still have the possibility to draw something in the client area.
90 It was therefore required to write a special purpose GTK widget, that would
91 represent a client area in the sense of wxWindows capable to do the jobs
92 2), 3) and 4). I have written this class and it resides in win_gtk.c of
95 All windows must have a widget, with which they interact with other under-
96 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
97 thw wxWindow class has a member variable called m_widget which holds a
98 pointer to this widget. When the window class represents a GTK native widget,
99 this is (in most cases) the only GTK widget the class manages. E.g. the
100 wxStatitText class handles only a GtkLabel widget a pointer to which you
101 can find in m_widget (defined in wxWindow)
103 When the class has a client area for drawing into and for containing children
104 it has to handle the client area widget (of the type GtkMyFixed, defined in
105 win_gtk.c), but there could be any number of widgets, handled by a class
106 The common rule for all windows is only, that the widget that interacts with
107 the rest of GTK must be referenced in m_widget and all other widgets must be
108 children of this widget on the GTK level. The top-most widget, which also
109 represents the client area, must be in the m_wxwindow field and must be of
112 As I said, the window classes that display a GTK native widget only have
113 one widget, so in the case of e.g. the wxButton class m_widget holds a
114 pointer to a GtkButton widget. But windows with client areas (for drawing
115 and children) have a m_widget field that is a pointer to a GtkScrolled-
116 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
117 one is (in the GTK sense) a child of the GtkScrolledWindow.
119 If the m_wxwindow field is set, then all input to this widget is inter-
120 cepted and sent to the wxWindows class. If not, all input to the widget
121 that gets pointed to by m_widget gets intercepted and sent to the class.
125 //-----------------------------------------------------------------------------
127 //-----------------------------------------------------------------------------
129 extern wxList wxPendingDelete
;
130 extern bool g_blockEventsOnDrag
;
131 extern bool g_blockEventsOnScroll
;
132 static bool g_capturing
= FALSE
;
133 static wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
135 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
136 the last click here */
137 static guint32 gs_timeLastClick
= 0;
139 //-----------------------------------------------------------------------------
141 //-----------------------------------------------------------------------------
145 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
146 GdkEvent
*WXUNUSED(event
),
150 static bool s_done = FALSE;
153 wxLog::AddTraceMask("focus");
156 wxLogTrace(_T("FOCUS NOW AT: %s"), name);
162 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
168 wxChar
*s
= new wxChar
[tmp
.Length()+1];
172 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
173 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
178 //-----------------------------------------------------------------------------
180 //-----------------------------------------------------------------------------
182 extern void wxapp_install_idle_handler();
183 extern bool g_isIdle
;
185 //-----------------------------------------------------------------------------
186 // key event conversion routines
187 //-----------------------------------------------------------------------------
189 static long map_to_unmodified_wx_keysym( KeySym keysym
)
196 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
198 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
199 case GDK_Menu
: key_code
= WXK_MENU
; break;
200 case GDK_Help
: key_code
= WXK_HELP
; break;
201 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
202 case GDK_ISO_Left_Tab
:
203 case GDK_Tab
: key_code
= WXK_TAB
; break;
204 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
205 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
206 case GDK_Return
: key_code
= WXK_RETURN
; break;
207 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
208 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
209 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
210 case GDK_Delete
: key_code
= WXK_DELETE
; break;
211 case GDK_Home
: key_code
= WXK_HOME
; break;
212 case GDK_Left
: key_code
= WXK_LEFT
; break;
213 case GDK_Up
: key_code
= WXK_UP
; break;
214 case GDK_Right
: key_code
= WXK_RIGHT
; break;
215 case GDK_Down
: key_code
= WXK_DOWN
; break;
216 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
217 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
218 case GDK_Next
: key_code
= WXK_NEXT
; break;
219 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
220 case GDK_End
: key_code
= WXK_END
; break;
221 case GDK_Begin
: key_code
= WXK_HOME
; break;
222 case GDK_Select
: key_code
= WXK_SELECT
; break;
223 case GDK_Print
: key_code
= WXK_PRINT
; break;
224 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
225 case GDK_Insert
: key_code
= WXK_INSERT
; break;
226 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
228 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
229 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
230 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
231 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
232 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
233 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
234 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
235 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
236 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
237 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
238 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
239 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
240 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
241 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
242 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
243 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
244 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
245 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
246 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
247 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
248 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
249 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
250 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
251 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
252 case GDK_KP_Next
: key_code
= WXK_NUMPAD_PRIOR
; break;
253 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
254 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
255 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
256 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
257 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
258 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
259 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
260 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
261 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
262 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
263 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
264 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
266 case GDK_F1
: key_code
= WXK_F1
; break;
267 case GDK_F2
: key_code
= WXK_F2
; break;
268 case GDK_F3
: key_code
= WXK_F3
; break;
269 case GDK_F4
: key_code
= WXK_F4
; break;
270 case GDK_F5
: key_code
= WXK_F5
; break;
271 case GDK_F6
: key_code
= WXK_F6
; break;
272 case GDK_F7
: key_code
= WXK_F7
; break;
273 case GDK_F8
: key_code
= WXK_F8
; break;
274 case GDK_F9
: key_code
= WXK_F9
; break;
275 case GDK_F10
: key_code
= WXK_F10
; break;
276 case GDK_F11
: key_code
= WXK_F11
; break;
277 case GDK_F12
: key_code
= WXK_F12
; break;
282 guint upper
= gdk_keyval_to_upper( keysym
);
283 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
292 static long map_to_wx_keysym( KeySym keysym
)
298 case GDK_Menu
: key_code
= WXK_MENU
; break;
299 case GDK_Help
: key_code
= WXK_HELP
; break;
300 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
301 case GDK_ISO_Left_Tab
:
302 case GDK_Tab
: key_code
= WXK_TAB
; break;
303 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
304 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
305 case GDK_Return
: key_code
= WXK_RETURN
; break;
306 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
307 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
308 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
309 case GDK_Delete
: key_code
= WXK_DELETE
; break;
310 case GDK_Home
: key_code
= WXK_HOME
; break;
311 case GDK_Left
: key_code
= WXK_LEFT
; break;
312 case GDK_Up
: key_code
= WXK_UP
; break;
313 case GDK_Right
: key_code
= WXK_RIGHT
; break;
314 case GDK_Down
: key_code
= WXK_DOWN
; break;
315 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
316 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
317 case GDK_Next
: key_code
= WXK_NEXT
; break;
318 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
319 case GDK_End
: key_code
= WXK_END
; break;
320 case GDK_Begin
: key_code
= WXK_HOME
; break;
321 case GDK_Select
: key_code
= WXK_SELECT
; break;
322 case GDK_Print
: key_code
= WXK_PRINT
; break;
323 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
324 case GDK_Insert
: key_code
= WXK_INSERT
; break;
325 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
327 case GDK_KP_0
: key_code
= '0'; break;
328 case GDK_KP_1
: key_code
= '1'; break;
329 case GDK_KP_2
: key_code
= '2'; break;
330 case GDK_KP_3
: key_code
= '3'; break;
331 case GDK_KP_4
: key_code
= '4'; break;
332 case GDK_KP_5
: key_code
= '5'; break;
333 case GDK_KP_6
: key_code
= '6'; break;
334 case GDK_KP_7
: key_code
= '7'; break;
335 case GDK_KP_8
: key_code
= '8'; break;
336 case GDK_KP_9
: key_code
= '9'; break;
337 case GDK_KP_Space
: key_code
= ' '; break;
338 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
339 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
340 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
341 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
342 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
343 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
344 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
345 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
346 case GDK_KP_Up
: key_code
= WXK_UP
; break;
347 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
348 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
349 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
350 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
351 case GDK_KP_Next
: key_code
= WXK_PRIOR
; break;
352 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
353 case GDK_KP_End
: key_code
= WXK_END
; break;
354 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
355 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
356 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
357 case GDK_KP_Equal
: key_code
= '='; break;
358 case GDK_KP_Multiply
: key_code
= '*'; break;
359 case GDK_KP_Add
: key_code
= '+'; break;
360 case GDK_KP_Separator
: key_code
= ','; break;
361 case GDK_KP_Subtract
: key_code
= '-'; break;
362 case GDK_KP_Decimal
: key_code
= '.'; break;
363 case GDK_KP_Divide
: key_code
= '/'; break;
365 case GDK_F1
: key_code
= WXK_F1
; break;
366 case GDK_F2
: key_code
= WXK_F2
; break;
367 case GDK_F3
: key_code
= WXK_F3
; break;
368 case GDK_F4
: key_code
= WXK_F4
; break;
369 case GDK_F5
: key_code
= WXK_F5
; break;
370 case GDK_F6
: key_code
= WXK_F6
; break;
371 case GDK_F7
: key_code
= WXK_F7
; break;
372 case GDK_F8
: key_code
= WXK_F8
; break;
373 case GDK_F9
: key_code
= WXK_F9
; break;
374 case GDK_F10
: key_code
= WXK_F10
; break;
375 case GDK_F11
: key_code
= WXK_F11
; break;
376 case GDK_F12
: key_code
= WXK_F12
; break;
389 static long get_unmodified_wx_keysym( GdkEventKey
*event
)
391 KeyCode keycode
= XKeysymToKeycode( GDK_DISPLAY(), event
->keyval
);
392 KeySym keysym
= XKeycodeToKeysym( GDK_DISPLAY(), keycode
, 0 );
394 return (map_to_unmodified_wx_keysym( keysym
));
397 //-----------------------------------------------------------------------------
398 // local code (see below)
399 //-----------------------------------------------------------------------------
401 #if (GTK_MINOR_VERSION > 0)
403 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
411 if (win
->HasScrolling())
413 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
414 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
417 GtkWidget *hscrollbar = scroll_window->hscrollbar;
418 GtkWidget *vscrollbar = scroll_window->vscrollbar;
420 we use this instead: range.slider_width = 11 + 2*2pts edge
423 if (scroll_window
->vscrollbar_visible
)
425 dw
+= 15; /* dw += vscrollbar->allocation.width; */
426 dw
+= scroll_class
->scrollbar_spacing
;
429 if (scroll_window
->hscrollbar_visible
)
431 dh
+= 15; /* dh += hscrollbar->allocation.height; */
432 dw
+= scroll_class
->scrollbar_spacing
;
438 if (GTK_WIDGET_NO_WINDOW (widget
))
440 dx
+= widget
->allocation
.x
;
441 dy
+= widget
->allocation
.y
;
444 if (win
->HasFlag(wxRAISED_BORDER
))
446 gtk_draw_shadow( widget
->style
,
451 win
->m_width
-dw
, win
->m_height
-dh
);
455 if (win
->HasFlag(wxSUNKEN_BORDER
))
457 gtk_draw_shadow( widget
->style
,
462 win
->m_width
-dw
, win
->m_height
-dh
);
467 //-----------------------------------------------------------------------------
468 // "expose_event" of m_widget
469 //-----------------------------------------------------------------------------
471 static void gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
473 if (gdk_event
->count
> 0) return;
474 draw_frame( widget
, win
);
477 //-----------------------------------------------------------------------------
478 // "draw" of m_wxwindow
479 //-----------------------------------------------------------------------------
481 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
483 draw_frame( widget
, win
);
486 #endif // GTK_MINOR_VERSION > 0
488 //-----------------------------------------------------------------------------
489 // "expose_event" of m_wxwindow
490 //-----------------------------------------------------------------------------
492 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
494 if ( !win
->m_hasVMT
)
497 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
499 gdk_event
->area
.width
,
500 gdk_event
->area
.height
);
502 if ( gdk_event
->count
> 0 )
506 printf( "OnExpose from " );
507 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
508 printf( win->GetClassInfo()->GetClassName() );
512 wxPaintEvent
event( win
->GetId() );
513 event
.SetEventObject( win
);
514 win
->GetEventHandler()->ProcessEvent( event
);
516 win
->GetUpdateRegion().Clear();
519 //-----------------------------------------------------------------------------
520 // "draw" of m_wxwindow
521 //-----------------------------------------------------------------------------
523 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
526 wxapp_install_idle_handler();
531 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
532 rect
->width
, rect
->height
);
534 wxPaintEvent
event( win
->GetId() );
535 event
.SetEventObject( win
);
536 win
->GetEventHandler()->ProcessEvent( event
);
538 win
->GetUpdateRegion().Clear();
541 //-----------------------------------------------------------------------------
542 // "key_press_event" from any window
543 //-----------------------------------------------------------------------------
545 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
548 wxapp_install_idle_handler();
550 if (!win
->m_hasVMT
) return FALSE
;
551 if (g_blockEventsOnDrag
) return FALSE
;
554 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
555 if (gdk_event->state & GDK_SHIFT_MASK)
556 printf( "ShiftDown.\n" );
558 printf( "ShiftUp.\n" );
559 if (gdk_event->state & GDK_CONTROL_MASK)
560 printf( "ControlDown.\n" );
562 printf( "ControlUp.\n" );
570 GdkModifierType state
;
571 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
573 long key_code
= get_unmodified_wx_keysym( gdk_event
);
575 wxKeyEvent
event( wxEVT_KEY_DOWN
);
576 event
.SetTimestamp( gdk_event
->time
);
577 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
578 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
579 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
580 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
581 event
.m_keyCode
= key_code
;
582 event
.m_scanCode
= gdk_event
->keyval
;
585 event
.SetEventObject( win
);
586 ret
= win
->GetEventHandler()->ProcessEvent( event
);
588 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
590 /* wxMSW doesn't send char events with Alt pressed */
591 if ((key_code
!= 0) &&
592 ((gdk_event
->state
& GDK_MOD1_MASK
) == 0) &&
593 ((gdk_event
->state
& GDK_MOD1_MASK
) == 0))
595 wxKeyEvent
event2( wxEVT_CHAR
);
596 event2
.SetTimestamp( gdk_event
->time
);
597 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
598 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
599 // event2.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
600 // event2.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
601 event2
.m_keyCode
= key_code
;
602 event2
.m_scanCode
= gdk_event
->keyval
;
605 event2
.SetEventObject( win
);
606 ret
= (ret
|| win
->GetEventHandler()->ProcessEvent( event2
));
611 wxWindow
*ancestor
= win
;
614 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
617 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
618 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
621 ancestor
= ancestor
->GetParent();
625 // win is a control: tab can be propagated up
627 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
628 (win
->HasFlag(wxTE_PROCESS_TAB
) == 0))
630 wxNavigationKeyEvent new_event
;
631 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
632 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
633 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
634 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
635 new_event
.SetCurrentFocus( win
);
636 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
640 (gdk_event
->keyval
== GDK_Escape
) )
642 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
643 new_event
.SetEventObject( win
);
644 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
648 Damn, I forgot why this didn't work, but it didn't work.
650 // win is a panel: up can be propagated to the panel
651 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
652 (gdk_event->keyval == GDK_Up))
654 win->m_parent->SetFocus();
658 // win is a panel: left/right can be propagated to the panel
659 if ((!ret) && (win->m_wxwindow) &&
660 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
661 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
663 wxNavigationKeyEvent new_event;
664 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
665 new_event.SetCurrentFocus( win );
666 ret = win->GetEventHandler()->ProcessEvent( new_event );
672 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
679 //-----------------------------------------------------------------------------
680 // "key_release_event" from any window
681 //-----------------------------------------------------------------------------
683 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
686 wxapp_install_idle_handler();
688 if (!win
->m_hasVMT
) return FALSE
;
689 if (g_blockEventsOnDrag
) return FALSE
;
692 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
693 if (gdk_event->state & GDK_SHIFT_MASK)
694 printf( "ShiftDown.\n" );
696 printf( "ShiftUp.\n" );
697 if (gdk_event->state & GDK_CONTROL_MASK)
698 printf( "ControlDown.\n" );
700 printf( "ControlUp.\n" );
704 long key_code
= get_unmodified_wx_keysym( gdk_event
);
708 GdkModifierType state
;
709 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
711 wxKeyEvent
event( wxEVT_KEY_UP
);
712 event
.SetTimestamp( gdk_event
->time
);
713 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
714 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
715 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
716 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
717 event
.m_keyCode
= key_code
;
718 event
.m_scanCode
= gdk_event
->keyval
;
721 event
.SetEventObject( win
);
723 if (win
->GetEventHandler()->ProcessEvent( event
))
725 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
732 //-----------------------------------------------------------------------------
733 // "button_press_event"
734 //-----------------------------------------------------------------------------
736 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
739 wxapp_install_idle_handler();
742 wxPrintf( _T("1) OnButtonPress from ") );
743 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
744 wxPrintf( win->GetClassInfo()->GetClassName() );
745 wxPrintf( _T(".\n") );
747 if (!win
->m_hasVMT
) return FALSE
;
748 if (g_blockEventsOnDrag
) return TRUE
;
749 if (g_blockEventsOnScroll
) return TRUE
;
751 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
755 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
757 gtk_widget_grab_focus (win
->m_wxwindow
);
760 wxPrintf( _T("GrabFocus from ") );
761 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
762 wxPrintf( win->GetClassInfo()->GetClassName() );
763 wxPrintf( _T(".\n") );
770 wxPrintf( _T("2) OnButtonPress from ") );
771 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
772 wxPrintf( win->GetClassInfo()->GetClassName() );
773 wxPrintf( _T(".\n") );
776 wxEventType event_type
= wxEVT_LEFT_DOWN
;
778 if (gdk_event
->button
== 1)
780 switch (gdk_event
->type
)
782 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
783 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
787 else if (gdk_event
->button
== 2)
789 switch (gdk_event
->type
)
791 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
792 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
796 else if (gdk_event
->button
== 3)
798 switch (gdk_event
->type
)
800 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
801 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
806 wxMouseEvent
event( event_type
);
807 event
.SetTimestamp( gdk_event
->time
);
808 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
809 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
810 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
811 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
812 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
813 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
814 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
816 event
.m_x
= (long)gdk_event
->x
;
817 event
.m_y
= (long)gdk_event
->y
;
819 // Some control don't have their own X window and thus cannot get
824 wxNode
*node
= win
->GetChildren().First();
827 wxWindow
*child
= (wxWindow
*)node
->Data();
829 if (child
->m_isStaticBox
)
831 // wxStaticBox is transparent in the box itself
834 int xx1
= child
->m_x
;
835 int yy1
= child
->m_y
;
836 int xx2
= child
->m_x
+ child
->m_width
;
837 int yy2
= child
->m_x
+ child
->m_height
;
840 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
842 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
844 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
846 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
849 event
.m_x
-= child
->m_x
;
850 event
.m_y
-= child
->m_y
;
857 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
858 (child
->m_x
<= event
.m_x
) &&
859 (child
->m_y
<= event
.m_y
) &&
860 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
861 (child
->m_y
+child
->m_height
>= event
.m_y
))
864 event
.m_x
-= child
->m_x
;
865 event
.m_y
-= child
->m_y
;
873 event
.SetEventObject( win
);
875 gs_timeLastClick
= gdk_event
->time
;
877 if (win
->GetEventHandler()->ProcessEvent( event
))
879 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
886 //-----------------------------------------------------------------------------
887 // "button_release_event"
888 //-----------------------------------------------------------------------------
890 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
893 wxapp_install_idle_handler();
895 if (!win
->m_hasVMT
) return FALSE
;
896 if (g_blockEventsOnDrag
) return FALSE
;
897 if (g_blockEventsOnScroll
) return FALSE
;
899 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
902 printf( "OnButtonRelease from " );
903 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
904 printf( win->GetClassInfo()->GetClassName() );
908 wxEventType event_type
= wxEVT_NULL
;
910 switch (gdk_event
->button
)
912 case 1: event_type
= wxEVT_LEFT_UP
; break;
913 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
914 case 3: event_type
= wxEVT_RIGHT_UP
; break;
917 wxMouseEvent
event( event_type
);
918 event
.SetTimestamp( gdk_event
->time
);
919 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
920 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
921 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
922 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
923 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
924 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
925 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
926 event
.m_x
= (long)gdk_event
->x
;
927 event
.m_y
= (long)gdk_event
->y
;
929 // Some control don't have their own X window and thus cannot get
934 wxNode
*node
= win
->GetChildren().First();
937 wxWindow
*child
= (wxWindow
*)node
->Data();
939 if (child
->m_isStaticBox
)
941 // wxStaticBox is transparent in the box itself
944 int xx1
= child
->m_x
;
945 int yy1
= child
->m_y
;
946 int xx2
= child
->m_x
+ child
->m_width
;
947 int yy2
= child
->m_x
+ child
->m_height
;
950 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
952 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
954 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
956 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
959 event
.m_x
-= child
->m_x
;
960 event
.m_y
-= child
->m_y
;
967 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
968 (child
->m_x
<= event
.m_x
) &&
969 (child
->m_y
<= event
.m_y
) &&
970 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
971 (child
->m_y
+child
->m_height
>= event
.m_y
))
974 event
.m_x
-= child
->m_x
;
975 event
.m_y
-= child
->m_y
;
983 event
.SetEventObject( win
);
985 if (win
->GetEventHandler()->ProcessEvent( event
))
987 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
994 //-----------------------------------------------------------------------------
995 // "motion_notify_event"
996 //-----------------------------------------------------------------------------
998 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1001 wxapp_install_idle_handler();
1003 if (!win
->m_hasVMT
) return FALSE
;
1004 if (g_blockEventsOnDrag
) return FALSE
;
1005 if (g_blockEventsOnScroll
) return FALSE
;
1007 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1009 if (gdk_event
->is_hint
)
1013 GdkModifierType state
;
1014 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1017 gdk_event
->state
= state
;
1021 printf( "OnMotion from " );
1022 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1023 printf( win->GetClassInfo()->GetClassName() );
1027 wxMouseEvent
event( wxEVT_MOTION
);
1028 event
.SetTimestamp( gdk_event
->time
);
1029 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1030 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1031 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1032 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1033 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1034 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1035 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1037 event
.m_x
= (long)gdk_event
->x
;
1038 event
.m_y
= (long)gdk_event
->y
;
1040 // Some control don't have their own X window and thus cannot get
1045 wxNode
*node
= win
->GetChildren().First();
1048 wxWindow
*child
= (wxWindow
*)node
->Data();
1050 if (child
->m_isStaticBox
)
1052 // wxStaticBox is transparent in the box itself
1055 int xx1
= child
->m_x
;
1056 int yy1
= child
->m_y
;
1057 int xx2
= child
->m_x
+ child
->m_width
;
1058 int yy2
= child
->m_x
+ child
->m_height
;
1061 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1063 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1065 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1067 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1070 event
.m_x
-= child
->m_x
;
1071 event
.m_y
-= child
->m_y
;
1078 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1079 (child
->m_x
<= event
.m_x
) &&
1080 (child
->m_y
<= event
.m_y
) &&
1081 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
1082 (child
->m_y
+child
->m_height
>= event
.m_y
))
1085 event
.m_x
-= child
->m_x
;
1086 event
.m_y
-= child
->m_y
;
1090 node
= node
->Next();
1094 event
.SetEventObject( win
);
1096 if (win
->GetEventHandler()->ProcessEvent( event
))
1098 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1105 //-----------------------------------------------------------------------------
1107 //-----------------------------------------------------------------------------
1109 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1112 wxapp_install_idle_handler();
1114 if (!win
->m_hasVMT
) return FALSE
;
1115 if (g_blockEventsOnDrag
) return FALSE
;
1117 g_focusWindow
= win
;
1119 if (win
->m_wxwindow
)
1121 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1123 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1125 printf( "SetFocus flag from " );
1126 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1127 printf( win->GetClassInfo()->GetClassName() );
1135 printf( "OnSetFocus from " );
1136 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1137 printf( win->GetClassInfo()->GetClassName() );
1139 printf( WXSTRINGCAST win->GetLabel() );
1143 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1144 event
.SetEventObject( win
);
1146 if (win
->GetEventHandler()->ProcessEvent( event
))
1148 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1155 //-----------------------------------------------------------------------------
1156 // "focus_out_event"
1157 //-----------------------------------------------------------------------------
1159 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1162 wxapp_install_idle_handler();
1164 if (!win
->m_hasVMT
) return FALSE
;
1165 if (g_blockEventsOnDrag
) return FALSE
;
1167 if (win
->m_wxwindow
)
1169 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1170 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1174 printf( "OnKillFocus from " );
1175 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1176 printf( win->GetClassInfo()->GetClassName() );
1180 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1181 event
.SetEventObject( win
);
1183 if (win
->GetEventHandler()->ProcessEvent( event
))
1185 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1192 //-----------------------------------------------------------------------------
1193 // "enter_notify_event"
1194 //-----------------------------------------------------------------------------
1196 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1199 wxapp_install_idle_handler();
1201 if (!win
->m_hasVMT
) return FALSE
;
1202 if (g_blockEventsOnDrag
) return FALSE
;
1204 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1206 if (widget
->window
&& win
->GetCursor().Ok() )
1207 gdk_window_set_cursor( widget
->window
, win
->GetCursor().GetCursor() );
1209 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1210 event
.SetTimestamp( gdk_event
->time
);
1211 event
.SetEventObject( win
);
1215 GdkModifierType state
= (GdkModifierType
)0;
1217 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1219 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1220 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1221 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1222 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1223 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1224 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1225 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1227 event
.m_x
= (long)x
;
1228 event
.m_y
= (long)y
;
1230 if (win
->GetEventHandler()->ProcessEvent( event
))
1232 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1239 //-----------------------------------------------------------------------------
1240 // "leave_notify_event"
1241 //-----------------------------------------------------------------------------
1243 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1246 wxapp_install_idle_handler();
1248 if (!win
->m_hasVMT
) return FALSE
;
1249 if (g_blockEventsOnDrag
) return FALSE
;
1251 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1253 if (widget
->window
&& win
->GetCursor().Ok() )
1254 gdk_window_set_cursor( widget
->window
, wxSTANDARD_CURSOR
->GetCursor() );
1256 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1257 event
.SetTimestamp( gdk_event
->time
);
1258 event
.SetEventObject( win
);
1262 GdkModifierType state
= (GdkModifierType
)0;
1264 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1266 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1267 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1268 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1269 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1270 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1271 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1272 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1274 event
.m_x
= (long)x
;
1275 event
.m_y
= (long)y
;
1277 if (win
->GetEventHandler()->ProcessEvent( event
))
1279 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1286 //-----------------------------------------------------------------------------
1287 // "value_changed" from m_vAdjust
1288 //-----------------------------------------------------------------------------
1290 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1293 wxapp_install_idle_handler();
1295 if (g_blockEventsOnDrag
) return;
1297 if (!win
->m_hasVMT
) return;
1299 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
1300 if (fabs(diff
) < 0.2) return;
1301 win
->m_oldVerticalPos
= win
->m_vAdjust
->value
;
1303 wxEventType command
= wxEVT_NULL
;
1305 float line_step
= win
->m_vAdjust
->step_increment
;
1306 float page_step
= win
->m_vAdjust
->page_increment
;
1308 if (win
->IsScrolling())
1310 command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1314 if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->lower
) < 0.2) command
= wxEVT_SCROLLWIN_BOTTOM
;
1315 else if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->upper
) < 0.2) command
= wxEVT_SCROLLWIN_TOP
;
1316 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1317 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEUP
;
1318 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1319 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEUP
;
1320 else command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1323 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1325 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1326 event
.SetEventObject( win
);
1327 win
->GetEventHandler()->ProcessEvent( event
);
1330 //-----------------------------------------------------------------------------
1331 // "value_changed" from m_hAdjust
1332 //-----------------------------------------------------------------------------
1334 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1337 wxapp_install_idle_handler();
1339 if (g_blockEventsOnDrag
) return;
1340 if (!win
->m_hasVMT
) return;
1342 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
1343 if (fabs(diff
) < 0.2) return;
1344 win
->m_oldHorizontalPos
= win
->m_hAdjust
->value
;
1346 wxEventType command
= wxEVT_NULL
;
1348 float line_step
= win
->m_hAdjust
->step_increment
;
1349 float page_step
= win
->m_hAdjust
->page_increment
;
1351 if (win
->IsScrolling())
1353 command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1357 if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->lower
) < 0.2) command
= wxEVT_SCROLLWIN_BOTTOM
;
1358 else if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->upper
) < 0.2) command
= wxEVT_SCROLLWIN_TOP
;
1359 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1360 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEUP
;
1361 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1362 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEUP
;
1363 else command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1366 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1368 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1369 event
.SetEventObject( win
);
1370 win
->GetEventHandler()->ProcessEvent( event
);
1373 //-----------------------------------------------------------------------------
1374 // "changed" from m_vAdjust
1375 //-----------------------------------------------------------------------------
1377 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1380 wxapp_install_idle_handler();
1382 if (g_blockEventsOnDrag
) return;
1383 if (!win
->m_hasVMT
) return;
1385 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1386 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1388 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1389 event
.SetEventObject( win
);
1390 win
->GetEventHandler()->ProcessEvent( event
);
1393 //-----------------------------------------------------------------------------
1394 // "changed" from m_hAdjust
1395 //-----------------------------------------------------------------------------
1397 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1400 wxapp_install_idle_handler();
1402 if (g_blockEventsOnDrag
) return;
1403 if (!win
->m_hasVMT
) return;
1405 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1406 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1408 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1409 event
.SetEventObject( win
);
1410 win
->GetEventHandler()->ProcessEvent( event
);
1413 //-----------------------------------------------------------------------------
1414 // "button_press_event" from scrollbar
1415 //-----------------------------------------------------------------------------
1417 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1418 GdkEventButton
*WXUNUSED(gdk_event
),
1422 wxapp_install_idle_handler();
1424 // don't test here as we can release the mouse while being over
1425 // a different window then the slider
1427 // if (gdk_event->window != widget->slider) return FALSE;
1429 win
->SetScrolling( TRUE
);
1434 //-----------------------------------------------------------------------------
1435 // "button_release_event" from scrollbar
1436 //-----------------------------------------------------------------------------
1438 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1439 GdkEventButton
*WXUNUSED(gdk_event
),
1443 // don't test here as we can release the mouse while being over
1444 // a different window then the slider
1446 // if (gdk_event->window != widget->slider) return FALSE;
1448 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1450 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1451 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_hAdjust
), "value_changed" );
1453 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_vAdjust
), "value_changed" );
1455 win
->SetScrolling( FALSE
);
1460 // ----------------------------------------------------------------------------
1461 // this wxWindowBase function is implemented here (in platform-specific file)
1462 // because it is static and so couldn't be made virtual
1463 // ----------------------------------------------------------------------------
1465 wxWindow
*wxWindowBase::FindFocus()
1467 return g_focusWindow
;
1470 //-----------------------------------------------------------------------------
1471 // "realize" from m_widget
1472 //-----------------------------------------------------------------------------
1474 /* we cannot set colours, fonts and cursors before the widget has
1475 been realized, so we do this directly after realization */
1478 gtk_window_realized_callback( GtkWidget
* WXUNUSED(widget
), wxWindow
*win
)
1481 wxapp_install_idle_handler();
1483 if (win
->m_delayedFont
)
1484 win
->SetFont( win
->GetFont() );
1486 if (win
->m_delayedBackgroundColour
)
1487 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1489 if (win
->m_delayedForegroundColour
)
1490 win
->SetForegroundColour( win
->GetForegroundColour() );
1492 win
->SetCursor( win
->GetCursor() );
1497 //-----------------------------------------------------------------------------
1498 // InsertChild for wxWindow.
1499 //-----------------------------------------------------------------------------
1501 /* Callback for wxWindow. This very strange beast has to be used because
1502 * C++ has no virtual methods in a constructor. We have to emulate a
1503 * virtual function here as wxNotebook requires a different way to insert
1504 * a child in it. I had opted for creating a wxNotebookPage window class
1505 * which would have made this superfluous (such in the MDI window system),
1506 * but no-one was listening to me... */
1508 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1510 gtk_myfixed_put( GTK_MYFIXED(parent
->m_wxwindow
),
1511 GTK_WIDGET(child
->m_widget
),
1517 if (parent
->HasFlag(wxTAB_TRAVERSAL
))
1519 /* we now allow a window to get the focus as long as it
1520 doesn't have any children. */
1521 GTK_WIDGET_UNSET_FLAGS( parent
->m_wxwindow
, GTK_CAN_FOCUS
);
1525 //-----------------------------------------------------------------------------
1527 //-----------------------------------------------------------------------------
1529 wxWindow
* wxGetActiveWindow()
1531 return g_focusWindow
;
1534 //-----------------------------------------------------------------------------
1536 //-----------------------------------------------------------------------------
1538 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1540 void wxWindow::Init()
1546 m_widget
= (GtkWidget
*) NULL
;
1547 m_wxwindow
= (GtkWidget
*) NULL
;
1557 m_needParent
= TRUE
;
1558 m_isBeingDeleted
= FALSE
;
1560 m_hasScrolling
= FALSE
;
1561 m_isScrolling
= FALSE
;
1563 m_hAdjust
= (GtkAdjustment
*) NULL
;
1564 m_vAdjust
= (GtkAdjustment
*) NULL
;
1565 m_oldHorizontalPos
= 0.0;
1566 m_oldVerticalPos
= 0.0;
1569 m_scrollGC
= (GdkGC
*) NULL
;
1570 m_widgetStyle
= (GtkStyle
*) NULL
;
1572 m_insertCallback
= wxInsertChildInWindow
;
1574 m_isStaticBox
= FALSE
;
1575 m_acceptsFocus
= FALSE
;
1578 wxWindow::wxWindow()
1583 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1584 const wxPoint
&pos
, const wxSize
&size
,
1585 long style
, const wxString
&name
)
1589 Create( parent
, id
, pos
, size
, style
, name
);
1592 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1593 const wxPoint
&pos
, const wxSize
&size
,
1594 long style
, const wxString
&name
)
1596 PreCreation( parent
, id
, pos
, size
, style
, name
);
1598 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1599 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1602 debug_focus_in( m_widget
, _T("wxWindow::m_widget"), name
);
1605 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1608 debug_focus_in( scrolledWindow
->hscrollbar
, _T("wxWindow::hsrcollbar"), name
);
1609 debug_focus_in( scrolledWindow
->vscrollbar
, _T("wxWindow::vsrcollbar"), name
);
1612 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1613 scroll_class
->scrollbar_spacing
= 0;
1615 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1617 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
1618 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
1620 m_wxwindow
= gtk_myfixed_new();
1623 debug_focus_in( m_wxwindow
, _T("wxWindow::m_wxwindow"), name
);
1626 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1628 #if (GTK_MINOR_VERSION > 0)
1629 GtkMyFixed
*myfixed
= GTK_MYFIXED(m_wxwindow
);
1631 if (HasFlag(wxRAISED_BORDER
))
1633 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_OUT
);
1635 else if (HasFlag(wxSUNKEN_BORDER
))
1637 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_IN
);
1641 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_NONE
);
1643 #else // GTK_MINOR_VERSION == 0
1644 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
1646 if (HasFlag(wxRAISED_BORDER
))
1648 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1650 else if (HasFlag(wxSUNKEN_BORDER
))
1652 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1656 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1658 #endif // GTK_MINOR_VERSION
1660 if (HasFlag(wxTAB_TRAVERSAL
))
1662 /* we now allow a window to get the focus as long as it
1663 doesn't have any children. */
1664 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1665 m_acceptsFocus
= FALSE
;
1669 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1670 m_acceptsFocus
= TRUE
;
1673 #if (GTK_MINOR_VERSION == 0)
1674 // shut the viewport up
1675 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1676 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1677 #endif // GTK_MINOR_VERSION == 0
1679 // I _really_ don't want scrollbars in the beginning
1680 m_vAdjust
->lower
= 0.0;
1681 m_vAdjust
->upper
= 1.0;
1682 m_vAdjust
->value
= 0.0;
1683 m_vAdjust
->step_increment
= 1.0;
1684 m_vAdjust
->page_increment
= 1.0;
1685 m_vAdjust
->page_size
= 5.0;
1686 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1687 m_hAdjust
->lower
= 0.0;
1688 m_hAdjust
->upper
= 1.0;
1689 m_hAdjust
->value
= 0.0;
1690 m_hAdjust
->step_increment
= 1.0;
1691 m_hAdjust
->page_increment
= 1.0;
1692 m_hAdjust
->page_size
= 5.0;
1693 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1695 // these handlers block mouse events to any window during scrolling such as
1696 // motion events and prevent GTK and wxWindows from fighting over where the
1699 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
1700 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1702 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
1703 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1705 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
1706 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1708 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
1709 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1711 // these handlers get notified when screen updates are required either when
1712 // scrolling or when the window size (and therefore scrollbar configuration)
1715 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
1716 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
1717 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
1718 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
1720 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
1721 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
1722 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
1723 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
1725 gtk_widget_show( m_wxwindow
);
1728 m_parent
->DoAddChild( this );
1737 wxWindow::~wxWindow()
1739 m_isBeingDeleted
= TRUE
;
1748 m_parent
->RemoveChild( this );
1752 gtk_style_unref( m_widgetStyle
);
1753 m_widgetStyle
= (GtkStyle
*) NULL
;
1758 gdk_gc_unref( m_scrollGC
);
1759 m_scrollGC
= (GdkGC
*) NULL
;
1764 gtk_widget_destroy( m_wxwindow
);
1765 m_wxwindow
= (GtkWidget
*) NULL
;
1770 gtk_widget_destroy( m_widget
);
1771 m_widget
= (GtkWidget
*) NULL
;
1775 void wxWindow::PreCreation( wxWindow
*parent
,
1780 const wxString
&name
)
1782 wxASSERT_MSG( !m_needParent
|| parent
, _T("Need complete parent.") );
1784 if ( !CreateBase(parent
, id
, pos
, size
, style
, name
) )
1786 wxFAIL_MSG(_T("window creation failed"));
1789 m_width
= WidthDefault(size
.x
);
1790 m_height
= HeightDefault(size
.y
);
1795 if (!parent
) /* some reasonable defaults */
1799 m_x
= (gdk_screen_width () - m_width
) / 2;
1800 if (m_x
< 10) m_x
= 10;
1804 m_y
= (gdk_screen_height () - m_height
) / 2;
1805 if (m_y
< 10) m_y
= 10;
1810 void wxWindow::PostCreation()
1812 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1816 /* these get reported to wxWindows -> wxPaintEvent */
1817 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1818 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1820 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1821 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1823 #if (GTK_MINOR_VERSION > 0)
1824 /* these are called when the "sunken" or "raised" borders are drawn */
1825 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
1826 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
1828 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
1829 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
1833 GtkWidget
*connect_widget
= GetConnectWidget();
1835 ConnectWidget( connect_widget
);
1837 /* we cannot set colours, fonts and cursors before the widget has
1838 been realized, so we do this directly after realization */
1839 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
1840 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
1845 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1847 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1848 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1850 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
1851 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
1853 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1854 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1856 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1857 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1859 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1860 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1862 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1863 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1865 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1866 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1868 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1869 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1871 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1872 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1875 bool wxWindow::Destroy()
1877 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1881 return wxWindowBase::Destroy();
1884 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1886 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1887 wxASSERT_MSG( (m_parent
!= NULL
), _T("wxWindow::SetSize requires parent.\n") );
1889 if (m_resizing
) return; /* I don't like recursions */
1892 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
1894 /* don't set the size for children of wxNotebook, just take the values. */
1902 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1904 if (x
!= -1) m_x
= x
;
1905 if (y
!= -1) m_y
= y
;
1906 if (width
!= -1) m_width
= width
;
1907 if (height
!= -1) m_height
= height
;
1917 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1919 if (width
== -1) m_width
= 80;
1922 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1924 if (height
== -1) m_height
= 26;
1927 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1928 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1929 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
1930 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
1934 if (GTK_WIDGET_HAS_DEFAULT(m_widget
))
1936 /* the default button has a border around it */
1940 /* this is the result of hours of debugging: the following code
1941 means that if we have a m_wxwindow and we set the size of
1942 m_widget, m_widget (which is a GtkScrolledWindow) does NOT
1943 automatically propagate its size down to its m_wxwindow,
1944 which is its client area. therefore, we have to tell the
1945 client area directly that it has to resize itself.
1946 this will lead to that m_widget (GtkScrolledWindow) will
1947 calculate how much size it needs for scrollbars etc and
1948 it will then call XXX_size_allocate of its child, which
1949 is m_wxwindow. m_wxwindow in turn will do the same with its
1950 children and so on. problems can arise if this happens
1951 before all the children have been realized as some widgets
1952 stupidy need to be realized during XXX_size_allocate (e.g.
1953 GtkNotebook) and they will segv if called otherwise. this
1954 emergency is tested in gtk_myfixed_size_allocate. Normally
1955 this shouldn't be needed and only gtk_widget_queue_resize()
1956 should be enough to provoke a resize at the next appropriate
1957 moment, but this seems to fail, e.g. when a wxNotebook contains
1958 a wxSplitterWindow: the splitter window's children won't
1959 show up properly resized then. */
1961 gtk_myfixed_set_size( GTK_MYFIXED(m_parent
->m_wxwindow
),
1966 m_height
+2*border
);
1971 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1972 event
.SetEventObject( this );
1973 GetEventHandler()->ProcessEvent( event
);
1978 void wxWindow::OnInternalIdle()
1983 void wxWindow::DoGetSize( int *width
, int *height
) const
1985 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
1987 if (width
) (*width
) = m_width
;
1988 if (height
) (*height
) = m_height
;
1991 void wxWindow::DoSetClientSize( int width
, int height
)
1993 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
1997 SetSize( width
, height
);
2004 if (!m_hasScrolling
)
2006 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
2008 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2010 dw
+= 2 * window_class
->xthickness
;
2011 dh
+= 2 * window_class
->ythickness
;
2016 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2017 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2019 #if (GTK_MINOR_VERSION == 0)
2020 GtkWidget
*viewport
= scroll_window
->viewport
;
2021 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2023 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2025 dw
+= 2 * viewport_class
->xthickness
;
2026 dh
+= 2 * viewport_class
->ythickness
;
2031 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2032 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2034 we use this instead: range.slider_width = 11 + 2*2pts edge
2037 if (scroll_window
->vscrollbar_visible
)
2039 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2040 dw
+= scroll_class
->scrollbar_spacing
;
2043 if (scroll_window
->hscrollbar_visible
)
2045 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2046 dw
+= scroll_class
->scrollbar_spacing
;
2050 SetSize( width
+dw
, height
+dh
);
2054 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2056 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2060 if (width
) (*width
) = m_width
;
2061 if (height
) (*height
) = m_height
;
2068 if (!m_hasScrolling
)
2070 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
2072 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2074 dw
+= 2 * window_class
->xthickness
;
2075 dh
+= 2 * window_class
->ythickness
;
2080 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2081 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2083 #if (GTK_MINOR_VERSION == 0)
2084 GtkWidget
*viewport
= scroll_window
->viewport
;
2085 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2087 if ( HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
) )
2089 dw
+= 2 * viewport_class
->xthickness
;
2090 dh
+= 2 * viewport_class
->ythickness
;
2094 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2095 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2097 we use this instead: range.slider_width = 11 + 2*2pts edge
2100 if (scroll_window
->vscrollbar_visible
)
2102 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2103 dw
+= scroll_class
->scrollbar_spacing
;
2106 if (scroll_window
->hscrollbar_visible
)
2108 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2109 dh
+= scroll_class
->scrollbar_spacing
;
2113 if (width
) (*width
) = m_width
- dw
;
2114 if (height
) (*height
) = m_height
- dh
;
2118 void wxWindow::DoGetPosition( int *x
, int *y
) const
2120 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2126 void wxWindow::ClientToScreen( int *x
, int *y
) const
2128 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2130 if (!m_widget
->window
) return;
2132 GdkWindow
*source
= (GdkWindow
*) NULL
;
2134 source
= m_wxwindow
->window
;
2136 source
= m_widget
->window
;
2140 gdk_window_get_origin( source
, &org_x
, &org_y
);
2144 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2146 org_x
+= m_widget
->allocation
.x
;
2147 org_y
+= m_widget
->allocation
.y
;
2155 void wxWindow::ScreenToClient( int *x
, int *y
) const
2157 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2159 if (!m_widget
->window
) return;
2161 GdkWindow
*source
= (GdkWindow
*) NULL
;
2163 source
= m_wxwindow
->window
;
2165 source
= m_widget
->window
;
2169 gdk_window_get_origin( source
, &org_x
, &org_y
);
2173 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2175 org_x
+= m_widget
->allocation
.x
;
2176 org_y
+= m_widget
->allocation
.y
;
2184 bool wxWindow::Show( bool show
)
2186 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2188 if (!wxWindowBase::Show(show
))
2195 gtk_widget_show( m_widget
);
2197 gtk_widget_hide( m_widget
);
2202 bool wxWindow::Enable( bool enable
)
2204 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2206 if (!wxWindowBase::Enable(enable
))
2212 gtk_widget_set_sensitive( m_widget
, enable
);
2214 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2219 int wxWindow::GetCharHeight() const
2221 wxCHECK_MSG( (m_widget
!= NULL
), 12, _T("invalid window") );
2223 wxCHECK_MSG( m_font
.Ok(), 12, _T("invalid font") );
2225 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2227 return font
->ascent
+ font
->descent
;
2230 int wxWindow::GetCharWidth() const
2232 wxCHECK_MSG( (m_widget
!= NULL
), 8, _T("invalid window") );
2234 wxCHECK_MSG( m_font
.Ok(), 8, _T("invalid font") );
2236 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2238 return gdk_string_width( font
, "H" );
2241 void wxWindow::GetTextExtent( const wxString
& string
,
2245 int *externalLeading
,
2246 const wxFont
*theFont
) const
2248 wxFont fontToUse
= m_font
;
2249 if (theFont
) fontToUse
= *theFont
;
2251 wxCHECK_RET( fontToUse
.Ok(), _T("invalid font") );
2253 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2254 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2255 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2256 if (descent
) (*descent
) = font
->descent
;
2257 if (externalLeading
) (*externalLeading
) = 0; // ??
2260 void wxWindow::SetFocus()
2262 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2264 GtkWidget
*connect_widget
= GetConnectWidget();
2267 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2269 gtk_widget_grab_focus (connect_widget
);
2271 else if (GTK_IS_CONTAINER(connect_widget
))
2273 gtk_container_focus( GTK_CONTAINER(connect_widget
), GTK_DIR_TAB_FORWARD
);
2281 bool wxWindow::AcceptsFocus() const
2283 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2286 bool wxWindow::Reparent( wxWindow
*newParent
)
2288 wxCHECK_MSG( (m_widget
!= NULL
), (wxWindow
*) NULL
, _T("invalid window") );
2290 gtk_widget_unparent( m_widget
);
2292 if ( !wxWindowBase::Reparent(newParent
) )
2298 void wxWindow::Raise()
2300 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2302 if (!m_widget
->window
) return;
2304 gdk_window_raise( m_widget
->window
);
2307 void wxWindow::Lower()
2309 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2311 if (!m_widget
->window
) return;
2313 gdk_window_lower( m_widget
->window
);
2316 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2318 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2320 if (!wxWindowBase::SetCursor(cursor
))
2322 // don't leave if the GTK widget has just
2324 if (!m_delayedCursor
) return FALSE
;
2327 GtkWidget
*connect_widget
= GetConnectWidget();
2328 if (!connect_widget
->window
)
2330 // indicate that a new style has been set
2331 // but it couldn't get applied as the
2332 // widget hasn't been realized yet.
2333 m_delayedCursor
= TRUE
;
2335 // pretend we have done something
2339 if ((m_widget
) && (m_widget
->window
))
2340 gdk_window_set_cursor( m_widget
->window
, GetCursor().GetCursor() );
2342 if ((m_wxwindow
) && (m_wxwindow
->window
))
2343 gdk_window_set_cursor( m_wxwindow
->window
, GetCursor().GetCursor() );
2349 void wxWindow::WarpPointer( int WXUNUSED(x
), int WXUNUSED(y
) )
2354 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2356 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2358 if (!m_widget
->window
) return;
2360 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2364 gdk_window_clear_area( m_wxwindow
->window
,
2366 rect
->width
, rect
->height
);
2370 gdk_window_clear( m_wxwindow
->window
);
2377 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2379 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2383 GdkRectangle gdk_rect
;
2384 gdk_rect
.x
= rect
->x
;
2385 gdk_rect
.y
= rect
->y
;
2386 gdk_rect
.width
= rect
->width
;
2387 gdk_rect
.height
= rect
->height
;
2390 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2392 gtk_widget_draw( m_widget
, &gdk_rect
);
2396 void wxWindow::Clear()
2398 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2400 if (!m_widget
->window
) return;
2402 if (m_wxwindow
&& m_wxwindow
->window
)
2404 gdk_window_clear( m_wxwindow
->window
);
2409 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2411 wxWindowBase::DoSetToolTip(tip
);
2414 m_tooltip
->Apply( this );
2417 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2419 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConv_current
->cWX2MB(tip
), (gchar
*) NULL
);
2421 #endif // wxUSE_TOOLTIPS
2423 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2425 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2427 if (!wxWindowBase::SetBackgroundColour(colour
))
2429 // don't leave if the GTK widget has just
2431 if (!m_delayedBackgroundColour
) return FALSE
;
2434 GtkWidget
*connect_widget
= GetConnectWidget();
2435 if (!connect_widget
->window
)
2437 // indicate that a new style has been set
2438 // but it couldn't get applied as the
2439 // widget hasn't been realized yet.
2440 m_delayedBackgroundColour
= TRUE
;
2442 // pretend we have done something
2446 if (m_wxwindow
&& m_wxwindow
->window
)
2448 /* wxMSW doesn't clear the window here. I don't do that either to
2449 provide compatibility. call Clear() to do the job. */
2451 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_wxwindow
->window
) );
2452 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
2455 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2457 if (sysbg
== m_backgroundColour
)
2459 m_backgroundColour
= wxNullColour
;
2461 m_backgroundColour
= sysbg
;
2471 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2473 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2475 if (!wxWindowBase::SetForegroundColour(colour
))
2477 // don't leave if the GTK widget has just
2479 if (!m_delayedForegroundColour
) return FALSE
;
2482 GtkWidget
*connect_widget
= GetConnectWidget();
2483 if (!connect_widget
->window
)
2485 // indicate that a new style has been set
2486 // but it couldn't get applied as the
2487 // widget hasn't been realized yet.
2488 m_delayedForegroundColour
= TRUE
;
2490 // pretend we have done something
2494 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2495 if (sysbg
== m_foregroundColour
)
2497 m_backgroundColour
= wxNullColour
;
2499 m_backgroundColour
= sysbg
;
2509 GtkStyle
*wxWindow::GetWidgetStyle()
2511 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2513 m_widgetStyle
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2515 return m_widgetStyle
;
2518 void wxWindow::SetWidgetStyle()
2520 GtkStyle
*style
= GetWidgetStyle();
2522 gdk_font_unref( style
->font
);
2523 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2525 if (m_foregroundColour
.Ok())
2527 m_foregroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2528 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2529 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2530 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2533 if (m_backgroundColour
.Ok())
2535 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2536 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2537 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2538 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2539 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2540 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2541 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2542 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2543 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2547 void wxWindow::ApplyWidgetStyle()
2551 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2553 menu
->SetInvokingWindow( win
);
2554 wxNode
*node
= menu
->GetItems().First();
2557 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2558 if (menuitem
->IsSubMenu())
2560 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2562 node
= node
->Next();
2566 static gint gs_pop_x
= 0;
2567 static gint gs_pop_y
= 0;
2569 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
2573 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
2578 bool wxWindow::PopupMenu( wxMenu
*menu
, int x
, int y
)
2580 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2582 wxCHECK_MSG( menu
!= NULL
, FALSE
, _T("invalid popup-menu") );
2584 SetInvokingWindow( menu
, this );
2592 GTK_MENU(menu
->m_menu
),
2593 (GtkWidget
*) NULL
, // parent menu shell
2594 (GtkWidget
*) NULL
, // parent menu item
2595 (GtkMenuPositionFunc
) pop_pos_callback
,
2596 (gpointer
) this, // client data
2597 0, // button used to activate it
2598 0 //gs_timeLastClick // the time of activation
2603 #if wxUSE_DRAG_AND_DROP
2605 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2607 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2609 GtkWidget
*dnd_widget
= GetConnectWidget();
2611 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
2613 if (m_dropTarget
) delete m_dropTarget
;
2614 m_dropTarget
= dropTarget
;
2616 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
2619 #endif // wxUSE_DRAG_AND_DROP
2621 GtkWidget
* wxWindow::GetConnectWidget()
2623 GtkWidget
*connect_widget
= m_widget
;
2624 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2626 return connect_widget
;
2629 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2631 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2632 return (window
== m_widget
->window
);
2635 bool wxWindow::SetFont( const wxFont
&font
)
2637 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T( "invalid window") );
2639 if (!wxWindowBase::SetFont(font
))
2641 // don't leave if the GTK widget has just
2643 if (!m_delayedFont
) return FALSE
;
2646 GtkWidget
*connect_widget
= GetConnectWidget();
2647 if (!connect_widget
->window
)
2649 // indicate that a new style has been set
2650 // but it couldn't get applied as the
2651 // widget hasn't been realized yet.
2652 m_delayedFont
= TRUE
;
2654 // pretend we have done something
2658 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2659 if ( sysbg
== m_backgroundColour
)
2661 m_backgroundColour
= wxNullColour
;
2663 m_backgroundColour
= sysbg
;
2673 void wxWindow::CaptureMouse()
2675 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2677 wxCHECK_RET( g_capturing
== FALSE
, _T("CaptureMouse called twice") );
2679 GtkWidget
*connect_widget
= GetConnectWidget();
2680 if (!connect_widget
->window
) return;
2682 gtk_grab_add( connect_widget
);
2683 gdk_pointer_grab( connect_widget
->window
, FALSE
,
2685 (GDK_BUTTON_PRESS_MASK
|
2686 GDK_BUTTON_RELEASE_MASK
|
2687 GDK_POINTER_MOTION_MASK
),
2694 void wxWindow::ReleaseMouse()
2696 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2698 wxCHECK_RET( g_capturing
== TRUE
, _T("ReleaseMouse called twice") );
2700 GtkWidget
*connect_widget
= GetConnectWidget();
2701 if (!connect_widget
->window
) return;
2703 gtk_grab_remove( connect_widget
);
2704 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2705 g_capturing
= FALSE
;
2708 bool wxWindow::IsRetained() const
2713 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2714 int range
, bool refresh
)
2716 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2718 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2720 m_hasScrolling
= TRUE
;
2722 if (orient
== wxHORIZONTAL
)
2724 float fpos
= (float)pos
;
2725 float frange
= (float)range
;
2726 float fthumb
= (float)thumbVisible
;
2727 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2728 if (fpos
< 0.0) fpos
= 0.0;
2730 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2731 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2733 SetScrollPos( orient
, pos
, refresh
);
2737 m_oldHorizontalPos
= fpos
;
2739 m_hAdjust
->lower
= 0.0;
2740 m_hAdjust
->upper
= frange
;
2741 m_hAdjust
->value
= fpos
;
2742 m_hAdjust
->step_increment
= 1.0;
2743 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2744 m_hAdjust
->page_size
= fthumb
;
2748 float fpos
= (float)pos
;
2749 float frange
= (float)range
;
2750 float fthumb
= (float)thumbVisible
;
2751 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2752 if (fpos
< 0.0) fpos
= 0.0;
2754 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2755 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2757 SetScrollPos( orient
, pos
, refresh
);
2761 m_oldVerticalPos
= fpos
;
2763 m_vAdjust
->lower
= 0.0;
2764 m_vAdjust
->upper
= frange
;
2765 m_vAdjust
->value
= fpos
;
2766 m_vAdjust
->step_increment
= 1.0;
2767 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2768 m_vAdjust
->page_size
= fthumb
;
2771 if (orient
== wxHORIZONTAL
)
2772 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2774 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2777 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2779 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2781 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2783 if (orient
== wxHORIZONTAL
)
2785 float fpos
= (float)pos
;
2786 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
2787 if (fpos
< 0.0) fpos
= 0.0;
2788 m_oldHorizontalPos
= fpos
;
2790 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2791 m_hAdjust
->value
= fpos
;
2795 float fpos
= (float)pos
;
2796 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
2797 if (fpos
< 0.0) fpos
= 0.0;
2798 m_oldVerticalPos
= fpos
;
2800 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2801 m_vAdjust
->value
= fpos
;
2804 if (!m_isScrolling
) /* prevent recursion */
2806 if (m_wxwindow
->window
)
2808 if (orient
== wxHORIZONTAL
)
2809 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2811 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2816 int wxWindow::GetScrollThumb( int orient
) const
2818 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2820 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2822 if (orient
== wxHORIZONTAL
)
2823 return (int)(m_hAdjust
->page_size
+0.5);
2825 return (int)(m_vAdjust
->page_size
+0.5);
2828 int wxWindow::GetScrollPos( int orient
) const
2830 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2832 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2834 if (orient
== wxHORIZONTAL
)
2835 return (int)(m_hAdjust
->value
+0.5);
2837 return (int)(m_vAdjust
->value
+0.5);
2840 int wxWindow::GetScrollRange( int orient
) const
2842 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2844 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2846 if (orient
== wxHORIZONTAL
)
2847 return (int)(m_hAdjust
->upper
+0.5);
2849 return (int)(m_vAdjust
->upper
+0.5);
2852 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2854 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2856 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2860 m_scrollGC
= gdk_gc_new( m_wxwindow
->window
);
2861 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
2866 GetClientSize( &cw
, &ch
);
2867 int w
= cw
- abs(dx
);
2868 int h
= ch
- abs(dy
);
2870 if ((h
< 0) || (w
< 0))
2878 if (dx
< 0) s_x
= -dx
;
2879 if (dy
< 0) s_y
= -dy
;
2882 if (dx
> 0) d_x
= dx
;
2883 if (dy
> 0) d_y
= dy
;
2885 gdk_window_copy_area( m_wxwindow
->window
, m_scrollGC
, d_x
, d_y
,
2886 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2889 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2890 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2891 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2892 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2894 Refresh( TRUE
, &rect
);
2897 wxNode
*node
= m_children
.First();
2900 wxWindow
*child
= (wxWindow
*) node
->Data();
2901 child
->Move( child
->m_x
+ dx
, child
->m_y
+ dy
);
2902 node
= node
->Next();
2906 void wxWindow::SetScrolling(bool scroll
)
2908 m_isScrolling
= g_blockEventsOnScroll
= scroll
;