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 #if (GTK_MINOR_VERSION == 0)
51 //-----------------------------------------------------------------------------
52 // documentation on internals
53 //-----------------------------------------------------------------------------
56 I have been asked several times about writing some documentation about
57 the GTK port of wxWindows, especially its internal structures. Obviously,
58 you cannot understand wxGTK without knowing a little about the GTK, but
59 some more information about what the wxWindow, which is the base class
60 for all other window classes, does seems required as well.
62 What does wxWindow do? It contains the common interface for the following
63 jobs of its descendants:
65 1) Define the rudimentary behaviour common to all window classes, such as
66 resizing, intercepting user input (so as to make it possible to use these
67 events for special purposes in a derived class), window names etc.
69 2) Provide the possibility to contain and manage children, if the derived
70 class is allowed to contain children, which holds true for those window
71 classes which do not display a native GTK widget. To name them, these
72 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
73 work classes are a special case and are handled a bit differently from
74 the rest. The same holds true for the wxNotebook class.
76 3) Provide the possibility to draw into a client area of a window. This,
77 too, only holds true for classes that do not display a native GTK widget
80 4) Provide the entire mechanism for scrolling widgets. This actual inter-
81 face for this is usually in wxScrolledWindow, but the GTK implementation
84 5) A multitude of helper or extra methods for special purposes, such as
85 Drag'n'Drop, managing validators etc.
87 Normally one might expect, that one wxWindows window would always correspond
88 to one GTK widget. Under GTK, there is no such allround widget that has all
89 the functionality. Moreover, the GTK defines a client area as a different
90 widget from the actual widget you are handling. Last but not least some
91 special classes (e.g. wxFrame) handle different categories of widgets and
92 still have the possibility to draw something in the client area.
93 It was therefore required to write a special purpose GTK widget, that would
94 represent a client area in the sense of wxWindows capable to do the jobs
95 2), 3) and 4). I have written this class and it resides in win_gtk.c of
98 All windows must have a widget, with which they interact with other under-
99 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
100 thw wxWindow class has a member variable called m_widget which holds a
101 pointer to this widget. When the window class represents a GTK native widget,
102 this is (in most cases) the only GTK widget the class manages. E.g. the
103 wxStatitText class handles only a GtkLabel widget a pointer to which you
104 can find in m_widget (defined in wxWindow)
106 When the class has a client area for drawing into and for containing children
107 it has to handle the client area widget (of the type GtkMyFixed, defined in
108 win_gtk.c), but there could be any number of widgets, handled by a class
109 The common rule for all windows is only, that the widget that interacts with
110 the rest of GTK must be referenced in m_widget and all other widgets must be
111 children of this widget on the GTK level. The top-most widget, which also
112 represents the client area, must be in the m_wxwindow field and must be of
115 As I said, the window classes that display a GTK native widget only have
116 one widget, so in the case of e.g. the wxButton class m_widget holds a
117 pointer to a GtkButton widget. But windows with client areas (for drawing
118 and children) have a m_widget field that is a pointer to a GtkScrolled-
119 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
120 one is (in the GTK sense) a child of the GtkScrolledWindow.
122 If the m_wxwindow field is set, then all input to this widget is inter-
123 cepted and sent to the wxWindows class. If not, all input to the widget
124 that gets pointed to by m_widget gets intercepted and sent to the class.
128 //-----------------------------------------------------------------------------
130 //-----------------------------------------------------------------------------
132 extern wxList wxPendingDelete
;
133 extern bool g_blockEventsOnDrag
;
134 extern bool g_blockEventsOnScroll
;
135 extern wxCursor g_globalCursor
;
136 static bool g_capturing
= FALSE
;
137 static wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
139 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
140 the last click here */
141 static guint32 gs_timeLastClick
= 0;
143 //-----------------------------------------------------------------------------
145 //-----------------------------------------------------------------------------
149 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
150 GdkEvent
*WXUNUSED(event
),
154 static bool s_done = FALSE;
157 wxLog::AddTraceMask("focus");
160 wxLogTrace(_T("FOCUS NOW AT: %s"), name);
166 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
172 wxChar
*s
= new wxChar
[tmp
.Length()+1];
176 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
177 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
182 //-----------------------------------------------------------------------------
184 //-----------------------------------------------------------------------------
186 extern void wxapp_install_idle_handler();
187 extern bool g_isIdle
;
189 //-----------------------------------------------------------------------------
190 // key event conversion routines
191 //-----------------------------------------------------------------------------
193 #if (GTK_MINOR_VERSION == 0)
195 gdk_keyval_to_upper (guint keyval
)
199 KeySym lower_val
= 0;
200 KeySym upper_val
= 0;
202 XConvertCase (keyval
, &lower_val
, &upper_val
);
209 static long map_to_unmodified_wx_keysym( KeySym keysym
)
216 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
218 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
224 case GDK_Super_R
: key_code
= WXK_ALT
; break;
225 case GDK_Menu
: key_code
= WXK_MENU
; break;
226 case GDK_Help
: key_code
= WXK_HELP
; break;
227 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
228 case GDK_ISO_Left_Tab
:
229 case GDK_Tab
: key_code
= WXK_TAB
; break;
230 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
231 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
232 case GDK_Return
: key_code
= WXK_RETURN
; break;
233 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
234 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
235 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
236 case GDK_Delete
: key_code
= WXK_DELETE
; break;
237 case GDK_Home
: key_code
= WXK_HOME
; break;
238 case GDK_Left
: key_code
= WXK_LEFT
; break;
239 case GDK_Up
: key_code
= WXK_UP
; break;
240 case GDK_Right
: key_code
= WXK_RIGHT
; break;
241 case GDK_Down
: key_code
= WXK_DOWN
; break;
242 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
243 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
244 case GDK_Next
: key_code
= WXK_NEXT
; break;
245 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
246 case GDK_End
: key_code
= WXK_END
; break;
247 case GDK_Begin
: key_code
= WXK_HOME
; break;
248 case GDK_Select
: key_code
= WXK_SELECT
; break;
249 case GDK_Print
: key_code
= WXK_PRINT
; break;
250 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
251 case GDK_Insert
: key_code
= WXK_INSERT
; break;
252 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
254 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
255 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
256 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
257 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
258 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
259 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
260 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
261 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
262 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
263 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
264 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
265 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
266 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
267 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
268 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
269 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
270 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
271 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
272 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
273 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
274 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
275 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
276 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
277 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
278 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
279 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
280 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
281 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
282 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
283 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
284 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
285 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
286 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
287 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
288 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
289 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
290 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
292 case GDK_F1
: key_code
= WXK_F1
; break;
293 case GDK_F2
: key_code
= WXK_F2
; break;
294 case GDK_F3
: key_code
= WXK_F3
; break;
295 case GDK_F4
: key_code
= WXK_F4
; break;
296 case GDK_F5
: key_code
= WXK_F5
; break;
297 case GDK_F6
: key_code
= WXK_F6
; break;
298 case GDK_F7
: key_code
= WXK_F7
; break;
299 case GDK_F8
: key_code
= WXK_F8
; break;
300 case GDK_F9
: key_code
= WXK_F9
; break;
301 case GDK_F10
: key_code
= WXK_F10
; break;
302 case GDK_F11
: key_code
= WXK_F11
; break;
303 case GDK_F12
: key_code
= WXK_F12
; break;
308 guint upper
= gdk_keyval_to_upper( keysym
);
309 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
318 static long map_to_wx_keysym( KeySym keysym
)
324 case GDK_Menu
: key_code
= WXK_MENU
; break;
325 case GDK_Help
: key_code
= WXK_HELP
; break;
326 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
327 case GDK_ISO_Left_Tab
:
328 case GDK_Tab
: key_code
= WXK_TAB
; break;
329 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
330 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
331 case GDK_Return
: key_code
= WXK_RETURN
; break;
332 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
333 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
334 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
335 case GDK_Delete
: key_code
= WXK_DELETE
; break;
336 case GDK_Home
: key_code
= WXK_HOME
; break;
337 case GDK_Left
: key_code
= WXK_LEFT
; break;
338 case GDK_Up
: key_code
= WXK_UP
; break;
339 case GDK_Right
: key_code
= WXK_RIGHT
; break;
340 case GDK_Down
: key_code
= WXK_DOWN
; break;
341 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
342 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
343 case GDK_Next
: key_code
= WXK_NEXT
; break;
344 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
345 case GDK_End
: key_code
= WXK_END
; break;
346 case GDK_Begin
: key_code
= WXK_HOME
; break;
347 case GDK_Select
: key_code
= WXK_SELECT
; break;
348 case GDK_Print
: key_code
= WXK_PRINT
; break;
349 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
350 case GDK_Insert
: key_code
= WXK_INSERT
; break;
351 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
353 case GDK_KP_0
: key_code
= '0'; break;
354 case GDK_KP_1
: key_code
= '1'; break;
355 case GDK_KP_2
: key_code
= '2'; break;
356 case GDK_KP_3
: key_code
= '3'; break;
357 case GDK_KP_4
: key_code
= '4'; break;
358 case GDK_KP_5
: key_code
= '5'; break;
359 case GDK_KP_6
: key_code
= '6'; break;
360 case GDK_KP_7
: key_code
= '7'; break;
361 case GDK_KP_8
: key_code
= '8'; break;
362 case GDK_KP_9
: key_code
= '9'; break;
363 case GDK_KP_Space
: key_code
= ' '; break;
364 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
365 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
366 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
367 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
368 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
369 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
370 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
371 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
372 case GDK_KP_Up
: key_code
= WXK_UP
; break;
373 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
374 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
375 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
376 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
377 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
378 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
379 case GDK_KP_End
: key_code
= WXK_END
; break;
380 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
381 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
382 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
383 case GDK_KP_Equal
: key_code
= '='; break;
384 case GDK_KP_Multiply
: key_code
= '*'; break;
385 case GDK_KP_Add
: key_code
= '+'; break;
386 case GDK_KP_Separator
: key_code
= ','; break;
387 case GDK_KP_Subtract
: key_code
= '-'; break;
388 case GDK_KP_Decimal
: key_code
= '.'; break;
389 case GDK_KP_Divide
: key_code
= '/'; break;
391 case GDK_F1
: key_code
= WXK_F1
; break;
392 case GDK_F2
: key_code
= WXK_F2
; break;
393 case GDK_F3
: key_code
= WXK_F3
; break;
394 case GDK_F4
: key_code
= WXK_F4
; break;
395 case GDK_F5
: key_code
= WXK_F5
; break;
396 case GDK_F6
: key_code
= WXK_F6
; break;
397 case GDK_F7
: key_code
= WXK_F7
; break;
398 case GDK_F8
: key_code
= WXK_F8
; break;
399 case GDK_F9
: key_code
= WXK_F9
; break;
400 case GDK_F10
: key_code
= WXK_F10
; break;
401 case GDK_F11
: key_code
= WXK_F11
; break;
402 case GDK_F12
: key_code
= WXK_F12
; break;
415 //-----------------------------------------------------------------------------
416 // local code (see below)
417 //-----------------------------------------------------------------------------
419 #if (GTK_MINOR_VERSION > 0)
421 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
429 if (win
->HasScrolling())
431 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
432 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
435 GtkWidget *hscrollbar = scroll_window->hscrollbar;
436 GtkWidget *vscrollbar = scroll_window->vscrollbar;
438 we use this instead: range.slider_width = 11 + 2*2pts edge
441 if (scroll_window
->vscrollbar_visible
)
443 dw
+= 15; /* dw += vscrollbar->allocation.width; */
444 dw
+= scroll_class
->scrollbar_spacing
;
447 if (scroll_window
->hscrollbar_visible
)
449 dh
+= 15; /* dh += hscrollbar->allocation.height; */
450 dh
+= scroll_class
->scrollbar_spacing
;
456 if (GTK_WIDGET_NO_WINDOW (widget
))
458 dx
+= widget
->allocation
.x
;
459 dy
+= widget
->allocation
.y
;
462 if (win
->HasFlag(wxRAISED_BORDER
))
464 gtk_draw_shadow( widget
->style
,
469 win
->m_width
-dw
, win
->m_height
-dh
);
473 if (win
->HasFlag(wxSUNKEN_BORDER
))
475 gtk_draw_shadow( widget
->style
,
480 win
->m_width
-dw
, win
->m_height
-dh
);
485 //-----------------------------------------------------------------------------
486 // "expose_event" of m_widget
487 //-----------------------------------------------------------------------------
489 static void gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
491 if (gdk_event
->count
> 0) return;
492 draw_frame( widget
, win
);
495 //-----------------------------------------------------------------------------
496 // "draw" of m_wxwindow
497 //-----------------------------------------------------------------------------
499 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
501 draw_frame( widget
, win
);
504 #endif // GTK_MINOR_VERSION > 0
506 //-----------------------------------------------------------------------------
507 // "expose_event" of m_wxwindow
508 //-----------------------------------------------------------------------------
510 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
512 if ( !win
->m_hasVMT
)
515 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
517 gdk_event
->area
.width
,
518 gdk_event
->area
.height
);
520 if ( gdk_event
->count
> 0 )
524 printf( "OnExpose from " );
525 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
526 printf( win->GetClassInfo()->GetClassName() );
530 wxPaintEvent
event( win
->GetId() );
531 event
.SetEventObject( win
);
532 win
->GetEventHandler()->ProcessEvent( event
);
534 win
->GetUpdateRegion().Clear();
537 //-----------------------------------------------------------------------------
538 // "draw" of m_wxwindow
539 //-----------------------------------------------------------------------------
541 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
544 wxapp_install_idle_handler();
549 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
550 rect
->width
, rect
->height
);
552 wxPaintEvent
event( win
->GetId() );
553 event
.SetEventObject( win
);
554 win
->GetEventHandler()->ProcessEvent( event
);
556 win
->GetUpdateRegion().Clear();
559 //-----------------------------------------------------------------------------
560 // "key_press_event" from any window
561 //-----------------------------------------------------------------------------
563 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
566 wxapp_install_idle_handler();
568 if (!win
->m_hasVMT
) return FALSE
;
569 if (g_blockEventsOnDrag
) return FALSE
;
572 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
573 if (gdk_event->state & GDK_SHIFT_MASK)
574 printf( "ShiftDown.\n" );
576 printf( "ShiftUp.\n" );
577 if (gdk_event->state & GDK_CONTROL_MASK)
578 printf( "ControlDown.\n" );
580 printf( "ControlUp.\n" );
585 GdkModifierType state
;
586 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
588 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
590 /* sending unknown key events doesn't really make sense */
591 if (key_code
== 0) return FALSE
;
595 wxKeyEvent
event( wxEVT_KEY_DOWN
);
596 event
.SetTimestamp( gdk_event
->time
);
597 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
598 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
599 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
600 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
601 event
.m_keyCode
= key_code
;
602 event
.m_scanCode
= gdk_event
->keyval
;
605 event
.SetEventObject( win
);
606 ret
= win
->GetEventHandler()->ProcessEvent( event
);
608 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
610 /* wxMSW doesn't send char events with Alt pressed */
611 if ((key_code
!= 0) &&
612 ((gdk_event
->state
& GDK_MOD1_MASK
) == 0) &&
613 ((gdk_event
->state
& GDK_MOD1_MASK
) == 0))
615 wxKeyEvent
event2( wxEVT_CHAR
);
616 event2
.SetTimestamp( gdk_event
->time
);
617 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
618 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
619 // event2.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
620 // event2.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
621 event2
.m_keyCode
= key_code
;
622 event2
.m_scanCode
= gdk_event
->keyval
;
625 event2
.SetEventObject( win
);
626 ret
= (ret
|| win
->GetEventHandler()->ProcessEvent( event2
));
631 wxWindow
*ancestor
= win
;
634 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
637 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
638 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
641 ancestor
= ancestor
->GetParent();
645 /* win is a control: tab can be propagated up */
647 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
648 (win
->HasFlag(wxTE_PROCESS_TAB
) == 0))
650 wxNavigationKeyEvent new_event
;
651 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
652 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
653 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
654 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
655 new_event
.SetCurrentFocus( win
);
656 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
659 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
661 (gdk_event
->keyval
== GDK_Escape
) )
663 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
664 new_event
.SetEventObject( win
);
665 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
668 #if (GTK_MINOR_VERSION > 0)
669 /* pressing F10 will activate the menu bar of the top frame */
671 (gdk_event
->keyval
== GDK_F10
) )
673 wxWindow
*ancestor
= win
;
676 if (wxIsKindOf(ancestor
,wxFrame
))
678 wxFrame
*frame
= (wxFrame
*) ancestor
;
679 wxMenuBar
*menubar
= frame
->GetMenuBar();
682 wxNode
*node
= menubar
->GetMenus().First();
685 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
686 // doesn't work correctly
687 // gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
693 ancestor
= ancestor
->GetParent();
699 Damn, I forgot why this didn't work, but it didn't work.
701 // win is a panel: up can be propagated to the panel
702 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
703 (gdk_event->keyval == GDK_Up))
705 win->m_parent->SetFocus();
709 // win is a panel: left/right can be propagated to the panel
710 if ((!ret) && (win->m_wxwindow) &&
711 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
712 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
714 wxNavigationKeyEvent new_event;
715 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
716 new_event.SetCurrentFocus( win );
717 ret = win->GetEventHandler()->ProcessEvent( new_event );
723 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
730 //-----------------------------------------------------------------------------
731 // "key_release_event" from any window
732 //-----------------------------------------------------------------------------
734 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
737 wxapp_install_idle_handler();
739 if (!win
->m_hasVMT
) return FALSE
;
740 if (g_blockEventsOnDrag
) return FALSE
;
743 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
744 if (gdk_event->state & GDK_SHIFT_MASK)
745 printf( "ShiftDown.\n" );
747 printf( "ShiftUp.\n" );
748 if (gdk_event->state & GDK_CONTROL_MASK)
749 printf( "ControlDown.\n" );
751 printf( "ControlUp.\n" );
755 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
757 /* sending unknown key events doesn't really make sense */
758 if (key_code
== 0) return FALSE
;
762 GdkModifierType state
;
763 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
765 wxKeyEvent
event( wxEVT_KEY_UP
);
766 event
.SetTimestamp( gdk_event
->time
);
767 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
768 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
769 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
770 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
771 event
.m_keyCode
= key_code
;
772 event
.m_scanCode
= gdk_event
->keyval
;
775 event
.SetEventObject( win
);
777 if (win
->GetEventHandler()->ProcessEvent( event
))
779 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
786 //-----------------------------------------------------------------------------
787 // "button_press_event"
788 //-----------------------------------------------------------------------------
790 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
793 wxapp_install_idle_handler();
796 wxPrintf( _T("1) OnButtonPress from ") );
797 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
798 wxPrintf( win->GetClassInfo()->GetClassName() );
799 wxPrintf( _T(".\n") );
801 if (!win
->m_hasVMT
) return FALSE
;
802 if (g_blockEventsOnDrag
) return TRUE
;
803 if (g_blockEventsOnScroll
) return TRUE
;
805 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
809 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
811 gtk_widget_grab_focus (win
->m_wxwindow
);
814 wxPrintf( _T("GrabFocus from ") );
815 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
816 wxPrintf( win->GetClassInfo()->GetClassName() );
817 wxPrintf( _T(".\n") );
824 wxPrintf( _T("2) OnButtonPress from ") );
825 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
826 wxPrintf( win->GetClassInfo()->GetClassName() );
827 wxPrintf( _T(".\n") );
830 wxEventType event_type
= wxEVT_LEFT_DOWN
;
832 if (gdk_event
->button
== 1)
834 switch (gdk_event
->type
)
836 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
837 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
841 else if (gdk_event
->button
== 2)
843 switch (gdk_event
->type
)
845 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
846 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
850 else if (gdk_event
->button
== 3)
852 switch (gdk_event
->type
)
854 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
855 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
860 wxMouseEvent
event( event_type
);
861 event
.SetTimestamp( gdk_event
->time
);
862 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
863 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
864 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
865 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
866 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
867 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
868 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
870 event
.m_x
= (long)gdk_event
->x
;
871 event
.m_y
= (long)gdk_event
->y
;
873 // Some control don't have their own X window and thus cannot get
878 wxNode
*node
= win
->GetChildren().First();
881 wxWindow
*child
= (wxWindow
*)node
->Data();
883 if (child
->m_isStaticBox
)
885 // wxStaticBox is transparent in the box itself
888 int xx1
= child
->m_x
;
889 int yy1
= child
->m_y
;
890 int xx2
= child
->m_x
+ child
->m_width
;
891 int yy2
= child
->m_x
+ child
->m_height
;
894 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
896 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
898 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
900 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
903 event
.m_x
-= child
->m_x
;
904 event
.m_y
-= child
->m_y
;
911 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
912 (child
->m_x
<= event
.m_x
) &&
913 (child
->m_y
<= event
.m_y
) &&
914 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
915 (child
->m_y
+child
->m_height
>= event
.m_y
))
918 event
.m_x
-= child
->m_x
;
919 event
.m_y
-= child
->m_y
;
927 event
.SetEventObject( win
);
929 gs_timeLastClick
= gdk_event
->time
;
931 if (win
->GetEventHandler()->ProcessEvent( event
))
933 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
940 //-----------------------------------------------------------------------------
941 // "button_release_event"
942 //-----------------------------------------------------------------------------
944 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
947 wxapp_install_idle_handler();
949 if (!win
->m_hasVMT
) return FALSE
;
950 if (g_blockEventsOnDrag
) return FALSE
;
951 if (g_blockEventsOnScroll
) return FALSE
;
953 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
956 printf( "OnButtonRelease from " );
957 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
958 printf( win->GetClassInfo()->GetClassName() );
962 wxEventType event_type
= wxEVT_NULL
;
964 switch (gdk_event
->button
)
966 case 1: event_type
= wxEVT_LEFT_UP
; break;
967 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
968 case 3: event_type
= wxEVT_RIGHT_UP
; break;
971 wxMouseEvent
event( event_type
);
972 event
.SetTimestamp( gdk_event
->time
);
973 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
974 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
975 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
976 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
977 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
978 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
979 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
980 event
.m_x
= (long)gdk_event
->x
;
981 event
.m_y
= (long)gdk_event
->y
;
983 // Some control don't have their own X window and thus cannot get
988 wxNode
*node
= win
->GetChildren().First();
991 wxWindow
*child
= (wxWindow
*)node
->Data();
993 if (child
->m_isStaticBox
)
995 // wxStaticBox is transparent in the box itself
998 int xx1
= child
->m_x
;
999 int yy1
= child
->m_y
;
1000 int xx2
= child
->m_x
+ child
->m_width
;
1001 int yy2
= child
->m_x
+ child
->m_height
;
1004 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1006 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1008 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1010 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1013 event
.m_x
-= child
->m_x
;
1014 event
.m_y
-= child
->m_y
;
1021 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1022 (child
->m_x
<= event
.m_x
) &&
1023 (child
->m_y
<= event
.m_y
) &&
1024 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
1025 (child
->m_y
+child
->m_height
>= event
.m_y
))
1028 event
.m_x
-= child
->m_x
;
1029 event
.m_y
-= child
->m_y
;
1033 node
= node
->Next();
1037 event
.SetEventObject( win
);
1039 if (win
->GetEventHandler()->ProcessEvent( event
))
1041 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1048 //-----------------------------------------------------------------------------
1049 // "motion_notify_event"
1050 //-----------------------------------------------------------------------------
1052 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1055 wxapp_install_idle_handler();
1057 if (!win
->m_hasVMT
) return FALSE
;
1058 if (g_blockEventsOnDrag
) return FALSE
;
1059 if (g_blockEventsOnScroll
) return FALSE
;
1061 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1063 if (gdk_event
->is_hint
)
1067 GdkModifierType state
;
1068 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1071 gdk_event
->state
= state
;
1075 printf( "OnMotion from " );
1076 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1077 printf( win->GetClassInfo()->GetClassName() );
1081 wxMouseEvent
event( wxEVT_MOTION
);
1082 event
.SetTimestamp( gdk_event
->time
);
1083 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1084 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1085 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1086 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1087 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1088 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1089 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1091 event
.m_x
= (long)gdk_event
->x
;
1092 event
.m_y
= (long)gdk_event
->y
;
1094 // Some control don't have their own X window and thus cannot get
1099 wxNode
*node
= win
->GetChildren().First();
1102 wxWindow
*child
= (wxWindow
*)node
->Data();
1104 if (child
->m_isStaticBox
)
1106 // wxStaticBox is transparent in the box itself
1109 int xx1
= child
->m_x
;
1110 int yy1
= child
->m_y
;
1111 int xx2
= child
->m_x
+ child
->m_width
;
1112 int yy2
= child
->m_x
+ child
->m_height
;
1115 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1117 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1119 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1121 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1124 event
.m_x
-= child
->m_x
;
1125 event
.m_y
-= child
->m_y
;
1132 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1133 (child
->m_x
<= event
.m_x
) &&
1134 (child
->m_y
<= event
.m_y
) &&
1135 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
1136 (child
->m_y
+child
->m_height
>= event
.m_y
))
1139 event
.m_x
-= child
->m_x
;
1140 event
.m_y
-= child
->m_y
;
1144 node
= node
->Next();
1148 event
.SetEventObject( win
);
1150 if (win
->GetEventHandler()->ProcessEvent( event
))
1152 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1159 //-----------------------------------------------------------------------------
1161 //-----------------------------------------------------------------------------
1163 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1166 wxapp_install_idle_handler();
1168 if (!win
->m_hasVMT
) return FALSE
;
1169 if (g_blockEventsOnDrag
) return FALSE
;
1171 g_focusWindow
= win
;
1173 if (win
->m_wxwindow
)
1175 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1177 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1179 printf( "SetFocus flag from " );
1180 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1181 printf( win->GetClassInfo()->GetClassName() );
1189 printf( "OnSetFocus from " );
1190 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1191 printf( win->GetClassInfo()->GetClassName() );
1193 printf( WXSTRINGCAST win->GetLabel() );
1197 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1198 event
.SetEventObject( win
);
1200 if (win
->GetEventHandler()->ProcessEvent( event
))
1202 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1209 //-----------------------------------------------------------------------------
1210 // "focus_out_event"
1211 //-----------------------------------------------------------------------------
1213 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1216 wxapp_install_idle_handler();
1218 if (!win
->m_hasVMT
) return FALSE
;
1219 if (g_blockEventsOnDrag
) return FALSE
;
1221 if (win
->m_wxwindow
)
1223 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1224 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1228 printf( "OnKillFocus from " );
1229 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1230 printf( win->GetClassInfo()->GetClassName() );
1234 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1235 event
.SetEventObject( win
);
1237 if (win
->GetEventHandler()->ProcessEvent( event
))
1239 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1246 //-----------------------------------------------------------------------------
1247 // "enter_notify_event"
1248 //-----------------------------------------------------------------------------
1250 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1253 wxapp_install_idle_handler();
1255 if (!win
->m_hasVMT
) return FALSE
;
1256 if (g_blockEventsOnDrag
) return FALSE
;
1258 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1260 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1261 #if (GTK_MINOR_VERSION > 0)
1262 event
.SetTimestamp( gdk_event
->time
);
1264 event
.SetEventObject( win
);
1268 GdkModifierType state
= (GdkModifierType
)0;
1270 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1272 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1273 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1274 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1275 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1276 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1277 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1278 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1280 event
.m_x
= (long)x
;
1281 event
.m_y
= (long)y
;
1283 if (win
->GetEventHandler()->ProcessEvent( event
))
1285 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1292 //-----------------------------------------------------------------------------
1293 // "leave_notify_event"
1294 //-----------------------------------------------------------------------------
1296 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1299 wxapp_install_idle_handler();
1301 if (!win
->m_hasVMT
) return FALSE
;
1302 if (g_blockEventsOnDrag
) return FALSE
;
1304 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1306 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1307 #if (GTK_MINOR_VERSION > 0)
1308 event
.SetTimestamp( gdk_event
->time
);
1310 event
.SetEventObject( win
);
1314 GdkModifierType state
= (GdkModifierType
)0;
1316 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1318 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1319 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1320 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1321 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1322 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1323 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1324 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1326 event
.m_x
= (long)x
;
1327 event
.m_y
= (long)y
;
1329 if (win
->GetEventHandler()->ProcessEvent( event
))
1331 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1338 //-----------------------------------------------------------------------------
1339 // "value_changed" from m_vAdjust
1340 //-----------------------------------------------------------------------------
1342 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1345 wxapp_install_idle_handler();
1347 if (g_blockEventsOnDrag
) return;
1349 if (!win
->m_hasVMT
) return;
1351 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
1352 if (fabs(diff
) < 0.2) return;
1353 win
->m_oldVerticalPos
= win
->m_vAdjust
->value
;
1355 wxEventType command
= wxEVT_NULL
;
1357 float line_step
= win
->m_vAdjust
->step_increment
;
1358 float page_step
= win
->m_vAdjust
->page_increment
;
1360 if (win
->IsScrolling())
1362 command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1366 if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->lower
) < 0.2) command
= wxEVT_SCROLLWIN_BOTTOM
;
1367 else if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->upper
) < 0.2) command
= wxEVT_SCROLLWIN_TOP
;
1368 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1369 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEUP
;
1370 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1371 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEUP
;
1372 else command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1375 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1377 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1378 event
.SetEventObject( win
);
1379 win
->GetEventHandler()->ProcessEvent( event
);
1382 //-----------------------------------------------------------------------------
1383 // "value_changed" from m_hAdjust
1384 //-----------------------------------------------------------------------------
1386 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1389 wxapp_install_idle_handler();
1391 if (g_blockEventsOnDrag
) return;
1392 if (!win
->m_hasVMT
) return;
1394 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
1395 if (fabs(diff
) < 0.2) return;
1396 win
->m_oldHorizontalPos
= win
->m_hAdjust
->value
;
1398 wxEventType command
= wxEVT_NULL
;
1400 float line_step
= win
->m_hAdjust
->step_increment
;
1401 float page_step
= win
->m_hAdjust
->page_increment
;
1403 if (win
->IsScrolling())
1405 command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1409 if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->lower
) < 0.2) command
= wxEVT_SCROLLWIN_BOTTOM
;
1410 else if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->upper
) < 0.2) command
= wxEVT_SCROLLWIN_TOP
;
1411 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1412 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEUP
;
1413 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1414 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEUP
;
1415 else command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1418 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1420 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1421 event
.SetEventObject( win
);
1422 win
->GetEventHandler()->ProcessEvent( event
);
1425 //-----------------------------------------------------------------------------
1426 // "changed" from m_vAdjust
1427 //-----------------------------------------------------------------------------
1429 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1432 wxapp_install_idle_handler();
1434 if (g_blockEventsOnDrag
) return;
1435 if (!win
->m_hasVMT
) return;
1437 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1438 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1440 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1441 event
.SetEventObject( win
);
1442 win
->GetEventHandler()->ProcessEvent( event
);
1445 //-----------------------------------------------------------------------------
1446 // "changed" from m_hAdjust
1447 //-----------------------------------------------------------------------------
1449 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1452 wxapp_install_idle_handler();
1454 if (g_blockEventsOnDrag
) return;
1455 if (!win
->m_hasVMT
) return;
1457 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1458 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1460 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1461 event
.SetEventObject( win
);
1462 win
->GetEventHandler()->ProcessEvent( event
);
1465 //-----------------------------------------------------------------------------
1466 // "button_press_event" from scrollbar
1467 //-----------------------------------------------------------------------------
1469 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1470 GdkEventButton
*WXUNUSED(gdk_event
),
1474 wxapp_install_idle_handler();
1476 // don't test here as we can release the mouse while being over
1477 // a different window then the slider
1479 // if (gdk_event->window != widget->slider) return FALSE;
1481 win
->SetScrolling( TRUE
);
1486 //-----------------------------------------------------------------------------
1487 // "button_release_event" from scrollbar
1488 //-----------------------------------------------------------------------------
1490 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1491 GdkEventButton
*WXUNUSED(gdk_event
),
1495 // don't test here as we can release the mouse while being over
1496 // a different window then the slider
1498 // if (gdk_event->window != widget->slider) return FALSE;
1500 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1502 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1503 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_hAdjust
), "value_changed" );
1505 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_vAdjust
), "value_changed" );
1507 win
->SetScrolling( FALSE
);
1512 // ----------------------------------------------------------------------------
1513 // this wxWindowBase function is implemented here (in platform-specific file)
1514 // because it is static and so couldn't be made virtual
1515 // ----------------------------------------------------------------------------
1517 wxWindow
*wxWindowBase::FindFocus()
1519 return g_focusWindow
;
1522 //-----------------------------------------------------------------------------
1523 // "realize" from m_widget
1524 //-----------------------------------------------------------------------------
1526 /* we cannot set colours, fonts and cursors before the widget has
1527 been realized, so we do this directly after realization */
1530 gtk_window_realized_callback( GtkWidget
* WXUNUSED(widget
), wxWindow
*win
)
1533 wxapp_install_idle_handler();
1535 if (win
->m_delayedFont
)
1536 win
->SetFont( win
->GetFont() );
1538 if (win
->m_delayedBackgroundColour
)
1539 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1541 if (win
->m_delayedForegroundColour
)
1542 win
->SetForegroundColour( win
->GetForegroundColour() );
1544 win
->SetCursor( win
->GetCursor() );
1546 wxWindowCreateEvent
event( win
);
1547 event
.SetEventObject( win
);
1548 win
->GetEventHandler()->ProcessEvent( event
);
1553 //-----------------------------------------------------------------------------
1554 // InsertChild for wxWindow.
1555 //-----------------------------------------------------------------------------
1557 /* Callback for wxWindow. This very strange beast has to be used because
1558 * C++ has no virtual methods in a constructor. We have to emulate a
1559 * virtual function here as wxNotebook requires a different way to insert
1560 * a child in it. I had opted for creating a wxNotebookPage window class
1561 * which would have made this superfluous (such in the MDI window system),
1562 * but no-one was listening to me... */
1564 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1566 gtk_myfixed_put( GTK_MYFIXED(parent
->m_wxwindow
),
1567 GTK_WIDGET(child
->m_widget
),
1573 if (parent
->HasFlag(wxTAB_TRAVERSAL
))
1575 /* we now allow a window to get the focus as long as it
1576 doesn't have any children. */
1577 GTK_WIDGET_UNSET_FLAGS( parent
->m_wxwindow
, GTK_CAN_FOCUS
);
1581 //-----------------------------------------------------------------------------
1583 //-----------------------------------------------------------------------------
1585 wxWindow
* wxGetActiveWindow()
1587 return g_focusWindow
;
1590 //-----------------------------------------------------------------------------
1592 //-----------------------------------------------------------------------------
1594 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1596 void wxWindow::Init()
1602 m_widget
= (GtkWidget
*) NULL
;
1603 m_wxwindow
= (GtkWidget
*) NULL
;
1613 m_needParent
= TRUE
;
1614 m_isBeingDeleted
= FALSE
;
1616 m_hasScrolling
= FALSE
;
1617 m_isScrolling
= FALSE
;
1619 m_hAdjust
= (GtkAdjustment
*) NULL
;
1620 m_vAdjust
= (GtkAdjustment
*) NULL
;
1621 m_oldHorizontalPos
= 0.0;
1622 m_oldVerticalPos
= 0.0;
1625 m_scrollGC
= (GdkGC
*) NULL
;
1626 m_widgetStyle
= (GtkStyle
*) NULL
;
1628 m_insertCallback
= wxInsertChildInWindow
;
1630 m_isStaticBox
= FALSE
;
1631 m_acceptsFocus
= FALSE
;
1634 wxWindow::wxWindow()
1639 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1640 const wxPoint
&pos
, const wxSize
&size
,
1641 long style
, const wxString
&name
)
1645 Create( parent
, id
, pos
, size
, style
, name
);
1648 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1649 const wxPoint
&pos
, const wxSize
&size
,
1650 long style
, const wxString
&name
)
1652 PreCreation( parent
, id
, pos
, size
, style
, name
);
1654 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1655 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1658 debug_focus_in( m_widget
, _T("wxWindow::m_widget"), name
);
1661 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1664 debug_focus_in( scrolledWindow
->hscrollbar
, _T("wxWindow::hsrcollbar"), name
);
1665 debug_focus_in( scrolledWindow
->vscrollbar
, _T("wxWindow::vsrcollbar"), name
);
1668 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1669 scroll_class
->scrollbar_spacing
= 0;
1671 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1673 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
1674 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
1676 m_wxwindow
= gtk_myfixed_new();
1679 debug_focus_in( m_wxwindow
, _T("wxWindow::m_wxwindow"), name
);
1682 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1684 #if (GTK_MINOR_VERSION > 0)
1685 GtkMyFixed
*myfixed
= GTK_MYFIXED(m_wxwindow
);
1687 if (HasFlag(wxRAISED_BORDER
))
1689 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_OUT
);
1691 else if (HasFlag(wxSUNKEN_BORDER
))
1693 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_IN
);
1697 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_NONE
);
1699 #else // GTK_MINOR_VERSION == 0
1700 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
1702 if (HasFlag(wxRAISED_BORDER
))
1704 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1706 else if (HasFlag(wxSUNKEN_BORDER
))
1708 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1712 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1714 #endif // GTK_MINOR_VERSION
1716 if (HasFlag(wxTAB_TRAVERSAL
))
1718 /* we now allow a window to get the focus as long as it
1719 doesn't have any children. */
1720 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1721 m_acceptsFocus
= FALSE
;
1725 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1726 m_acceptsFocus
= TRUE
;
1729 #if (GTK_MINOR_VERSION == 0)
1730 // shut the viewport up
1731 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1732 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1733 #endif // GTK_MINOR_VERSION == 0
1735 // I _really_ don't want scrollbars in the beginning
1736 m_vAdjust
->lower
= 0.0;
1737 m_vAdjust
->upper
= 1.0;
1738 m_vAdjust
->value
= 0.0;
1739 m_vAdjust
->step_increment
= 1.0;
1740 m_vAdjust
->page_increment
= 1.0;
1741 m_vAdjust
->page_size
= 5.0;
1742 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1743 m_hAdjust
->lower
= 0.0;
1744 m_hAdjust
->upper
= 1.0;
1745 m_hAdjust
->value
= 0.0;
1746 m_hAdjust
->step_increment
= 1.0;
1747 m_hAdjust
->page_increment
= 1.0;
1748 m_hAdjust
->page_size
= 5.0;
1749 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1751 // these handlers block mouse events to any window during scrolling such as
1752 // motion events and prevent GTK and wxWindows from fighting over where the
1755 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
1756 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1758 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
1759 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1761 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
1762 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1764 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
1765 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1767 // these handlers get notified when screen updates are required either when
1768 // scrolling or when the window size (and therefore scrollbar configuration)
1771 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
1772 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
1773 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
1774 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
1776 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
1777 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
1778 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
1779 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
1781 gtk_widget_show( m_wxwindow
);
1784 m_parent
->DoAddChild( this );
1793 wxWindow::~wxWindow()
1795 m_isBeingDeleted
= TRUE
;
1804 m_parent
->RemoveChild( this );
1808 gtk_style_unref( m_widgetStyle
);
1809 m_widgetStyle
= (GtkStyle
*) NULL
;
1814 gdk_gc_unref( m_scrollGC
);
1815 m_scrollGC
= (GdkGC
*) NULL
;
1820 gtk_widget_destroy( m_wxwindow
);
1821 m_wxwindow
= (GtkWidget
*) NULL
;
1826 gtk_widget_destroy( m_widget
);
1827 m_widget
= (GtkWidget
*) NULL
;
1831 void wxWindow::PreCreation( wxWindow
*parent
,
1836 const wxString
&name
)
1838 wxASSERT_MSG( !m_needParent
|| parent
, _T("Need complete parent.") );
1840 if ( !CreateBase(parent
, id
, pos
, size
, style
, name
) )
1842 wxFAIL_MSG(_T("window creation failed"));
1845 m_width
= WidthDefault(size
.x
);
1846 m_height
= HeightDefault(size
.y
);
1851 if (!parent
) /* some reasonable defaults */
1855 m_x
= (gdk_screen_width () - m_width
) / 2;
1856 if (m_x
< 10) m_x
= 10;
1860 m_y
= (gdk_screen_height () - m_height
) / 2;
1861 if (m_y
< 10) m_y
= 10;
1866 void wxWindow::PostCreation()
1868 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1872 /* these get reported to wxWindows -> wxPaintEvent */
1873 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1874 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1876 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1877 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1879 #if (GTK_MINOR_VERSION > 0)
1880 /* these are called when the "sunken" or "raised" borders are drawn */
1881 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
1882 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
1884 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
1885 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
1889 GtkWidget
*connect_widget
= GetConnectWidget();
1891 ConnectWidget( connect_widget
);
1893 /* we cannot set colours, fonts and cursors before the widget has
1894 been realized, so we do this directly after realization */
1895 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
1896 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
1901 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1903 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1904 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1906 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
1907 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
1909 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1910 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1912 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1913 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1915 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1916 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1918 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1919 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1921 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1922 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1924 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1925 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1927 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1928 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1931 bool wxWindow::Destroy()
1933 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1937 return wxWindowBase::Destroy();
1940 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1942 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1943 wxASSERT_MSG( (m_parent
!= NULL
), _T("wxWindow::SetSize requires parent.\n") );
1945 if (m_resizing
) return; /* I don't like recursions */
1948 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
1950 /* don't set the size for children of wxNotebook, just take the values. */
1958 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1960 if (x
!= -1) m_x
= x
;
1961 if (y
!= -1) m_y
= y
;
1962 if (width
!= -1) m_width
= width
;
1963 if (height
!= -1) m_height
= height
;
1973 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1975 if (width
== -1) m_width
= 80;
1978 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1980 if (height
== -1) m_height
= 26;
1983 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1984 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1985 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
1986 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
1989 int bottom_border
= 0;
1991 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
1993 /* the default button has a border around it */
1998 /* this is the result of hours of debugging: the following code
1999 means that if we have a m_wxwindow and we set the size of
2000 m_widget, m_widget (which is a GtkScrolledWindow) does NOT
2001 automatically propagate its size down to its m_wxwindow,
2002 which is its client area. therefore, we have to tell the
2003 client area directly that it has to resize itself.
2004 this will lead to that m_widget (GtkScrolledWindow) will
2005 calculate how much size it needs for scrollbars etc and
2006 it will then call XXX_size_allocate of its child, which
2007 is m_wxwindow. m_wxwindow in turn will do the same with its
2008 children and so on. problems can arise if this happens
2009 before all the children have been realized as some widgets
2010 stupidy need to be realized during XXX_size_allocate (e.g.
2011 GtkNotebook) and they will segv if called otherwise. this
2012 emergency is tested in gtk_myfixed_size_allocate. Normally
2013 this shouldn't be needed and only gtk_widget_queue_resize()
2014 should be enough to provoke a resize at the next appropriate
2015 moment, but this seems to fail, e.g. when a wxNotebook contains
2016 a wxSplitterWindow: the splitter window's children won't
2017 show up properly resized then. */
2019 gtk_myfixed_set_size( GTK_MYFIXED(m_parent
->m_wxwindow
),
2024 m_height
+border
+bottom_border
);
2029 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2030 event
.SetEventObject( this );
2031 GetEventHandler()->ProcessEvent( event
);
2036 void wxWindow::OnInternalIdle()
2038 GdkWindow
*window
= GetConnectWidget()->window
;
2041 wxCursor cursor
= m_cursor
;
2042 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2044 if (m_currentGdkCursor
!= cursor
)
2046 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2047 m_currentGdkCursor
= cursor
;
2054 void wxWindow::DoGetSize( int *width
, int *height
) const
2056 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2058 if (width
) (*width
) = m_width
;
2059 if (height
) (*height
) = m_height
;
2062 void wxWindow::DoSetClientSize( int width
, int height
)
2064 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2068 SetSize( width
, height
);
2075 if (!m_hasScrolling
)
2077 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
2079 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2081 dw
+= 2 * window_class
->xthickness
;
2082 dh
+= 2 * window_class
->ythickness
;
2087 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2088 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2090 #if (GTK_MINOR_VERSION == 0)
2091 GtkWidget
*viewport
= scroll_window
->viewport
;
2092 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2094 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2096 dw
+= 2 * viewport_class
->xthickness
;
2097 dh
+= 2 * viewport_class
->ythickness
;
2102 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2103 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2105 we use this instead: range.slider_width = 11 + 2*2pts edge
2108 if (scroll_window
->vscrollbar_visible
)
2110 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2111 dw
+= scroll_class
->scrollbar_spacing
;
2114 if (scroll_window
->hscrollbar_visible
)
2116 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2117 dh
+= scroll_class
->scrollbar_spacing
;
2121 SetSize( width
+dw
, height
+dh
);
2125 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2127 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2131 if (width
) (*width
) = m_width
;
2132 if (height
) (*height
) = m_height
;
2139 if (!m_hasScrolling
)
2141 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
2143 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2145 dw
+= 2 * window_class
->xthickness
;
2146 dh
+= 2 * window_class
->ythickness
;
2151 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2152 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2154 #if (GTK_MINOR_VERSION == 0)
2155 GtkWidget
*viewport
= scroll_window
->viewport
;
2156 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2158 if ( HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
) )
2160 dw
+= 2 * viewport_class
->xthickness
;
2161 dh
+= 2 * viewport_class
->ythickness
;
2165 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2166 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2168 we use this instead: range.slider_width = 11 + 2*2pts edge
2171 if (scroll_window
->vscrollbar_visible
)
2173 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2174 dw
+= scroll_class
->scrollbar_spacing
;
2177 if (scroll_window
->hscrollbar_visible
)
2179 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2180 dh
+= scroll_class
->scrollbar_spacing
;
2184 if (width
) (*width
) = m_width
- dw
;
2185 if (height
) (*height
) = m_height
- dh
;
2189 void wxWindow::DoGetPosition( int *x
, int *y
) const
2191 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2197 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2199 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2201 if (!m_widget
->window
) return;
2203 GdkWindow
*source
= (GdkWindow
*) NULL
;
2205 source
= m_wxwindow
->window
;
2207 source
= m_widget
->window
;
2211 gdk_window_get_origin( source
, &org_x
, &org_y
);
2215 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2217 org_x
+= m_widget
->allocation
.x
;
2218 org_y
+= m_widget
->allocation
.y
;
2226 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2228 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2230 if (!m_widget
->window
) return;
2232 GdkWindow
*source
= (GdkWindow
*) NULL
;
2234 source
= m_wxwindow
->window
;
2236 source
= m_widget
->window
;
2240 gdk_window_get_origin( source
, &org_x
, &org_y
);
2244 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2246 org_x
+= m_widget
->allocation
.x
;
2247 org_y
+= m_widget
->allocation
.y
;
2255 bool wxWindow::Show( bool show
)
2257 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2259 if (!wxWindowBase::Show(show
))
2266 gtk_widget_show( m_widget
);
2268 gtk_widget_hide( m_widget
);
2273 bool wxWindow::Enable( bool enable
)
2275 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2277 if (!wxWindowBase::Enable(enable
))
2283 gtk_widget_set_sensitive( m_widget
, enable
);
2285 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2290 int wxWindow::GetCharHeight() const
2292 wxCHECK_MSG( (m_widget
!= NULL
), 12, _T("invalid window") );
2294 wxCHECK_MSG( m_font
.Ok(), 12, _T("invalid font") );
2296 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2298 return font
->ascent
+ font
->descent
;
2301 int wxWindow::GetCharWidth() const
2303 wxCHECK_MSG( (m_widget
!= NULL
), 8, _T("invalid window") );
2305 wxCHECK_MSG( m_font
.Ok(), 8, _T("invalid font") );
2307 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2309 return gdk_string_width( font
, "H" );
2312 void wxWindow::GetTextExtent( const wxString
& string
,
2316 int *externalLeading
,
2317 const wxFont
*theFont
) const
2319 wxFont fontToUse
= m_font
;
2320 if (theFont
) fontToUse
= *theFont
;
2322 wxCHECK_RET( fontToUse
.Ok(), _T("invalid font") );
2324 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2325 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2326 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2327 if (descent
) (*descent
) = font
->descent
;
2328 if (externalLeading
) (*externalLeading
) = 0; // ??
2331 void wxWindow::SetFocus()
2333 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2335 GtkWidget
*connect_widget
= GetConnectWidget();
2338 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2340 gtk_widget_grab_focus (connect_widget
);
2342 else if (GTK_IS_CONTAINER(connect_widget
))
2344 gtk_container_focus( GTK_CONTAINER(connect_widget
), GTK_DIR_TAB_FORWARD
);
2352 bool wxWindow::AcceptsFocus() const
2354 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2357 bool wxWindow::Reparent( wxWindow
*newParent
)
2359 wxCHECK_MSG( (m_widget
!= NULL
), (wxWindow
*) NULL
, _T("invalid window") );
2361 gtk_widget_unparent( m_widget
);
2363 if ( !wxWindowBase::Reparent(newParent
) )
2369 void wxWindow::Raise()
2371 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2373 if (!m_widget
->window
) return;
2375 gdk_window_raise( m_widget
->window
);
2378 void wxWindow::Lower()
2380 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2382 if (!m_widget
->window
) return;
2384 gdk_window_lower( m_widget
->window
);
2387 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2389 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2391 if (!wxWindowBase::SetCursor(cursor
))
2393 // don't leave if the GTK widget has just
2395 if (!m_delayedCursor
) return FALSE
;
2398 GtkWidget
*connect_widget
= GetConnectWidget();
2399 if (!connect_widget
->window
)
2401 // indicate that a new style has been set
2402 // but it couldn't get applied as the
2403 // widget hasn't been realized yet.
2404 m_delayedCursor
= TRUE
;
2406 // pretend we have done something
2410 // gdk_window_set_cursor( connect_widget->window, GetCursor().GetCursor() );
2416 void wxWindow::WarpPointer( int WXUNUSED(x
), int WXUNUSED(y
) )
2421 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2423 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2425 if (!m_widget
->window
) return;
2427 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2431 gdk_window_clear_area( m_wxwindow
->window
,
2433 rect
->width
, rect
->height
);
2437 gdk_window_clear( m_wxwindow
->window
);
2444 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2446 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2450 GdkRectangle gdk_rect
;
2451 gdk_rect
.x
= rect
->x
;
2452 gdk_rect
.y
= rect
->y
;
2453 gdk_rect
.width
= rect
->width
;
2454 gdk_rect
.height
= rect
->height
;
2457 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2459 gtk_widget_draw( m_widget
, &gdk_rect
);
2463 void wxWindow::Clear()
2465 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2467 if (!m_widget
->window
) return;
2469 if (m_wxwindow
&& m_wxwindow
->window
)
2471 gdk_window_clear( m_wxwindow
->window
);
2476 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2478 wxWindowBase::DoSetToolTip(tip
);
2481 m_tooltip
->Apply( this );
2484 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2486 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConv_current
->cWX2MB(tip
), (gchar
*) NULL
);
2488 #endif // wxUSE_TOOLTIPS
2490 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2492 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2494 if (!wxWindowBase::SetBackgroundColour(colour
))
2496 // don't leave if the GTK widget has just
2498 if (!m_delayedBackgroundColour
) return FALSE
;
2501 GtkWidget
*connect_widget
= GetConnectWidget();
2502 if (!connect_widget
->window
)
2504 // indicate that a new style has been set
2505 // but it couldn't get applied as the
2506 // widget hasn't been realized yet.
2507 m_delayedBackgroundColour
= TRUE
;
2509 // pretend we have done something
2513 if (m_wxwindow
&& m_wxwindow
->window
)
2515 /* wxMSW doesn't clear the window here. I don't do that either to
2516 provide compatibility. call Clear() to do the job. */
2518 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_wxwindow
->window
) );
2519 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
2522 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2524 if (sysbg
== m_backgroundColour
)
2526 m_backgroundColour
= wxNullColour
;
2528 m_backgroundColour
= sysbg
;
2538 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2540 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2542 if (!wxWindowBase::SetForegroundColour(colour
))
2544 // don't leave if the GTK widget has just
2546 if (!m_delayedForegroundColour
) return FALSE
;
2549 GtkWidget
*connect_widget
= GetConnectWidget();
2550 if (!connect_widget
->window
)
2552 // indicate that a new style has been set
2553 // but it couldn't get applied as the
2554 // widget hasn't been realized yet.
2555 m_delayedForegroundColour
= TRUE
;
2557 // pretend we have done something
2561 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2562 if (sysbg
== m_foregroundColour
)
2564 m_backgroundColour
= wxNullColour
;
2566 m_backgroundColour
= sysbg
;
2576 GtkStyle
*wxWindow::GetWidgetStyle()
2578 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2580 m_widgetStyle
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2582 return m_widgetStyle
;
2585 void wxWindow::SetWidgetStyle()
2587 GtkStyle
*style
= GetWidgetStyle();
2589 gdk_font_unref( style
->font
);
2590 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2592 if (m_foregroundColour
.Ok())
2594 m_foregroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2595 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2596 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2597 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2600 if (m_backgroundColour
.Ok())
2602 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2603 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2604 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2605 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2606 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2607 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2608 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2609 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2610 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2614 void wxWindow::ApplyWidgetStyle()
2618 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2620 menu
->SetInvokingWindow( win
);
2621 wxNode
*node
= menu
->GetItems().First();
2624 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2625 if (menuitem
->IsSubMenu())
2627 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2629 node
= node
->Next();
2633 static gint gs_pop_x
= 0;
2634 static gint gs_pop_y
= 0;
2636 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
2640 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
2645 bool wxWindow::PopupMenu( wxMenu
*menu
, int x
, int y
)
2647 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2649 wxCHECK_MSG( menu
!= NULL
, FALSE
, _T("invalid popup-menu") );
2651 SetInvokingWindow( menu
, this );
2659 GTK_MENU(menu
->m_menu
),
2660 (GtkWidget
*) NULL
, // parent menu shell
2661 (GtkWidget
*) NULL
, // parent menu item
2662 (GtkMenuPositionFunc
) pop_pos_callback
,
2663 (gpointer
) this, // client data
2664 0, // button used to activate it
2665 0 //gs_timeLastClick // the time of activation
2670 #if wxUSE_DRAG_AND_DROP
2672 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2674 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2676 GtkWidget
*dnd_widget
= GetConnectWidget();
2678 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
2680 if (m_dropTarget
) delete m_dropTarget
;
2681 m_dropTarget
= dropTarget
;
2683 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
2686 #endif // wxUSE_DRAG_AND_DROP
2688 GtkWidget
* wxWindow::GetConnectWidget()
2690 GtkWidget
*connect_widget
= m_widget
;
2691 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2693 return connect_widget
;
2696 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2698 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2699 return (window
== m_widget
->window
);
2702 bool wxWindow::SetFont( const wxFont
&font
)
2704 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T( "invalid window") );
2706 if (!wxWindowBase::SetFont(font
))
2708 // don't leave if the GTK widget has just
2710 if (!m_delayedFont
) return FALSE
;
2713 GtkWidget
*connect_widget
= GetConnectWidget();
2714 if (!connect_widget
->window
)
2716 // indicate that a new style has been set
2717 // but it couldn't get applied as the
2718 // widget hasn't been realized yet.
2719 m_delayedFont
= TRUE
;
2721 // pretend we have done something
2725 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2726 if ( sysbg
== m_backgroundColour
)
2728 m_backgroundColour
= wxNullColour
;
2730 m_backgroundColour
= sysbg
;
2740 void wxWindow::CaptureMouse()
2742 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2744 wxCHECK_RET( g_capturing
== FALSE
, _T("CaptureMouse called twice") );
2746 GtkWidget
*connect_widget
= GetConnectWidget();
2747 if (!connect_widget
->window
) return;
2749 gtk_grab_add( connect_widget
);
2750 gdk_pointer_grab( connect_widget
->window
, FALSE
,
2752 (GDK_BUTTON_PRESS_MASK
|
2753 GDK_BUTTON_RELEASE_MASK
|
2754 GDK_POINTER_MOTION_MASK
),
2761 void wxWindow::ReleaseMouse()
2763 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2765 wxCHECK_RET( g_capturing
== TRUE
, _T("ReleaseMouse called twice") );
2767 GtkWidget
*connect_widget
= GetConnectWidget();
2768 if (!connect_widget
->window
) return;
2770 gtk_grab_remove( connect_widget
);
2771 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2772 g_capturing
= FALSE
;
2775 bool wxWindow::IsRetained() const
2780 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2781 int range
, bool refresh
)
2783 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2785 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2787 m_hasScrolling
= TRUE
;
2789 if (orient
== wxHORIZONTAL
)
2791 float fpos
= (float)pos
;
2792 float frange
= (float)range
;
2793 float fthumb
= (float)thumbVisible
;
2794 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2795 if (fpos
< 0.0) fpos
= 0.0;
2797 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2798 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2800 SetScrollPos( orient
, pos
, refresh
);
2804 m_oldHorizontalPos
= fpos
;
2806 m_hAdjust
->lower
= 0.0;
2807 m_hAdjust
->upper
= frange
;
2808 m_hAdjust
->value
= fpos
;
2809 m_hAdjust
->step_increment
= 1.0;
2810 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2811 m_hAdjust
->page_size
= fthumb
;
2815 float fpos
= (float)pos
;
2816 float frange
= (float)range
;
2817 float fthumb
= (float)thumbVisible
;
2818 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2819 if (fpos
< 0.0) fpos
= 0.0;
2821 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2822 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2824 SetScrollPos( orient
, pos
, refresh
);
2828 m_oldVerticalPos
= fpos
;
2830 m_vAdjust
->lower
= 0.0;
2831 m_vAdjust
->upper
= frange
;
2832 m_vAdjust
->value
= fpos
;
2833 m_vAdjust
->step_increment
= 1.0;
2834 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2835 m_vAdjust
->page_size
= fthumb
;
2838 if (orient
== wxHORIZONTAL
)
2839 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2841 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2844 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2846 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2848 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2850 if (orient
== wxHORIZONTAL
)
2852 float fpos
= (float)pos
;
2853 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
2854 if (fpos
< 0.0) fpos
= 0.0;
2855 m_oldHorizontalPos
= fpos
;
2857 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2858 m_hAdjust
->value
= fpos
;
2862 float fpos
= (float)pos
;
2863 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
2864 if (fpos
< 0.0) fpos
= 0.0;
2865 m_oldVerticalPos
= fpos
;
2867 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2868 m_vAdjust
->value
= fpos
;
2871 if (!m_isScrolling
) /* prevent recursion */
2873 if (m_wxwindow
->window
)
2875 if (orient
== wxHORIZONTAL
)
2876 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2878 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2883 int wxWindow::GetScrollThumb( int orient
) const
2885 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2887 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2889 if (orient
== wxHORIZONTAL
)
2890 return (int)(m_hAdjust
->page_size
+0.5);
2892 return (int)(m_vAdjust
->page_size
+0.5);
2895 int wxWindow::GetScrollPos( int orient
) const
2897 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2899 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2901 if (orient
== wxHORIZONTAL
)
2902 return (int)(m_hAdjust
->value
+0.5);
2904 return (int)(m_vAdjust
->value
+0.5);
2907 int wxWindow::GetScrollRange( int orient
) const
2909 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2911 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2913 if (orient
== wxHORIZONTAL
)
2914 return (int)(m_hAdjust
->upper
+0.5);
2916 return (int)(m_vAdjust
->upper
+0.5);
2919 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2921 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2923 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2927 m_scrollGC
= gdk_gc_new( m_wxwindow
->window
);
2928 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
2931 wxNode
*node
= m_children
.First();
2934 wxWindow
*child
= (wxWindow
*) node
->Data();
2935 child
->Move( child
->m_x
+ dx
, child
->m_y
+ dy
);
2936 node
= node
->Next();
2941 GetClientSize( &cw
, &ch
);
2942 int w
= cw
- abs(dx
);
2943 int h
= ch
- abs(dy
);
2945 if ((h
< 0) || (w
< 0))
2953 if (dx
< 0) s_x
= -dx
;
2954 if (dy
< 0) s_y
= -dy
;
2957 if (dx
> 0) d_x
= dx
;
2958 if (dy
> 0) d_y
= dy
;
2960 gdk_window_copy_area( m_wxwindow
->window
, m_scrollGC
, d_x
, d_y
,
2961 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2964 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2965 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2966 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2967 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2969 Refresh( TRUE
, &rect
);
2973 void wxWindow::SetScrolling(bool scroll
)
2975 m_isScrolling
= g_blockEventsOnScroll
= scroll
;