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_NEXT
; 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_NEXT
; 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 dh
+= 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" );
558 GdkModifierType state
;
559 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
561 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
563 /* sending unknown key events doesn't really make sense */
564 if (key_code
== 0) return FALSE
;
568 wxKeyEvent
event( wxEVT_KEY_DOWN
);
569 event
.SetTimestamp( gdk_event
->time
);
570 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
571 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
572 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
573 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
574 event
.m_keyCode
= key_code
;
575 event
.m_scanCode
= gdk_event
->keyval
;
578 event
.SetEventObject( win
);
579 ret
= win
->GetEventHandler()->ProcessEvent( event
);
581 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
583 /* wxMSW doesn't send char events with Alt pressed */
584 if ((key_code
!= 0) &&
585 ((gdk_event
->state
& GDK_MOD1_MASK
) == 0) &&
586 ((gdk_event
->state
& GDK_MOD1_MASK
) == 0))
588 wxKeyEvent
event2( wxEVT_CHAR
);
589 event2
.SetTimestamp( gdk_event
->time
);
590 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
591 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
592 // event2.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
593 // event2.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
594 event2
.m_keyCode
= key_code
;
595 event2
.m_scanCode
= gdk_event
->keyval
;
598 event2
.SetEventObject( win
);
599 ret
= (ret
|| win
->GetEventHandler()->ProcessEvent( event2
));
604 wxWindow
*ancestor
= win
;
607 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
610 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
611 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
614 ancestor
= ancestor
->GetParent();
618 // win is a control: tab can be propagated up
620 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
621 (win
->HasFlag(wxTE_PROCESS_TAB
) == 0))
623 wxNavigationKeyEvent new_event
;
624 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
625 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
626 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
627 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
628 new_event
.SetCurrentFocus( win
);
629 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
632 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
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
);
641 /* pressing F10 will activate the menu bar of the top frame */
643 (gdk_event
->keyval
== GDK_F10
) )
645 wxWindow
*ancestor
= win
;
648 if (wxIsKindOf(ancestor
,wxFrame
))
650 wxFrame
*frame
= (wxFrame
*) ancestor
;
651 wxMenuBar
*menubar
= frame
->GetMenuBar();
654 wxNode
*node
= menubar
->GetMenus().First();
657 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
658 // doesn't work correctly
659 // gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
665 ancestor
= ancestor
->GetParent();
670 Damn, I forgot why this didn't work, but it didn't work.
672 // win is a panel: up can be propagated to the panel
673 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
674 (gdk_event->keyval == GDK_Up))
676 win->m_parent->SetFocus();
680 // win is a panel: left/right can be propagated to the panel
681 if ((!ret) && (win->m_wxwindow) &&
682 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
683 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
685 wxNavigationKeyEvent new_event;
686 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
687 new_event.SetCurrentFocus( win );
688 ret = win->GetEventHandler()->ProcessEvent( new_event );
694 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
701 //-----------------------------------------------------------------------------
702 // "key_release_event" from any window
703 //-----------------------------------------------------------------------------
705 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
708 wxapp_install_idle_handler();
710 if (!win
->m_hasVMT
) return FALSE
;
711 if (g_blockEventsOnDrag
) return FALSE
;
714 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
715 if (gdk_event->state & GDK_SHIFT_MASK)
716 printf( "ShiftDown.\n" );
718 printf( "ShiftUp.\n" );
719 if (gdk_event->state & GDK_CONTROL_MASK)
720 printf( "ControlDown.\n" );
722 printf( "ControlUp.\n" );
726 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
728 /* sending unknown key events doesn't really make sense */
729 if (key_code
== 0) return FALSE
;
733 GdkModifierType state
;
734 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
736 wxKeyEvent
event( wxEVT_KEY_UP
);
737 event
.SetTimestamp( gdk_event
->time
);
738 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
739 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
740 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
741 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
742 event
.m_keyCode
= key_code
;
743 event
.m_scanCode
= gdk_event
->keyval
;
746 event
.SetEventObject( win
);
748 if (win
->GetEventHandler()->ProcessEvent( event
))
750 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
757 //-----------------------------------------------------------------------------
758 // "button_press_event"
759 //-----------------------------------------------------------------------------
761 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
764 wxapp_install_idle_handler();
767 wxPrintf( _T("1) OnButtonPress from ") );
768 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
769 wxPrintf( win->GetClassInfo()->GetClassName() );
770 wxPrintf( _T(".\n") );
772 if (!win
->m_hasVMT
) return FALSE
;
773 if (g_blockEventsOnDrag
) return TRUE
;
774 if (g_blockEventsOnScroll
) return TRUE
;
776 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
780 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
782 gtk_widget_grab_focus (win
->m_wxwindow
);
785 wxPrintf( _T("GrabFocus from ") );
786 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
787 wxPrintf( win->GetClassInfo()->GetClassName() );
788 wxPrintf( _T(".\n") );
795 wxPrintf( _T("2) OnButtonPress from ") );
796 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
797 wxPrintf( win->GetClassInfo()->GetClassName() );
798 wxPrintf( _T(".\n") );
801 wxEventType event_type
= wxEVT_LEFT_DOWN
;
803 if (gdk_event
->button
== 1)
805 switch (gdk_event
->type
)
807 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
808 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
812 else if (gdk_event
->button
== 2)
814 switch (gdk_event
->type
)
816 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
817 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
821 else if (gdk_event
->button
== 3)
823 switch (gdk_event
->type
)
825 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
826 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
831 wxMouseEvent
event( event_type
);
832 event
.SetTimestamp( gdk_event
->time
);
833 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
834 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
835 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
836 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
837 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
838 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
839 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
841 event
.m_x
= (long)gdk_event
->x
;
842 event
.m_y
= (long)gdk_event
->y
;
844 // Some control don't have their own X window and thus cannot get
849 wxNode
*node
= win
->GetChildren().First();
852 wxWindow
*child
= (wxWindow
*)node
->Data();
854 if (child
->m_isStaticBox
)
856 // wxStaticBox is transparent in the box itself
859 int xx1
= child
->m_x
;
860 int yy1
= child
->m_y
;
861 int xx2
= child
->m_x
+ child
->m_width
;
862 int yy2
= child
->m_x
+ child
->m_height
;
865 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
867 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
869 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
871 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
874 event
.m_x
-= child
->m_x
;
875 event
.m_y
-= child
->m_y
;
882 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
883 (child
->m_x
<= event
.m_x
) &&
884 (child
->m_y
<= event
.m_y
) &&
885 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
886 (child
->m_y
+child
->m_height
>= event
.m_y
))
889 event
.m_x
-= child
->m_x
;
890 event
.m_y
-= child
->m_y
;
898 event
.SetEventObject( win
);
900 gs_timeLastClick
= gdk_event
->time
;
902 if (win
->GetEventHandler()->ProcessEvent( event
))
904 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
911 //-----------------------------------------------------------------------------
912 // "button_release_event"
913 //-----------------------------------------------------------------------------
915 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
918 wxapp_install_idle_handler();
920 if (!win
->m_hasVMT
) return FALSE
;
921 if (g_blockEventsOnDrag
) return FALSE
;
922 if (g_blockEventsOnScroll
) return FALSE
;
924 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
927 printf( "OnButtonRelease from " );
928 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
929 printf( win->GetClassInfo()->GetClassName() );
933 wxEventType event_type
= wxEVT_NULL
;
935 switch (gdk_event
->button
)
937 case 1: event_type
= wxEVT_LEFT_UP
; break;
938 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
939 case 3: event_type
= wxEVT_RIGHT_UP
; break;
942 wxMouseEvent
event( event_type
);
943 event
.SetTimestamp( gdk_event
->time
);
944 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
945 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
946 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
947 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
948 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
949 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
950 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
951 event
.m_x
= (long)gdk_event
->x
;
952 event
.m_y
= (long)gdk_event
->y
;
954 // Some control don't have their own X window and thus cannot get
959 wxNode
*node
= win
->GetChildren().First();
962 wxWindow
*child
= (wxWindow
*)node
->Data();
964 if (child
->m_isStaticBox
)
966 // wxStaticBox is transparent in the box itself
969 int xx1
= child
->m_x
;
970 int yy1
= child
->m_y
;
971 int xx2
= child
->m_x
+ child
->m_width
;
972 int yy2
= child
->m_x
+ child
->m_height
;
975 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
977 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
979 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
981 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
984 event
.m_x
-= child
->m_x
;
985 event
.m_y
-= child
->m_y
;
992 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
993 (child
->m_x
<= event
.m_x
) &&
994 (child
->m_y
<= event
.m_y
) &&
995 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
996 (child
->m_y
+child
->m_height
>= event
.m_y
))
999 event
.m_x
-= child
->m_x
;
1000 event
.m_y
-= child
->m_y
;
1004 node
= node
->Next();
1008 event
.SetEventObject( win
);
1010 if (win
->GetEventHandler()->ProcessEvent( event
))
1012 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1019 //-----------------------------------------------------------------------------
1020 // "motion_notify_event"
1021 //-----------------------------------------------------------------------------
1023 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1026 wxapp_install_idle_handler();
1028 if (!win
->m_hasVMT
) return FALSE
;
1029 if (g_blockEventsOnDrag
) return FALSE
;
1030 if (g_blockEventsOnScroll
) return FALSE
;
1032 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1034 if (gdk_event
->is_hint
)
1038 GdkModifierType state
;
1039 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1042 gdk_event
->state
= state
;
1046 printf( "OnMotion from " );
1047 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1048 printf( win->GetClassInfo()->GetClassName() );
1052 wxMouseEvent
event( wxEVT_MOTION
);
1053 event
.SetTimestamp( gdk_event
->time
);
1054 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1055 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1056 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1057 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1058 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1059 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1060 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1062 event
.m_x
= (long)gdk_event
->x
;
1063 event
.m_y
= (long)gdk_event
->y
;
1065 // Some control don't have their own X window and thus cannot get
1070 wxNode
*node
= win
->GetChildren().First();
1073 wxWindow
*child
= (wxWindow
*)node
->Data();
1075 if (child
->m_isStaticBox
)
1077 // wxStaticBox is transparent in the box itself
1080 int xx1
= child
->m_x
;
1081 int yy1
= child
->m_y
;
1082 int xx2
= child
->m_x
+ child
->m_width
;
1083 int yy2
= child
->m_x
+ child
->m_height
;
1086 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1088 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1090 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1092 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1095 event
.m_x
-= child
->m_x
;
1096 event
.m_y
-= child
->m_y
;
1103 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1104 (child
->m_x
<= event
.m_x
) &&
1105 (child
->m_y
<= event
.m_y
) &&
1106 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
1107 (child
->m_y
+child
->m_height
>= event
.m_y
))
1110 event
.m_x
-= child
->m_x
;
1111 event
.m_y
-= child
->m_y
;
1115 node
= node
->Next();
1119 event
.SetEventObject( win
);
1121 if (win
->GetEventHandler()->ProcessEvent( event
))
1123 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1130 //-----------------------------------------------------------------------------
1132 //-----------------------------------------------------------------------------
1134 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1137 wxapp_install_idle_handler();
1139 if (!win
->m_hasVMT
) return FALSE
;
1140 if (g_blockEventsOnDrag
) return FALSE
;
1142 g_focusWindow
= win
;
1144 if (win
->m_wxwindow
)
1146 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1148 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1150 printf( "SetFocus flag from " );
1151 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1152 printf( win->GetClassInfo()->GetClassName() );
1160 printf( "OnSetFocus from " );
1161 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1162 printf( win->GetClassInfo()->GetClassName() );
1164 printf( WXSTRINGCAST win->GetLabel() );
1168 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1169 event
.SetEventObject( win
);
1171 if (win
->GetEventHandler()->ProcessEvent( event
))
1173 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1180 //-----------------------------------------------------------------------------
1181 // "focus_out_event"
1182 //-----------------------------------------------------------------------------
1184 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1187 wxapp_install_idle_handler();
1189 if (!win
->m_hasVMT
) return FALSE
;
1190 if (g_blockEventsOnDrag
) return FALSE
;
1192 if (win
->m_wxwindow
)
1194 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1195 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1199 printf( "OnKillFocus from " );
1200 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1201 printf( win->GetClassInfo()->GetClassName() );
1205 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1206 event
.SetEventObject( win
);
1208 if (win
->GetEventHandler()->ProcessEvent( event
))
1210 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1217 //-----------------------------------------------------------------------------
1218 // "enter_notify_event"
1219 //-----------------------------------------------------------------------------
1221 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1224 wxapp_install_idle_handler();
1226 if (!win
->m_hasVMT
) return FALSE
;
1227 if (g_blockEventsOnDrag
) return FALSE
;
1229 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1231 if (widget
->window
&& win
->GetCursor().Ok() )
1232 gdk_window_set_cursor( widget
->window
, win
->GetCursor().GetCursor() );
1234 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1235 event
.SetTimestamp( gdk_event
->time
);
1236 event
.SetEventObject( win
);
1240 GdkModifierType state
= (GdkModifierType
)0;
1242 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1244 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1245 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1246 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1247 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1248 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1249 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1250 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1252 event
.m_x
= (long)x
;
1253 event
.m_y
= (long)y
;
1255 if (win
->GetEventHandler()->ProcessEvent( event
))
1257 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1264 //-----------------------------------------------------------------------------
1265 // "leave_notify_event"
1266 //-----------------------------------------------------------------------------
1268 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1271 wxapp_install_idle_handler();
1273 if (!win
->m_hasVMT
) return FALSE
;
1274 if (g_blockEventsOnDrag
) return FALSE
;
1276 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1278 if (widget
->window
&& win
->GetCursor().Ok() )
1279 gdk_window_set_cursor( widget
->window
, wxSTANDARD_CURSOR
->GetCursor() );
1281 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1282 event
.SetTimestamp( gdk_event
->time
);
1283 event
.SetEventObject( win
);
1287 GdkModifierType state
= (GdkModifierType
)0;
1289 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1291 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1292 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1293 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1294 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1295 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1296 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1297 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1299 event
.m_x
= (long)x
;
1300 event
.m_y
= (long)y
;
1302 if (win
->GetEventHandler()->ProcessEvent( event
))
1304 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1311 //-----------------------------------------------------------------------------
1312 // "value_changed" from m_vAdjust
1313 //-----------------------------------------------------------------------------
1315 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1318 wxapp_install_idle_handler();
1320 if (g_blockEventsOnDrag
) return;
1322 if (!win
->m_hasVMT
) return;
1324 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
1325 if (fabs(diff
) < 0.2) return;
1326 win
->m_oldVerticalPos
= win
->m_vAdjust
->value
;
1328 wxEventType command
= wxEVT_NULL
;
1330 float line_step
= win
->m_vAdjust
->step_increment
;
1331 float page_step
= win
->m_vAdjust
->page_increment
;
1333 if (win
->IsScrolling())
1335 command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1339 if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->lower
) < 0.2) command
= wxEVT_SCROLLWIN_BOTTOM
;
1340 else if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->upper
) < 0.2) command
= wxEVT_SCROLLWIN_TOP
;
1341 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1342 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEUP
;
1343 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1344 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEUP
;
1345 else command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1348 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1350 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1351 event
.SetEventObject( win
);
1352 win
->GetEventHandler()->ProcessEvent( event
);
1355 //-----------------------------------------------------------------------------
1356 // "value_changed" from m_hAdjust
1357 //-----------------------------------------------------------------------------
1359 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1362 wxapp_install_idle_handler();
1364 if (g_blockEventsOnDrag
) return;
1365 if (!win
->m_hasVMT
) return;
1367 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
1368 if (fabs(diff
) < 0.2) return;
1369 win
->m_oldHorizontalPos
= win
->m_hAdjust
->value
;
1371 wxEventType command
= wxEVT_NULL
;
1373 float line_step
= win
->m_hAdjust
->step_increment
;
1374 float page_step
= win
->m_hAdjust
->page_increment
;
1376 if (win
->IsScrolling())
1378 command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1382 if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->lower
) < 0.2) command
= wxEVT_SCROLLWIN_BOTTOM
;
1383 else if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->upper
) < 0.2) command
= wxEVT_SCROLLWIN_TOP
;
1384 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1385 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEUP
;
1386 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1387 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEUP
;
1388 else command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1391 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1393 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1394 event
.SetEventObject( win
);
1395 win
->GetEventHandler()->ProcessEvent( event
);
1398 //-----------------------------------------------------------------------------
1399 // "changed" from m_vAdjust
1400 //-----------------------------------------------------------------------------
1402 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1405 wxapp_install_idle_handler();
1407 if (g_blockEventsOnDrag
) return;
1408 if (!win
->m_hasVMT
) return;
1410 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1411 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1413 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1414 event
.SetEventObject( win
);
1415 win
->GetEventHandler()->ProcessEvent( event
);
1418 //-----------------------------------------------------------------------------
1419 // "changed" from m_hAdjust
1420 //-----------------------------------------------------------------------------
1422 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1425 wxapp_install_idle_handler();
1427 if (g_blockEventsOnDrag
) return;
1428 if (!win
->m_hasVMT
) return;
1430 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1431 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1433 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1434 event
.SetEventObject( win
);
1435 win
->GetEventHandler()->ProcessEvent( event
);
1438 //-----------------------------------------------------------------------------
1439 // "button_press_event" from scrollbar
1440 //-----------------------------------------------------------------------------
1442 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1443 GdkEventButton
*WXUNUSED(gdk_event
),
1447 wxapp_install_idle_handler();
1449 // don't test here as we can release the mouse while being over
1450 // a different window then the slider
1452 // if (gdk_event->window != widget->slider) return FALSE;
1454 win
->SetScrolling( TRUE
);
1459 //-----------------------------------------------------------------------------
1460 // "button_release_event" from scrollbar
1461 //-----------------------------------------------------------------------------
1463 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1464 GdkEventButton
*WXUNUSED(gdk_event
),
1468 // don't test here as we can release the mouse while being over
1469 // a different window then the slider
1471 // if (gdk_event->window != widget->slider) return FALSE;
1473 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1475 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1476 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_hAdjust
), "value_changed" );
1478 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_vAdjust
), "value_changed" );
1480 win
->SetScrolling( FALSE
);
1485 // ----------------------------------------------------------------------------
1486 // this wxWindowBase function is implemented here (in platform-specific file)
1487 // because it is static and so couldn't be made virtual
1488 // ----------------------------------------------------------------------------
1490 wxWindow
*wxWindowBase::FindFocus()
1492 return g_focusWindow
;
1495 //-----------------------------------------------------------------------------
1496 // "realize" from m_widget
1497 //-----------------------------------------------------------------------------
1499 /* we cannot set colours, fonts and cursors before the widget has
1500 been realized, so we do this directly after realization */
1503 gtk_window_realized_callback( GtkWidget
* WXUNUSED(widget
), wxWindow
*win
)
1506 wxapp_install_idle_handler();
1508 if (win
->m_delayedFont
)
1509 win
->SetFont( win
->GetFont() );
1511 if (win
->m_delayedBackgroundColour
)
1512 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1514 if (win
->m_delayedForegroundColour
)
1515 win
->SetForegroundColour( win
->GetForegroundColour() );
1517 win
->SetCursor( win
->GetCursor() );
1522 //-----------------------------------------------------------------------------
1523 // InsertChild for wxWindow.
1524 //-----------------------------------------------------------------------------
1526 /* Callback for wxWindow. This very strange beast has to be used because
1527 * C++ has no virtual methods in a constructor. We have to emulate a
1528 * virtual function here as wxNotebook requires a different way to insert
1529 * a child in it. I had opted for creating a wxNotebookPage window class
1530 * which would have made this superfluous (such in the MDI window system),
1531 * but no-one was listening to me... */
1533 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1535 gtk_myfixed_put( GTK_MYFIXED(parent
->m_wxwindow
),
1536 GTK_WIDGET(child
->m_widget
),
1542 if (parent
->HasFlag(wxTAB_TRAVERSAL
))
1544 /* we now allow a window to get the focus as long as it
1545 doesn't have any children. */
1546 GTK_WIDGET_UNSET_FLAGS( parent
->m_wxwindow
, GTK_CAN_FOCUS
);
1550 //-----------------------------------------------------------------------------
1552 //-----------------------------------------------------------------------------
1554 wxWindow
* wxGetActiveWindow()
1556 return g_focusWindow
;
1559 //-----------------------------------------------------------------------------
1561 //-----------------------------------------------------------------------------
1563 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1565 void wxWindow::Init()
1571 m_widget
= (GtkWidget
*) NULL
;
1572 m_wxwindow
= (GtkWidget
*) NULL
;
1582 m_needParent
= TRUE
;
1583 m_isBeingDeleted
= FALSE
;
1585 m_hasScrolling
= FALSE
;
1586 m_isScrolling
= FALSE
;
1588 m_hAdjust
= (GtkAdjustment
*) NULL
;
1589 m_vAdjust
= (GtkAdjustment
*) NULL
;
1590 m_oldHorizontalPos
= 0.0;
1591 m_oldVerticalPos
= 0.0;
1594 m_scrollGC
= (GdkGC
*) NULL
;
1595 m_widgetStyle
= (GtkStyle
*) NULL
;
1597 m_insertCallback
= wxInsertChildInWindow
;
1599 m_isStaticBox
= FALSE
;
1600 m_acceptsFocus
= FALSE
;
1603 wxWindow::wxWindow()
1608 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1609 const wxPoint
&pos
, const wxSize
&size
,
1610 long style
, const wxString
&name
)
1614 Create( parent
, id
, pos
, size
, style
, name
);
1617 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1618 const wxPoint
&pos
, const wxSize
&size
,
1619 long style
, const wxString
&name
)
1621 PreCreation( parent
, id
, pos
, size
, style
, name
);
1623 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1624 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1627 debug_focus_in( m_widget
, _T("wxWindow::m_widget"), name
);
1630 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1633 debug_focus_in( scrolledWindow
->hscrollbar
, _T("wxWindow::hsrcollbar"), name
);
1634 debug_focus_in( scrolledWindow
->vscrollbar
, _T("wxWindow::vsrcollbar"), name
);
1637 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1638 scroll_class
->scrollbar_spacing
= 0;
1640 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1642 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
1643 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
1645 m_wxwindow
= gtk_myfixed_new();
1648 debug_focus_in( m_wxwindow
, _T("wxWindow::m_wxwindow"), name
);
1651 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1653 #if (GTK_MINOR_VERSION > 0)
1654 GtkMyFixed
*myfixed
= GTK_MYFIXED(m_wxwindow
);
1656 if (HasFlag(wxRAISED_BORDER
))
1658 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_OUT
);
1660 else if (HasFlag(wxSUNKEN_BORDER
))
1662 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_IN
);
1666 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_NONE
);
1668 #else // GTK_MINOR_VERSION == 0
1669 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
1671 if (HasFlag(wxRAISED_BORDER
))
1673 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1675 else if (HasFlag(wxSUNKEN_BORDER
))
1677 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1681 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1683 #endif // GTK_MINOR_VERSION
1685 if (HasFlag(wxTAB_TRAVERSAL
))
1687 /* we now allow a window to get the focus as long as it
1688 doesn't have any children. */
1689 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1690 m_acceptsFocus
= FALSE
;
1694 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1695 m_acceptsFocus
= TRUE
;
1698 #if (GTK_MINOR_VERSION == 0)
1699 // shut the viewport up
1700 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1701 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1702 #endif // GTK_MINOR_VERSION == 0
1704 // I _really_ don't want scrollbars in the beginning
1705 m_vAdjust
->lower
= 0.0;
1706 m_vAdjust
->upper
= 1.0;
1707 m_vAdjust
->value
= 0.0;
1708 m_vAdjust
->step_increment
= 1.0;
1709 m_vAdjust
->page_increment
= 1.0;
1710 m_vAdjust
->page_size
= 5.0;
1711 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1712 m_hAdjust
->lower
= 0.0;
1713 m_hAdjust
->upper
= 1.0;
1714 m_hAdjust
->value
= 0.0;
1715 m_hAdjust
->step_increment
= 1.0;
1716 m_hAdjust
->page_increment
= 1.0;
1717 m_hAdjust
->page_size
= 5.0;
1718 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1720 // these handlers block mouse events to any window during scrolling such as
1721 // motion events and prevent GTK and wxWindows from fighting over where the
1724 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
1725 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1727 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
1728 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1730 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
1731 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1733 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
1734 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1736 // these handlers get notified when screen updates are required either when
1737 // scrolling or when the window size (and therefore scrollbar configuration)
1740 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
1741 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
1742 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
1743 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
1745 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
1746 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
1747 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
1748 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
1750 gtk_widget_show( m_wxwindow
);
1753 m_parent
->DoAddChild( this );
1762 wxWindow::~wxWindow()
1764 m_isBeingDeleted
= TRUE
;
1773 m_parent
->RemoveChild( this );
1777 gtk_style_unref( m_widgetStyle
);
1778 m_widgetStyle
= (GtkStyle
*) NULL
;
1783 gdk_gc_unref( m_scrollGC
);
1784 m_scrollGC
= (GdkGC
*) NULL
;
1789 gtk_widget_destroy( m_wxwindow
);
1790 m_wxwindow
= (GtkWidget
*) NULL
;
1795 gtk_widget_destroy( m_widget
);
1796 m_widget
= (GtkWidget
*) NULL
;
1800 void wxWindow::PreCreation( wxWindow
*parent
,
1805 const wxString
&name
)
1807 wxASSERT_MSG( !m_needParent
|| parent
, _T("Need complete parent.") );
1809 if ( !CreateBase(parent
, id
, pos
, size
, style
, name
) )
1811 wxFAIL_MSG(_T("window creation failed"));
1814 m_width
= WidthDefault(size
.x
);
1815 m_height
= HeightDefault(size
.y
);
1820 if (!parent
) /* some reasonable defaults */
1824 m_x
= (gdk_screen_width () - m_width
) / 2;
1825 if (m_x
< 10) m_x
= 10;
1829 m_y
= (gdk_screen_height () - m_height
) / 2;
1830 if (m_y
< 10) m_y
= 10;
1835 void wxWindow::PostCreation()
1837 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1841 /* these get reported to wxWindows -> wxPaintEvent */
1842 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1843 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1845 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1846 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1848 #if (GTK_MINOR_VERSION > 0)
1849 /* these are called when the "sunken" or "raised" borders are drawn */
1850 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
1851 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
1853 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
1854 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
1858 GtkWidget
*connect_widget
= GetConnectWidget();
1860 ConnectWidget( connect_widget
);
1862 /* we cannot set colours, fonts and cursors before the widget has
1863 been realized, so we do this directly after realization */
1864 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
1865 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
1870 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1872 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1873 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1875 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
1876 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
1878 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1879 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1881 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1882 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1884 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1885 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1887 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1888 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1890 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1891 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1893 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1894 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1896 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1897 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1900 bool wxWindow::Destroy()
1902 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1906 return wxWindowBase::Destroy();
1909 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1911 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1912 wxASSERT_MSG( (m_parent
!= NULL
), _T("wxWindow::SetSize requires parent.\n") );
1914 if (m_resizing
) return; /* I don't like recursions */
1917 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
1919 /* don't set the size for children of wxNotebook, just take the values. */
1927 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1929 if (x
!= -1) m_x
= x
;
1930 if (y
!= -1) m_y
= y
;
1931 if (width
!= -1) m_width
= width
;
1932 if (height
!= -1) m_height
= height
;
1942 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1944 if (width
== -1) m_width
= 80;
1947 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1949 if (height
== -1) m_height
= 26;
1952 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1953 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1954 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
1955 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
1959 if (GTK_WIDGET_HAS_DEFAULT(m_widget
))
1961 /* the default button has a border around it */
1965 /* this is the result of hours of debugging: the following code
1966 means that if we have a m_wxwindow and we set the size of
1967 m_widget, m_widget (which is a GtkScrolledWindow) does NOT
1968 automatically propagate its size down to its m_wxwindow,
1969 which is its client area. therefore, we have to tell the
1970 client area directly that it has to resize itself.
1971 this will lead to that m_widget (GtkScrolledWindow) will
1972 calculate how much size it needs for scrollbars etc and
1973 it will then call XXX_size_allocate of its child, which
1974 is m_wxwindow. m_wxwindow in turn will do the same with its
1975 children and so on. problems can arise if this happens
1976 before all the children have been realized as some widgets
1977 stupidy need to be realized during XXX_size_allocate (e.g.
1978 GtkNotebook) and they will segv if called otherwise. this
1979 emergency is tested in gtk_myfixed_size_allocate. Normally
1980 this shouldn't be needed and only gtk_widget_queue_resize()
1981 should be enough to provoke a resize at the next appropriate
1982 moment, but this seems to fail, e.g. when a wxNotebook contains
1983 a wxSplitterWindow: the splitter window's children won't
1984 show up properly resized then. */
1986 gtk_myfixed_set_size( GTK_MYFIXED(m_parent
->m_wxwindow
),
1991 m_height
+2*border
);
1996 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1997 event
.SetEventObject( this );
1998 GetEventHandler()->ProcessEvent( event
);
2003 void wxWindow::OnInternalIdle()
2008 void wxWindow::DoGetSize( int *width
, int *height
) const
2010 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2012 if (width
) (*width
) = m_width
;
2013 if (height
) (*height
) = m_height
;
2016 void wxWindow::DoSetClientSize( int width
, int height
)
2018 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2022 SetSize( width
, height
);
2029 if (!m_hasScrolling
)
2031 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
2033 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2035 dw
+= 2 * window_class
->xthickness
;
2036 dh
+= 2 * window_class
->ythickness
;
2041 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2042 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2044 #if (GTK_MINOR_VERSION == 0)
2045 GtkWidget
*viewport
= scroll_window
->viewport
;
2046 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2048 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2050 dw
+= 2 * viewport_class
->xthickness
;
2051 dh
+= 2 * viewport_class
->ythickness
;
2056 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2057 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2059 we use this instead: range.slider_width = 11 + 2*2pts edge
2062 if (scroll_window
->vscrollbar_visible
)
2064 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2065 dw
+= scroll_class
->scrollbar_spacing
;
2068 if (scroll_window
->hscrollbar_visible
)
2070 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2071 dh
+= scroll_class
->scrollbar_spacing
;
2075 SetSize( width
+dw
, height
+dh
);
2079 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2081 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2085 if (width
) (*width
) = m_width
;
2086 if (height
) (*height
) = m_height
;
2093 if (!m_hasScrolling
)
2095 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
2097 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2099 dw
+= 2 * window_class
->xthickness
;
2100 dh
+= 2 * window_class
->ythickness
;
2105 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2106 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2108 #if (GTK_MINOR_VERSION == 0)
2109 GtkWidget
*viewport
= scroll_window
->viewport
;
2110 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2112 if ( HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
) )
2114 dw
+= 2 * viewport_class
->xthickness
;
2115 dh
+= 2 * viewport_class
->ythickness
;
2119 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2120 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2122 we use this instead: range.slider_width = 11 + 2*2pts edge
2125 if (scroll_window
->vscrollbar_visible
)
2127 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2128 dw
+= scroll_class
->scrollbar_spacing
;
2131 if (scroll_window
->hscrollbar_visible
)
2133 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2134 dh
+= scroll_class
->scrollbar_spacing
;
2138 if (width
) (*width
) = m_width
- dw
;
2139 if (height
) (*height
) = m_height
- dh
;
2143 void wxWindow::DoGetPosition( int *x
, int *y
) const
2145 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2151 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2153 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2155 if (!m_widget
->window
) return;
2157 GdkWindow
*source
= (GdkWindow
*) NULL
;
2159 source
= m_wxwindow
->window
;
2161 source
= m_widget
->window
;
2165 gdk_window_get_origin( source
, &org_x
, &org_y
);
2169 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2171 org_x
+= m_widget
->allocation
.x
;
2172 org_y
+= m_widget
->allocation
.y
;
2180 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2182 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2184 if (!m_widget
->window
) return;
2186 GdkWindow
*source
= (GdkWindow
*) NULL
;
2188 source
= m_wxwindow
->window
;
2190 source
= m_widget
->window
;
2194 gdk_window_get_origin( source
, &org_x
, &org_y
);
2198 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2200 org_x
+= m_widget
->allocation
.x
;
2201 org_y
+= m_widget
->allocation
.y
;
2209 bool wxWindow::Show( bool show
)
2211 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2213 if (!wxWindowBase::Show(show
))
2220 gtk_widget_show( m_widget
);
2222 gtk_widget_hide( m_widget
);
2227 bool wxWindow::Enable( bool enable
)
2229 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2231 if (!wxWindowBase::Enable(enable
))
2237 gtk_widget_set_sensitive( m_widget
, enable
);
2239 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2244 int wxWindow::GetCharHeight() const
2246 wxCHECK_MSG( (m_widget
!= NULL
), 12, _T("invalid window") );
2248 wxCHECK_MSG( m_font
.Ok(), 12, _T("invalid font") );
2250 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2252 return font
->ascent
+ font
->descent
;
2255 int wxWindow::GetCharWidth() const
2257 wxCHECK_MSG( (m_widget
!= NULL
), 8, _T("invalid window") );
2259 wxCHECK_MSG( m_font
.Ok(), 8, _T("invalid font") );
2261 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2263 return gdk_string_width( font
, "H" );
2266 void wxWindow::GetTextExtent( const wxString
& string
,
2270 int *externalLeading
,
2271 const wxFont
*theFont
) const
2273 wxFont fontToUse
= m_font
;
2274 if (theFont
) fontToUse
= *theFont
;
2276 wxCHECK_RET( fontToUse
.Ok(), _T("invalid font") );
2278 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2279 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2280 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2281 if (descent
) (*descent
) = font
->descent
;
2282 if (externalLeading
) (*externalLeading
) = 0; // ??
2285 void wxWindow::SetFocus()
2287 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2289 GtkWidget
*connect_widget
= GetConnectWidget();
2292 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2294 gtk_widget_grab_focus (connect_widget
);
2296 else if (GTK_IS_CONTAINER(connect_widget
))
2298 gtk_container_focus( GTK_CONTAINER(connect_widget
), GTK_DIR_TAB_FORWARD
);
2306 bool wxWindow::AcceptsFocus() const
2308 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2311 bool wxWindow::Reparent( wxWindow
*newParent
)
2313 wxCHECK_MSG( (m_widget
!= NULL
), (wxWindow
*) NULL
, _T("invalid window") );
2315 gtk_widget_unparent( m_widget
);
2317 if ( !wxWindowBase::Reparent(newParent
) )
2323 void wxWindow::Raise()
2325 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2327 if (!m_widget
->window
) return;
2329 gdk_window_raise( m_widget
->window
);
2332 void wxWindow::Lower()
2334 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2336 if (!m_widget
->window
) return;
2338 gdk_window_lower( m_widget
->window
);
2341 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2343 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2345 if (!wxWindowBase::SetCursor(cursor
))
2347 // don't leave if the GTK widget has just
2349 if (!m_delayedCursor
) return FALSE
;
2352 GtkWidget
*connect_widget
= GetConnectWidget();
2353 if (!connect_widget
->window
)
2355 // indicate that a new style has been set
2356 // but it couldn't get applied as the
2357 // widget hasn't been realized yet.
2358 m_delayedCursor
= TRUE
;
2360 // pretend we have done something
2364 if ((m_widget
) && (m_widget
->window
))
2365 gdk_window_set_cursor( m_widget
->window
, GetCursor().GetCursor() );
2367 if ((m_wxwindow
) && (m_wxwindow
->window
))
2368 gdk_window_set_cursor( m_wxwindow
->window
, GetCursor().GetCursor() );
2374 void wxWindow::WarpPointer( int WXUNUSED(x
), int WXUNUSED(y
) )
2379 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2381 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2383 if (!m_widget
->window
) return;
2385 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2389 gdk_window_clear_area( m_wxwindow
->window
,
2391 rect
->width
, rect
->height
);
2395 gdk_window_clear( m_wxwindow
->window
);
2402 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2404 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2408 GdkRectangle gdk_rect
;
2409 gdk_rect
.x
= rect
->x
;
2410 gdk_rect
.y
= rect
->y
;
2411 gdk_rect
.width
= rect
->width
;
2412 gdk_rect
.height
= rect
->height
;
2415 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2417 gtk_widget_draw( m_widget
, &gdk_rect
);
2421 void wxWindow::Clear()
2423 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2425 if (!m_widget
->window
) return;
2427 if (m_wxwindow
&& m_wxwindow
->window
)
2429 gdk_window_clear( m_wxwindow
->window
);
2434 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2436 wxWindowBase::DoSetToolTip(tip
);
2439 m_tooltip
->Apply( this );
2442 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2444 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConv_current
->cWX2MB(tip
), (gchar
*) NULL
);
2446 #endif // wxUSE_TOOLTIPS
2448 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2450 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2452 if (!wxWindowBase::SetBackgroundColour(colour
))
2454 // don't leave if the GTK widget has just
2456 if (!m_delayedBackgroundColour
) return FALSE
;
2459 GtkWidget
*connect_widget
= GetConnectWidget();
2460 if (!connect_widget
->window
)
2462 // indicate that a new style has been set
2463 // but it couldn't get applied as the
2464 // widget hasn't been realized yet.
2465 m_delayedBackgroundColour
= TRUE
;
2467 // pretend we have done something
2471 if (m_wxwindow
&& m_wxwindow
->window
)
2473 /* wxMSW doesn't clear the window here. I don't do that either to
2474 provide compatibility. call Clear() to do the job. */
2476 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_wxwindow
->window
) );
2477 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
2480 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2482 if (sysbg
== m_backgroundColour
)
2484 m_backgroundColour
= wxNullColour
;
2486 m_backgroundColour
= sysbg
;
2496 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2498 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2500 if (!wxWindowBase::SetForegroundColour(colour
))
2502 // don't leave if the GTK widget has just
2504 if (!m_delayedForegroundColour
) return FALSE
;
2507 GtkWidget
*connect_widget
= GetConnectWidget();
2508 if (!connect_widget
->window
)
2510 // indicate that a new style has been set
2511 // but it couldn't get applied as the
2512 // widget hasn't been realized yet.
2513 m_delayedForegroundColour
= TRUE
;
2515 // pretend we have done something
2519 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2520 if (sysbg
== m_foregroundColour
)
2522 m_backgroundColour
= wxNullColour
;
2524 m_backgroundColour
= sysbg
;
2534 GtkStyle
*wxWindow::GetWidgetStyle()
2536 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2538 m_widgetStyle
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2540 return m_widgetStyle
;
2543 void wxWindow::SetWidgetStyle()
2545 GtkStyle
*style
= GetWidgetStyle();
2547 gdk_font_unref( style
->font
);
2548 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2550 if (m_foregroundColour
.Ok())
2552 m_foregroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2553 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2554 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2555 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2558 if (m_backgroundColour
.Ok())
2560 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2561 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2562 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2563 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2564 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2565 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2566 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2567 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2568 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2572 void wxWindow::ApplyWidgetStyle()
2576 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2578 menu
->SetInvokingWindow( win
);
2579 wxNode
*node
= menu
->GetItems().First();
2582 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2583 if (menuitem
->IsSubMenu())
2585 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2587 node
= node
->Next();
2591 static gint gs_pop_x
= 0;
2592 static gint gs_pop_y
= 0;
2594 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
2598 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
2603 bool wxWindow::PopupMenu( wxMenu
*menu
, int x
, int y
)
2605 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2607 wxCHECK_MSG( menu
!= NULL
, FALSE
, _T("invalid popup-menu") );
2609 SetInvokingWindow( menu
, this );
2617 GTK_MENU(menu
->m_menu
),
2618 (GtkWidget
*) NULL
, // parent menu shell
2619 (GtkWidget
*) NULL
, // parent menu item
2620 (GtkMenuPositionFunc
) pop_pos_callback
,
2621 (gpointer
) this, // client data
2622 0, // button used to activate it
2623 0 //gs_timeLastClick // the time of activation
2628 #if wxUSE_DRAG_AND_DROP
2630 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2632 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2634 GtkWidget
*dnd_widget
= GetConnectWidget();
2636 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
2638 if (m_dropTarget
) delete m_dropTarget
;
2639 m_dropTarget
= dropTarget
;
2641 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
2644 #endif // wxUSE_DRAG_AND_DROP
2646 GtkWidget
* wxWindow::GetConnectWidget()
2648 GtkWidget
*connect_widget
= m_widget
;
2649 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2651 return connect_widget
;
2654 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2656 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2657 return (window
== m_widget
->window
);
2660 bool wxWindow::SetFont( const wxFont
&font
)
2662 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T( "invalid window") );
2664 if (!wxWindowBase::SetFont(font
))
2666 // don't leave if the GTK widget has just
2668 if (!m_delayedFont
) return FALSE
;
2671 GtkWidget
*connect_widget
= GetConnectWidget();
2672 if (!connect_widget
->window
)
2674 // indicate that a new style has been set
2675 // but it couldn't get applied as the
2676 // widget hasn't been realized yet.
2677 m_delayedFont
= TRUE
;
2679 // pretend we have done something
2683 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2684 if ( sysbg
== m_backgroundColour
)
2686 m_backgroundColour
= wxNullColour
;
2688 m_backgroundColour
= sysbg
;
2698 void wxWindow::CaptureMouse()
2700 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2702 wxCHECK_RET( g_capturing
== FALSE
, _T("CaptureMouse called twice") );
2704 GtkWidget
*connect_widget
= GetConnectWidget();
2705 if (!connect_widget
->window
) return;
2707 gtk_grab_add( connect_widget
);
2708 gdk_pointer_grab( connect_widget
->window
, FALSE
,
2710 (GDK_BUTTON_PRESS_MASK
|
2711 GDK_BUTTON_RELEASE_MASK
|
2712 GDK_POINTER_MOTION_MASK
),
2719 void wxWindow::ReleaseMouse()
2721 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2723 wxCHECK_RET( g_capturing
== TRUE
, _T("ReleaseMouse called twice") );
2725 GtkWidget
*connect_widget
= GetConnectWidget();
2726 if (!connect_widget
->window
) return;
2728 gtk_grab_remove( connect_widget
);
2729 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2730 g_capturing
= FALSE
;
2733 bool wxWindow::IsRetained() const
2738 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2739 int range
, bool refresh
)
2741 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2743 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2745 m_hasScrolling
= TRUE
;
2747 if (orient
== wxHORIZONTAL
)
2749 float fpos
= (float)pos
;
2750 float frange
= (float)range
;
2751 float fthumb
= (float)thumbVisible
;
2752 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2753 if (fpos
< 0.0) fpos
= 0.0;
2755 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2756 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2758 SetScrollPos( orient
, pos
, refresh
);
2762 m_oldHorizontalPos
= fpos
;
2764 m_hAdjust
->lower
= 0.0;
2765 m_hAdjust
->upper
= frange
;
2766 m_hAdjust
->value
= fpos
;
2767 m_hAdjust
->step_increment
= 1.0;
2768 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2769 m_hAdjust
->page_size
= fthumb
;
2773 float fpos
= (float)pos
;
2774 float frange
= (float)range
;
2775 float fthumb
= (float)thumbVisible
;
2776 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2777 if (fpos
< 0.0) fpos
= 0.0;
2779 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2780 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2782 SetScrollPos( orient
, pos
, refresh
);
2786 m_oldVerticalPos
= fpos
;
2788 m_vAdjust
->lower
= 0.0;
2789 m_vAdjust
->upper
= frange
;
2790 m_vAdjust
->value
= fpos
;
2791 m_vAdjust
->step_increment
= 1.0;
2792 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2793 m_vAdjust
->page_size
= fthumb
;
2796 if (orient
== wxHORIZONTAL
)
2797 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2799 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2802 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2804 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2806 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2808 if (orient
== wxHORIZONTAL
)
2810 float fpos
= (float)pos
;
2811 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
2812 if (fpos
< 0.0) fpos
= 0.0;
2813 m_oldHorizontalPos
= fpos
;
2815 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2816 m_hAdjust
->value
= fpos
;
2820 float fpos
= (float)pos
;
2821 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
2822 if (fpos
< 0.0) fpos
= 0.0;
2823 m_oldVerticalPos
= fpos
;
2825 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2826 m_vAdjust
->value
= fpos
;
2829 if (!m_isScrolling
) /* prevent recursion */
2831 if (m_wxwindow
->window
)
2833 if (orient
== wxHORIZONTAL
)
2834 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2836 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2841 int wxWindow::GetScrollThumb( int orient
) const
2843 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2845 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2847 if (orient
== wxHORIZONTAL
)
2848 return (int)(m_hAdjust
->page_size
+0.5);
2850 return (int)(m_vAdjust
->page_size
+0.5);
2853 int wxWindow::GetScrollPos( int orient
) const
2855 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2857 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2859 if (orient
== wxHORIZONTAL
)
2860 return (int)(m_hAdjust
->value
+0.5);
2862 return (int)(m_vAdjust
->value
+0.5);
2865 int wxWindow::GetScrollRange( int orient
) const
2867 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2869 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2871 if (orient
== wxHORIZONTAL
)
2872 return (int)(m_hAdjust
->upper
+0.5);
2874 return (int)(m_vAdjust
->upper
+0.5);
2877 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2879 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2881 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2885 m_scrollGC
= gdk_gc_new( m_wxwindow
->window
);
2886 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
2889 wxNode
*node
= m_children
.First();
2892 wxWindow
*child
= (wxWindow
*) node
->Data();
2893 child
->Move( child
->m_x
+ dx
, child
->m_y
+ dy
);
2894 node
= node
->Next();
2899 GetClientSize( &cw
, &ch
);
2900 int w
= cw
- abs(dx
);
2901 int h
= ch
- abs(dy
);
2903 if ((h
< 0) || (w
< 0))
2911 if (dx
< 0) s_x
= -dx
;
2912 if (dy
< 0) s_y
= -dy
;
2915 if (dx
> 0) d_x
= dx
;
2916 if (dy
> 0) d_y
= dy
;
2918 gdk_window_copy_area( m_wxwindow
->window
, m_scrollGC
, d_x
, d_y
,
2919 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2922 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2923 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2924 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2925 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2927 Refresh( TRUE
, &rect
);
2931 void wxWindow::SetScrolling(bool scroll
)
2933 m_isScrolling
= g_blockEventsOnScroll
= scroll
;