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"
45 #include "wx/gtk/win_gtk.h"
47 //-----------------------------------------------------------------------------
48 // documentation on internals
49 //-----------------------------------------------------------------------------
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.
58 What does wxWindow do? It contains the common interface for the following
59 jobs of its descendants:
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.
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.
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
76 4) Provide the entire mechanism for scrolling widgets. This actual inter-
77 face for this is usually in wxScrolledWindow, but the GTK implementation
80 5) A multitude of helper or extra methods for special purposes, such as
81 Drag'n'Drop, managing validators etc.
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
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)
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
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.
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.
124 //-----------------------------------------------------------------------------
126 //-----------------------------------------------------------------------------
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
;
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;
138 //-----------------------------------------------------------------------------
140 //-----------------------------------------------------------------------------
144 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
145 GdkEvent
*WXUNUSED(event
),
149 static bool s_done = FALSE;
152 wxLog::AddTraceMask("focus");
155 wxLogTrace(_T("FOCUS NOW AT: %s"), name);
161 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
167 wxChar
*s
= new wxChar
[tmp
.Length()+1];
171 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
172 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
177 //-----------------------------------------------------------------------------
179 //-----------------------------------------------------------------------------
181 extern void wxapp_install_idle_handler();
182 extern bool g_isIdle
;
184 //-----------------------------------------------------------------------------
185 // key event conversion routines
186 //-----------------------------------------------------------------------------
188 static long map_to_unmodified_wx_keysym( KeySym keysym
)
195 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
197 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
198 case GDK_Menu
: key_code
= WXK_MENU
; break;
199 case GDK_Help
: key_code
= WXK_HELP
; break;
200 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
201 case GDK_ISO_Left_Tab
:
202 case GDK_Tab
: key_code
= WXK_TAB
; break;
203 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
204 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
205 case GDK_Return
: key_code
= WXK_RETURN
; break;
206 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
207 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
208 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
209 case GDK_Delete
: key_code
= WXK_DELETE
; break;
210 case GDK_Home
: key_code
= WXK_HOME
; break;
211 case GDK_Left
: key_code
= WXK_LEFT
; break;
212 case GDK_Up
: key_code
= WXK_UP
; break;
213 case GDK_Right
: key_code
= WXK_RIGHT
; break;
214 case GDK_Down
: key_code
= WXK_DOWN
; break;
215 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
216 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
217 case GDK_Next
: key_code
= WXK_NEXT
; break;
218 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
219 case GDK_End
: key_code
= WXK_END
; break;
220 case GDK_Begin
: key_code
= WXK_HOME
; break;
221 case GDK_Select
: key_code
= WXK_SELECT
; break;
222 case GDK_Print
: key_code
= WXK_PRINT
; break;
223 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
224 case GDK_Insert
: key_code
= WXK_INSERT
; break;
225 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
227 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
228 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
229 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
230 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
231 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
232 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
233 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
234 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
235 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
236 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
237 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
238 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
239 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
240 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
241 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
242 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
243 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
244 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
245 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
246 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
247 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
248 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
249 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
250 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
251 case GDK_KP_Next
: key_code
= WXK_NUMPAD_PRIOR
; break;
252 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
253 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
254 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
255 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
256 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
257 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
258 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
259 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
260 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
261 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
262 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
263 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
265 case GDK_F1
: key_code
= WXK_F1
; break;
266 case GDK_F2
: key_code
= WXK_F2
; break;
267 case GDK_F3
: key_code
= WXK_F3
; break;
268 case GDK_F4
: key_code
= WXK_F4
; break;
269 case GDK_F5
: key_code
= WXK_F5
; break;
270 case GDK_F6
: key_code
= WXK_F6
; break;
271 case GDK_F7
: key_code
= WXK_F7
; break;
272 case GDK_F8
: key_code
= WXK_F8
; break;
273 case GDK_F9
: key_code
= WXK_F9
; break;
274 case GDK_F10
: key_code
= WXK_F10
; break;
275 case GDK_F11
: key_code
= WXK_F11
; break;
276 case GDK_F12
: key_code
= WXK_F12
; break;
281 guint upper
= gdk_keyval_to_upper( keysym
);
282 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
291 static long map_to_wx_keysym( KeySym keysym
)
297 case GDK_Menu
: key_code
= WXK_MENU
; break;
298 case GDK_Help
: key_code
= WXK_HELP
; break;
299 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
300 case GDK_ISO_Left_Tab
:
301 case GDK_Tab
: key_code
= WXK_TAB
; break;
302 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
303 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
304 case GDK_Return
: key_code
= WXK_RETURN
; break;
305 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
306 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
307 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
308 case GDK_Delete
: key_code
= WXK_DELETE
; break;
309 case GDK_Home
: key_code
= WXK_HOME
; break;
310 case GDK_Left
: key_code
= WXK_LEFT
; break;
311 case GDK_Up
: key_code
= WXK_UP
; break;
312 case GDK_Right
: key_code
= WXK_RIGHT
; break;
313 case GDK_Down
: key_code
= WXK_DOWN
; break;
314 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
315 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
316 case GDK_Next
: key_code
= WXK_NEXT
; break;
317 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
318 case GDK_End
: key_code
= WXK_END
; break;
319 case GDK_Begin
: key_code
= WXK_HOME
; break;
320 case GDK_Select
: key_code
= WXK_SELECT
; break;
321 case GDK_Print
: key_code
= WXK_PRINT
; break;
322 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
323 case GDK_Insert
: key_code
= WXK_INSERT
; break;
324 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
326 case GDK_KP_0
: key_code
= '0'; break;
327 case GDK_KP_1
: key_code
= '1'; break;
328 case GDK_KP_2
: key_code
= '2'; break;
329 case GDK_KP_3
: key_code
= '3'; break;
330 case GDK_KP_4
: key_code
= '4'; break;
331 case GDK_KP_5
: key_code
= '5'; break;
332 case GDK_KP_6
: key_code
= '6'; break;
333 case GDK_KP_7
: key_code
= '7'; break;
334 case GDK_KP_8
: key_code
= '8'; break;
335 case GDK_KP_9
: key_code
= '9'; break;
336 case GDK_KP_Space
: key_code
= ' '; break;
337 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
338 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
339 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
340 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
341 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
342 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
343 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
344 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
345 case GDK_KP_Up
: key_code
= WXK_UP
; break;
346 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
347 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
348 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
349 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
350 case GDK_KP_Next
: key_code
= WXK_PRIOR
; break;
351 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
352 case GDK_KP_End
: key_code
= WXK_END
; break;
353 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
354 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
355 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
356 case GDK_KP_Equal
: key_code
= '='; break;
357 case GDK_KP_Multiply
: key_code
= '*'; break;
358 case GDK_KP_Add
: key_code
= '+'; break;
359 case GDK_KP_Separator
: key_code
= ','; break;
360 case GDK_KP_Subtract
: key_code
= '-'; break;
361 case GDK_KP_Decimal
: key_code
= '.'; break;
362 case GDK_KP_Divide
: key_code
= '/'; break;
364 case GDK_F1
: key_code
= WXK_F1
; break;
365 case GDK_F2
: key_code
= WXK_F2
; break;
366 case GDK_F3
: key_code
= WXK_F3
; break;
367 case GDK_F4
: key_code
= WXK_F4
; break;
368 case GDK_F5
: key_code
= WXK_F5
; break;
369 case GDK_F6
: key_code
= WXK_F6
; break;
370 case GDK_F7
: key_code
= WXK_F7
; break;
371 case GDK_F8
: key_code
= WXK_F8
; break;
372 case GDK_F9
: key_code
= WXK_F9
; break;
373 case GDK_F10
: key_code
= WXK_F10
; break;
374 case GDK_F11
: key_code
= WXK_F11
; break;
375 case GDK_F12
: key_code
= WXK_F12
; break;
388 //-----------------------------------------------------------------------------
389 // local code (see below)
390 //-----------------------------------------------------------------------------
392 #if (GTK_MINOR_VERSION > 0)
394 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
402 if (win
->HasScrolling())
404 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
405 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
408 GtkWidget *hscrollbar = scroll_window->hscrollbar;
409 GtkWidget *vscrollbar = scroll_window->vscrollbar;
411 we use this instead: range.slider_width = 11 + 2*2pts edge
414 if (scroll_window
->vscrollbar_visible
)
416 dw
+= 15; /* dw += vscrollbar->allocation.width; */
417 dw
+= scroll_class
->scrollbar_spacing
;
420 if (scroll_window
->hscrollbar_visible
)
422 dh
+= 15; /* dh += hscrollbar->allocation.height; */
423 dw
+= scroll_class
->scrollbar_spacing
;
429 if (GTK_WIDGET_NO_WINDOW (widget
))
431 dx
+= widget
->allocation
.x
;
432 dy
+= widget
->allocation
.y
;
435 if (win
->HasFlag(wxRAISED_BORDER
))
437 gtk_draw_shadow( widget
->style
,
442 win
->m_width
-dw
, win
->m_height
-dh
);
446 if (win
->HasFlag(wxSUNKEN_BORDER
))
448 gtk_draw_shadow( widget
->style
,
453 win
->m_width
-dw
, win
->m_height
-dh
);
458 //-----------------------------------------------------------------------------
459 // "expose_event" of m_widget
460 //-----------------------------------------------------------------------------
462 static void gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
464 if (gdk_event
->count
> 0) return;
465 draw_frame( widget
, win
);
468 //-----------------------------------------------------------------------------
469 // "draw" of m_wxwindow
470 //-----------------------------------------------------------------------------
472 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
474 draw_frame( widget
, win
);
477 #endif // GTK_MINOR_VERSION > 0
479 //-----------------------------------------------------------------------------
480 // "expose_event" of m_wxwindow
481 //-----------------------------------------------------------------------------
483 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
485 if ( !win
->m_hasVMT
)
488 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
490 gdk_event
->area
.width
,
491 gdk_event
->area
.height
);
493 if ( gdk_event
->count
> 0 )
497 printf( "OnExpose from " );
498 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
499 printf( win->GetClassInfo()->GetClassName() );
503 wxPaintEvent
event( win
->GetId() );
504 event
.SetEventObject( win
);
505 win
->GetEventHandler()->ProcessEvent( event
);
507 win
->GetUpdateRegion().Clear();
510 //-----------------------------------------------------------------------------
511 // "draw" of m_wxwindow
512 //-----------------------------------------------------------------------------
514 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
517 wxapp_install_idle_handler();
522 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
523 rect
->width
, rect
->height
);
525 wxPaintEvent
event( win
->GetId() );
526 event
.SetEventObject( win
);
527 win
->GetEventHandler()->ProcessEvent( event
);
529 win
->GetUpdateRegion().Clear();
532 //-----------------------------------------------------------------------------
533 // "key_press_event" from any window
534 //-----------------------------------------------------------------------------
536 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
539 wxapp_install_idle_handler();
541 if (!win
->m_hasVMT
) return FALSE
;
542 if (g_blockEventsOnDrag
) return FALSE
;
545 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
546 if (gdk_event->state & GDK_SHIFT_MASK)
547 printf( "ShiftDown.\n" );
549 printf( "ShiftUp.\n" );
550 if (gdk_event->state & GDK_CONTROL_MASK)
551 printf( "ControlDown.\n" );
553 printf( "ControlUp.\n" );
559 GdkModifierType state
;
560 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
562 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
564 /* sending unknown key events doesn't really make sense */
565 if (key_code
== 0) return FALSE
;
569 wxKeyEvent
event( wxEVT_KEY_DOWN
);
570 event
.SetTimestamp( gdk_event
->time
);
571 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
572 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
573 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
574 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
575 event
.m_keyCode
= key_code
;
576 event
.m_scanCode
= gdk_event
->keyval
;
579 event
.SetEventObject( win
);
580 ret
= win
->GetEventHandler()->ProcessEvent( event
);
582 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
584 /* wxMSW doesn't send char events with Alt pressed */
585 if ((key_code
!= 0) &&
586 ((gdk_event
->state
& GDK_MOD1_MASK
) == 0) &&
587 ((gdk_event
->state
& GDK_MOD1_MASK
) == 0))
589 wxKeyEvent
event2( wxEVT_CHAR
);
590 event2
.SetTimestamp( gdk_event
->time
);
591 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
592 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
593 // event2.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
594 // event2.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
595 event2
.m_keyCode
= key_code
;
596 event2
.m_scanCode
= gdk_event
->keyval
;
599 event2
.SetEventObject( win
);
600 ret
= (ret
|| win
->GetEventHandler()->ProcessEvent( event2
));
605 wxWindow
*ancestor
= win
;
608 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
611 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
612 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
615 ancestor
= ancestor
->GetParent();
619 // win is a control: tab can be propagated up
621 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
622 (win
->HasFlag(wxTE_PROCESS_TAB
) == 0))
624 wxNavigationKeyEvent new_event
;
625 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
626 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
627 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
628 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
629 new_event
.SetCurrentFocus( win
);
630 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
634 (gdk_event
->keyval
== GDK_Escape
) )
636 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
637 new_event
.SetEventObject( win
);
638 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
642 Damn, I forgot why this didn't work, but it didn't work.
644 // win is a panel: up can be propagated to the panel
645 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
646 (gdk_event->keyval == GDK_Up))
648 win->m_parent->SetFocus();
652 // win is a panel: left/right can be propagated to the panel
653 if ((!ret) && (win->m_wxwindow) &&
654 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
655 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
657 wxNavigationKeyEvent new_event;
658 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
659 new_event.SetCurrentFocus( win );
660 ret = win->GetEventHandler()->ProcessEvent( new_event );
666 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
673 //-----------------------------------------------------------------------------
674 // "key_release_event" from any window
675 //-----------------------------------------------------------------------------
677 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
680 wxapp_install_idle_handler();
682 if (!win
->m_hasVMT
) return FALSE
;
683 if (g_blockEventsOnDrag
) return FALSE
;
686 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
687 if (gdk_event->state & GDK_SHIFT_MASK)
688 printf( "ShiftDown.\n" );
690 printf( "ShiftUp.\n" );
691 if (gdk_event->state & GDK_CONTROL_MASK)
692 printf( "ControlDown.\n" );
694 printf( "ControlUp.\n" );
698 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
700 /* sending unknown key events doesn't really make sense */
701 if (key_code
== 0) return FALSE
;
705 GdkModifierType state
;
706 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
708 wxKeyEvent
event( wxEVT_KEY_UP
);
709 event
.SetTimestamp( gdk_event
->time
);
710 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
711 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
712 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
713 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
714 event
.m_keyCode
= key_code
;
715 event
.m_scanCode
= gdk_event
->keyval
;
718 event
.SetEventObject( win
);
720 if (win
->GetEventHandler()->ProcessEvent( event
))
722 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
729 //-----------------------------------------------------------------------------
730 // "button_press_event"
731 //-----------------------------------------------------------------------------
733 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
736 wxapp_install_idle_handler();
739 wxPrintf( _T("1) OnButtonPress from ") );
740 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
741 wxPrintf( win->GetClassInfo()->GetClassName() );
742 wxPrintf( _T(".\n") );
744 if (!win
->m_hasVMT
) return FALSE
;
745 if (g_blockEventsOnDrag
) return TRUE
;
746 if (g_blockEventsOnScroll
) return TRUE
;
748 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
752 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
754 gtk_widget_grab_focus (win
->m_wxwindow
);
757 wxPrintf( _T("GrabFocus from ") );
758 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
759 wxPrintf( win->GetClassInfo()->GetClassName() );
760 wxPrintf( _T(".\n") );
767 wxPrintf( _T("2) OnButtonPress from ") );
768 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
769 wxPrintf( win->GetClassInfo()->GetClassName() );
770 wxPrintf( _T(".\n") );
773 wxEventType event_type
= wxEVT_LEFT_DOWN
;
775 if (gdk_event
->button
== 1)
777 switch (gdk_event
->type
)
779 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
780 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
784 else if (gdk_event
->button
== 2)
786 switch (gdk_event
->type
)
788 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
789 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
793 else if (gdk_event
->button
== 3)
795 switch (gdk_event
->type
)
797 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
798 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
803 wxMouseEvent
event( event_type
);
804 event
.SetTimestamp( gdk_event
->time
);
805 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
806 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
807 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
808 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
809 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
810 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
811 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
813 event
.m_x
= (long)gdk_event
->x
;
814 event
.m_y
= (long)gdk_event
->y
;
816 // Some control don't have their own X window and thus cannot get
821 wxNode
*node
= win
->GetChildren().First();
824 wxWindow
*child
= (wxWindow
*)node
->Data();
826 if (child
->m_isStaticBox
)
828 // wxStaticBox is transparent in the box itself
831 int xx1
= child
->m_x
;
832 int yy1
= child
->m_y
;
833 int xx2
= child
->m_x
+ child
->m_width
;
834 int yy2
= child
->m_x
+ child
->m_height
;
837 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
839 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
841 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
843 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
846 event
.m_x
-= child
->m_x
;
847 event
.m_y
-= child
->m_y
;
854 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
855 (child
->m_x
<= event
.m_x
) &&
856 (child
->m_y
<= event
.m_y
) &&
857 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
858 (child
->m_y
+child
->m_height
>= event
.m_y
))
861 event
.m_x
-= child
->m_x
;
862 event
.m_y
-= child
->m_y
;
870 event
.SetEventObject( win
);
872 gs_timeLastClick
= gdk_event
->time
;
874 if (win
->GetEventHandler()->ProcessEvent( event
))
876 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
883 //-----------------------------------------------------------------------------
884 // "button_release_event"
885 //-----------------------------------------------------------------------------
887 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
890 wxapp_install_idle_handler();
892 if (!win
->m_hasVMT
) return FALSE
;
893 if (g_blockEventsOnDrag
) return FALSE
;
894 if (g_blockEventsOnScroll
) return FALSE
;
896 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
899 printf( "OnButtonRelease from " );
900 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
901 printf( win->GetClassInfo()->GetClassName() );
905 wxEventType event_type
= wxEVT_NULL
;
907 switch (gdk_event
->button
)
909 case 1: event_type
= wxEVT_LEFT_UP
; break;
910 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
911 case 3: event_type
= wxEVT_RIGHT_UP
; break;
914 wxMouseEvent
event( event_type
);
915 event
.SetTimestamp( gdk_event
->time
);
916 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
917 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
918 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
919 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
920 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
921 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
922 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
923 event
.m_x
= (long)gdk_event
->x
;
924 event
.m_y
= (long)gdk_event
->y
;
926 // Some control don't have their own X window and thus cannot get
931 wxNode
*node
= win
->GetChildren().First();
934 wxWindow
*child
= (wxWindow
*)node
->Data();
936 if (child
->m_isStaticBox
)
938 // wxStaticBox is transparent in the box itself
941 int xx1
= child
->m_x
;
942 int yy1
= child
->m_y
;
943 int xx2
= child
->m_x
+ child
->m_width
;
944 int yy2
= child
->m_x
+ child
->m_height
;
947 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
949 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
951 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
953 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
956 event
.m_x
-= child
->m_x
;
957 event
.m_y
-= child
->m_y
;
964 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
965 (child
->m_x
<= event
.m_x
) &&
966 (child
->m_y
<= event
.m_y
) &&
967 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
968 (child
->m_y
+child
->m_height
>= event
.m_y
))
971 event
.m_x
-= child
->m_x
;
972 event
.m_y
-= child
->m_y
;
980 event
.SetEventObject( win
);
982 if (win
->GetEventHandler()->ProcessEvent( event
))
984 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
991 //-----------------------------------------------------------------------------
992 // "motion_notify_event"
993 //-----------------------------------------------------------------------------
995 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
998 wxapp_install_idle_handler();
1000 if (!win
->m_hasVMT
) return FALSE
;
1001 if (g_blockEventsOnDrag
) return FALSE
;
1002 if (g_blockEventsOnScroll
) return FALSE
;
1004 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1006 if (gdk_event
->is_hint
)
1010 GdkModifierType state
;
1011 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1014 gdk_event
->state
= state
;
1018 printf( "OnMotion from " );
1019 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1020 printf( win->GetClassInfo()->GetClassName() );
1024 wxMouseEvent
event( wxEVT_MOTION
);
1025 event
.SetTimestamp( gdk_event
->time
);
1026 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1027 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1028 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1029 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1030 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1031 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1032 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1034 event
.m_x
= (long)gdk_event
->x
;
1035 event
.m_y
= (long)gdk_event
->y
;
1037 // Some control don't have their own X window and thus cannot get
1042 wxNode
*node
= win
->GetChildren().First();
1045 wxWindow
*child
= (wxWindow
*)node
->Data();
1047 if (child
->m_isStaticBox
)
1049 // wxStaticBox is transparent in the box itself
1052 int xx1
= child
->m_x
;
1053 int yy1
= child
->m_y
;
1054 int xx2
= child
->m_x
+ child
->m_width
;
1055 int yy2
= child
->m_x
+ child
->m_height
;
1058 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1060 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1062 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1064 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1067 event
.m_x
-= child
->m_x
;
1068 event
.m_y
-= child
->m_y
;
1075 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1076 (child
->m_x
<= event
.m_x
) &&
1077 (child
->m_y
<= event
.m_y
) &&
1078 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
1079 (child
->m_y
+child
->m_height
>= event
.m_y
))
1082 event
.m_x
-= child
->m_x
;
1083 event
.m_y
-= child
->m_y
;
1087 node
= node
->Next();
1091 event
.SetEventObject( win
);
1093 if (win
->GetEventHandler()->ProcessEvent( event
))
1095 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1102 //-----------------------------------------------------------------------------
1104 //-----------------------------------------------------------------------------
1106 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1109 wxapp_install_idle_handler();
1111 if (!win
->m_hasVMT
) return FALSE
;
1112 if (g_blockEventsOnDrag
) return FALSE
;
1114 g_focusWindow
= win
;
1116 if (win
->m_wxwindow
)
1118 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1120 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1122 printf( "SetFocus flag from " );
1123 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1124 printf( win->GetClassInfo()->GetClassName() );
1132 printf( "OnSetFocus from " );
1133 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1134 printf( win->GetClassInfo()->GetClassName() );
1136 printf( WXSTRINGCAST win->GetLabel() );
1140 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1141 event
.SetEventObject( win
);
1143 if (win
->GetEventHandler()->ProcessEvent( event
))
1145 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1152 //-----------------------------------------------------------------------------
1153 // "focus_out_event"
1154 //-----------------------------------------------------------------------------
1156 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1159 wxapp_install_idle_handler();
1161 if (!win
->m_hasVMT
) return FALSE
;
1162 if (g_blockEventsOnDrag
) return FALSE
;
1164 if (win
->m_wxwindow
)
1166 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1167 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1171 printf( "OnKillFocus from " );
1172 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1173 printf( win->GetClassInfo()->GetClassName() );
1177 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1178 event
.SetEventObject( win
);
1180 if (win
->GetEventHandler()->ProcessEvent( event
))
1182 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1189 //-----------------------------------------------------------------------------
1190 // "enter_notify_event"
1191 //-----------------------------------------------------------------------------
1193 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1196 wxapp_install_idle_handler();
1198 if (!win
->m_hasVMT
) return FALSE
;
1199 if (g_blockEventsOnDrag
) return FALSE
;
1201 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1203 if (widget
->window
&& win
->GetCursor().Ok() )
1204 gdk_window_set_cursor( widget
->window
, win
->GetCursor().GetCursor() );
1206 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1207 event
.SetTimestamp( gdk_event
->time
);
1208 event
.SetEventObject( win
);
1212 GdkModifierType state
= (GdkModifierType
)0;
1214 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1216 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1217 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1218 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1219 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1220 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1221 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1222 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1224 event
.m_x
= (long)x
;
1225 event
.m_y
= (long)y
;
1227 if (win
->GetEventHandler()->ProcessEvent( event
))
1229 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1236 //-----------------------------------------------------------------------------
1237 // "leave_notify_event"
1238 //-----------------------------------------------------------------------------
1240 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1243 wxapp_install_idle_handler();
1245 if (!win
->m_hasVMT
) return FALSE
;
1246 if (g_blockEventsOnDrag
) return FALSE
;
1248 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1250 if (widget
->window
&& win
->GetCursor().Ok() )
1251 gdk_window_set_cursor( widget
->window
, wxSTANDARD_CURSOR
->GetCursor() );
1253 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1254 event
.SetTimestamp( gdk_event
->time
);
1255 event
.SetEventObject( win
);
1259 GdkModifierType state
= (GdkModifierType
)0;
1261 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1263 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1264 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1265 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1266 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1267 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1268 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1269 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1271 event
.m_x
= (long)x
;
1272 event
.m_y
= (long)y
;
1274 if (win
->GetEventHandler()->ProcessEvent( event
))
1276 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1283 //-----------------------------------------------------------------------------
1284 // "value_changed" from m_vAdjust
1285 //-----------------------------------------------------------------------------
1287 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1290 wxapp_install_idle_handler();
1292 if (g_blockEventsOnDrag
) return;
1294 if (!win
->m_hasVMT
) return;
1296 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
1297 if (fabs(diff
) < 0.2) return;
1298 win
->m_oldVerticalPos
= win
->m_vAdjust
->value
;
1300 wxEventType command
= wxEVT_NULL
;
1302 float line_step
= win
->m_vAdjust
->step_increment
;
1303 float page_step
= win
->m_vAdjust
->page_increment
;
1305 if (win
->IsScrolling())
1307 command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1311 if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->lower
) < 0.2) command
= wxEVT_SCROLLWIN_BOTTOM
;
1312 else if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->upper
) < 0.2) command
= wxEVT_SCROLLWIN_TOP
;
1313 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1314 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEUP
;
1315 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1316 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEUP
;
1317 else command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1320 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1322 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1323 event
.SetEventObject( win
);
1324 win
->GetEventHandler()->ProcessEvent( event
);
1327 //-----------------------------------------------------------------------------
1328 // "value_changed" from m_hAdjust
1329 //-----------------------------------------------------------------------------
1331 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1334 wxapp_install_idle_handler();
1336 if (g_blockEventsOnDrag
) return;
1337 if (!win
->m_hasVMT
) return;
1339 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
1340 if (fabs(diff
) < 0.2) return;
1341 win
->m_oldHorizontalPos
= win
->m_hAdjust
->value
;
1343 wxEventType command
= wxEVT_NULL
;
1345 float line_step
= win
->m_hAdjust
->step_increment
;
1346 float page_step
= win
->m_hAdjust
->page_increment
;
1348 if (win
->IsScrolling())
1350 command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1354 if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->lower
) < 0.2) command
= wxEVT_SCROLLWIN_BOTTOM
;
1355 else if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->upper
) < 0.2) command
= wxEVT_SCROLLWIN_TOP
;
1356 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1357 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEUP
;
1358 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1359 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEUP
;
1360 else command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1363 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1365 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1366 event
.SetEventObject( win
);
1367 win
->GetEventHandler()->ProcessEvent( event
);
1370 //-----------------------------------------------------------------------------
1371 // "changed" from m_vAdjust
1372 //-----------------------------------------------------------------------------
1374 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1377 wxapp_install_idle_handler();
1379 if (g_blockEventsOnDrag
) return;
1380 if (!win
->m_hasVMT
) return;
1382 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1383 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1385 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1386 event
.SetEventObject( win
);
1387 win
->GetEventHandler()->ProcessEvent( event
);
1390 //-----------------------------------------------------------------------------
1391 // "changed" from m_hAdjust
1392 //-----------------------------------------------------------------------------
1394 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1397 wxapp_install_idle_handler();
1399 if (g_blockEventsOnDrag
) return;
1400 if (!win
->m_hasVMT
) return;
1402 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1403 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1405 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1406 event
.SetEventObject( win
);
1407 win
->GetEventHandler()->ProcessEvent( event
);
1410 //-----------------------------------------------------------------------------
1411 // "button_press_event" from scrollbar
1412 //-----------------------------------------------------------------------------
1414 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1415 GdkEventButton
*WXUNUSED(gdk_event
),
1419 wxapp_install_idle_handler();
1421 // don't test here as we can release the mouse while being over
1422 // a different window then the slider
1424 // if (gdk_event->window != widget->slider) return FALSE;
1426 win
->SetScrolling( TRUE
);
1431 //-----------------------------------------------------------------------------
1432 // "button_release_event" from scrollbar
1433 //-----------------------------------------------------------------------------
1435 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1436 GdkEventButton
*WXUNUSED(gdk_event
),
1440 // don't test here as we can release the mouse while being over
1441 // a different window then the slider
1443 // if (gdk_event->window != widget->slider) return FALSE;
1445 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1447 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1448 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_hAdjust
), "value_changed" );
1450 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_vAdjust
), "value_changed" );
1452 win
->SetScrolling( FALSE
);
1457 // ----------------------------------------------------------------------------
1458 // this wxWindowBase function is implemented here (in platform-specific file)
1459 // because it is static and so couldn't be made virtual
1460 // ----------------------------------------------------------------------------
1462 wxWindow
*wxWindowBase::FindFocus()
1464 return g_focusWindow
;
1467 //-----------------------------------------------------------------------------
1468 // "realize" from m_widget
1469 //-----------------------------------------------------------------------------
1471 /* we cannot set colours, fonts and cursors before the widget has
1472 been realized, so we do this directly after realization */
1475 gtk_window_realized_callback( GtkWidget
* WXUNUSED(widget
), wxWindow
*win
)
1478 wxapp_install_idle_handler();
1480 if (win
->m_delayedFont
)
1481 win
->SetFont( win
->GetFont() );
1483 if (win
->m_delayedBackgroundColour
)
1484 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1486 if (win
->m_delayedForegroundColour
)
1487 win
->SetForegroundColour( win
->GetForegroundColour() );
1489 win
->SetCursor( win
->GetCursor() );
1494 //-----------------------------------------------------------------------------
1495 // InsertChild for wxWindow.
1496 //-----------------------------------------------------------------------------
1498 /* Callback for wxWindow. This very strange beast has to be used because
1499 * C++ has no virtual methods in a constructor. We have to emulate a
1500 * virtual function here as wxNotebook requires a different way to insert
1501 * a child in it. I had opted for creating a wxNotebookPage window class
1502 * which would have made this superfluous (such in the MDI window system),
1503 * but no-one was listening to me... */
1505 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1507 gtk_myfixed_put( GTK_MYFIXED(parent
->m_wxwindow
),
1508 GTK_WIDGET(child
->m_widget
),
1514 if (parent
->HasFlag(wxTAB_TRAVERSAL
))
1516 /* we now allow a window to get the focus as long as it
1517 doesn't have any children. */
1518 GTK_WIDGET_UNSET_FLAGS( parent
->m_wxwindow
, GTK_CAN_FOCUS
);
1522 //-----------------------------------------------------------------------------
1524 //-----------------------------------------------------------------------------
1526 wxWindow
* wxGetActiveWindow()
1528 return g_focusWindow
;
1531 //-----------------------------------------------------------------------------
1533 //-----------------------------------------------------------------------------
1535 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1537 void wxWindow::Init()
1543 m_widget
= (GtkWidget
*) NULL
;
1544 m_wxwindow
= (GtkWidget
*) NULL
;
1554 m_needParent
= TRUE
;
1555 m_isBeingDeleted
= FALSE
;
1557 m_hasScrolling
= FALSE
;
1558 m_isScrolling
= FALSE
;
1560 m_hAdjust
= (GtkAdjustment
*) NULL
;
1561 m_vAdjust
= (GtkAdjustment
*) NULL
;
1562 m_oldHorizontalPos
= 0.0;
1563 m_oldVerticalPos
= 0.0;
1566 m_scrollGC
= (GdkGC
*) NULL
;
1567 m_widgetStyle
= (GtkStyle
*) NULL
;
1569 m_insertCallback
= wxInsertChildInWindow
;
1571 m_isStaticBox
= FALSE
;
1572 m_acceptsFocus
= FALSE
;
1575 wxWindow::wxWindow()
1580 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1581 const wxPoint
&pos
, const wxSize
&size
,
1582 long style
, const wxString
&name
)
1586 Create( parent
, id
, pos
, size
, style
, name
);
1589 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1590 const wxPoint
&pos
, const wxSize
&size
,
1591 long style
, const wxString
&name
)
1593 PreCreation( parent
, id
, pos
, size
, style
, name
);
1595 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1596 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1599 debug_focus_in( m_widget
, _T("wxWindow::m_widget"), name
);
1602 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1605 debug_focus_in( scrolledWindow
->hscrollbar
, _T("wxWindow::hsrcollbar"), name
);
1606 debug_focus_in( scrolledWindow
->vscrollbar
, _T("wxWindow::vsrcollbar"), name
);
1609 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1610 scroll_class
->scrollbar_spacing
= 0;
1612 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1614 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
1615 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
1617 m_wxwindow
= gtk_myfixed_new();
1620 debug_focus_in( m_wxwindow
, _T("wxWindow::m_wxwindow"), name
);
1623 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1625 #if (GTK_MINOR_VERSION > 0)
1626 GtkMyFixed
*myfixed
= GTK_MYFIXED(m_wxwindow
);
1628 if (HasFlag(wxRAISED_BORDER
))
1630 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_OUT
);
1632 else if (HasFlag(wxSUNKEN_BORDER
))
1634 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_IN
);
1638 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_NONE
);
1640 #else // GTK_MINOR_VERSION == 0
1641 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
1643 if (HasFlag(wxRAISED_BORDER
))
1645 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1647 else if (HasFlag(wxSUNKEN_BORDER
))
1649 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1653 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1655 #endif // GTK_MINOR_VERSION
1657 if (HasFlag(wxTAB_TRAVERSAL
))
1659 /* we now allow a window to get the focus as long as it
1660 doesn't have any children. */
1661 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1662 m_acceptsFocus
= FALSE
;
1666 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1667 m_acceptsFocus
= TRUE
;
1670 #if (GTK_MINOR_VERSION == 0)
1671 // shut the viewport up
1672 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1673 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1674 #endif // GTK_MINOR_VERSION == 0
1676 // I _really_ don't want scrollbars in the beginning
1677 m_vAdjust
->lower
= 0.0;
1678 m_vAdjust
->upper
= 1.0;
1679 m_vAdjust
->value
= 0.0;
1680 m_vAdjust
->step_increment
= 1.0;
1681 m_vAdjust
->page_increment
= 1.0;
1682 m_vAdjust
->page_size
= 5.0;
1683 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1684 m_hAdjust
->lower
= 0.0;
1685 m_hAdjust
->upper
= 1.0;
1686 m_hAdjust
->value
= 0.0;
1687 m_hAdjust
->step_increment
= 1.0;
1688 m_hAdjust
->page_increment
= 1.0;
1689 m_hAdjust
->page_size
= 5.0;
1690 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1692 // these handlers block mouse events to any window during scrolling such as
1693 // motion events and prevent GTK and wxWindows from fighting over where the
1696 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
1697 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1699 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
1700 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1702 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
1703 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1705 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
1706 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1708 // these handlers get notified when screen updates are required either when
1709 // scrolling or when the window size (and therefore scrollbar configuration)
1712 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
1713 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
1714 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
1715 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
1717 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
1718 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
1719 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
1720 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
1722 gtk_widget_show( m_wxwindow
);
1725 m_parent
->DoAddChild( this );
1734 wxWindow::~wxWindow()
1736 m_isBeingDeleted
= TRUE
;
1745 m_parent
->RemoveChild( this );
1749 gtk_style_unref( m_widgetStyle
);
1750 m_widgetStyle
= (GtkStyle
*) NULL
;
1755 gdk_gc_unref( m_scrollGC
);
1756 m_scrollGC
= (GdkGC
*) NULL
;
1761 gtk_widget_destroy( m_wxwindow
);
1762 m_wxwindow
= (GtkWidget
*) NULL
;
1767 gtk_widget_destroy( m_widget
);
1768 m_widget
= (GtkWidget
*) NULL
;
1772 void wxWindow::PreCreation( wxWindow
*parent
,
1777 const wxString
&name
)
1779 wxASSERT_MSG( !m_needParent
|| parent
, _T("Need complete parent.") );
1781 if ( !CreateBase(parent
, id
, pos
, size
, style
, name
) )
1783 wxFAIL_MSG(_T("window creation failed"));
1786 m_width
= WidthDefault(size
.x
);
1787 m_height
= HeightDefault(size
.y
);
1792 if (!parent
) /* some reasonable defaults */
1796 m_x
= (gdk_screen_width () - m_width
) / 2;
1797 if (m_x
< 10) m_x
= 10;
1801 m_y
= (gdk_screen_height () - m_height
) / 2;
1802 if (m_y
< 10) m_y
= 10;
1807 void wxWindow::PostCreation()
1809 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1813 /* these get reported to wxWindows -> wxPaintEvent */
1814 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1815 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1817 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1818 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1820 #if (GTK_MINOR_VERSION > 0)
1821 /* these are called when the "sunken" or "raised" borders are drawn */
1822 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
1823 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
1825 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
1826 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
1830 GtkWidget
*connect_widget
= GetConnectWidget();
1832 ConnectWidget( connect_widget
);
1834 /* we cannot set colours, fonts and cursors before the widget has
1835 been realized, so we do this directly after realization */
1836 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
1837 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
1842 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1844 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1845 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1847 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
1848 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
1850 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1851 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1853 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1854 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1856 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1857 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1859 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1860 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1862 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1863 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1865 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1866 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1868 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1869 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1872 bool wxWindow::Destroy()
1874 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1878 return wxWindowBase::Destroy();
1881 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1883 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1884 wxASSERT_MSG( (m_parent
!= NULL
), _T("wxWindow::SetSize requires parent.\n") );
1886 if (m_resizing
) return; /* I don't like recursions */
1889 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
1891 /* don't set the size for children of wxNotebook, just take the values. */
1899 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1901 if (x
!= -1) m_x
= x
;
1902 if (y
!= -1) m_y
= y
;
1903 if (width
!= -1) m_width
= width
;
1904 if (height
!= -1) m_height
= height
;
1914 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1916 if (width
== -1) m_width
= 80;
1919 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1921 if (height
== -1) m_height
= 26;
1924 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1925 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1926 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
1927 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
1931 if (GTK_WIDGET_HAS_DEFAULT(m_widget
))
1933 /* the default button has a border around it */
1937 /* this is the result of hours of debugging: the following code
1938 means that if we have a m_wxwindow and we set the size of
1939 m_widget, m_widget (which is a GtkScrolledWindow) does NOT
1940 automatically propagate its size down to its m_wxwindow,
1941 which is its client area. therefore, we have to tell the
1942 client area directly that it has to resize itself.
1943 this will lead to that m_widget (GtkScrolledWindow) will
1944 calculate how much size it needs for scrollbars etc and
1945 it will then call XXX_size_allocate of its child, which
1946 is m_wxwindow. m_wxwindow in turn will do the same with its
1947 children and so on. problems can arise if this happens
1948 before all the children have been realized as some widgets
1949 stupidy need to be realized during XXX_size_allocate (e.g.
1950 GtkNotebook) and they will segv if called otherwise. this
1951 emergency is tested in gtk_myfixed_size_allocate. Normally
1952 this shouldn't be needed and only gtk_widget_queue_resize()
1953 should be enough to provoke a resize at the next appropriate
1954 moment, but this seems to fail, e.g. when a wxNotebook contains
1955 a wxSplitterWindow: the splitter window's children won't
1956 show up properly resized then. */
1958 gtk_myfixed_set_size( GTK_MYFIXED(m_parent
->m_wxwindow
),
1963 m_height
+2*border
);
1968 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1969 event
.SetEventObject( this );
1970 GetEventHandler()->ProcessEvent( event
);
1975 void wxWindow::OnInternalIdle()
1980 void wxWindow::DoGetSize( int *width
, int *height
) const
1982 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
1984 if (width
) (*width
) = m_width
;
1985 if (height
) (*height
) = m_height
;
1988 void wxWindow::DoSetClientSize( int width
, int height
)
1990 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
1994 SetSize( width
, height
);
2001 if (!m_hasScrolling
)
2003 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
2005 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2007 dw
+= 2 * window_class
->xthickness
;
2008 dh
+= 2 * window_class
->ythickness
;
2013 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2014 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2016 #if (GTK_MINOR_VERSION == 0)
2017 GtkWidget
*viewport
= scroll_window
->viewport
;
2018 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2020 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2022 dw
+= 2 * viewport_class
->xthickness
;
2023 dh
+= 2 * viewport_class
->ythickness
;
2028 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2029 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2031 we use this instead: range.slider_width = 11 + 2*2pts edge
2034 if (scroll_window
->vscrollbar_visible
)
2036 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2037 dw
+= scroll_class
->scrollbar_spacing
;
2040 if (scroll_window
->hscrollbar_visible
)
2042 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2043 dw
+= scroll_class
->scrollbar_spacing
;
2047 SetSize( width
+dw
, height
+dh
);
2051 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2053 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2057 if (width
) (*width
) = m_width
;
2058 if (height
) (*height
) = m_height
;
2065 if (!m_hasScrolling
)
2067 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
2069 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2071 dw
+= 2 * window_class
->xthickness
;
2072 dh
+= 2 * window_class
->ythickness
;
2077 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2078 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2080 #if (GTK_MINOR_VERSION == 0)
2081 GtkWidget
*viewport
= scroll_window
->viewport
;
2082 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2084 if ( HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
) )
2086 dw
+= 2 * viewport_class
->xthickness
;
2087 dh
+= 2 * viewport_class
->ythickness
;
2091 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2092 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2094 we use this instead: range.slider_width = 11 + 2*2pts edge
2097 if (scroll_window
->vscrollbar_visible
)
2099 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2100 dw
+= scroll_class
->scrollbar_spacing
;
2103 if (scroll_window
->hscrollbar_visible
)
2105 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2106 dh
+= scroll_class
->scrollbar_spacing
;
2110 if (width
) (*width
) = m_width
- dw
;
2111 if (height
) (*height
) = m_height
- dh
;
2115 void wxWindow::DoGetPosition( int *x
, int *y
) const
2117 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2123 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2125 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2127 if (!m_widget
->window
) return;
2129 GdkWindow
*source
= (GdkWindow
*) NULL
;
2131 source
= m_wxwindow
->window
;
2133 source
= m_widget
->window
;
2137 gdk_window_get_origin( source
, &org_x
, &org_y
);
2141 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2143 org_x
+= m_widget
->allocation
.x
;
2144 org_y
+= m_widget
->allocation
.y
;
2152 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2154 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2156 if (!m_widget
->window
) return;
2158 GdkWindow
*source
= (GdkWindow
*) NULL
;
2160 source
= m_wxwindow
->window
;
2162 source
= m_widget
->window
;
2166 gdk_window_get_origin( source
, &org_x
, &org_y
);
2170 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2172 org_x
+= m_widget
->allocation
.x
;
2173 org_y
+= m_widget
->allocation
.y
;
2181 bool wxWindow::Show( bool show
)
2183 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2185 if (!wxWindowBase::Show(show
))
2192 gtk_widget_show( m_widget
);
2194 gtk_widget_hide( m_widget
);
2199 bool wxWindow::Enable( bool enable
)
2201 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2203 if (!wxWindowBase::Enable(enable
))
2209 gtk_widget_set_sensitive( m_widget
, enable
);
2211 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2216 int wxWindow::GetCharHeight() const
2218 wxCHECK_MSG( (m_widget
!= NULL
), 12, _T("invalid window") );
2220 wxCHECK_MSG( m_font
.Ok(), 12, _T("invalid font") );
2222 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2224 return font
->ascent
+ font
->descent
;
2227 int wxWindow::GetCharWidth() const
2229 wxCHECK_MSG( (m_widget
!= NULL
), 8, _T("invalid window") );
2231 wxCHECK_MSG( m_font
.Ok(), 8, _T("invalid font") );
2233 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2235 return gdk_string_width( font
, "H" );
2238 void wxWindow::GetTextExtent( const wxString
& string
,
2242 int *externalLeading
,
2243 const wxFont
*theFont
) const
2245 wxFont fontToUse
= m_font
;
2246 if (theFont
) fontToUse
= *theFont
;
2248 wxCHECK_RET( fontToUse
.Ok(), _T("invalid font") );
2250 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2251 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2252 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2253 if (descent
) (*descent
) = font
->descent
;
2254 if (externalLeading
) (*externalLeading
) = 0; // ??
2257 void wxWindow::SetFocus()
2259 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2261 GtkWidget
*connect_widget
= GetConnectWidget();
2264 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2266 gtk_widget_grab_focus (connect_widget
);
2268 else if (GTK_IS_CONTAINER(connect_widget
))
2270 gtk_container_focus( GTK_CONTAINER(connect_widget
), GTK_DIR_TAB_FORWARD
);
2278 bool wxWindow::AcceptsFocus() const
2280 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2283 bool wxWindow::Reparent( wxWindow
*newParent
)
2285 wxCHECK_MSG( (m_widget
!= NULL
), (wxWindow
*) NULL
, _T("invalid window") );
2287 gtk_widget_unparent( m_widget
);
2289 if ( !wxWindowBase::Reparent(newParent
) )
2295 void wxWindow::Raise()
2297 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2299 if (!m_widget
->window
) return;
2301 gdk_window_raise( m_widget
->window
);
2304 void wxWindow::Lower()
2306 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2308 if (!m_widget
->window
) return;
2310 gdk_window_lower( m_widget
->window
);
2313 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2315 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2317 if (!wxWindowBase::SetCursor(cursor
))
2319 // don't leave if the GTK widget has just
2321 if (!m_delayedCursor
) return FALSE
;
2324 GtkWidget
*connect_widget
= GetConnectWidget();
2325 if (!connect_widget
->window
)
2327 // indicate that a new style has been set
2328 // but it couldn't get applied as the
2329 // widget hasn't been realized yet.
2330 m_delayedCursor
= TRUE
;
2332 // pretend we have done something
2336 if ((m_widget
) && (m_widget
->window
))
2337 gdk_window_set_cursor( m_widget
->window
, GetCursor().GetCursor() );
2339 if ((m_wxwindow
) && (m_wxwindow
->window
))
2340 gdk_window_set_cursor( m_wxwindow
->window
, GetCursor().GetCursor() );
2346 void wxWindow::WarpPointer( int WXUNUSED(x
), int WXUNUSED(y
) )
2351 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2353 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2355 if (!m_widget
->window
) return;
2357 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2361 gdk_window_clear_area( m_wxwindow
->window
,
2363 rect
->width
, rect
->height
);
2367 gdk_window_clear( m_wxwindow
->window
);
2374 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2376 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2380 GdkRectangle gdk_rect
;
2381 gdk_rect
.x
= rect
->x
;
2382 gdk_rect
.y
= rect
->y
;
2383 gdk_rect
.width
= rect
->width
;
2384 gdk_rect
.height
= rect
->height
;
2387 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2389 gtk_widget_draw( m_widget
, &gdk_rect
);
2393 void wxWindow::Clear()
2395 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2397 if (!m_widget
->window
) return;
2399 if (m_wxwindow
&& m_wxwindow
->window
)
2401 gdk_window_clear( m_wxwindow
->window
);
2406 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2408 wxWindowBase::DoSetToolTip(tip
);
2411 m_tooltip
->Apply( this );
2414 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2416 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConv_current
->cWX2MB(tip
), (gchar
*) NULL
);
2418 #endif // wxUSE_TOOLTIPS
2420 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2422 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2424 if (!wxWindowBase::SetBackgroundColour(colour
))
2426 // don't leave if the GTK widget has just
2428 if (!m_delayedBackgroundColour
) return FALSE
;
2431 GtkWidget
*connect_widget
= GetConnectWidget();
2432 if (!connect_widget
->window
)
2434 // indicate that a new style has been set
2435 // but it couldn't get applied as the
2436 // widget hasn't been realized yet.
2437 m_delayedBackgroundColour
= TRUE
;
2439 // pretend we have done something
2443 if (m_wxwindow
&& m_wxwindow
->window
)
2445 /* wxMSW doesn't clear the window here. I don't do that either to
2446 provide compatibility. call Clear() to do the job. */
2448 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_wxwindow
->window
) );
2449 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
2452 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2454 if (sysbg
== m_backgroundColour
)
2456 m_backgroundColour
= wxNullColour
;
2458 m_backgroundColour
= sysbg
;
2468 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2470 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2472 if (!wxWindowBase::SetForegroundColour(colour
))
2474 // don't leave if the GTK widget has just
2476 if (!m_delayedForegroundColour
) return FALSE
;
2479 GtkWidget
*connect_widget
= GetConnectWidget();
2480 if (!connect_widget
->window
)
2482 // indicate that a new style has been set
2483 // but it couldn't get applied as the
2484 // widget hasn't been realized yet.
2485 m_delayedForegroundColour
= TRUE
;
2487 // pretend we have done something
2491 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2492 if (sysbg
== m_foregroundColour
)
2494 m_backgroundColour
= wxNullColour
;
2496 m_backgroundColour
= sysbg
;
2506 GtkStyle
*wxWindow::GetWidgetStyle()
2508 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2510 m_widgetStyle
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2512 return m_widgetStyle
;
2515 void wxWindow::SetWidgetStyle()
2517 GtkStyle
*style
= GetWidgetStyle();
2519 gdk_font_unref( style
->font
);
2520 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2522 if (m_foregroundColour
.Ok())
2524 m_foregroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2525 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2526 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2527 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2530 if (m_backgroundColour
.Ok())
2532 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2533 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2534 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2535 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2536 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2537 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2538 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2539 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2540 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2544 void wxWindow::ApplyWidgetStyle()
2548 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2550 menu
->SetInvokingWindow( win
);
2551 wxNode
*node
= menu
->GetItems().First();
2554 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2555 if (menuitem
->IsSubMenu())
2557 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2559 node
= node
->Next();
2563 static gint gs_pop_x
= 0;
2564 static gint gs_pop_y
= 0;
2566 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
2570 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
2575 bool wxWindow::PopupMenu( wxMenu
*menu
, int x
, int y
)
2577 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2579 wxCHECK_MSG( menu
!= NULL
, FALSE
, _T("invalid popup-menu") );
2581 SetInvokingWindow( menu
, this );
2589 GTK_MENU(menu
->m_menu
),
2590 (GtkWidget
*) NULL
, // parent menu shell
2591 (GtkWidget
*) NULL
, // parent menu item
2592 (GtkMenuPositionFunc
) pop_pos_callback
,
2593 (gpointer
) this, // client data
2594 0, // button used to activate it
2595 0 //gs_timeLastClick // the time of activation
2600 #if wxUSE_DRAG_AND_DROP
2602 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2604 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2606 GtkWidget
*dnd_widget
= GetConnectWidget();
2608 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
2610 if (m_dropTarget
) delete m_dropTarget
;
2611 m_dropTarget
= dropTarget
;
2613 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
2616 #endif // wxUSE_DRAG_AND_DROP
2618 GtkWidget
* wxWindow::GetConnectWidget()
2620 GtkWidget
*connect_widget
= m_widget
;
2621 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2623 return connect_widget
;
2626 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2628 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2629 return (window
== m_widget
->window
);
2632 bool wxWindow::SetFont( const wxFont
&font
)
2634 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T( "invalid window") );
2636 if (!wxWindowBase::SetFont(font
))
2638 // don't leave if the GTK widget has just
2640 if (!m_delayedFont
) return FALSE
;
2643 GtkWidget
*connect_widget
= GetConnectWidget();
2644 if (!connect_widget
->window
)
2646 // indicate that a new style has been set
2647 // but it couldn't get applied as the
2648 // widget hasn't been realized yet.
2649 m_delayedFont
= TRUE
;
2651 // pretend we have done something
2655 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2656 if ( sysbg
== m_backgroundColour
)
2658 m_backgroundColour
= wxNullColour
;
2660 m_backgroundColour
= sysbg
;
2670 void wxWindow::CaptureMouse()
2672 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2674 wxCHECK_RET( g_capturing
== FALSE
, _T("CaptureMouse called twice") );
2676 GtkWidget
*connect_widget
= GetConnectWidget();
2677 if (!connect_widget
->window
) return;
2679 gtk_grab_add( connect_widget
);
2680 gdk_pointer_grab( connect_widget
->window
, FALSE
,
2682 (GDK_BUTTON_PRESS_MASK
|
2683 GDK_BUTTON_RELEASE_MASK
|
2684 GDK_POINTER_MOTION_MASK
),
2691 void wxWindow::ReleaseMouse()
2693 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2695 wxCHECK_RET( g_capturing
== TRUE
, _T("ReleaseMouse called twice") );
2697 GtkWidget
*connect_widget
= GetConnectWidget();
2698 if (!connect_widget
->window
) return;
2700 gtk_grab_remove( connect_widget
);
2701 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2702 g_capturing
= FALSE
;
2705 bool wxWindow::IsRetained() const
2710 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2711 int range
, bool refresh
)
2713 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2715 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2717 m_hasScrolling
= TRUE
;
2719 if (orient
== wxHORIZONTAL
)
2721 float fpos
= (float)pos
;
2722 float frange
= (float)range
;
2723 float fthumb
= (float)thumbVisible
;
2724 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2725 if (fpos
< 0.0) fpos
= 0.0;
2727 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2728 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2730 SetScrollPos( orient
, pos
, refresh
);
2734 m_oldHorizontalPos
= fpos
;
2736 m_hAdjust
->lower
= 0.0;
2737 m_hAdjust
->upper
= frange
;
2738 m_hAdjust
->value
= fpos
;
2739 m_hAdjust
->step_increment
= 1.0;
2740 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2741 m_hAdjust
->page_size
= fthumb
;
2745 float fpos
= (float)pos
;
2746 float frange
= (float)range
;
2747 float fthumb
= (float)thumbVisible
;
2748 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2749 if (fpos
< 0.0) fpos
= 0.0;
2751 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2752 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2754 SetScrollPos( orient
, pos
, refresh
);
2758 m_oldVerticalPos
= fpos
;
2760 m_vAdjust
->lower
= 0.0;
2761 m_vAdjust
->upper
= frange
;
2762 m_vAdjust
->value
= fpos
;
2763 m_vAdjust
->step_increment
= 1.0;
2764 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2765 m_vAdjust
->page_size
= fthumb
;
2768 if (orient
== wxHORIZONTAL
)
2769 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2771 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2774 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2776 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2778 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2780 if (orient
== wxHORIZONTAL
)
2782 float fpos
= (float)pos
;
2783 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
2784 if (fpos
< 0.0) fpos
= 0.0;
2785 m_oldHorizontalPos
= fpos
;
2787 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2788 m_hAdjust
->value
= fpos
;
2792 float fpos
= (float)pos
;
2793 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
2794 if (fpos
< 0.0) fpos
= 0.0;
2795 m_oldVerticalPos
= fpos
;
2797 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2798 m_vAdjust
->value
= fpos
;
2801 if (!m_isScrolling
) /* prevent recursion */
2803 if (m_wxwindow
->window
)
2805 if (orient
== wxHORIZONTAL
)
2806 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2808 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2813 int wxWindow::GetScrollThumb( int orient
) const
2815 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2817 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2819 if (orient
== wxHORIZONTAL
)
2820 return (int)(m_hAdjust
->page_size
+0.5);
2822 return (int)(m_vAdjust
->page_size
+0.5);
2825 int wxWindow::GetScrollPos( int orient
) const
2827 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2829 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2831 if (orient
== wxHORIZONTAL
)
2832 return (int)(m_hAdjust
->value
+0.5);
2834 return (int)(m_vAdjust
->value
+0.5);
2837 int wxWindow::GetScrollRange( int orient
) const
2839 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2841 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2843 if (orient
== wxHORIZONTAL
)
2844 return (int)(m_hAdjust
->upper
+0.5);
2846 return (int)(m_vAdjust
->upper
+0.5);
2849 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2851 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2853 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2857 m_scrollGC
= gdk_gc_new( m_wxwindow
->window
);
2858 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
2863 GetClientSize( &cw
, &ch
);
2864 int w
= cw
- abs(dx
);
2865 int h
= ch
- abs(dy
);
2867 if ((h
< 0) || (w
< 0))
2875 if (dx
< 0) s_x
= -dx
;
2876 if (dy
< 0) s_y
= -dy
;
2879 if (dx
> 0) d_x
= dx
;
2880 if (dy
> 0) d_y
= dy
;
2882 gdk_window_copy_area( m_wxwindow
->window
, m_scrollGC
, d_x
, d_y
,
2883 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2886 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2887 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2888 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2889 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2891 Refresh( TRUE
, &rect
);
2894 wxNode
*node
= m_children
.First();
2897 wxWindow
*child
= (wxWindow
*) node
->Data();
2898 child
->Move( child
->m_x
+ dx
, child
->m_y
+ dy
);
2899 node
= node
->Next();
2903 void wxWindow::SetScrolling(bool scroll
)
2905 m_isScrolling
= g_blockEventsOnScroll
= scroll
;