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;
219 case GDK_Menu
: key_code
= WXK_MENU
; break;
220 case GDK_Help
: key_code
= WXK_HELP
; break;
221 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
222 case GDK_ISO_Left_Tab
:
223 case GDK_Tab
: key_code
= WXK_TAB
; break;
224 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
225 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
226 case GDK_Return
: key_code
= WXK_RETURN
; break;
227 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
228 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
229 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
230 case GDK_Delete
: key_code
= WXK_DELETE
; break;
231 case GDK_Home
: key_code
= WXK_HOME
; break;
232 case GDK_Left
: key_code
= WXK_LEFT
; break;
233 case GDK_Up
: key_code
= WXK_UP
; break;
234 case GDK_Right
: key_code
= WXK_RIGHT
; break;
235 case GDK_Down
: key_code
= WXK_DOWN
; break;
236 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
237 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
238 case GDK_Next
: key_code
= WXK_NEXT
; break;
239 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
240 case GDK_End
: key_code
= WXK_END
; break;
241 case GDK_Begin
: key_code
= WXK_HOME
; break;
242 case GDK_Select
: key_code
= WXK_SELECT
; break;
243 case GDK_Print
: key_code
= WXK_PRINT
; break;
244 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
245 case GDK_Insert
: key_code
= WXK_INSERT
; break;
246 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
248 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
249 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
250 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
251 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
252 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
253 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
254 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
255 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
256 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
257 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
258 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
259 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
260 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
261 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
262 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
263 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
264 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
265 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
266 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
267 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
268 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
269 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
270 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
271 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
272 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
273 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
274 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
275 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
276 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
277 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
278 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
279 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
280 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
281 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
282 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
283 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
284 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
286 case GDK_F1
: key_code
= WXK_F1
; break;
287 case GDK_F2
: key_code
= WXK_F2
; break;
288 case GDK_F3
: key_code
= WXK_F3
; break;
289 case GDK_F4
: key_code
= WXK_F4
; break;
290 case GDK_F5
: key_code
= WXK_F5
; break;
291 case GDK_F6
: key_code
= WXK_F6
; break;
292 case GDK_F7
: key_code
= WXK_F7
; break;
293 case GDK_F8
: key_code
= WXK_F8
; break;
294 case GDK_F9
: key_code
= WXK_F9
; break;
295 case GDK_F10
: key_code
= WXK_F10
; break;
296 case GDK_F11
: key_code
= WXK_F11
; break;
297 case GDK_F12
: key_code
= WXK_F12
; break;
302 guint upper
= gdk_keyval_to_upper( keysym
);
303 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
312 static long map_to_wx_keysym( KeySym keysym
)
318 case GDK_Menu
: key_code
= WXK_MENU
; break;
319 case GDK_Help
: key_code
= WXK_HELP
; break;
320 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
321 case GDK_ISO_Left_Tab
:
322 case GDK_Tab
: key_code
= WXK_TAB
; break;
323 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
324 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
325 case GDK_Return
: key_code
= WXK_RETURN
; break;
326 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
327 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
328 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
329 case GDK_Delete
: key_code
= WXK_DELETE
; break;
330 case GDK_Home
: key_code
= WXK_HOME
; break;
331 case GDK_Left
: key_code
= WXK_LEFT
; break;
332 case GDK_Up
: key_code
= WXK_UP
; break;
333 case GDK_Right
: key_code
= WXK_RIGHT
; break;
334 case GDK_Down
: key_code
= WXK_DOWN
; break;
335 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
336 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
337 case GDK_Next
: key_code
= WXK_NEXT
; break;
338 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
339 case GDK_End
: key_code
= WXK_END
; break;
340 case GDK_Begin
: key_code
= WXK_HOME
; break;
341 case GDK_Select
: key_code
= WXK_SELECT
; break;
342 case GDK_Print
: key_code
= WXK_PRINT
; break;
343 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
344 case GDK_Insert
: key_code
= WXK_INSERT
; break;
345 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
347 case GDK_KP_0
: key_code
= '0'; break;
348 case GDK_KP_1
: key_code
= '1'; break;
349 case GDK_KP_2
: key_code
= '2'; break;
350 case GDK_KP_3
: key_code
= '3'; break;
351 case GDK_KP_4
: key_code
= '4'; break;
352 case GDK_KP_5
: key_code
= '5'; break;
353 case GDK_KP_6
: key_code
= '6'; break;
354 case GDK_KP_7
: key_code
= '7'; break;
355 case GDK_KP_8
: key_code
= '8'; break;
356 case GDK_KP_9
: key_code
= '9'; break;
357 case GDK_KP_Space
: key_code
= ' '; break;
358 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
359 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
360 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
361 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
362 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
363 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
364 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
365 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
366 case GDK_KP_Up
: key_code
= WXK_UP
; break;
367 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
368 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
369 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
370 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
371 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
372 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
373 case GDK_KP_End
: key_code
= WXK_END
; break;
374 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
375 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
376 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
377 case GDK_KP_Equal
: key_code
= '='; break;
378 case GDK_KP_Multiply
: key_code
= '*'; break;
379 case GDK_KP_Add
: key_code
= '+'; break;
380 case GDK_KP_Separator
: key_code
= ','; break;
381 case GDK_KP_Subtract
: key_code
= '-'; break;
382 case GDK_KP_Decimal
: key_code
= '.'; break;
383 case GDK_KP_Divide
: key_code
= '/'; break;
385 case GDK_F1
: key_code
= WXK_F1
; break;
386 case GDK_F2
: key_code
= WXK_F2
; break;
387 case GDK_F3
: key_code
= WXK_F3
; break;
388 case GDK_F4
: key_code
= WXK_F4
; break;
389 case GDK_F5
: key_code
= WXK_F5
; break;
390 case GDK_F6
: key_code
= WXK_F6
; break;
391 case GDK_F7
: key_code
= WXK_F7
; break;
392 case GDK_F8
: key_code
= WXK_F8
; break;
393 case GDK_F9
: key_code
= WXK_F9
; break;
394 case GDK_F10
: key_code
= WXK_F10
; break;
395 case GDK_F11
: key_code
= WXK_F11
; break;
396 case GDK_F12
: key_code
= WXK_F12
; break;
409 //-----------------------------------------------------------------------------
410 // local code (see below)
411 //-----------------------------------------------------------------------------
413 #if (GTK_MINOR_VERSION > 0)
415 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
423 if (win
->HasScrolling())
425 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
426 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
429 GtkWidget *hscrollbar = scroll_window->hscrollbar;
430 GtkWidget *vscrollbar = scroll_window->vscrollbar;
432 we use this instead: range.slider_width = 11 + 2*2pts edge
435 if (scroll_window
->vscrollbar_visible
)
437 dw
+= 15; /* dw += vscrollbar->allocation.width; */
438 dw
+= scroll_class
->scrollbar_spacing
;
441 if (scroll_window
->hscrollbar_visible
)
443 dh
+= 15; /* dh += hscrollbar->allocation.height; */
444 dh
+= scroll_class
->scrollbar_spacing
;
450 if (GTK_WIDGET_NO_WINDOW (widget
))
452 dx
+= widget
->allocation
.x
;
453 dy
+= widget
->allocation
.y
;
456 if (win
->HasFlag(wxRAISED_BORDER
))
458 gtk_draw_shadow( widget
->style
,
463 win
->m_width
-dw
, win
->m_height
-dh
);
467 if (win
->HasFlag(wxSUNKEN_BORDER
))
469 gtk_draw_shadow( widget
->style
,
474 win
->m_width
-dw
, win
->m_height
-dh
);
479 //-----------------------------------------------------------------------------
480 // "expose_event" of m_widget
481 //-----------------------------------------------------------------------------
483 static void gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
485 if (gdk_event
->count
> 0) return;
486 draw_frame( widget
, win
);
489 //-----------------------------------------------------------------------------
490 // "draw" of m_wxwindow
491 //-----------------------------------------------------------------------------
493 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
495 draw_frame( widget
, win
);
498 #endif // GTK_MINOR_VERSION > 0
500 //-----------------------------------------------------------------------------
501 // "expose_event" of m_wxwindow
502 //-----------------------------------------------------------------------------
504 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
506 if ( !win
->m_hasVMT
)
509 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
511 gdk_event
->area
.width
,
512 gdk_event
->area
.height
);
514 if ( gdk_event
->count
> 0 )
518 printf( "OnExpose from " );
519 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
520 printf( win->GetClassInfo()->GetClassName() );
524 wxPaintEvent
event( win
->GetId() );
525 event
.SetEventObject( win
);
526 win
->GetEventHandler()->ProcessEvent( event
);
528 win
->GetUpdateRegion().Clear();
531 //-----------------------------------------------------------------------------
532 // "draw" of m_wxwindow
533 //-----------------------------------------------------------------------------
535 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
538 wxapp_install_idle_handler();
543 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
544 rect
->width
, rect
->height
);
546 wxPaintEvent
event( win
->GetId() );
547 event
.SetEventObject( win
);
548 win
->GetEventHandler()->ProcessEvent( event
);
550 win
->GetUpdateRegion().Clear();
553 //-----------------------------------------------------------------------------
554 // "key_press_event" from any window
555 //-----------------------------------------------------------------------------
557 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
560 wxapp_install_idle_handler();
562 if (!win
->m_hasVMT
) return FALSE
;
563 if (g_blockEventsOnDrag
) return FALSE
;
566 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
567 if (gdk_event->state & GDK_SHIFT_MASK)
568 printf( "ShiftDown.\n" );
570 printf( "ShiftUp.\n" );
571 if (gdk_event->state & GDK_CONTROL_MASK)
572 printf( "ControlDown.\n" );
574 printf( "ControlUp.\n" );
579 GdkModifierType state
;
580 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
582 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
584 /* sending unknown key events doesn't really make sense */
585 if (key_code
== 0) return FALSE
;
589 wxKeyEvent
event( wxEVT_KEY_DOWN
);
590 event
.SetTimestamp( gdk_event
->time
);
591 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
592 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
593 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
594 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
595 event
.m_keyCode
= key_code
;
596 event
.m_scanCode
= gdk_event
->keyval
;
599 event
.SetEventObject( win
);
600 ret
= win
->GetEventHandler()->ProcessEvent( event
);
602 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
604 /* wxMSW doesn't send char events with Alt pressed */
605 if ((key_code
!= 0) &&
606 ((gdk_event
->state
& GDK_MOD1_MASK
) == 0) &&
607 ((gdk_event
->state
& GDK_MOD1_MASK
) == 0))
609 wxKeyEvent
event2( wxEVT_CHAR
);
610 event2
.SetTimestamp( gdk_event
->time
);
611 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
612 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
613 // event2.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
614 // event2.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
615 event2
.m_keyCode
= key_code
;
616 event2
.m_scanCode
= gdk_event
->keyval
;
619 event2
.SetEventObject( win
);
620 ret
= (ret
|| win
->GetEventHandler()->ProcessEvent( event2
));
625 wxWindow
*ancestor
= win
;
628 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
631 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
632 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
635 ancestor
= ancestor
->GetParent();
639 /* win is a control: tab can be propagated up */
641 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
642 (win
->HasFlag(wxTE_PROCESS_TAB
) == 0))
644 wxNavigationKeyEvent new_event
;
645 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
646 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
647 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
648 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
649 new_event
.SetCurrentFocus( win
);
650 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
653 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
655 (gdk_event
->keyval
== GDK_Escape
) )
657 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
658 new_event
.SetEventObject( win
);
659 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
662 #if (GTK_MINOR_VERSION > 0)
663 /* pressing F10 will activate the menu bar of the top frame */
665 (gdk_event
->keyval
== GDK_F10
) )
667 wxWindow
*ancestor
= win
;
670 if (wxIsKindOf(ancestor
,wxFrame
))
672 wxFrame
*frame
= (wxFrame
*) ancestor
;
673 wxMenuBar
*menubar
= frame
->GetMenuBar();
676 wxNode
*node
= menubar
->GetMenus().First();
679 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
680 // doesn't work correctly
681 // gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
687 ancestor
= ancestor
->GetParent();
693 Damn, I forgot why this didn't work, but it didn't work.
695 // win is a panel: up can be propagated to the panel
696 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
697 (gdk_event->keyval == GDK_Up))
699 win->m_parent->SetFocus();
703 // win is a panel: left/right can be propagated to the panel
704 if ((!ret) && (win->m_wxwindow) &&
705 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
706 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
708 wxNavigationKeyEvent new_event;
709 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
710 new_event.SetCurrentFocus( win );
711 ret = win->GetEventHandler()->ProcessEvent( new_event );
717 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
724 //-----------------------------------------------------------------------------
725 // "key_release_event" from any window
726 //-----------------------------------------------------------------------------
728 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
731 wxapp_install_idle_handler();
733 if (!win
->m_hasVMT
) return FALSE
;
734 if (g_blockEventsOnDrag
) return FALSE
;
737 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
738 if (gdk_event->state & GDK_SHIFT_MASK)
739 printf( "ShiftDown.\n" );
741 printf( "ShiftUp.\n" );
742 if (gdk_event->state & GDK_CONTROL_MASK)
743 printf( "ControlDown.\n" );
745 printf( "ControlUp.\n" );
749 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
751 /* sending unknown key events doesn't really make sense */
752 if (key_code
== 0) return FALSE
;
756 GdkModifierType state
;
757 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
759 wxKeyEvent
event( wxEVT_KEY_UP
);
760 event
.SetTimestamp( gdk_event
->time
);
761 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
762 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
763 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
764 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
765 event
.m_keyCode
= key_code
;
766 event
.m_scanCode
= gdk_event
->keyval
;
769 event
.SetEventObject( win
);
771 if (win
->GetEventHandler()->ProcessEvent( event
))
773 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
780 //-----------------------------------------------------------------------------
781 // "button_press_event"
782 //-----------------------------------------------------------------------------
784 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
787 wxapp_install_idle_handler();
790 wxPrintf( _T("1) OnButtonPress from ") );
791 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
792 wxPrintf( win->GetClassInfo()->GetClassName() );
793 wxPrintf( _T(".\n") );
795 if (!win
->m_hasVMT
) return FALSE
;
796 if (g_blockEventsOnDrag
) return TRUE
;
797 if (g_blockEventsOnScroll
) return TRUE
;
799 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
803 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
805 gtk_widget_grab_focus (win
->m_wxwindow
);
808 wxPrintf( _T("GrabFocus from ") );
809 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
810 wxPrintf( win->GetClassInfo()->GetClassName() );
811 wxPrintf( _T(".\n") );
818 wxPrintf( _T("2) OnButtonPress from ") );
819 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
820 wxPrintf( win->GetClassInfo()->GetClassName() );
821 wxPrintf( _T(".\n") );
824 wxEventType event_type
= wxEVT_LEFT_DOWN
;
826 if (gdk_event
->button
== 1)
828 switch (gdk_event
->type
)
830 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
831 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
835 else if (gdk_event
->button
== 2)
837 switch (gdk_event
->type
)
839 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
840 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
844 else if (gdk_event
->button
== 3)
846 switch (gdk_event
->type
)
848 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
849 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
854 wxMouseEvent
event( event_type
);
855 event
.SetTimestamp( gdk_event
->time
);
856 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
857 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
858 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
859 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
860 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
861 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
862 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
864 event
.m_x
= (long)gdk_event
->x
;
865 event
.m_y
= (long)gdk_event
->y
;
867 // Some control don't have their own X window and thus cannot get
872 wxNode
*node
= win
->GetChildren().First();
875 wxWindow
*child
= (wxWindow
*)node
->Data();
877 if (child
->m_isStaticBox
)
879 // wxStaticBox is transparent in the box itself
882 int xx1
= child
->m_x
;
883 int yy1
= child
->m_y
;
884 int xx2
= child
->m_x
+ child
->m_width
;
885 int yy2
= child
->m_x
+ child
->m_height
;
888 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
890 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
892 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
894 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
897 event
.m_x
-= child
->m_x
;
898 event
.m_y
-= child
->m_y
;
905 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
906 (child
->m_x
<= event
.m_x
) &&
907 (child
->m_y
<= event
.m_y
) &&
908 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
909 (child
->m_y
+child
->m_height
>= event
.m_y
))
912 event
.m_x
-= child
->m_x
;
913 event
.m_y
-= child
->m_y
;
921 event
.SetEventObject( win
);
923 gs_timeLastClick
= gdk_event
->time
;
925 if (win
->GetEventHandler()->ProcessEvent( event
))
927 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
934 //-----------------------------------------------------------------------------
935 // "button_release_event"
936 //-----------------------------------------------------------------------------
938 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
941 wxapp_install_idle_handler();
943 if (!win
->m_hasVMT
) return FALSE
;
944 if (g_blockEventsOnDrag
) return FALSE
;
945 if (g_blockEventsOnScroll
) return FALSE
;
947 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
950 printf( "OnButtonRelease from " );
951 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
952 printf( win->GetClassInfo()->GetClassName() );
956 wxEventType event_type
= wxEVT_NULL
;
958 switch (gdk_event
->button
)
960 case 1: event_type
= wxEVT_LEFT_UP
; break;
961 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
962 case 3: event_type
= wxEVT_RIGHT_UP
; break;
965 wxMouseEvent
event( event_type
);
966 event
.SetTimestamp( gdk_event
->time
);
967 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
968 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
969 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
970 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
971 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
972 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
973 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
974 event
.m_x
= (long)gdk_event
->x
;
975 event
.m_y
= (long)gdk_event
->y
;
977 // Some control don't have their own X window and thus cannot get
982 wxNode
*node
= win
->GetChildren().First();
985 wxWindow
*child
= (wxWindow
*)node
->Data();
987 if (child
->m_isStaticBox
)
989 // wxStaticBox is transparent in the box itself
992 int xx1
= child
->m_x
;
993 int yy1
= child
->m_y
;
994 int xx2
= child
->m_x
+ child
->m_width
;
995 int yy2
= child
->m_x
+ child
->m_height
;
998 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1000 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1002 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1004 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1007 event
.m_x
-= child
->m_x
;
1008 event
.m_y
-= child
->m_y
;
1015 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1016 (child
->m_x
<= event
.m_x
) &&
1017 (child
->m_y
<= event
.m_y
) &&
1018 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
1019 (child
->m_y
+child
->m_height
>= event
.m_y
))
1022 event
.m_x
-= child
->m_x
;
1023 event
.m_y
-= child
->m_y
;
1027 node
= node
->Next();
1031 event
.SetEventObject( win
);
1033 if (win
->GetEventHandler()->ProcessEvent( event
))
1035 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1042 //-----------------------------------------------------------------------------
1043 // "motion_notify_event"
1044 //-----------------------------------------------------------------------------
1046 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1049 wxapp_install_idle_handler();
1051 if (!win
->m_hasVMT
) return FALSE
;
1052 if (g_blockEventsOnDrag
) return FALSE
;
1053 if (g_blockEventsOnScroll
) return FALSE
;
1055 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1057 if (gdk_event
->is_hint
)
1061 GdkModifierType state
;
1062 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1065 gdk_event
->state
= state
;
1069 printf( "OnMotion from " );
1070 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1071 printf( win->GetClassInfo()->GetClassName() );
1075 wxMouseEvent
event( wxEVT_MOTION
);
1076 event
.SetTimestamp( gdk_event
->time
);
1077 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1078 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1079 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1080 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1081 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1082 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1083 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1085 event
.m_x
= (long)gdk_event
->x
;
1086 event
.m_y
= (long)gdk_event
->y
;
1088 // Some control don't have their own X window and thus cannot get
1093 wxNode
*node
= win
->GetChildren().First();
1096 wxWindow
*child
= (wxWindow
*)node
->Data();
1098 if (child
->m_isStaticBox
)
1100 // wxStaticBox is transparent in the box itself
1103 int xx1
= child
->m_x
;
1104 int yy1
= child
->m_y
;
1105 int xx2
= child
->m_x
+ child
->m_width
;
1106 int yy2
= child
->m_x
+ child
->m_height
;
1109 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1111 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1113 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1115 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1118 event
.m_x
-= child
->m_x
;
1119 event
.m_y
-= child
->m_y
;
1126 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1127 (child
->m_x
<= event
.m_x
) &&
1128 (child
->m_y
<= event
.m_y
) &&
1129 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
1130 (child
->m_y
+child
->m_height
>= event
.m_y
))
1133 event
.m_x
-= child
->m_x
;
1134 event
.m_y
-= child
->m_y
;
1138 node
= node
->Next();
1142 event
.SetEventObject( win
);
1144 if (win
->GetEventHandler()->ProcessEvent( event
))
1146 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1153 //-----------------------------------------------------------------------------
1155 //-----------------------------------------------------------------------------
1157 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1160 wxapp_install_idle_handler();
1162 if (!win
->m_hasVMT
) return FALSE
;
1163 if (g_blockEventsOnDrag
) return FALSE
;
1165 g_focusWindow
= win
;
1167 if (win
->m_wxwindow
)
1169 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1171 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1173 printf( "SetFocus flag from " );
1174 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1175 printf( win->GetClassInfo()->GetClassName() );
1183 printf( "OnSetFocus from " );
1184 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1185 printf( win->GetClassInfo()->GetClassName() );
1187 printf( WXSTRINGCAST win->GetLabel() );
1191 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1192 event
.SetEventObject( win
);
1194 if (win
->GetEventHandler()->ProcessEvent( event
))
1196 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1203 //-----------------------------------------------------------------------------
1204 // "focus_out_event"
1205 //-----------------------------------------------------------------------------
1207 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1210 wxapp_install_idle_handler();
1212 if (!win
->m_hasVMT
) return FALSE
;
1213 if (g_blockEventsOnDrag
) return FALSE
;
1215 if (win
->m_wxwindow
)
1217 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1218 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1222 printf( "OnKillFocus from " );
1223 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1224 printf( win->GetClassInfo()->GetClassName() );
1228 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1229 event
.SetEventObject( win
);
1231 if (win
->GetEventHandler()->ProcessEvent( event
))
1233 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1240 //-----------------------------------------------------------------------------
1241 // "enter_notify_event"
1242 //-----------------------------------------------------------------------------
1244 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1247 wxapp_install_idle_handler();
1249 if (!win
->m_hasVMT
) return FALSE
;
1250 if (g_blockEventsOnDrag
) return FALSE
;
1252 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1254 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1255 #if (GTK_MINOR_VERSION > 0)
1256 event
.SetTimestamp( gdk_event
->time
);
1258 event
.SetEventObject( win
);
1262 GdkModifierType state
= (GdkModifierType
)0;
1264 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1266 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1267 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1268 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1269 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1270 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1271 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1272 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1274 event
.m_x
= (long)x
;
1275 event
.m_y
= (long)y
;
1277 if (win
->GetEventHandler()->ProcessEvent( event
))
1279 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1286 //-----------------------------------------------------------------------------
1287 // "leave_notify_event"
1288 //-----------------------------------------------------------------------------
1290 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1293 wxapp_install_idle_handler();
1295 if (!win
->m_hasVMT
) return FALSE
;
1296 if (g_blockEventsOnDrag
) return FALSE
;
1298 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1300 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1301 #if (GTK_MINOR_VERSION > 0)
1302 event
.SetTimestamp( gdk_event
->time
);
1304 event
.SetEventObject( win
);
1308 GdkModifierType state
= (GdkModifierType
)0;
1310 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1312 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1313 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1314 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1315 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1316 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1317 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1318 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1320 event
.m_x
= (long)x
;
1321 event
.m_y
= (long)y
;
1323 if (win
->GetEventHandler()->ProcessEvent( event
))
1325 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1332 //-----------------------------------------------------------------------------
1333 // "value_changed" from m_vAdjust
1334 //-----------------------------------------------------------------------------
1336 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1339 wxapp_install_idle_handler();
1341 if (g_blockEventsOnDrag
) return;
1343 if (!win
->m_hasVMT
) return;
1345 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
1346 if (fabs(diff
) < 0.2) return;
1347 win
->m_oldVerticalPos
= win
->m_vAdjust
->value
;
1349 wxEventType command
= wxEVT_NULL
;
1351 float line_step
= win
->m_vAdjust
->step_increment
;
1352 float page_step
= win
->m_vAdjust
->page_increment
;
1354 if (win
->IsScrolling())
1356 command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1360 if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->lower
) < 0.2) command
= wxEVT_SCROLLWIN_BOTTOM
;
1361 else if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->upper
) < 0.2) command
= wxEVT_SCROLLWIN_TOP
;
1362 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1363 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEUP
;
1364 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1365 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEUP
;
1366 else command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1369 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1371 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1372 event
.SetEventObject( win
);
1373 win
->GetEventHandler()->ProcessEvent( event
);
1376 //-----------------------------------------------------------------------------
1377 // "value_changed" from m_hAdjust
1378 //-----------------------------------------------------------------------------
1380 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1383 wxapp_install_idle_handler();
1385 if (g_blockEventsOnDrag
) return;
1386 if (!win
->m_hasVMT
) return;
1388 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
1389 if (fabs(diff
) < 0.2) return;
1390 win
->m_oldHorizontalPos
= win
->m_hAdjust
->value
;
1392 wxEventType command
= wxEVT_NULL
;
1394 float line_step
= win
->m_hAdjust
->step_increment
;
1395 float page_step
= win
->m_hAdjust
->page_increment
;
1397 if (win
->IsScrolling())
1399 command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1403 if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->lower
) < 0.2) command
= wxEVT_SCROLLWIN_BOTTOM
;
1404 else if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->upper
) < 0.2) command
= wxEVT_SCROLLWIN_TOP
;
1405 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1406 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEUP
;
1407 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1408 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEUP
;
1409 else command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1412 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1414 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1415 event
.SetEventObject( win
);
1416 win
->GetEventHandler()->ProcessEvent( event
);
1419 //-----------------------------------------------------------------------------
1420 // "changed" from m_vAdjust
1421 //-----------------------------------------------------------------------------
1423 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1426 wxapp_install_idle_handler();
1428 if (g_blockEventsOnDrag
) return;
1429 if (!win
->m_hasVMT
) return;
1431 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1432 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1434 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1435 event
.SetEventObject( win
);
1436 win
->GetEventHandler()->ProcessEvent( event
);
1439 //-----------------------------------------------------------------------------
1440 // "changed" from m_hAdjust
1441 //-----------------------------------------------------------------------------
1443 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1446 wxapp_install_idle_handler();
1448 if (g_blockEventsOnDrag
) return;
1449 if (!win
->m_hasVMT
) return;
1451 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1452 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1454 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1455 event
.SetEventObject( win
);
1456 win
->GetEventHandler()->ProcessEvent( event
);
1459 //-----------------------------------------------------------------------------
1460 // "button_press_event" from scrollbar
1461 //-----------------------------------------------------------------------------
1463 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1464 GdkEventButton
*WXUNUSED(gdk_event
),
1468 wxapp_install_idle_handler();
1470 // don't test here as we can release the mouse while being over
1471 // a different window then the slider
1473 // if (gdk_event->window != widget->slider) return FALSE;
1475 win
->SetScrolling( TRUE
);
1480 //-----------------------------------------------------------------------------
1481 // "button_release_event" from scrollbar
1482 //-----------------------------------------------------------------------------
1484 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1485 GdkEventButton
*WXUNUSED(gdk_event
),
1489 // don't test here as we can release the mouse while being over
1490 // a different window then the slider
1492 // if (gdk_event->window != widget->slider) return FALSE;
1494 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1496 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1497 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_hAdjust
), "value_changed" );
1499 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_vAdjust
), "value_changed" );
1501 win
->SetScrolling( FALSE
);
1506 // ----------------------------------------------------------------------------
1507 // this wxWindowBase function is implemented here (in platform-specific file)
1508 // because it is static and so couldn't be made virtual
1509 // ----------------------------------------------------------------------------
1511 wxWindow
*wxWindowBase::FindFocus()
1513 return g_focusWindow
;
1516 //-----------------------------------------------------------------------------
1517 // "realize" from m_widget
1518 //-----------------------------------------------------------------------------
1520 /* we cannot set colours, fonts and cursors before the widget has
1521 been realized, so we do this directly after realization */
1524 gtk_window_realized_callback( GtkWidget
* WXUNUSED(widget
), wxWindow
*win
)
1527 wxapp_install_idle_handler();
1529 if (win
->m_delayedFont
)
1530 win
->SetFont( win
->GetFont() );
1532 if (win
->m_delayedBackgroundColour
)
1533 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1535 if (win
->m_delayedForegroundColour
)
1536 win
->SetForegroundColour( win
->GetForegroundColour() );
1538 win
->SetCursor( win
->GetCursor() );
1540 wxWindowCreateEvent
event( win
);
1541 event
.SetEventObject( win
);
1542 win
->GetEventHandler()->ProcessEvent( event
);
1547 //-----------------------------------------------------------------------------
1548 // InsertChild for wxWindow.
1549 //-----------------------------------------------------------------------------
1551 /* Callback for wxWindow. This very strange beast has to be used because
1552 * C++ has no virtual methods in a constructor. We have to emulate a
1553 * virtual function here as wxNotebook requires a different way to insert
1554 * a child in it. I had opted for creating a wxNotebookPage window class
1555 * which would have made this superfluous (such in the MDI window system),
1556 * but no-one was listening to me... */
1558 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1560 gtk_myfixed_put( GTK_MYFIXED(parent
->m_wxwindow
),
1561 GTK_WIDGET(child
->m_widget
),
1567 if (parent
->HasFlag(wxTAB_TRAVERSAL
))
1569 /* we now allow a window to get the focus as long as it
1570 doesn't have any children. */
1571 GTK_WIDGET_UNSET_FLAGS( parent
->m_wxwindow
, GTK_CAN_FOCUS
);
1575 //-----------------------------------------------------------------------------
1577 //-----------------------------------------------------------------------------
1579 wxWindow
* wxGetActiveWindow()
1581 return g_focusWindow
;
1584 //-----------------------------------------------------------------------------
1586 //-----------------------------------------------------------------------------
1588 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1590 void wxWindow::Init()
1596 m_widget
= (GtkWidget
*) NULL
;
1597 m_wxwindow
= (GtkWidget
*) NULL
;
1607 m_needParent
= TRUE
;
1608 m_isBeingDeleted
= FALSE
;
1610 m_hasScrolling
= FALSE
;
1611 m_isScrolling
= FALSE
;
1613 m_hAdjust
= (GtkAdjustment
*) NULL
;
1614 m_vAdjust
= (GtkAdjustment
*) NULL
;
1615 m_oldHorizontalPos
= 0.0;
1616 m_oldVerticalPos
= 0.0;
1619 m_scrollGC
= (GdkGC
*) NULL
;
1620 m_widgetStyle
= (GtkStyle
*) NULL
;
1622 m_insertCallback
= wxInsertChildInWindow
;
1624 m_isStaticBox
= FALSE
;
1625 m_acceptsFocus
= FALSE
;
1628 wxWindow::wxWindow()
1633 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1634 const wxPoint
&pos
, const wxSize
&size
,
1635 long style
, const wxString
&name
)
1639 Create( parent
, id
, pos
, size
, style
, name
);
1642 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1643 const wxPoint
&pos
, const wxSize
&size
,
1644 long style
, const wxString
&name
)
1646 PreCreation( parent
, id
, pos
, size
, style
, name
);
1648 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1649 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1652 debug_focus_in( m_widget
, _T("wxWindow::m_widget"), name
);
1655 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1658 debug_focus_in( scrolledWindow
->hscrollbar
, _T("wxWindow::hsrcollbar"), name
);
1659 debug_focus_in( scrolledWindow
->vscrollbar
, _T("wxWindow::vsrcollbar"), name
);
1662 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1663 scroll_class
->scrollbar_spacing
= 0;
1665 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1667 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
1668 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
1670 m_wxwindow
= gtk_myfixed_new();
1673 debug_focus_in( m_wxwindow
, _T("wxWindow::m_wxwindow"), name
);
1676 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1678 #if (GTK_MINOR_VERSION > 0)
1679 GtkMyFixed
*myfixed
= GTK_MYFIXED(m_wxwindow
);
1681 if (HasFlag(wxRAISED_BORDER
))
1683 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_OUT
);
1685 else if (HasFlag(wxSUNKEN_BORDER
))
1687 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_IN
);
1691 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_NONE
);
1693 #else // GTK_MINOR_VERSION == 0
1694 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
1696 if (HasFlag(wxRAISED_BORDER
))
1698 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1700 else if (HasFlag(wxSUNKEN_BORDER
))
1702 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1706 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1708 #endif // GTK_MINOR_VERSION
1710 if (HasFlag(wxTAB_TRAVERSAL
))
1712 /* we now allow a window to get the focus as long as it
1713 doesn't have any children. */
1714 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1715 m_acceptsFocus
= FALSE
;
1719 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1720 m_acceptsFocus
= TRUE
;
1723 #if (GTK_MINOR_VERSION == 0)
1724 // shut the viewport up
1725 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1726 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1727 #endif // GTK_MINOR_VERSION == 0
1729 // I _really_ don't want scrollbars in the beginning
1730 m_vAdjust
->lower
= 0.0;
1731 m_vAdjust
->upper
= 1.0;
1732 m_vAdjust
->value
= 0.0;
1733 m_vAdjust
->step_increment
= 1.0;
1734 m_vAdjust
->page_increment
= 1.0;
1735 m_vAdjust
->page_size
= 5.0;
1736 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1737 m_hAdjust
->lower
= 0.0;
1738 m_hAdjust
->upper
= 1.0;
1739 m_hAdjust
->value
= 0.0;
1740 m_hAdjust
->step_increment
= 1.0;
1741 m_hAdjust
->page_increment
= 1.0;
1742 m_hAdjust
->page_size
= 5.0;
1743 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1745 // these handlers block mouse events to any window during scrolling such as
1746 // motion events and prevent GTK and wxWindows from fighting over where the
1749 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
1750 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1752 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
1753 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1755 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
1756 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1758 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
1759 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1761 // these handlers get notified when screen updates are required either when
1762 // scrolling or when the window size (and therefore scrollbar configuration)
1765 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
1766 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
1767 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
1768 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
1770 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
1771 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
1772 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
1773 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
1775 gtk_widget_show( m_wxwindow
);
1778 m_parent
->DoAddChild( this );
1787 wxWindow::~wxWindow()
1789 m_isBeingDeleted
= TRUE
;
1798 m_parent
->RemoveChild( this );
1802 gtk_style_unref( m_widgetStyle
);
1803 m_widgetStyle
= (GtkStyle
*) NULL
;
1808 gdk_gc_unref( m_scrollGC
);
1809 m_scrollGC
= (GdkGC
*) NULL
;
1814 gtk_widget_destroy( m_wxwindow
);
1815 m_wxwindow
= (GtkWidget
*) NULL
;
1820 gtk_widget_destroy( m_widget
);
1821 m_widget
= (GtkWidget
*) NULL
;
1825 void wxWindow::PreCreation( wxWindow
*parent
,
1830 const wxString
&name
)
1832 wxASSERT_MSG( !m_needParent
|| parent
, _T("Need complete parent.") );
1834 if ( !CreateBase(parent
, id
, pos
, size
, style
, name
) )
1836 wxFAIL_MSG(_T("window creation failed"));
1839 m_width
= WidthDefault(size
.x
);
1840 m_height
= HeightDefault(size
.y
);
1845 if (!parent
) /* some reasonable defaults */
1849 m_x
= (gdk_screen_width () - m_width
) / 2;
1850 if (m_x
< 10) m_x
= 10;
1854 m_y
= (gdk_screen_height () - m_height
) / 2;
1855 if (m_y
< 10) m_y
= 10;
1860 void wxWindow::PostCreation()
1862 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1866 /* these get reported to wxWindows -> wxPaintEvent */
1867 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1868 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1870 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1871 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1873 #if (GTK_MINOR_VERSION > 0)
1874 /* these are called when the "sunken" or "raised" borders are drawn */
1875 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
1876 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
1878 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
1879 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
1883 GtkWidget
*connect_widget
= GetConnectWidget();
1885 ConnectWidget( connect_widget
);
1887 /* we cannot set colours, fonts and cursors before the widget has
1888 been realized, so we do this directly after realization */
1889 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
1890 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
1895 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1897 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1898 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1900 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
1901 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
1903 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1904 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1906 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1907 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1909 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1910 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1912 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1913 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1915 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1916 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1918 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1919 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1921 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1922 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1925 bool wxWindow::Destroy()
1927 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1931 return wxWindowBase::Destroy();
1934 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1936 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1937 wxASSERT_MSG( (m_parent
!= NULL
), _T("wxWindow::SetSize requires parent.\n") );
1939 if (m_resizing
) return; /* I don't like recursions */
1942 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
1944 /* don't set the size for children of wxNotebook, just take the values. */
1952 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1954 if (x
!= -1) m_x
= x
;
1955 if (y
!= -1) m_y
= y
;
1956 if (width
!= -1) m_width
= width
;
1957 if (height
!= -1) m_height
= height
;
1967 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1969 if (width
== -1) m_width
= 80;
1972 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1974 if (height
== -1) m_height
= 26;
1977 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1978 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1979 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
1980 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
1983 int bottom_border
= 0;
1985 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
1987 /* the default button has a border around it */
1992 /* this is the result of hours of debugging: the following code
1993 means that if we have a m_wxwindow and we set the size of
1994 m_widget, m_widget (which is a GtkScrolledWindow) does NOT
1995 automatically propagate its size down to its m_wxwindow,
1996 which is its client area. therefore, we have to tell the
1997 client area directly that it has to resize itself.
1998 this will lead to that m_widget (GtkScrolledWindow) will
1999 calculate how much size it needs for scrollbars etc and
2000 it will then call XXX_size_allocate of its child, which
2001 is m_wxwindow. m_wxwindow in turn will do the same with its
2002 children and so on. problems can arise if this happens
2003 before all the children have been realized as some widgets
2004 stupidy need to be realized during XXX_size_allocate (e.g.
2005 GtkNotebook) and they will segv if called otherwise. this
2006 emergency is tested in gtk_myfixed_size_allocate. Normally
2007 this shouldn't be needed and only gtk_widget_queue_resize()
2008 should be enough to provoke a resize at the next appropriate
2009 moment, but this seems to fail, e.g. when a wxNotebook contains
2010 a wxSplitterWindow: the splitter window's children won't
2011 show up properly resized then. */
2013 gtk_myfixed_set_size( GTK_MYFIXED(m_parent
->m_wxwindow
),
2018 m_height
+border
+bottom_border
);
2023 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2024 event
.SetEventObject( this );
2025 GetEventHandler()->ProcessEvent( event
);
2030 void wxWindow::OnInternalIdle()
2032 GdkWindow
*window
= GetConnectWidget()->window
;
2035 wxCursor cursor
= m_cursor
;
2036 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2038 if (m_currentGdkCursor
!= cursor
)
2040 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2041 m_currentGdkCursor
= cursor
;
2048 void wxWindow::DoGetSize( int *width
, int *height
) const
2050 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2052 if (width
) (*width
) = m_width
;
2053 if (height
) (*height
) = m_height
;
2056 void wxWindow::DoSetClientSize( int width
, int height
)
2058 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2062 SetSize( width
, height
);
2069 if (!m_hasScrolling
)
2071 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
2073 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2075 dw
+= 2 * window_class
->xthickness
;
2076 dh
+= 2 * window_class
->ythickness
;
2081 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2082 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2084 #if (GTK_MINOR_VERSION == 0)
2085 GtkWidget
*viewport
= scroll_window
->viewport
;
2086 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2088 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2090 dw
+= 2 * viewport_class
->xthickness
;
2091 dh
+= 2 * viewport_class
->ythickness
;
2096 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2097 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2099 we use this instead: range.slider_width = 11 + 2*2pts edge
2102 if (scroll_window
->vscrollbar_visible
)
2104 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2105 dw
+= scroll_class
->scrollbar_spacing
;
2108 if (scroll_window
->hscrollbar_visible
)
2110 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2111 dh
+= scroll_class
->scrollbar_spacing
;
2115 SetSize( width
+dw
, height
+dh
);
2119 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2121 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2125 if (width
) (*width
) = m_width
;
2126 if (height
) (*height
) = m_height
;
2133 if (!m_hasScrolling
)
2135 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
2137 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2139 dw
+= 2 * window_class
->xthickness
;
2140 dh
+= 2 * window_class
->ythickness
;
2145 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2146 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2148 #if (GTK_MINOR_VERSION == 0)
2149 GtkWidget
*viewport
= scroll_window
->viewport
;
2150 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2152 if ( HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
) )
2154 dw
+= 2 * viewport_class
->xthickness
;
2155 dh
+= 2 * viewport_class
->ythickness
;
2159 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2160 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2162 we use this instead: range.slider_width = 11 + 2*2pts edge
2165 if (scroll_window
->vscrollbar_visible
)
2167 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2168 dw
+= scroll_class
->scrollbar_spacing
;
2171 if (scroll_window
->hscrollbar_visible
)
2173 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2174 dh
+= scroll_class
->scrollbar_spacing
;
2178 if (width
) (*width
) = m_width
- dw
;
2179 if (height
) (*height
) = m_height
- dh
;
2183 void wxWindow::DoGetPosition( int *x
, int *y
) const
2185 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2191 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2193 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2195 if (!m_widget
->window
) return;
2197 GdkWindow
*source
= (GdkWindow
*) NULL
;
2199 source
= m_wxwindow
->window
;
2201 source
= m_widget
->window
;
2205 gdk_window_get_origin( source
, &org_x
, &org_y
);
2209 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2211 org_x
+= m_widget
->allocation
.x
;
2212 org_y
+= m_widget
->allocation
.y
;
2220 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2222 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2224 if (!m_widget
->window
) return;
2226 GdkWindow
*source
= (GdkWindow
*) NULL
;
2228 source
= m_wxwindow
->window
;
2230 source
= m_widget
->window
;
2234 gdk_window_get_origin( source
, &org_x
, &org_y
);
2238 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2240 org_x
+= m_widget
->allocation
.x
;
2241 org_y
+= m_widget
->allocation
.y
;
2249 bool wxWindow::Show( bool show
)
2251 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2253 if (!wxWindowBase::Show(show
))
2260 gtk_widget_show( m_widget
);
2262 gtk_widget_hide( m_widget
);
2267 bool wxWindow::Enable( bool enable
)
2269 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2271 if (!wxWindowBase::Enable(enable
))
2277 gtk_widget_set_sensitive( m_widget
, enable
);
2279 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2284 int wxWindow::GetCharHeight() const
2286 wxCHECK_MSG( (m_widget
!= NULL
), 12, _T("invalid window") );
2288 wxCHECK_MSG( m_font
.Ok(), 12, _T("invalid font") );
2290 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2292 return font
->ascent
+ font
->descent
;
2295 int wxWindow::GetCharWidth() const
2297 wxCHECK_MSG( (m_widget
!= NULL
), 8, _T("invalid window") );
2299 wxCHECK_MSG( m_font
.Ok(), 8, _T("invalid font") );
2301 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2303 return gdk_string_width( font
, "H" );
2306 void wxWindow::GetTextExtent( const wxString
& string
,
2310 int *externalLeading
,
2311 const wxFont
*theFont
) const
2313 wxFont fontToUse
= m_font
;
2314 if (theFont
) fontToUse
= *theFont
;
2316 wxCHECK_RET( fontToUse
.Ok(), _T("invalid font") );
2318 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2319 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2320 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2321 if (descent
) (*descent
) = font
->descent
;
2322 if (externalLeading
) (*externalLeading
) = 0; // ??
2325 void wxWindow::SetFocus()
2327 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2329 GtkWidget
*connect_widget
= GetConnectWidget();
2332 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2334 gtk_widget_grab_focus (connect_widget
);
2336 else if (GTK_IS_CONTAINER(connect_widget
))
2338 gtk_container_focus( GTK_CONTAINER(connect_widget
), GTK_DIR_TAB_FORWARD
);
2346 bool wxWindow::AcceptsFocus() const
2348 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2351 bool wxWindow::Reparent( wxWindow
*newParent
)
2353 wxCHECK_MSG( (m_widget
!= NULL
), (wxWindow
*) NULL
, _T("invalid window") );
2355 gtk_widget_unparent( m_widget
);
2357 if ( !wxWindowBase::Reparent(newParent
) )
2363 void wxWindow::Raise()
2365 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2367 if (!m_widget
->window
) return;
2369 gdk_window_raise( m_widget
->window
);
2372 void wxWindow::Lower()
2374 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2376 if (!m_widget
->window
) return;
2378 gdk_window_lower( m_widget
->window
);
2381 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2383 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2385 if (!wxWindowBase::SetCursor(cursor
))
2387 // don't leave if the GTK widget has just
2389 if (!m_delayedCursor
) return FALSE
;
2392 GtkWidget
*connect_widget
= GetConnectWidget();
2393 if (!connect_widget
->window
)
2395 // indicate that a new style has been set
2396 // but it couldn't get applied as the
2397 // widget hasn't been realized yet.
2398 m_delayedCursor
= TRUE
;
2400 // pretend we have done something
2404 // gdk_window_set_cursor( connect_widget->window, GetCursor().GetCursor() );
2410 void wxWindow::WarpPointer( int WXUNUSED(x
), int WXUNUSED(y
) )
2415 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2417 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2419 if (!m_widget
->window
) return;
2421 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2425 gdk_window_clear_area( m_wxwindow
->window
,
2427 rect
->width
, rect
->height
);
2431 gdk_window_clear( m_wxwindow
->window
);
2438 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2440 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2444 GdkRectangle gdk_rect
;
2445 gdk_rect
.x
= rect
->x
;
2446 gdk_rect
.y
= rect
->y
;
2447 gdk_rect
.width
= rect
->width
;
2448 gdk_rect
.height
= rect
->height
;
2451 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2453 gtk_widget_draw( m_widget
, &gdk_rect
);
2457 void wxWindow::Clear()
2459 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2461 if (!m_widget
->window
) return;
2463 if (m_wxwindow
&& m_wxwindow
->window
)
2465 gdk_window_clear( m_wxwindow
->window
);
2470 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2472 wxWindowBase::DoSetToolTip(tip
);
2475 m_tooltip
->Apply( this );
2478 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2480 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConv_current
->cWX2MB(tip
), (gchar
*) NULL
);
2482 #endif // wxUSE_TOOLTIPS
2484 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2486 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2488 if (!wxWindowBase::SetBackgroundColour(colour
))
2490 // don't leave if the GTK widget has just
2492 if (!m_delayedBackgroundColour
) return FALSE
;
2495 GtkWidget
*connect_widget
= GetConnectWidget();
2496 if (!connect_widget
->window
)
2498 // indicate that a new style has been set
2499 // but it couldn't get applied as the
2500 // widget hasn't been realized yet.
2501 m_delayedBackgroundColour
= TRUE
;
2503 // pretend we have done something
2507 if (m_wxwindow
&& m_wxwindow
->window
)
2509 /* wxMSW doesn't clear the window here. I don't do that either to
2510 provide compatibility. call Clear() to do the job. */
2512 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_wxwindow
->window
) );
2513 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
2516 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2518 if (sysbg
== m_backgroundColour
)
2520 m_backgroundColour
= wxNullColour
;
2522 m_backgroundColour
= sysbg
;
2532 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2534 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2536 if (!wxWindowBase::SetForegroundColour(colour
))
2538 // don't leave if the GTK widget has just
2540 if (!m_delayedForegroundColour
) return FALSE
;
2543 GtkWidget
*connect_widget
= GetConnectWidget();
2544 if (!connect_widget
->window
)
2546 // indicate that a new style has been set
2547 // but it couldn't get applied as the
2548 // widget hasn't been realized yet.
2549 m_delayedForegroundColour
= TRUE
;
2551 // pretend we have done something
2555 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2556 if (sysbg
== m_foregroundColour
)
2558 m_backgroundColour
= wxNullColour
;
2560 m_backgroundColour
= sysbg
;
2570 GtkStyle
*wxWindow::GetWidgetStyle()
2572 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2574 m_widgetStyle
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2576 return m_widgetStyle
;
2579 void wxWindow::SetWidgetStyle()
2581 GtkStyle
*style
= GetWidgetStyle();
2583 gdk_font_unref( style
->font
);
2584 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2586 if (m_foregroundColour
.Ok())
2588 m_foregroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2589 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2590 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2591 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2594 if (m_backgroundColour
.Ok())
2596 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2597 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2598 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2599 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2600 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2601 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2602 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2603 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2604 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2608 void wxWindow::ApplyWidgetStyle()
2612 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2614 menu
->SetInvokingWindow( win
);
2615 wxNode
*node
= menu
->GetItems().First();
2618 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2619 if (menuitem
->IsSubMenu())
2621 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2623 node
= node
->Next();
2627 static gint gs_pop_x
= 0;
2628 static gint gs_pop_y
= 0;
2630 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
2634 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
2639 bool wxWindow::PopupMenu( wxMenu
*menu
, int x
, int y
)
2641 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2643 wxCHECK_MSG( menu
!= NULL
, FALSE
, _T("invalid popup-menu") );
2645 SetInvokingWindow( menu
, this );
2653 GTK_MENU(menu
->m_menu
),
2654 (GtkWidget
*) NULL
, // parent menu shell
2655 (GtkWidget
*) NULL
, // parent menu item
2656 (GtkMenuPositionFunc
) pop_pos_callback
,
2657 (gpointer
) this, // client data
2658 0, // button used to activate it
2659 0 //gs_timeLastClick // the time of activation
2664 #if wxUSE_DRAG_AND_DROP
2666 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2668 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2670 GtkWidget
*dnd_widget
= GetConnectWidget();
2672 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
2674 if (m_dropTarget
) delete m_dropTarget
;
2675 m_dropTarget
= dropTarget
;
2677 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
2680 #endif // wxUSE_DRAG_AND_DROP
2682 GtkWidget
* wxWindow::GetConnectWidget()
2684 GtkWidget
*connect_widget
= m_widget
;
2685 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2687 return connect_widget
;
2690 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2692 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2693 return (window
== m_widget
->window
);
2696 bool wxWindow::SetFont( const wxFont
&font
)
2698 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T( "invalid window") );
2700 if (!wxWindowBase::SetFont(font
))
2702 // don't leave if the GTK widget has just
2704 if (!m_delayedFont
) return FALSE
;
2707 GtkWidget
*connect_widget
= GetConnectWidget();
2708 if (!connect_widget
->window
)
2710 // indicate that a new style has been set
2711 // but it couldn't get applied as the
2712 // widget hasn't been realized yet.
2713 m_delayedFont
= TRUE
;
2715 // pretend we have done something
2719 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2720 if ( sysbg
== m_backgroundColour
)
2722 m_backgroundColour
= wxNullColour
;
2724 m_backgroundColour
= sysbg
;
2734 void wxWindow::CaptureMouse()
2736 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2738 wxCHECK_RET( g_capturing
== FALSE
, _T("CaptureMouse called twice") );
2740 GtkWidget
*connect_widget
= GetConnectWidget();
2741 if (!connect_widget
->window
) return;
2743 gtk_grab_add( connect_widget
);
2744 gdk_pointer_grab( connect_widget
->window
, FALSE
,
2746 (GDK_BUTTON_PRESS_MASK
|
2747 GDK_BUTTON_RELEASE_MASK
|
2748 GDK_POINTER_MOTION_MASK
),
2755 void wxWindow::ReleaseMouse()
2757 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2759 wxCHECK_RET( g_capturing
== TRUE
, _T("ReleaseMouse called twice") );
2761 GtkWidget
*connect_widget
= GetConnectWidget();
2762 if (!connect_widget
->window
) return;
2764 gtk_grab_remove( connect_widget
);
2765 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2766 g_capturing
= FALSE
;
2769 bool wxWindow::IsRetained() const
2774 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2775 int range
, bool refresh
)
2777 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2779 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2781 m_hasScrolling
= TRUE
;
2783 if (orient
== wxHORIZONTAL
)
2785 float fpos
= (float)pos
;
2786 float frange
= (float)range
;
2787 float fthumb
= (float)thumbVisible
;
2788 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2789 if (fpos
< 0.0) fpos
= 0.0;
2791 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2792 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2794 SetScrollPos( orient
, pos
, refresh
);
2798 m_oldHorizontalPos
= fpos
;
2800 m_hAdjust
->lower
= 0.0;
2801 m_hAdjust
->upper
= frange
;
2802 m_hAdjust
->value
= fpos
;
2803 m_hAdjust
->step_increment
= 1.0;
2804 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2805 m_hAdjust
->page_size
= fthumb
;
2809 float fpos
= (float)pos
;
2810 float frange
= (float)range
;
2811 float fthumb
= (float)thumbVisible
;
2812 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2813 if (fpos
< 0.0) fpos
= 0.0;
2815 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2816 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2818 SetScrollPos( orient
, pos
, refresh
);
2822 m_oldVerticalPos
= fpos
;
2824 m_vAdjust
->lower
= 0.0;
2825 m_vAdjust
->upper
= frange
;
2826 m_vAdjust
->value
= fpos
;
2827 m_vAdjust
->step_increment
= 1.0;
2828 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2829 m_vAdjust
->page_size
= fthumb
;
2832 if (orient
== wxHORIZONTAL
)
2833 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2835 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2838 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2840 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2842 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2844 if (orient
== wxHORIZONTAL
)
2846 float fpos
= (float)pos
;
2847 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
2848 if (fpos
< 0.0) fpos
= 0.0;
2849 m_oldHorizontalPos
= fpos
;
2851 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2852 m_hAdjust
->value
= fpos
;
2856 float fpos
= (float)pos
;
2857 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
2858 if (fpos
< 0.0) fpos
= 0.0;
2859 m_oldVerticalPos
= fpos
;
2861 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2862 m_vAdjust
->value
= fpos
;
2865 if (!m_isScrolling
) /* prevent recursion */
2867 if (m_wxwindow
->window
)
2869 if (orient
== wxHORIZONTAL
)
2870 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2872 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2877 int wxWindow::GetScrollThumb( int orient
) const
2879 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2881 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2883 if (orient
== wxHORIZONTAL
)
2884 return (int)(m_hAdjust
->page_size
+0.5);
2886 return (int)(m_vAdjust
->page_size
+0.5);
2889 int wxWindow::GetScrollPos( int orient
) const
2891 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2893 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2895 if (orient
== wxHORIZONTAL
)
2896 return (int)(m_hAdjust
->value
+0.5);
2898 return (int)(m_vAdjust
->value
+0.5);
2901 int wxWindow::GetScrollRange( int orient
) const
2903 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2905 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2907 if (orient
== wxHORIZONTAL
)
2908 return (int)(m_hAdjust
->upper
+0.5);
2910 return (int)(m_vAdjust
->upper
+0.5);
2913 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2915 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2917 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2921 m_scrollGC
= gdk_gc_new( m_wxwindow
->window
);
2922 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
2925 wxNode
*node
= m_children
.First();
2928 wxWindow
*child
= (wxWindow
*) node
->Data();
2929 child
->Move( child
->m_x
+ dx
, child
->m_y
+ dy
);
2930 node
= node
->Next();
2935 GetClientSize( &cw
, &ch
);
2936 int w
= cw
- abs(dx
);
2937 int h
= ch
- abs(dy
);
2939 if ((h
< 0) || (w
< 0))
2947 if (dx
< 0) s_x
= -dx
;
2948 if (dy
< 0) s_y
= -dy
;
2951 if (dx
> 0) d_x
= dx
;
2952 if (dy
> 0) d_y
= dy
;
2954 gdk_window_copy_area( m_wxwindow
->window
, m_scrollGC
, d_x
, d_y
,
2955 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2958 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2959 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2960 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2961 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2963 Refresh( TRUE
, &rect
);
2967 void wxWindow::SetScrolling(bool scroll
)
2969 m_isScrolling
= g_blockEventsOnScroll
= scroll
;