1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #include "wx/window.h"
20 #include "wx/layout.h"
22 #include "wx/dialog.h"
23 #include "wx/msgdlg.h"
25 #if wxUSE_DRAG_AND_DROP
30 #include "wx/tooltip.h"
34 #include "wx/statusbr.h"
36 #include "wx/settings.h"
43 #include "gdk/gdkprivate.h"
44 #include "gdk/gdkkeysyms.h"
45 #include "wx/gtk/win_gtk.h"
47 //-----------------------------------------------------------------------------
48 // documentation on internals
49 //-----------------------------------------------------------------------------
52 I have been asked several times about writing some documentation about
53 the GTK port of wxWindows, especially its internal structures. Obviously,
54 you cannot understand wxGTK without knowing a little about the GTK, but
55 some more information about what the wxWindow, which is the base class
56 for all other window classes, does seems required as well.
58 What does wxWindow do? It contains the common interface for the following
59 jobs of its descendants:
61 1) Define the rudimentary behaviour common to all window classes, such as
62 resizing, intercepting user input (so as to make it possible to use these
63 events for special purposes in a derived class), window names etc.
65 2) Provide the possibility to contain and manage children, if the derived
66 class is allowed to contain children, which holds true for those window
67 classes which do not display a native GTK widget. To name them, these
68 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
69 work classes are a special case and are handled a bit differently from
70 the rest. The same holds true for the wxNotebook class.
72 3) Provide the possibility to draw into a client area of a window. This,
73 too, only holds true for classes that do not display a native GTK widget
76 4) Provide the entire mechanism for scrolling widgets. This actual inter-
77 face for this is usually in wxScrolledWindow, but the GTK implementation
80 5) A multitude of helper or extra methods for special purposes, such as
81 Drag'n'Drop, managing validators etc.
83 Normally one might expect, that one wxWindows window would always correspond
84 to one GTK widget. Under GTK, there is no such allround widget that has all
85 the functionality. Moreover, the GTK defines a client area as a different
86 widget from the actual widget you are handling. Last but not least some
87 special classes (e.g. wxFrame) handle different categories of widgets and
88 still have the possibility to draw something in the client area.
89 It was therefore required to write a special purpose GTK widget, that would
90 represent a client area in the sense of wxWindows capable to do the jobs
91 2), 3) and 4). I have written this class and it resides in win_gtk.c of
94 All windows must have a widget, with which they interact with other under-
95 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
96 thw wxWindow class has a member variable called m_widget which holds a
97 pointer to this widget. When the window class represents a GTK native widget,
98 this is (in most cases) the only GTK widget the class manages. E.g. the
99 wxStatitText class handles only a GtkLabel widget a pointer to which you
100 can find in m_widget (defined in wxWindow)
102 When the class has a client area for drawing into and for containing children
103 it has to handle the client area widget (of the type GtkMyFixed, defined in
104 win_gtk.c), but there could be any number of widgets, handled by a class
105 The common rule for all windows is only, that the widget that interacts with
106 the rest of GTK must be referenced in m_widget and all other widgets must be
107 children of this widget on the GTK level. The top-most widget, which also
108 represents the client area, must be in the m_wxwindow field and must be of
111 As I said, the window classes that display a GTK native widget only have
112 one widget, so in the case of e.g. the wxButton class m_widget holds a
113 pointer to a GtkButton widget. But windows with client areas (for drawing
114 and children) have a m_widget field that is a pointer to a GtkScrolled-
115 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
116 one is (in the GTK sense) a child of the GtkScrolledWindow.
118 If the m_wxwindow field is set, then all input to this widget is inter-
119 cepted and sent to the wxWindows class. If not, all input to the widget
120 that gets pointed to by m_widget gets intercepted and sent to the class.
124 //-----------------------------------------------------------------------------
126 //-----------------------------------------------------------------------------
128 extern wxList wxPendingDelete
;
129 extern bool g_blockEventsOnDrag
;
130 extern bool g_blockEventsOnScroll
;
131 static bool g_capturing
= FALSE
;
132 static wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
134 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
135 the last click here */
136 static guint32 gs_timeLastClick
= 0;
138 //-----------------------------------------------------------------------------
140 //-----------------------------------------------------------------------------
144 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
145 GdkEvent
*WXUNUSED(event
),
149 static bool s_done = FALSE;
152 wxLog::AddTraceMask("focus");
155 wxLogTrace(_T("FOCUS NOW AT: %s"), name);
161 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
167 wxChar
*s
= new wxChar
[tmp
.Length()+1];
171 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
172 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
177 //-----------------------------------------------------------------------------
179 //-----------------------------------------------------------------------------
181 extern void wxapp_install_idle_handler();
182 extern bool g_isIdle
;
184 //-----------------------------------------------------------------------------
185 // key event conversion routines
186 //-----------------------------------------------------------------------------
188 static long map_to_unmodified_wx_keysym( KeySym keysym
)
195 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
197 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
198 case GDK_Menu
: key_code
= WXK_MENU
; break;
199 case GDK_Help
: key_code
= WXK_HELP
; break;
200 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
201 case GDK_ISO_Left_Tab
:
202 case GDK_Tab
: key_code
= WXK_TAB
; break;
203 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
204 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
205 case GDK_Return
: key_code
= WXK_RETURN
; break;
206 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
207 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
208 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
209 case GDK_Delete
: key_code
= WXK_DELETE
; break;
210 case GDK_Home
: key_code
= WXK_HOME
; break;
211 case GDK_Left
: key_code
= WXK_LEFT
; break;
212 case GDK_Up
: key_code
= WXK_UP
; break;
213 case GDK_Right
: key_code
= WXK_RIGHT
; break;
214 case GDK_Down
: key_code
= WXK_DOWN
; break;
215 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
216 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
217 case GDK_Next
: key_code
= WXK_NEXT
; break;
218 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
219 case GDK_End
: key_code
= WXK_END
; break;
220 case GDK_Begin
: key_code
= WXK_HOME
; break;
221 case GDK_Select
: key_code
= WXK_SELECT
; break;
222 case GDK_Print
: key_code
= WXK_PRINT
; break;
223 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
224 case GDK_Insert
: key_code
= WXK_INSERT
; break;
225 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
227 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
228 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
229 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
230 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
231 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
232 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
233 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
234 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
235 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
236 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
237 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
238 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
239 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
240 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
241 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
242 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
243 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
244 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
245 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
246 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
247 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
248 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
249 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
250 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
251 case GDK_KP_Next
: key_code
= WXK_NUMPAD_PRIOR
; break;
252 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
253 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
254 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
255 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
256 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
257 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
258 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
259 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
260 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
261 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
262 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
263 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
265 case GDK_F1
: key_code
= WXK_F1
; break;
266 case GDK_F2
: key_code
= WXK_F2
; break;
267 case GDK_F3
: key_code
= WXK_F3
; break;
268 case GDK_F4
: key_code
= WXK_F4
; break;
269 case GDK_F5
: key_code
= WXK_F5
; break;
270 case GDK_F6
: key_code
= WXK_F6
; break;
271 case GDK_F7
: key_code
= WXK_F7
; break;
272 case GDK_F8
: key_code
= WXK_F8
; break;
273 case GDK_F9
: key_code
= WXK_F9
; break;
274 case GDK_F10
: key_code
= WXK_F10
; break;
275 case GDK_F11
: key_code
= WXK_F11
; break;
276 case GDK_F12
: key_code
= WXK_F12
; break;
281 guint upper
= gdk_keyval_to_upper( keysym
);
282 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
291 static long map_to_wx_keysym( KeySym keysym
)
297 case GDK_Menu
: key_code
= WXK_MENU
; break;
298 case GDK_Help
: key_code
= WXK_HELP
; break;
299 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
300 case GDK_ISO_Left_Tab
:
301 case GDK_Tab
: key_code
= WXK_TAB
; break;
302 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
303 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
304 case GDK_Return
: key_code
= WXK_RETURN
; break;
305 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
306 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
307 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
308 case GDK_Delete
: key_code
= WXK_DELETE
; break;
309 case GDK_Home
: key_code
= WXK_HOME
; break;
310 case GDK_Left
: key_code
= WXK_LEFT
; break;
311 case GDK_Up
: key_code
= WXK_UP
; break;
312 case GDK_Right
: key_code
= WXK_RIGHT
; break;
313 case GDK_Down
: key_code
= WXK_DOWN
; break;
314 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
315 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
316 case GDK_Next
: key_code
= WXK_NEXT
; break;
317 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
318 case GDK_End
: key_code
= WXK_END
; break;
319 case GDK_Begin
: key_code
= WXK_HOME
; break;
320 case GDK_Select
: key_code
= WXK_SELECT
; break;
321 case GDK_Print
: key_code
= WXK_PRINT
; break;
322 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
323 case GDK_Insert
: key_code
= WXK_INSERT
; break;
324 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
326 case GDK_KP_0
: key_code
= '0'; break;
327 case GDK_KP_1
: key_code
= '1'; break;
328 case GDK_KP_2
: key_code
= '2'; break;
329 case GDK_KP_3
: key_code
= '3'; break;
330 case GDK_KP_4
: key_code
= '4'; break;
331 case GDK_KP_5
: key_code
= '5'; break;
332 case GDK_KP_6
: key_code
= '6'; break;
333 case GDK_KP_7
: key_code
= '7'; break;
334 case GDK_KP_8
: key_code
= '8'; break;
335 case GDK_KP_9
: key_code
= '9'; break;
336 case GDK_KP_Space
: key_code
= ' '; break;
337 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
338 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
339 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
340 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
341 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
342 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
343 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
344 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
345 case GDK_KP_Up
: key_code
= WXK_UP
; break;
346 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
347 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
348 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
349 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
350 case GDK_KP_Next
: key_code
= WXK_PRIOR
; break;
351 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
352 case GDK_KP_End
: key_code
= WXK_END
; break;
353 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
354 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
355 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
356 case GDK_KP_Equal
: key_code
= '='; break;
357 case GDK_KP_Multiply
: key_code
= '*'; break;
358 case GDK_KP_Add
: key_code
= '+'; break;
359 case GDK_KP_Separator
: key_code
= ','; break;
360 case GDK_KP_Subtract
: key_code
= '-'; break;
361 case GDK_KP_Decimal
: key_code
= '.'; break;
362 case GDK_KP_Divide
: key_code
= '/'; break;
364 case GDK_F1
: key_code
= WXK_F1
; break;
365 case GDK_F2
: key_code
= WXK_F2
; break;
366 case GDK_F3
: key_code
= WXK_F3
; break;
367 case GDK_F4
: key_code
= WXK_F4
; break;
368 case GDK_F5
: key_code
= WXK_F5
; break;
369 case GDK_F6
: key_code
= WXK_F6
; break;
370 case GDK_F7
: key_code
= WXK_F7
; break;
371 case GDK_F8
: key_code
= WXK_F8
; break;
372 case GDK_F9
: key_code
= WXK_F9
; break;
373 case GDK_F10
: key_code
= WXK_F10
; break;
374 case GDK_F11
: key_code
= WXK_F11
; break;
375 case GDK_F12
: key_code
= WXK_F12
; break;
388 //-----------------------------------------------------------------------------
389 // local code (see below)
390 //-----------------------------------------------------------------------------
392 #if (GTK_MINOR_VERSION > 0)
394 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
402 if (win
->HasScrolling())
404 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
405 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
408 GtkWidget *hscrollbar = scroll_window->hscrollbar;
409 GtkWidget *vscrollbar = scroll_window->vscrollbar;
411 we use this instead: range.slider_width = 11 + 2*2pts edge
414 if (scroll_window
->vscrollbar_visible
)
416 dw
+= 15; /* dw += vscrollbar->allocation.width; */
417 dw
+= scroll_class
->scrollbar_spacing
;
420 if (scroll_window
->hscrollbar_visible
)
422 dh
+= 15; /* dh += hscrollbar->allocation.height; */
423 dw
+= scroll_class
->scrollbar_spacing
;
429 if (GTK_WIDGET_NO_WINDOW (widget
))
431 dx
+= widget
->allocation
.x
;
432 dy
+= widget
->allocation
.y
;
435 if (win
->HasFlag(wxRAISED_BORDER
))
437 gtk_draw_shadow( widget
->style
,
442 win
->m_width
-dw
, win
->m_height
-dh
);
446 if (win
->HasFlag(wxSUNKEN_BORDER
))
448 gtk_draw_shadow( widget
->style
,
453 win
->m_width
-dw
, win
->m_height
-dh
);
458 //-----------------------------------------------------------------------------
459 // "expose_event" of m_widget
460 //-----------------------------------------------------------------------------
462 static void gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
464 if (gdk_event
->count
> 0) return;
465 draw_frame( widget
, win
);
468 //-----------------------------------------------------------------------------
469 // "draw" of m_wxwindow
470 //-----------------------------------------------------------------------------
472 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
474 draw_frame( widget
, win
);
477 #endif // GTK_MINOR_VERSION > 0
479 //-----------------------------------------------------------------------------
480 // "expose_event" of m_wxwindow
481 //-----------------------------------------------------------------------------
483 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
485 if ( !win
->m_hasVMT
)
488 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
490 gdk_event
->area
.width
,
491 gdk_event
->area
.height
);
493 if ( gdk_event
->count
> 0 )
497 printf( "OnExpose from " );
498 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
499 printf( win->GetClassInfo()->GetClassName() );
503 wxPaintEvent
event( win
->GetId() );
504 event
.SetEventObject( win
);
505 win
->GetEventHandler()->ProcessEvent( event
);
507 win
->GetUpdateRegion().Clear();
510 //-----------------------------------------------------------------------------
511 // "draw" of m_wxwindow
512 //-----------------------------------------------------------------------------
514 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
517 wxapp_install_idle_handler();
522 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
523 rect
->width
, rect
->height
);
525 wxPaintEvent
event( win
->GetId() );
526 event
.SetEventObject( win
);
527 win
->GetEventHandler()->ProcessEvent( event
);
529 win
->GetUpdateRegion().Clear();
532 //-----------------------------------------------------------------------------
533 // "key_press_event" from any window
534 //-----------------------------------------------------------------------------
536 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
539 wxapp_install_idle_handler();
541 if (!win
->m_hasVMT
) return FALSE
;
542 if (g_blockEventsOnDrag
) return FALSE
;
545 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
546 if (gdk_event->state & GDK_SHIFT_MASK)
547 printf( "ShiftDown.\n" );
549 printf( "ShiftUp.\n" );
550 if (gdk_event->state & GDK_CONTROL_MASK)
551 printf( "ControlDown.\n" );
553 printf( "ControlUp.\n" );
559 GdkModifierType state
;
560 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
562 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
564 /* sending unknown key events doesn't really make sense */
565 if (key_code
== 0) return FALSE
;
569 wxKeyEvent
event( wxEVT_KEY_DOWN
);
570 event
.SetTimestamp( gdk_event
->time
);
571 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
572 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
573 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
574 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
575 event
.m_keyCode
= key_code
;
576 event
.m_scanCode
= gdk_event
->keyval
;
579 event
.SetEventObject( win
);
580 ret
= win
->GetEventHandler()->ProcessEvent( event
);
582 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
584 /* wxMSW doesn't send char events with Alt pressed */
585 if ((key_code
!= 0) &&
586 ((gdk_event
->state
& GDK_MOD1_MASK
) == 0) &&
587 ((gdk_event
->state
& GDK_MOD1_MASK
) == 0))
589 wxKeyEvent
event2( wxEVT_CHAR
);
590 event2
.SetTimestamp( gdk_event
->time
);
591 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
592 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
593 // event2.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
594 // event2.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
595 event2
.m_keyCode
= key_code
;
596 event2
.m_scanCode
= gdk_event
->keyval
;
599 event2
.SetEventObject( win
);
600 ret
= (ret
|| win
->GetEventHandler()->ProcessEvent( event2
));
605 wxWindow
*ancestor
= win
;
608 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
611 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
612 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
615 ancestor
= ancestor
->GetParent();
619 // win is a control: tab can be propagated up
621 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
622 (win
->HasFlag(wxTE_PROCESS_TAB
) == 0))
624 wxNavigationKeyEvent new_event
;
625 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
626 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
627 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
628 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
629 new_event
.SetCurrentFocus( win
);
630 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
633 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
635 (gdk_event
->keyval
== GDK_Escape
) )
637 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
638 new_event
.SetEventObject( win
);
639 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
642 /* pressing F10 will activate the menu bar of the top frame */
644 (gdk_event
->keyval
== GDK_F10
) )
646 wxWindow
*ancestor
= win
;
649 if (wxIsKindOf(ancestor
,wxFrame
))
651 wxFrame
*frame
= (wxFrame
*) ancestor
;
652 wxMenuBar
*menubar
= frame
->GetMenuBar();
655 wxNode
*node
= menubar
->GetMenus().First();
658 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
659 gtk_menu_shell_select_item(
660 GTK_MENU_SHELL(menubar
->m_menubar
),
661 firstMenu
->m_owner
);
668 ancestor
= ancestor
->GetParent();
673 Damn, I forgot why this didn't work, but it didn't work.
675 // win is a panel: up can be propagated to the panel
676 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
677 (gdk_event->keyval == GDK_Up))
679 win->m_parent->SetFocus();
683 // win is a panel: left/right can be propagated to the panel
684 if ((!ret) && (win->m_wxwindow) &&
685 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
686 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
688 wxNavigationKeyEvent new_event;
689 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
690 new_event.SetCurrentFocus( win );
691 ret = win->GetEventHandler()->ProcessEvent( new_event );
697 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
704 //-----------------------------------------------------------------------------
705 // "key_release_event" from any window
706 //-----------------------------------------------------------------------------
708 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
711 wxapp_install_idle_handler();
713 if (!win
->m_hasVMT
) return FALSE
;
714 if (g_blockEventsOnDrag
) return FALSE
;
717 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
718 if (gdk_event->state & GDK_SHIFT_MASK)
719 printf( "ShiftDown.\n" );
721 printf( "ShiftUp.\n" );
722 if (gdk_event->state & GDK_CONTROL_MASK)
723 printf( "ControlDown.\n" );
725 printf( "ControlUp.\n" );
729 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
731 /* sending unknown key events doesn't really make sense */
732 if (key_code
== 0) return FALSE
;
736 GdkModifierType state
;
737 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
739 wxKeyEvent
event( wxEVT_KEY_UP
);
740 event
.SetTimestamp( gdk_event
->time
);
741 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
742 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
743 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
744 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
745 event
.m_keyCode
= key_code
;
746 event
.m_scanCode
= gdk_event
->keyval
;
749 event
.SetEventObject( win
);
751 if (win
->GetEventHandler()->ProcessEvent( event
))
753 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
760 //-----------------------------------------------------------------------------
761 // "button_press_event"
762 //-----------------------------------------------------------------------------
764 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
767 wxapp_install_idle_handler();
770 wxPrintf( _T("1) OnButtonPress from ") );
771 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
772 wxPrintf( win->GetClassInfo()->GetClassName() );
773 wxPrintf( _T(".\n") );
775 if (!win
->m_hasVMT
) return FALSE
;
776 if (g_blockEventsOnDrag
) return TRUE
;
777 if (g_blockEventsOnScroll
) return TRUE
;
779 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
783 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
785 gtk_widget_grab_focus (win
->m_wxwindow
);
788 wxPrintf( _T("GrabFocus from ") );
789 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
790 wxPrintf( win->GetClassInfo()->GetClassName() );
791 wxPrintf( _T(".\n") );
798 wxPrintf( _T("2) OnButtonPress from ") );
799 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
800 wxPrintf( win->GetClassInfo()->GetClassName() );
801 wxPrintf( _T(".\n") );
804 wxEventType event_type
= wxEVT_LEFT_DOWN
;
806 if (gdk_event
->button
== 1)
808 switch (gdk_event
->type
)
810 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
811 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
815 else if (gdk_event
->button
== 2)
817 switch (gdk_event
->type
)
819 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
820 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
824 else if (gdk_event
->button
== 3)
826 switch (gdk_event
->type
)
828 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
829 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
834 wxMouseEvent
event( event_type
);
835 event
.SetTimestamp( gdk_event
->time
);
836 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
837 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
838 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
839 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
840 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
841 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
842 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
844 event
.m_x
= (long)gdk_event
->x
;
845 event
.m_y
= (long)gdk_event
->y
;
847 // Some control don't have their own X window and thus cannot get
852 wxNode
*node
= win
->GetChildren().First();
855 wxWindow
*child
= (wxWindow
*)node
->Data();
857 if (child
->m_isStaticBox
)
859 // wxStaticBox is transparent in the box itself
862 int xx1
= child
->m_x
;
863 int yy1
= child
->m_y
;
864 int xx2
= child
->m_x
+ child
->m_width
;
865 int yy2
= child
->m_x
+ child
->m_height
;
868 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
870 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
872 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
874 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
877 event
.m_x
-= child
->m_x
;
878 event
.m_y
-= child
->m_y
;
885 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
886 (child
->m_x
<= event
.m_x
) &&
887 (child
->m_y
<= event
.m_y
) &&
888 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
889 (child
->m_y
+child
->m_height
>= event
.m_y
))
892 event
.m_x
-= child
->m_x
;
893 event
.m_y
-= child
->m_y
;
901 event
.SetEventObject( win
);
903 gs_timeLastClick
= gdk_event
->time
;
905 if (win
->GetEventHandler()->ProcessEvent( event
))
907 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
914 //-----------------------------------------------------------------------------
915 // "button_release_event"
916 //-----------------------------------------------------------------------------
918 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
921 wxapp_install_idle_handler();
923 if (!win
->m_hasVMT
) return FALSE
;
924 if (g_blockEventsOnDrag
) return FALSE
;
925 if (g_blockEventsOnScroll
) return FALSE
;
927 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
930 printf( "OnButtonRelease from " );
931 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
932 printf( win->GetClassInfo()->GetClassName() );
936 wxEventType event_type
= wxEVT_NULL
;
938 switch (gdk_event
->button
)
940 case 1: event_type
= wxEVT_LEFT_UP
; break;
941 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
942 case 3: event_type
= wxEVT_RIGHT_UP
; break;
945 wxMouseEvent
event( event_type
);
946 event
.SetTimestamp( gdk_event
->time
);
947 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
948 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
949 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
950 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
951 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
952 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
953 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
954 event
.m_x
= (long)gdk_event
->x
;
955 event
.m_y
= (long)gdk_event
->y
;
957 // Some control don't have their own X window and thus cannot get
962 wxNode
*node
= win
->GetChildren().First();
965 wxWindow
*child
= (wxWindow
*)node
->Data();
967 if (child
->m_isStaticBox
)
969 // wxStaticBox is transparent in the box itself
972 int xx1
= child
->m_x
;
973 int yy1
= child
->m_y
;
974 int xx2
= child
->m_x
+ child
->m_width
;
975 int yy2
= child
->m_x
+ child
->m_height
;
978 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
980 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
982 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
984 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
987 event
.m_x
-= child
->m_x
;
988 event
.m_y
-= child
->m_y
;
995 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
996 (child
->m_x
<= event
.m_x
) &&
997 (child
->m_y
<= event
.m_y
) &&
998 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
999 (child
->m_y
+child
->m_height
>= event
.m_y
))
1002 event
.m_x
-= child
->m_x
;
1003 event
.m_y
-= child
->m_y
;
1007 node
= node
->Next();
1011 event
.SetEventObject( win
);
1013 if (win
->GetEventHandler()->ProcessEvent( event
))
1015 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1022 //-----------------------------------------------------------------------------
1023 // "motion_notify_event"
1024 //-----------------------------------------------------------------------------
1026 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1029 wxapp_install_idle_handler();
1031 if (!win
->m_hasVMT
) return FALSE
;
1032 if (g_blockEventsOnDrag
) return FALSE
;
1033 if (g_blockEventsOnScroll
) return FALSE
;
1035 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1037 if (gdk_event
->is_hint
)
1041 GdkModifierType state
;
1042 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1045 gdk_event
->state
= state
;
1049 printf( "OnMotion from " );
1050 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1051 printf( win->GetClassInfo()->GetClassName() );
1055 wxMouseEvent
event( wxEVT_MOTION
);
1056 event
.SetTimestamp( gdk_event
->time
);
1057 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1058 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1059 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1060 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1061 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1062 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1063 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1065 event
.m_x
= (long)gdk_event
->x
;
1066 event
.m_y
= (long)gdk_event
->y
;
1068 // Some control don't have their own X window and thus cannot get
1073 wxNode
*node
= win
->GetChildren().First();
1076 wxWindow
*child
= (wxWindow
*)node
->Data();
1078 if (child
->m_isStaticBox
)
1080 // wxStaticBox is transparent in the box itself
1083 int xx1
= child
->m_x
;
1084 int yy1
= child
->m_y
;
1085 int xx2
= child
->m_x
+ child
->m_width
;
1086 int yy2
= child
->m_x
+ child
->m_height
;
1089 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1091 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1093 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1095 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1098 event
.m_x
-= child
->m_x
;
1099 event
.m_y
-= child
->m_y
;
1106 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1107 (child
->m_x
<= event
.m_x
) &&
1108 (child
->m_y
<= event
.m_y
) &&
1109 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
1110 (child
->m_y
+child
->m_height
>= event
.m_y
))
1113 event
.m_x
-= child
->m_x
;
1114 event
.m_y
-= child
->m_y
;
1118 node
= node
->Next();
1122 event
.SetEventObject( win
);
1124 if (win
->GetEventHandler()->ProcessEvent( event
))
1126 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1133 //-----------------------------------------------------------------------------
1135 //-----------------------------------------------------------------------------
1137 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1140 wxapp_install_idle_handler();
1142 if (!win
->m_hasVMT
) return FALSE
;
1143 if (g_blockEventsOnDrag
) return FALSE
;
1145 g_focusWindow
= win
;
1147 if (win
->m_wxwindow
)
1149 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1151 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1153 printf( "SetFocus flag from " );
1154 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1155 printf( win->GetClassInfo()->GetClassName() );
1163 printf( "OnSetFocus from " );
1164 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1165 printf( win->GetClassInfo()->GetClassName() );
1167 printf( WXSTRINGCAST win->GetLabel() );
1171 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1172 event
.SetEventObject( win
);
1174 if (win
->GetEventHandler()->ProcessEvent( event
))
1176 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1183 //-----------------------------------------------------------------------------
1184 // "focus_out_event"
1185 //-----------------------------------------------------------------------------
1187 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1190 wxapp_install_idle_handler();
1192 if (!win
->m_hasVMT
) return FALSE
;
1193 if (g_blockEventsOnDrag
) return FALSE
;
1195 if (win
->m_wxwindow
)
1197 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1198 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1202 printf( "OnKillFocus from " );
1203 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1204 printf( win->GetClassInfo()->GetClassName() );
1208 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1209 event
.SetEventObject( win
);
1211 if (win
->GetEventHandler()->ProcessEvent( event
))
1213 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1220 //-----------------------------------------------------------------------------
1221 // "enter_notify_event"
1222 //-----------------------------------------------------------------------------
1224 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1227 wxapp_install_idle_handler();
1229 if (!win
->m_hasVMT
) return FALSE
;
1230 if (g_blockEventsOnDrag
) return FALSE
;
1232 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1234 if (widget
->window
&& win
->GetCursor().Ok() )
1235 gdk_window_set_cursor( widget
->window
, win
->GetCursor().GetCursor() );
1237 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1238 event
.SetTimestamp( gdk_event
->time
);
1239 event
.SetEventObject( win
);
1243 GdkModifierType state
= (GdkModifierType
)0;
1245 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1247 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1248 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1249 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1250 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1251 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1252 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1253 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1255 event
.m_x
= (long)x
;
1256 event
.m_y
= (long)y
;
1258 if (win
->GetEventHandler()->ProcessEvent( event
))
1260 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1267 //-----------------------------------------------------------------------------
1268 // "leave_notify_event"
1269 //-----------------------------------------------------------------------------
1271 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1274 wxapp_install_idle_handler();
1276 if (!win
->m_hasVMT
) return FALSE
;
1277 if (g_blockEventsOnDrag
) return FALSE
;
1279 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1281 if (widget
->window
&& win
->GetCursor().Ok() )
1282 gdk_window_set_cursor( widget
->window
, wxSTANDARD_CURSOR
->GetCursor() );
1284 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1285 event
.SetTimestamp( gdk_event
->time
);
1286 event
.SetEventObject( win
);
1290 GdkModifierType state
= (GdkModifierType
)0;
1292 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1294 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1295 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1296 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1297 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1298 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1299 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1300 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1302 event
.m_x
= (long)x
;
1303 event
.m_y
= (long)y
;
1305 if (win
->GetEventHandler()->ProcessEvent( event
))
1307 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1314 //-----------------------------------------------------------------------------
1315 // "value_changed" from m_vAdjust
1316 //-----------------------------------------------------------------------------
1318 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1321 wxapp_install_idle_handler();
1323 if (g_blockEventsOnDrag
) return;
1325 if (!win
->m_hasVMT
) return;
1327 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
1328 if (fabs(diff
) < 0.2) return;
1329 win
->m_oldVerticalPos
= win
->m_vAdjust
->value
;
1331 wxEventType command
= wxEVT_NULL
;
1333 float line_step
= win
->m_vAdjust
->step_increment
;
1334 float page_step
= win
->m_vAdjust
->page_increment
;
1336 if (win
->IsScrolling())
1338 command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1342 if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->lower
) < 0.2) command
= wxEVT_SCROLLWIN_BOTTOM
;
1343 else if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->upper
) < 0.2) command
= wxEVT_SCROLLWIN_TOP
;
1344 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1345 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEUP
;
1346 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1347 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEUP
;
1348 else command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1351 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1353 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1354 event
.SetEventObject( win
);
1355 win
->GetEventHandler()->ProcessEvent( event
);
1358 //-----------------------------------------------------------------------------
1359 // "value_changed" from m_hAdjust
1360 //-----------------------------------------------------------------------------
1362 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1365 wxapp_install_idle_handler();
1367 if (g_blockEventsOnDrag
) return;
1368 if (!win
->m_hasVMT
) return;
1370 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
1371 if (fabs(diff
) < 0.2) return;
1372 win
->m_oldHorizontalPos
= win
->m_hAdjust
->value
;
1374 wxEventType command
= wxEVT_NULL
;
1376 float line_step
= win
->m_hAdjust
->step_increment
;
1377 float page_step
= win
->m_hAdjust
->page_increment
;
1379 if (win
->IsScrolling())
1381 command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1385 if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->lower
) < 0.2) command
= wxEVT_SCROLLWIN_BOTTOM
;
1386 else if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->upper
) < 0.2) command
= wxEVT_SCROLLWIN_TOP
;
1387 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1388 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEUP
;
1389 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1390 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEUP
;
1391 else command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1394 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1396 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1397 event
.SetEventObject( win
);
1398 win
->GetEventHandler()->ProcessEvent( event
);
1401 //-----------------------------------------------------------------------------
1402 // "changed" from m_vAdjust
1403 //-----------------------------------------------------------------------------
1405 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1408 wxapp_install_idle_handler();
1410 if (g_blockEventsOnDrag
) return;
1411 if (!win
->m_hasVMT
) return;
1413 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1414 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1416 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1417 event
.SetEventObject( win
);
1418 win
->GetEventHandler()->ProcessEvent( event
);
1421 //-----------------------------------------------------------------------------
1422 // "changed" from m_hAdjust
1423 //-----------------------------------------------------------------------------
1425 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1428 wxapp_install_idle_handler();
1430 if (g_blockEventsOnDrag
) return;
1431 if (!win
->m_hasVMT
) return;
1433 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1434 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1436 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1437 event
.SetEventObject( win
);
1438 win
->GetEventHandler()->ProcessEvent( event
);
1441 //-----------------------------------------------------------------------------
1442 // "button_press_event" from scrollbar
1443 //-----------------------------------------------------------------------------
1445 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1446 GdkEventButton
*WXUNUSED(gdk_event
),
1450 wxapp_install_idle_handler();
1452 // don't test here as we can release the mouse while being over
1453 // a different window then the slider
1455 // if (gdk_event->window != widget->slider) return FALSE;
1457 win
->SetScrolling( TRUE
);
1462 //-----------------------------------------------------------------------------
1463 // "button_release_event" from scrollbar
1464 //-----------------------------------------------------------------------------
1466 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1467 GdkEventButton
*WXUNUSED(gdk_event
),
1471 // don't test here as we can release the mouse while being over
1472 // a different window then the slider
1474 // if (gdk_event->window != widget->slider) return FALSE;
1476 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1478 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1479 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_hAdjust
), "value_changed" );
1481 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_vAdjust
), "value_changed" );
1483 win
->SetScrolling( FALSE
);
1488 // ----------------------------------------------------------------------------
1489 // this wxWindowBase function is implemented here (in platform-specific file)
1490 // because it is static and so couldn't be made virtual
1491 // ----------------------------------------------------------------------------
1493 wxWindow
*wxWindowBase::FindFocus()
1495 return g_focusWindow
;
1498 //-----------------------------------------------------------------------------
1499 // "realize" from m_widget
1500 //-----------------------------------------------------------------------------
1502 /* we cannot set colours, fonts and cursors before the widget has
1503 been realized, so we do this directly after realization */
1506 gtk_window_realized_callback( GtkWidget
* WXUNUSED(widget
), wxWindow
*win
)
1509 wxapp_install_idle_handler();
1511 if (win
->m_delayedFont
)
1512 win
->SetFont( win
->GetFont() );
1514 if (win
->m_delayedBackgroundColour
)
1515 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1517 if (win
->m_delayedForegroundColour
)
1518 win
->SetForegroundColour( win
->GetForegroundColour() );
1520 win
->SetCursor( win
->GetCursor() );
1525 //-----------------------------------------------------------------------------
1526 // InsertChild for wxWindow.
1527 //-----------------------------------------------------------------------------
1529 /* Callback for wxWindow. This very strange beast has to be used because
1530 * C++ has no virtual methods in a constructor. We have to emulate a
1531 * virtual function here as wxNotebook requires a different way to insert
1532 * a child in it. I had opted for creating a wxNotebookPage window class
1533 * which would have made this superfluous (such in the MDI window system),
1534 * but no-one was listening to me... */
1536 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1538 gtk_myfixed_put( GTK_MYFIXED(parent
->m_wxwindow
),
1539 GTK_WIDGET(child
->m_widget
),
1545 if (parent
->HasFlag(wxTAB_TRAVERSAL
))
1547 /* we now allow a window to get the focus as long as it
1548 doesn't have any children. */
1549 GTK_WIDGET_UNSET_FLAGS( parent
->m_wxwindow
, GTK_CAN_FOCUS
);
1553 //-----------------------------------------------------------------------------
1555 //-----------------------------------------------------------------------------
1557 wxWindow
* wxGetActiveWindow()
1559 return g_focusWindow
;
1562 //-----------------------------------------------------------------------------
1564 //-----------------------------------------------------------------------------
1566 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1568 void wxWindow::Init()
1574 m_widget
= (GtkWidget
*) NULL
;
1575 m_wxwindow
= (GtkWidget
*) NULL
;
1585 m_needParent
= TRUE
;
1586 m_isBeingDeleted
= FALSE
;
1588 m_hasScrolling
= FALSE
;
1589 m_isScrolling
= FALSE
;
1591 m_hAdjust
= (GtkAdjustment
*) NULL
;
1592 m_vAdjust
= (GtkAdjustment
*) NULL
;
1593 m_oldHorizontalPos
= 0.0;
1594 m_oldVerticalPos
= 0.0;
1597 m_scrollGC
= (GdkGC
*) NULL
;
1598 m_widgetStyle
= (GtkStyle
*) NULL
;
1600 m_insertCallback
= wxInsertChildInWindow
;
1602 m_isStaticBox
= FALSE
;
1603 m_acceptsFocus
= FALSE
;
1606 wxWindow::wxWindow()
1611 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1612 const wxPoint
&pos
, const wxSize
&size
,
1613 long style
, const wxString
&name
)
1617 Create( parent
, id
, pos
, size
, style
, name
);
1620 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1621 const wxPoint
&pos
, const wxSize
&size
,
1622 long style
, const wxString
&name
)
1624 PreCreation( parent
, id
, pos
, size
, style
, name
);
1626 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1627 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1630 debug_focus_in( m_widget
, _T("wxWindow::m_widget"), name
);
1633 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1636 debug_focus_in( scrolledWindow
->hscrollbar
, _T("wxWindow::hsrcollbar"), name
);
1637 debug_focus_in( scrolledWindow
->vscrollbar
, _T("wxWindow::vsrcollbar"), name
);
1640 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1641 scroll_class
->scrollbar_spacing
= 0;
1643 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1645 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
1646 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
1648 m_wxwindow
= gtk_myfixed_new();
1651 debug_focus_in( m_wxwindow
, _T("wxWindow::m_wxwindow"), name
);
1654 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1656 #if (GTK_MINOR_VERSION > 0)
1657 GtkMyFixed
*myfixed
= GTK_MYFIXED(m_wxwindow
);
1659 if (HasFlag(wxRAISED_BORDER
))
1661 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_OUT
);
1663 else if (HasFlag(wxSUNKEN_BORDER
))
1665 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_IN
);
1669 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_NONE
);
1671 #else // GTK_MINOR_VERSION == 0
1672 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
1674 if (HasFlag(wxRAISED_BORDER
))
1676 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1678 else if (HasFlag(wxSUNKEN_BORDER
))
1680 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1684 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1686 #endif // GTK_MINOR_VERSION
1688 if (HasFlag(wxTAB_TRAVERSAL
))
1690 /* we now allow a window to get the focus as long as it
1691 doesn't have any children. */
1692 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1693 m_acceptsFocus
= FALSE
;
1697 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1698 m_acceptsFocus
= TRUE
;
1701 #if (GTK_MINOR_VERSION == 0)
1702 // shut the viewport up
1703 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1704 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1705 #endif // GTK_MINOR_VERSION == 0
1707 // I _really_ don't want scrollbars in the beginning
1708 m_vAdjust
->lower
= 0.0;
1709 m_vAdjust
->upper
= 1.0;
1710 m_vAdjust
->value
= 0.0;
1711 m_vAdjust
->step_increment
= 1.0;
1712 m_vAdjust
->page_increment
= 1.0;
1713 m_vAdjust
->page_size
= 5.0;
1714 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1715 m_hAdjust
->lower
= 0.0;
1716 m_hAdjust
->upper
= 1.0;
1717 m_hAdjust
->value
= 0.0;
1718 m_hAdjust
->step_increment
= 1.0;
1719 m_hAdjust
->page_increment
= 1.0;
1720 m_hAdjust
->page_size
= 5.0;
1721 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1723 // these handlers block mouse events to any window during scrolling such as
1724 // motion events and prevent GTK and wxWindows from fighting over where the
1727 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
1728 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1730 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
1731 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1733 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
1734 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1736 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
1737 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1739 // these handlers get notified when screen updates are required either when
1740 // scrolling or when the window size (and therefore scrollbar configuration)
1743 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
1744 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
1745 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
1746 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
1748 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
1749 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
1750 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
1751 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
1753 gtk_widget_show( m_wxwindow
);
1756 m_parent
->DoAddChild( this );
1765 wxWindow::~wxWindow()
1767 m_isBeingDeleted
= TRUE
;
1776 m_parent
->RemoveChild( this );
1780 gtk_style_unref( m_widgetStyle
);
1781 m_widgetStyle
= (GtkStyle
*) NULL
;
1786 gdk_gc_unref( m_scrollGC
);
1787 m_scrollGC
= (GdkGC
*) NULL
;
1792 gtk_widget_destroy( m_wxwindow
);
1793 m_wxwindow
= (GtkWidget
*) NULL
;
1798 gtk_widget_destroy( m_widget
);
1799 m_widget
= (GtkWidget
*) NULL
;
1803 void wxWindow::PreCreation( wxWindow
*parent
,
1808 const wxString
&name
)
1810 wxASSERT_MSG( !m_needParent
|| parent
, _T("Need complete parent.") );
1812 if ( !CreateBase(parent
, id
, pos
, size
, style
, name
) )
1814 wxFAIL_MSG(_T("window creation failed"));
1817 m_width
= WidthDefault(size
.x
);
1818 m_height
= HeightDefault(size
.y
);
1823 if (!parent
) /* some reasonable defaults */
1827 m_x
= (gdk_screen_width () - m_width
) / 2;
1828 if (m_x
< 10) m_x
= 10;
1832 m_y
= (gdk_screen_height () - m_height
) / 2;
1833 if (m_y
< 10) m_y
= 10;
1838 void wxWindow::PostCreation()
1840 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1844 /* these get reported to wxWindows -> wxPaintEvent */
1845 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1846 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1848 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1849 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1851 #if (GTK_MINOR_VERSION > 0)
1852 /* these are called when the "sunken" or "raised" borders are drawn */
1853 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
1854 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
1856 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
1857 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
1861 GtkWidget
*connect_widget
= GetConnectWidget();
1863 ConnectWidget( connect_widget
);
1865 /* we cannot set colours, fonts and cursors before the widget has
1866 been realized, so we do this directly after realization */
1867 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
1868 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
1873 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1875 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1876 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1878 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
1879 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
1881 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1882 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1884 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1885 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1887 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1888 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1890 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1891 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1893 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1894 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1896 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1897 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1899 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1900 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1903 bool wxWindow::Destroy()
1905 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1909 return wxWindowBase::Destroy();
1912 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1914 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1915 wxASSERT_MSG( (m_parent
!= NULL
), _T("wxWindow::SetSize requires parent.\n") );
1917 if (m_resizing
) return; /* I don't like recursions */
1920 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
1922 /* don't set the size for children of wxNotebook, just take the values. */
1930 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1932 if (x
!= -1) m_x
= x
;
1933 if (y
!= -1) m_y
= y
;
1934 if (width
!= -1) m_width
= width
;
1935 if (height
!= -1) m_height
= height
;
1945 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1947 if (width
== -1) m_width
= 80;
1950 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1952 if (height
== -1) m_height
= 26;
1955 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1956 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1957 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
1958 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
1962 if (GTK_WIDGET_HAS_DEFAULT(m_widget
))
1964 /* the default button has a border around it */
1968 /* this is the result of hours of debugging: the following code
1969 means that if we have a m_wxwindow and we set the size of
1970 m_widget, m_widget (which is a GtkScrolledWindow) does NOT
1971 automatically propagate its size down to its m_wxwindow,
1972 which is its client area. therefore, we have to tell the
1973 client area directly that it has to resize itself.
1974 this will lead to that m_widget (GtkScrolledWindow) will
1975 calculate how much size it needs for scrollbars etc and
1976 it will then call XXX_size_allocate of its child, which
1977 is m_wxwindow. m_wxwindow in turn will do the same with its
1978 children and so on. problems can arise if this happens
1979 before all the children have been realized as some widgets
1980 stupidy need to be realized during XXX_size_allocate (e.g.
1981 GtkNotebook) and they will segv if called otherwise. this
1982 emergency is tested in gtk_myfixed_size_allocate. Normally
1983 this shouldn't be needed and only gtk_widget_queue_resize()
1984 should be enough to provoke a resize at the next appropriate
1985 moment, but this seems to fail, e.g. when a wxNotebook contains
1986 a wxSplitterWindow: the splitter window's children won't
1987 show up properly resized then. */
1989 gtk_myfixed_set_size( GTK_MYFIXED(m_parent
->m_wxwindow
),
1994 m_height
+2*border
);
1999 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2000 event
.SetEventObject( this );
2001 GetEventHandler()->ProcessEvent( event
);
2006 void wxWindow::OnInternalIdle()
2011 void wxWindow::DoGetSize( int *width
, int *height
) const
2013 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2015 if (width
) (*width
) = m_width
;
2016 if (height
) (*height
) = m_height
;
2019 void wxWindow::DoSetClientSize( int width
, int height
)
2021 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2025 SetSize( width
, height
);
2032 if (!m_hasScrolling
)
2034 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
2036 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2038 dw
+= 2 * window_class
->xthickness
;
2039 dh
+= 2 * window_class
->ythickness
;
2044 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2045 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2047 #if (GTK_MINOR_VERSION == 0)
2048 GtkWidget
*viewport
= scroll_window
->viewport
;
2049 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2051 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2053 dw
+= 2 * viewport_class
->xthickness
;
2054 dh
+= 2 * viewport_class
->ythickness
;
2059 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2060 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2062 we use this instead: range.slider_width = 11 + 2*2pts edge
2065 if (scroll_window
->vscrollbar_visible
)
2067 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2068 dw
+= scroll_class
->scrollbar_spacing
;
2071 if (scroll_window
->hscrollbar_visible
)
2073 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2074 dw
+= scroll_class
->scrollbar_spacing
;
2078 SetSize( width
+dw
, height
+dh
);
2082 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2084 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2088 if (width
) (*width
) = m_width
;
2089 if (height
) (*height
) = m_height
;
2096 if (!m_hasScrolling
)
2098 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
2100 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2102 dw
+= 2 * window_class
->xthickness
;
2103 dh
+= 2 * window_class
->ythickness
;
2108 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2109 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2111 #if (GTK_MINOR_VERSION == 0)
2112 GtkWidget
*viewport
= scroll_window
->viewport
;
2113 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2115 if ( HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
) )
2117 dw
+= 2 * viewport_class
->xthickness
;
2118 dh
+= 2 * viewport_class
->ythickness
;
2122 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2123 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2125 we use this instead: range.slider_width = 11 + 2*2pts edge
2128 if (scroll_window
->vscrollbar_visible
)
2130 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2131 dw
+= scroll_class
->scrollbar_spacing
;
2134 if (scroll_window
->hscrollbar_visible
)
2136 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2137 dh
+= scroll_class
->scrollbar_spacing
;
2141 if (width
) (*width
) = m_width
- dw
;
2142 if (height
) (*height
) = m_height
- dh
;
2146 void wxWindow::DoGetPosition( int *x
, int *y
) const
2148 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2154 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2156 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2158 if (!m_widget
->window
) return;
2160 GdkWindow
*source
= (GdkWindow
*) NULL
;
2162 source
= m_wxwindow
->window
;
2164 source
= m_widget
->window
;
2168 gdk_window_get_origin( source
, &org_x
, &org_y
);
2172 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2174 org_x
+= m_widget
->allocation
.x
;
2175 org_y
+= m_widget
->allocation
.y
;
2183 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2185 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2187 if (!m_widget
->window
) return;
2189 GdkWindow
*source
= (GdkWindow
*) NULL
;
2191 source
= m_wxwindow
->window
;
2193 source
= m_widget
->window
;
2197 gdk_window_get_origin( source
, &org_x
, &org_y
);
2201 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2203 org_x
+= m_widget
->allocation
.x
;
2204 org_y
+= m_widget
->allocation
.y
;
2212 bool wxWindow::Show( bool show
)
2214 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2216 if (!wxWindowBase::Show(show
))
2223 gtk_widget_show( m_widget
);
2225 gtk_widget_hide( m_widget
);
2230 bool wxWindow::Enable( bool enable
)
2232 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2234 if (!wxWindowBase::Enable(enable
))
2240 gtk_widget_set_sensitive( m_widget
, enable
);
2242 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2247 int wxWindow::GetCharHeight() const
2249 wxCHECK_MSG( (m_widget
!= NULL
), 12, _T("invalid window") );
2251 wxCHECK_MSG( m_font
.Ok(), 12, _T("invalid font") );
2253 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2255 return font
->ascent
+ font
->descent
;
2258 int wxWindow::GetCharWidth() const
2260 wxCHECK_MSG( (m_widget
!= NULL
), 8, _T("invalid window") );
2262 wxCHECK_MSG( m_font
.Ok(), 8, _T("invalid font") );
2264 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2266 return gdk_string_width( font
, "H" );
2269 void wxWindow::GetTextExtent( const wxString
& string
,
2273 int *externalLeading
,
2274 const wxFont
*theFont
) const
2276 wxFont fontToUse
= m_font
;
2277 if (theFont
) fontToUse
= *theFont
;
2279 wxCHECK_RET( fontToUse
.Ok(), _T("invalid font") );
2281 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2282 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2283 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2284 if (descent
) (*descent
) = font
->descent
;
2285 if (externalLeading
) (*externalLeading
) = 0; // ??
2288 void wxWindow::SetFocus()
2290 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2292 GtkWidget
*connect_widget
= GetConnectWidget();
2295 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2297 gtk_widget_grab_focus (connect_widget
);
2299 else if (GTK_IS_CONTAINER(connect_widget
))
2301 gtk_container_focus( GTK_CONTAINER(connect_widget
), GTK_DIR_TAB_FORWARD
);
2309 bool wxWindow::AcceptsFocus() const
2311 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2314 bool wxWindow::Reparent( wxWindow
*newParent
)
2316 wxCHECK_MSG( (m_widget
!= NULL
), (wxWindow
*) NULL
, _T("invalid window") );
2318 gtk_widget_unparent( m_widget
);
2320 if ( !wxWindowBase::Reparent(newParent
) )
2326 void wxWindow::Raise()
2328 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2330 if (!m_widget
->window
) return;
2332 gdk_window_raise( m_widget
->window
);
2335 void wxWindow::Lower()
2337 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2339 if (!m_widget
->window
) return;
2341 gdk_window_lower( m_widget
->window
);
2344 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2346 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2348 if (!wxWindowBase::SetCursor(cursor
))
2350 // don't leave if the GTK widget has just
2352 if (!m_delayedCursor
) return FALSE
;
2355 GtkWidget
*connect_widget
= GetConnectWidget();
2356 if (!connect_widget
->window
)
2358 // indicate that a new style has been set
2359 // but it couldn't get applied as the
2360 // widget hasn't been realized yet.
2361 m_delayedCursor
= TRUE
;
2363 // pretend we have done something
2367 if ((m_widget
) && (m_widget
->window
))
2368 gdk_window_set_cursor( m_widget
->window
, GetCursor().GetCursor() );
2370 if ((m_wxwindow
) && (m_wxwindow
->window
))
2371 gdk_window_set_cursor( m_wxwindow
->window
, GetCursor().GetCursor() );
2377 void wxWindow::WarpPointer( int WXUNUSED(x
), int WXUNUSED(y
) )
2382 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2384 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2386 if (!m_widget
->window
) return;
2388 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2392 gdk_window_clear_area( m_wxwindow
->window
,
2394 rect
->width
, rect
->height
);
2398 gdk_window_clear( m_wxwindow
->window
);
2405 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2407 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2411 GdkRectangle gdk_rect
;
2412 gdk_rect
.x
= rect
->x
;
2413 gdk_rect
.y
= rect
->y
;
2414 gdk_rect
.width
= rect
->width
;
2415 gdk_rect
.height
= rect
->height
;
2418 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2420 gtk_widget_draw( m_widget
, &gdk_rect
);
2424 void wxWindow::Clear()
2426 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2428 if (!m_widget
->window
) return;
2430 if (m_wxwindow
&& m_wxwindow
->window
)
2432 gdk_window_clear( m_wxwindow
->window
);
2437 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2439 wxWindowBase::DoSetToolTip(tip
);
2442 m_tooltip
->Apply( this );
2445 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2447 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConv_current
->cWX2MB(tip
), (gchar
*) NULL
);
2449 #endif // wxUSE_TOOLTIPS
2451 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2453 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2455 if (!wxWindowBase::SetBackgroundColour(colour
))
2457 // don't leave if the GTK widget has just
2459 if (!m_delayedBackgroundColour
) return FALSE
;
2462 GtkWidget
*connect_widget
= GetConnectWidget();
2463 if (!connect_widget
->window
)
2465 // indicate that a new style has been set
2466 // but it couldn't get applied as the
2467 // widget hasn't been realized yet.
2468 m_delayedBackgroundColour
= TRUE
;
2470 // pretend we have done something
2474 if (m_wxwindow
&& m_wxwindow
->window
)
2476 /* wxMSW doesn't clear the window here. I don't do that either to
2477 provide compatibility. call Clear() to do the job. */
2479 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_wxwindow
->window
) );
2480 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
2483 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2485 if (sysbg
== m_backgroundColour
)
2487 m_backgroundColour
= wxNullColour
;
2489 m_backgroundColour
= sysbg
;
2499 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2501 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2503 if (!wxWindowBase::SetForegroundColour(colour
))
2505 // don't leave if the GTK widget has just
2507 if (!m_delayedForegroundColour
) return FALSE
;
2510 GtkWidget
*connect_widget
= GetConnectWidget();
2511 if (!connect_widget
->window
)
2513 // indicate that a new style has been set
2514 // but it couldn't get applied as the
2515 // widget hasn't been realized yet.
2516 m_delayedForegroundColour
= TRUE
;
2518 // pretend we have done something
2522 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2523 if (sysbg
== m_foregroundColour
)
2525 m_backgroundColour
= wxNullColour
;
2527 m_backgroundColour
= sysbg
;
2537 GtkStyle
*wxWindow::GetWidgetStyle()
2539 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2541 m_widgetStyle
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2543 return m_widgetStyle
;
2546 void wxWindow::SetWidgetStyle()
2548 GtkStyle
*style
= GetWidgetStyle();
2550 gdk_font_unref( style
->font
);
2551 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2553 if (m_foregroundColour
.Ok())
2555 m_foregroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2556 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2557 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2558 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2561 if (m_backgroundColour
.Ok())
2563 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2564 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2565 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2566 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2567 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2568 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2569 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2570 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2571 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2575 void wxWindow::ApplyWidgetStyle()
2579 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2581 menu
->SetInvokingWindow( win
);
2582 wxNode
*node
= menu
->GetItems().First();
2585 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2586 if (menuitem
->IsSubMenu())
2588 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2590 node
= node
->Next();
2594 static gint gs_pop_x
= 0;
2595 static gint gs_pop_y
= 0;
2597 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
2601 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
2606 bool wxWindow::PopupMenu( wxMenu
*menu
, int x
, int y
)
2608 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2610 wxCHECK_MSG( menu
!= NULL
, FALSE
, _T("invalid popup-menu") );
2612 SetInvokingWindow( menu
, this );
2620 GTK_MENU(menu
->m_menu
),
2621 (GtkWidget
*) NULL
, // parent menu shell
2622 (GtkWidget
*) NULL
, // parent menu item
2623 (GtkMenuPositionFunc
) pop_pos_callback
,
2624 (gpointer
) this, // client data
2625 0, // button used to activate it
2626 0 //gs_timeLastClick // the time of activation
2631 #if wxUSE_DRAG_AND_DROP
2633 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2635 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2637 GtkWidget
*dnd_widget
= GetConnectWidget();
2639 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
2641 if (m_dropTarget
) delete m_dropTarget
;
2642 m_dropTarget
= dropTarget
;
2644 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
2647 #endif // wxUSE_DRAG_AND_DROP
2649 GtkWidget
* wxWindow::GetConnectWidget()
2651 GtkWidget
*connect_widget
= m_widget
;
2652 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2654 return connect_widget
;
2657 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2659 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2660 return (window
== m_widget
->window
);
2663 bool wxWindow::SetFont( const wxFont
&font
)
2665 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T( "invalid window") );
2667 if (!wxWindowBase::SetFont(font
))
2669 // don't leave if the GTK widget has just
2671 if (!m_delayedFont
) return FALSE
;
2674 GtkWidget
*connect_widget
= GetConnectWidget();
2675 if (!connect_widget
->window
)
2677 // indicate that a new style has been set
2678 // but it couldn't get applied as the
2679 // widget hasn't been realized yet.
2680 m_delayedFont
= TRUE
;
2682 // pretend we have done something
2686 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2687 if ( sysbg
== m_backgroundColour
)
2689 m_backgroundColour
= wxNullColour
;
2691 m_backgroundColour
= sysbg
;
2701 void wxWindow::CaptureMouse()
2703 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2705 wxCHECK_RET( g_capturing
== FALSE
, _T("CaptureMouse called twice") );
2707 GtkWidget
*connect_widget
= GetConnectWidget();
2708 if (!connect_widget
->window
) return;
2710 gtk_grab_add( connect_widget
);
2711 gdk_pointer_grab( connect_widget
->window
, FALSE
,
2713 (GDK_BUTTON_PRESS_MASK
|
2714 GDK_BUTTON_RELEASE_MASK
|
2715 GDK_POINTER_MOTION_MASK
),
2722 void wxWindow::ReleaseMouse()
2724 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2726 wxCHECK_RET( g_capturing
== TRUE
, _T("ReleaseMouse called twice") );
2728 GtkWidget
*connect_widget
= GetConnectWidget();
2729 if (!connect_widget
->window
) return;
2731 gtk_grab_remove( connect_widget
);
2732 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2733 g_capturing
= FALSE
;
2736 bool wxWindow::IsRetained() const
2741 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2742 int range
, bool refresh
)
2744 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2746 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2748 m_hasScrolling
= TRUE
;
2750 if (orient
== wxHORIZONTAL
)
2752 float fpos
= (float)pos
;
2753 float frange
= (float)range
;
2754 float fthumb
= (float)thumbVisible
;
2755 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2756 if (fpos
< 0.0) fpos
= 0.0;
2758 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2759 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2761 SetScrollPos( orient
, pos
, refresh
);
2765 m_oldHorizontalPos
= fpos
;
2767 m_hAdjust
->lower
= 0.0;
2768 m_hAdjust
->upper
= frange
;
2769 m_hAdjust
->value
= fpos
;
2770 m_hAdjust
->step_increment
= 1.0;
2771 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2772 m_hAdjust
->page_size
= fthumb
;
2776 float fpos
= (float)pos
;
2777 float frange
= (float)range
;
2778 float fthumb
= (float)thumbVisible
;
2779 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2780 if (fpos
< 0.0) fpos
= 0.0;
2782 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2783 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2785 SetScrollPos( orient
, pos
, refresh
);
2789 m_oldVerticalPos
= fpos
;
2791 m_vAdjust
->lower
= 0.0;
2792 m_vAdjust
->upper
= frange
;
2793 m_vAdjust
->value
= fpos
;
2794 m_vAdjust
->step_increment
= 1.0;
2795 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2796 m_vAdjust
->page_size
= fthumb
;
2799 if (orient
== wxHORIZONTAL
)
2800 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2802 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2805 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2807 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2809 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2811 if (orient
== wxHORIZONTAL
)
2813 float fpos
= (float)pos
;
2814 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
2815 if (fpos
< 0.0) fpos
= 0.0;
2816 m_oldHorizontalPos
= fpos
;
2818 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2819 m_hAdjust
->value
= fpos
;
2823 float fpos
= (float)pos
;
2824 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
2825 if (fpos
< 0.0) fpos
= 0.0;
2826 m_oldVerticalPos
= fpos
;
2828 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2829 m_vAdjust
->value
= fpos
;
2832 if (!m_isScrolling
) /* prevent recursion */
2834 if (m_wxwindow
->window
)
2836 if (orient
== wxHORIZONTAL
)
2837 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2839 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2844 int wxWindow::GetScrollThumb( int orient
) const
2846 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2848 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2850 if (orient
== wxHORIZONTAL
)
2851 return (int)(m_hAdjust
->page_size
+0.5);
2853 return (int)(m_vAdjust
->page_size
+0.5);
2856 int wxWindow::GetScrollPos( int orient
) const
2858 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2860 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2862 if (orient
== wxHORIZONTAL
)
2863 return (int)(m_hAdjust
->value
+0.5);
2865 return (int)(m_vAdjust
->value
+0.5);
2868 int wxWindow::GetScrollRange( int orient
) const
2870 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2872 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2874 if (orient
== wxHORIZONTAL
)
2875 return (int)(m_hAdjust
->upper
+0.5);
2877 return (int)(m_vAdjust
->upper
+0.5);
2880 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2882 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2884 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2888 m_scrollGC
= gdk_gc_new( m_wxwindow
->window
);
2889 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
2892 wxNode
*node
= m_children
.First();
2895 wxWindow
*child
= (wxWindow
*) node
->Data();
2896 child
->Move( child
->m_x
+ dx
, child
->m_y
+ dy
);
2897 node
= node
->Next();
2902 GetClientSize( &cw
, &ch
);
2903 int w
= cw
- abs(dx
);
2904 int h
= ch
- abs(dy
);
2906 if ((h
< 0) || (w
< 0))
2914 if (dx
< 0) s_x
= -dx
;
2915 if (dy
< 0) s_y
= -dy
;
2918 if (dx
> 0) d_x
= dx
;
2919 if (dy
> 0) d_y
= dy
;
2921 gdk_window_copy_area( m_wxwindow
->window
, m_scrollGC
, d_x
, d_y
,
2922 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2925 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2926 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2927 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2928 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2930 Refresh( TRUE
, &rect
);
2934 void wxWindow::SetScrolling(bool scroll
)
2936 m_isScrolling
= g_blockEventsOnScroll
= scroll
;