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 static bool g_capturing
= FALSE
;
136 static wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
138 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
139 the last click here */
140 static guint32 gs_timeLastClick
= 0;
142 //-----------------------------------------------------------------------------
144 //-----------------------------------------------------------------------------
148 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
149 GdkEvent
*WXUNUSED(event
),
153 static bool s_done = FALSE;
156 wxLog::AddTraceMask("focus");
159 wxLogTrace(_T("FOCUS NOW AT: %s"), name);
165 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
171 wxChar
*s
= new wxChar
[tmp
.Length()+1];
175 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
176 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
181 //-----------------------------------------------------------------------------
183 //-----------------------------------------------------------------------------
185 extern void wxapp_install_idle_handler();
186 extern bool g_isIdle
;
188 //-----------------------------------------------------------------------------
189 // key event conversion routines
190 //-----------------------------------------------------------------------------
192 #if (GTK_MINOR_VERSION == 0)
194 gdk_keyval_to_upper (guint keyval
)
198 KeySym lower_val
= 0;
199 KeySym upper_val
= 0;
201 XConvertCase (keyval
, &lower_val
, &upper_val
);
208 static long map_to_unmodified_wx_keysym( KeySym keysym
)
215 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
217 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
218 case GDK_Menu
: key_code
= WXK_MENU
; break;
219 case GDK_Help
: key_code
= WXK_HELP
; break;
220 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
221 case GDK_ISO_Left_Tab
:
222 case GDK_Tab
: key_code
= WXK_TAB
; break;
223 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
224 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
225 case GDK_Return
: key_code
= WXK_RETURN
; break;
226 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
227 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
228 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
229 case GDK_Delete
: key_code
= WXK_DELETE
; break;
230 case GDK_Home
: key_code
= WXK_HOME
; break;
231 case GDK_Left
: key_code
= WXK_LEFT
; break;
232 case GDK_Up
: key_code
= WXK_UP
; break;
233 case GDK_Right
: key_code
= WXK_RIGHT
; break;
234 case GDK_Down
: key_code
= WXK_DOWN
; break;
235 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
236 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
237 case GDK_Next
: key_code
= WXK_NEXT
; break;
238 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
239 case GDK_End
: key_code
= WXK_END
; break;
240 case GDK_Begin
: key_code
= WXK_HOME
; break;
241 case GDK_Select
: key_code
= WXK_SELECT
; break;
242 case GDK_Print
: key_code
= WXK_PRINT
; break;
243 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
244 case GDK_Insert
: key_code
= WXK_INSERT
; break;
245 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
247 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
248 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
249 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
250 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
251 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
252 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
253 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
254 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
255 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
256 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
257 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
258 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
259 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
260 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
261 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
262 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
263 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
264 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
265 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
266 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
267 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
268 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
269 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
270 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
271 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
272 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
273 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
274 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
275 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
276 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
277 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
278 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
279 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
280 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
281 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
282 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
283 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
285 case GDK_F1
: key_code
= WXK_F1
; break;
286 case GDK_F2
: key_code
= WXK_F2
; break;
287 case GDK_F3
: key_code
= WXK_F3
; break;
288 case GDK_F4
: key_code
= WXK_F4
; break;
289 case GDK_F5
: key_code
= WXK_F5
; break;
290 case GDK_F6
: key_code
= WXK_F6
; break;
291 case GDK_F7
: key_code
= WXK_F7
; break;
292 case GDK_F8
: key_code
= WXK_F8
; break;
293 case GDK_F9
: key_code
= WXK_F9
; break;
294 case GDK_F10
: key_code
= WXK_F10
; break;
295 case GDK_F11
: key_code
= WXK_F11
; break;
296 case GDK_F12
: key_code
= WXK_F12
; break;
301 guint upper
= gdk_keyval_to_upper( keysym
);
302 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
311 static long map_to_wx_keysym( KeySym keysym
)
317 case GDK_Menu
: key_code
= WXK_MENU
; break;
318 case GDK_Help
: key_code
= WXK_HELP
; break;
319 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
320 case GDK_ISO_Left_Tab
:
321 case GDK_Tab
: key_code
= WXK_TAB
; break;
322 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
323 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
324 case GDK_Return
: key_code
= WXK_RETURN
; break;
325 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
326 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
327 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
328 case GDK_Delete
: key_code
= WXK_DELETE
; break;
329 case GDK_Home
: key_code
= WXK_HOME
; break;
330 case GDK_Left
: key_code
= WXK_LEFT
; break;
331 case GDK_Up
: key_code
= WXK_UP
; break;
332 case GDK_Right
: key_code
= WXK_RIGHT
; break;
333 case GDK_Down
: key_code
= WXK_DOWN
; break;
334 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
335 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
336 case GDK_Next
: key_code
= WXK_NEXT
; break;
337 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
338 case GDK_End
: key_code
= WXK_END
; break;
339 case GDK_Begin
: key_code
= WXK_HOME
; break;
340 case GDK_Select
: key_code
= WXK_SELECT
; break;
341 case GDK_Print
: key_code
= WXK_PRINT
; break;
342 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
343 case GDK_Insert
: key_code
= WXK_INSERT
; break;
344 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
346 case GDK_KP_0
: key_code
= '0'; break;
347 case GDK_KP_1
: key_code
= '1'; break;
348 case GDK_KP_2
: key_code
= '2'; break;
349 case GDK_KP_3
: key_code
= '3'; break;
350 case GDK_KP_4
: key_code
= '4'; break;
351 case GDK_KP_5
: key_code
= '5'; break;
352 case GDK_KP_6
: key_code
= '6'; break;
353 case GDK_KP_7
: key_code
= '7'; break;
354 case GDK_KP_8
: key_code
= '8'; break;
355 case GDK_KP_9
: key_code
= '9'; break;
356 case GDK_KP_Space
: key_code
= ' '; break;
357 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
358 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
359 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
360 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
361 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
362 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
363 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
364 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
365 case GDK_KP_Up
: key_code
= WXK_UP
; break;
366 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
367 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
368 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
369 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
370 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
371 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
372 case GDK_KP_End
: key_code
= WXK_END
; break;
373 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
374 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
375 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
376 case GDK_KP_Equal
: key_code
= '='; break;
377 case GDK_KP_Multiply
: key_code
= '*'; break;
378 case GDK_KP_Add
: key_code
= '+'; break;
379 case GDK_KP_Separator
: key_code
= ','; break;
380 case GDK_KP_Subtract
: key_code
= '-'; break;
381 case GDK_KP_Decimal
: key_code
= '.'; break;
382 case GDK_KP_Divide
: key_code
= '/'; break;
384 case GDK_F1
: key_code
= WXK_F1
; break;
385 case GDK_F2
: key_code
= WXK_F2
; break;
386 case GDK_F3
: key_code
= WXK_F3
; break;
387 case GDK_F4
: key_code
= WXK_F4
; break;
388 case GDK_F5
: key_code
= WXK_F5
; break;
389 case GDK_F6
: key_code
= WXK_F6
; break;
390 case GDK_F7
: key_code
= WXK_F7
; break;
391 case GDK_F8
: key_code
= WXK_F8
; break;
392 case GDK_F9
: key_code
= WXK_F9
; break;
393 case GDK_F10
: key_code
= WXK_F10
; break;
394 case GDK_F11
: key_code
= WXK_F11
; break;
395 case GDK_F12
: key_code
= WXK_F12
; break;
408 //-----------------------------------------------------------------------------
409 // local code (see below)
410 //-----------------------------------------------------------------------------
412 #if (GTK_MINOR_VERSION > 0)
414 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
422 if (win
->HasScrolling())
424 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
425 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
428 GtkWidget *hscrollbar = scroll_window->hscrollbar;
429 GtkWidget *vscrollbar = scroll_window->vscrollbar;
431 we use this instead: range.slider_width = 11 + 2*2pts edge
434 if (scroll_window
->vscrollbar_visible
)
436 dw
+= 15; /* dw += vscrollbar->allocation.width; */
437 dw
+= scroll_class
->scrollbar_spacing
;
440 if (scroll_window
->hscrollbar_visible
)
442 dh
+= 15; /* dh += hscrollbar->allocation.height; */
443 dh
+= scroll_class
->scrollbar_spacing
;
449 if (GTK_WIDGET_NO_WINDOW (widget
))
451 dx
+= widget
->allocation
.x
;
452 dy
+= widget
->allocation
.y
;
455 if (win
->HasFlag(wxRAISED_BORDER
))
457 gtk_draw_shadow( widget
->style
,
462 win
->m_width
-dw
, win
->m_height
-dh
);
466 if (win
->HasFlag(wxSUNKEN_BORDER
))
468 gtk_draw_shadow( widget
->style
,
473 win
->m_width
-dw
, win
->m_height
-dh
);
478 //-----------------------------------------------------------------------------
479 // "expose_event" of m_widget
480 //-----------------------------------------------------------------------------
482 static void gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
484 if (gdk_event
->count
> 0) return;
485 draw_frame( widget
, win
);
488 //-----------------------------------------------------------------------------
489 // "draw" of m_wxwindow
490 //-----------------------------------------------------------------------------
492 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
494 draw_frame( widget
, win
);
497 #endif // GTK_MINOR_VERSION > 0
499 //-----------------------------------------------------------------------------
500 // "expose_event" of m_wxwindow
501 //-----------------------------------------------------------------------------
503 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
505 if ( !win
->m_hasVMT
)
508 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
510 gdk_event
->area
.width
,
511 gdk_event
->area
.height
);
513 if ( gdk_event
->count
> 0 )
517 printf( "OnExpose from " );
518 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
519 printf( win->GetClassInfo()->GetClassName() );
523 wxPaintEvent
event( win
->GetId() );
524 event
.SetEventObject( win
);
525 win
->GetEventHandler()->ProcessEvent( event
);
527 win
->GetUpdateRegion().Clear();
530 //-----------------------------------------------------------------------------
531 // "draw" of m_wxwindow
532 //-----------------------------------------------------------------------------
534 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
537 wxapp_install_idle_handler();
542 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
543 rect
->width
, rect
->height
);
545 wxPaintEvent
event( win
->GetId() );
546 event
.SetEventObject( win
);
547 win
->GetEventHandler()->ProcessEvent( event
);
549 win
->GetUpdateRegion().Clear();
552 //-----------------------------------------------------------------------------
553 // "key_press_event" from any window
554 //-----------------------------------------------------------------------------
556 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
559 wxapp_install_idle_handler();
561 if (!win
->m_hasVMT
) return FALSE
;
562 if (g_blockEventsOnDrag
) return FALSE
;
565 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
566 if (gdk_event->state & GDK_SHIFT_MASK)
567 printf( "ShiftDown.\n" );
569 printf( "ShiftUp.\n" );
570 if (gdk_event->state & GDK_CONTROL_MASK)
571 printf( "ControlDown.\n" );
573 printf( "ControlUp.\n" );
578 GdkModifierType state
;
579 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
581 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
583 /* sending unknown key events doesn't really make sense */
584 if (key_code
== 0) return FALSE
;
588 wxKeyEvent
event( wxEVT_KEY_DOWN
);
589 event
.SetTimestamp( gdk_event
->time
);
590 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
591 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
592 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
593 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
594 event
.m_keyCode
= key_code
;
595 event
.m_scanCode
= gdk_event
->keyval
;
598 event
.SetEventObject( win
);
599 ret
= win
->GetEventHandler()->ProcessEvent( event
);
601 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
603 /* wxMSW doesn't send char events with Alt pressed */
604 if ((key_code
!= 0) &&
605 ((gdk_event
->state
& GDK_MOD1_MASK
) == 0) &&
606 ((gdk_event
->state
& GDK_MOD1_MASK
) == 0))
608 wxKeyEvent
event2( wxEVT_CHAR
);
609 event2
.SetTimestamp( gdk_event
->time
);
610 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
611 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
612 // event2.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
613 // event2.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
614 event2
.m_keyCode
= key_code
;
615 event2
.m_scanCode
= gdk_event
->keyval
;
618 event2
.SetEventObject( win
);
619 ret
= (ret
|| win
->GetEventHandler()->ProcessEvent( event2
));
624 wxWindow
*ancestor
= win
;
627 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
630 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
631 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
634 ancestor
= ancestor
->GetParent();
638 // win is a control: tab can be propagated up
640 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
641 (win
->HasFlag(wxTE_PROCESS_TAB
) == 0))
643 wxNavigationKeyEvent new_event
;
644 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
645 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
646 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
647 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
648 new_event
.SetCurrentFocus( win
);
649 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
652 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
654 (gdk_event
->keyval
== GDK_Escape
) )
656 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
657 new_event
.SetEventObject( win
);
658 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
661 #if (GTK_MINOR_VERSION > 0)
662 /* pressing F10 will activate the menu bar of the top frame */
664 (gdk_event
->keyval
== GDK_F10
) )
666 wxWindow
*ancestor
= win
;
669 if (wxIsKindOf(ancestor
,wxFrame
))
671 wxFrame
*frame
= (wxFrame
*) ancestor
;
672 wxMenuBar
*menubar
= frame
->GetMenuBar();
675 wxNode
*node
= menubar
->GetMenus().First();
678 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
679 // doesn't work correctly
680 // gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
686 ancestor
= ancestor
->GetParent();
692 Damn, I forgot why this didn't work, but it didn't work.
694 // win is a panel: up can be propagated to the panel
695 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
696 (gdk_event->keyval == GDK_Up))
698 win->m_parent->SetFocus();
702 // win is a panel: left/right can be propagated to the panel
703 if ((!ret) && (win->m_wxwindow) &&
704 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
705 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
707 wxNavigationKeyEvent new_event;
708 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
709 new_event.SetCurrentFocus( win );
710 ret = win->GetEventHandler()->ProcessEvent( new_event );
716 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
723 //-----------------------------------------------------------------------------
724 // "key_release_event" from any window
725 //-----------------------------------------------------------------------------
727 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
730 wxapp_install_idle_handler();
732 if (!win
->m_hasVMT
) return FALSE
;
733 if (g_blockEventsOnDrag
) return FALSE
;
736 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
737 if (gdk_event->state & GDK_SHIFT_MASK)
738 printf( "ShiftDown.\n" );
740 printf( "ShiftUp.\n" );
741 if (gdk_event->state & GDK_CONTROL_MASK)
742 printf( "ControlDown.\n" );
744 printf( "ControlUp.\n" );
748 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
750 /* sending unknown key events doesn't really make sense */
751 if (key_code
== 0) return FALSE
;
755 GdkModifierType state
;
756 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
758 wxKeyEvent
event( wxEVT_KEY_UP
);
759 event
.SetTimestamp( gdk_event
->time
);
760 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
761 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
762 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
763 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
764 event
.m_keyCode
= key_code
;
765 event
.m_scanCode
= gdk_event
->keyval
;
768 event
.SetEventObject( win
);
770 if (win
->GetEventHandler()->ProcessEvent( event
))
772 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
779 //-----------------------------------------------------------------------------
780 // "button_press_event"
781 //-----------------------------------------------------------------------------
783 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
786 wxapp_install_idle_handler();
789 wxPrintf( _T("1) OnButtonPress from ") );
790 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
791 wxPrintf( win->GetClassInfo()->GetClassName() );
792 wxPrintf( _T(".\n") );
794 if (!win
->m_hasVMT
) return FALSE
;
795 if (g_blockEventsOnDrag
) return TRUE
;
796 if (g_blockEventsOnScroll
) return TRUE
;
798 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
802 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
804 gtk_widget_grab_focus (win
->m_wxwindow
);
807 wxPrintf( _T("GrabFocus from ") );
808 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
809 wxPrintf( win->GetClassInfo()->GetClassName() );
810 wxPrintf( _T(".\n") );
817 wxPrintf( _T("2) OnButtonPress from ") );
818 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
819 wxPrintf( win->GetClassInfo()->GetClassName() );
820 wxPrintf( _T(".\n") );
823 wxEventType event_type
= wxEVT_LEFT_DOWN
;
825 if (gdk_event
->button
== 1)
827 switch (gdk_event
->type
)
829 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
830 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
834 else if (gdk_event
->button
== 2)
836 switch (gdk_event
->type
)
838 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
839 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
843 else if (gdk_event
->button
== 3)
845 switch (gdk_event
->type
)
847 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
848 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
853 wxMouseEvent
event( event_type
);
854 event
.SetTimestamp( gdk_event
->time
);
855 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
856 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
857 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
858 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
859 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
860 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
861 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
863 event
.m_x
= (long)gdk_event
->x
;
864 event
.m_y
= (long)gdk_event
->y
;
866 // Some control don't have their own X window and thus cannot get
871 wxNode
*node
= win
->GetChildren().First();
874 wxWindow
*child
= (wxWindow
*)node
->Data();
876 if (child
->m_isStaticBox
)
878 // wxStaticBox is transparent in the box itself
881 int xx1
= child
->m_x
;
882 int yy1
= child
->m_y
;
883 int xx2
= child
->m_x
+ child
->m_width
;
884 int yy2
= child
->m_x
+ child
->m_height
;
887 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
889 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
891 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
893 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
896 event
.m_x
-= child
->m_x
;
897 event
.m_y
-= child
->m_y
;
904 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
905 (child
->m_x
<= event
.m_x
) &&
906 (child
->m_y
<= event
.m_y
) &&
907 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
908 (child
->m_y
+child
->m_height
>= event
.m_y
))
911 event
.m_x
-= child
->m_x
;
912 event
.m_y
-= child
->m_y
;
920 event
.SetEventObject( win
);
922 gs_timeLastClick
= gdk_event
->time
;
924 if (win
->GetEventHandler()->ProcessEvent( event
))
926 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
933 //-----------------------------------------------------------------------------
934 // "button_release_event"
935 //-----------------------------------------------------------------------------
937 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
940 wxapp_install_idle_handler();
942 if (!win
->m_hasVMT
) return FALSE
;
943 if (g_blockEventsOnDrag
) return FALSE
;
944 if (g_blockEventsOnScroll
) return FALSE
;
946 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
949 printf( "OnButtonRelease from " );
950 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
951 printf( win->GetClassInfo()->GetClassName() );
955 wxEventType event_type
= wxEVT_NULL
;
957 switch (gdk_event
->button
)
959 case 1: event_type
= wxEVT_LEFT_UP
; break;
960 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
961 case 3: event_type
= wxEVT_RIGHT_UP
; break;
964 wxMouseEvent
event( event_type
);
965 event
.SetTimestamp( gdk_event
->time
);
966 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
967 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
968 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
969 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
970 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
971 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
972 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
973 event
.m_x
= (long)gdk_event
->x
;
974 event
.m_y
= (long)gdk_event
->y
;
976 // Some control don't have their own X window and thus cannot get
981 wxNode
*node
= win
->GetChildren().First();
984 wxWindow
*child
= (wxWindow
*)node
->Data();
986 if (child
->m_isStaticBox
)
988 // wxStaticBox is transparent in the box itself
991 int xx1
= child
->m_x
;
992 int yy1
= child
->m_y
;
993 int xx2
= child
->m_x
+ child
->m_width
;
994 int yy2
= child
->m_x
+ child
->m_height
;
997 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
999 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1001 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1003 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1006 event
.m_x
-= child
->m_x
;
1007 event
.m_y
-= child
->m_y
;
1014 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1015 (child
->m_x
<= event
.m_x
) &&
1016 (child
->m_y
<= event
.m_y
) &&
1017 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
1018 (child
->m_y
+child
->m_height
>= event
.m_y
))
1021 event
.m_x
-= child
->m_x
;
1022 event
.m_y
-= child
->m_y
;
1026 node
= node
->Next();
1030 event
.SetEventObject( win
);
1032 if (win
->GetEventHandler()->ProcessEvent( event
))
1034 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1041 //-----------------------------------------------------------------------------
1042 // "motion_notify_event"
1043 //-----------------------------------------------------------------------------
1045 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1048 wxapp_install_idle_handler();
1050 if (!win
->m_hasVMT
) return FALSE
;
1051 if (g_blockEventsOnDrag
) return FALSE
;
1052 if (g_blockEventsOnScroll
) return FALSE
;
1054 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1056 if (gdk_event
->is_hint
)
1060 GdkModifierType state
;
1061 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1064 gdk_event
->state
= state
;
1068 printf( "OnMotion from " );
1069 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1070 printf( win->GetClassInfo()->GetClassName() );
1074 wxMouseEvent
event( wxEVT_MOTION
);
1075 event
.SetTimestamp( gdk_event
->time
);
1076 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1077 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1078 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1079 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1080 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1081 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1082 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1084 event
.m_x
= (long)gdk_event
->x
;
1085 event
.m_y
= (long)gdk_event
->y
;
1087 // Some control don't have their own X window and thus cannot get
1092 wxNode
*node
= win
->GetChildren().First();
1095 wxWindow
*child
= (wxWindow
*)node
->Data();
1097 if (child
->m_isStaticBox
)
1099 // wxStaticBox is transparent in the box itself
1102 int xx1
= child
->m_x
;
1103 int yy1
= child
->m_y
;
1104 int xx2
= child
->m_x
+ child
->m_width
;
1105 int yy2
= child
->m_x
+ child
->m_height
;
1108 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1110 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1112 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1114 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1117 event
.m_x
-= child
->m_x
;
1118 event
.m_y
-= child
->m_y
;
1125 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1126 (child
->m_x
<= event
.m_x
) &&
1127 (child
->m_y
<= event
.m_y
) &&
1128 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
1129 (child
->m_y
+child
->m_height
>= event
.m_y
))
1132 event
.m_x
-= child
->m_x
;
1133 event
.m_y
-= child
->m_y
;
1137 node
= node
->Next();
1141 event
.SetEventObject( win
);
1143 if (win
->GetEventHandler()->ProcessEvent( event
))
1145 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1152 //-----------------------------------------------------------------------------
1154 //-----------------------------------------------------------------------------
1156 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1159 wxapp_install_idle_handler();
1161 if (!win
->m_hasVMT
) return FALSE
;
1162 if (g_blockEventsOnDrag
) return FALSE
;
1164 g_focusWindow
= win
;
1166 if (win
->m_wxwindow
)
1168 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1170 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1172 printf( "SetFocus flag from " );
1173 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1174 printf( win->GetClassInfo()->GetClassName() );
1182 printf( "OnSetFocus from " );
1183 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1184 printf( win->GetClassInfo()->GetClassName() );
1186 printf( WXSTRINGCAST win->GetLabel() );
1190 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1191 event
.SetEventObject( win
);
1193 if (win
->GetEventHandler()->ProcessEvent( event
))
1195 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1202 //-----------------------------------------------------------------------------
1203 // "focus_out_event"
1204 //-----------------------------------------------------------------------------
1206 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1209 wxapp_install_idle_handler();
1211 if (!win
->m_hasVMT
) return FALSE
;
1212 if (g_blockEventsOnDrag
) return FALSE
;
1214 if (win
->m_wxwindow
)
1216 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1217 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1221 printf( "OnKillFocus from " );
1222 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1223 printf( win->GetClassInfo()->GetClassName() );
1227 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1228 event
.SetEventObject( win
);
1230 if (win
->GetEventHandler()->ProcessEvent( event
))
1232 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1239 //-----------------------------------------------------------------------------
1240 // "enter_notify_event"
1241 //-----------------------------------------------------------------------------
1243 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1246 wxapp_install_idle_handler();
1248 if (!win
->m_hasVMT
) return FALSE
;
1249 if (g_blockEventsOnDrag
) return FALSE
;
1251 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1253 if (widget
->window
&& win
->GetCursor().Ok() )
1254 gdk_window_set_cursor( widget
->window
, win
->GetCursor().GetCursor() );
1256 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1257 #if (GTK_MINOR_VERSION > 0)
1258 event
.SetTimestamp( gdk_event
->time
);
1260 event
.SetEventObject( win
);
1264 GdkModifierType state
= (GdkModifierType
)0;
1266 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1268 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1269 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1270 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1271 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1272 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1273 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1274 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1276 event
.m_x
= (long)x
;
1277 event
.m_y
= (long)y
;
1279 if (win
->GetEventHandler()->ProcessEvent( event
))
1281 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1288 //-----------------------------------------------------------------------------
1289 // "leave_notify_event"
1290 //-----------------------------------------------------------------------------
1292 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1295 wxapp_install_idle_handler();
1297 if (!win
->m_hasVMT
) return FALSE
;
1298 if (g_blockEventsOnDrag
) return FALSE
;
1300 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1302 if (widget
->window
&& win
->GetCursor().Ok() )
1303 gdk_window_set_cursor( widget
->window
, wxSTANDARD_CURSOR
->GetCursor() );
1305 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1306 #if (GTK_MINOR_VERSION > 0)
1307 event
.SetTimestamp( gdk_event
->time
);
1309 event
.SetEventObject( win
);
1313 GdkModifierType state
= (GdkModifierType
)0;
1315 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1317 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1318 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1319 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1320 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1321 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1322 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1323 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1325 event
.m_x
= (long)x
;
1326 event
.m_y
= (long)y
;
1328 if (win
->GetEventHandler()->ProcessEvent( event
))
1330 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1337 //-----------------------------------------------------------------------------
1338 // "value_changed" from m_vAdjust
1339 //-----------------------------------------------------------------------------
1341 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1344 wxapp_install_idle_handler();
1346 if (g_blockEventsOnDrag
) return;
1348 if (!win
->m_hasVMT
) return;
1350 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
1351 if (fabs(diff
) < 0.2) return;
1352 win
->m_oldVerticalPos
= win
->m_vAdjust
->value
;
1354 wxEventType command
= wxEVT_NULL
;
1356 float line_step
= win
->m_vAdjust
->step_increment
;
1357 float page_step
= win
->m_vAdjust
->page_increment
;
1359 if (win
->IsScrolling())
1361 command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1365 if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->lower
) < 0.2) command
= wxEVT_SCROLLWIN_BOTTOM
;
1366 else if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->upper
) < 0.2) command
= wxEVT_SCROLLWIN_TOP
;
1367 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1368 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEUP
;
1369 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1370 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEUP
;
1371 else command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1374 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1376 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1377 event
.SetEventObject( win
);
1378 win
->GetEventHandler()->ProcessEvent( event
);
1381 //-----------------------------------------------------------------------------
1382 // "value_changed" from m_hAdjust
1383 //-----------------------------------------------------------------------------
1385 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1388 wxapp_install_idle_handler();
1390 if (g_blockEventsOnDrag
) return;
1391 if (!win
->m_hasVMT
) return;
1393 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
1394 if (fabs(diff
) < 0.2) return;
1395 win
->m_oldHorizontalPos
= win
->m_hAdjust
->value
;
1397 wxEventType command
= wxEVT_NULL
;
1399 float line_step
= win
->m_hAdjust
->step_increment
;
1400 float page_step
= win
->m_hAdjust
->page_increment
;
1402 if (win
->IsScrolling())
1404 command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1408 if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->lower
) < 0.2) command
= wxEVT_SCROLLWIN_BOTTOM
;
1409 else if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->upper
) < 0.2) command
= wxEVT_SCROLLWIN_TOP
;
1410 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1411 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEUP
;
1412 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1413 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEUP
;
1414 else command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1417 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1419 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1420 event
.SetEventObject( win
);
1421 win
->GetEventHandler()->ProcessEvent( event
);
1424 //-----------------------------------------------------------------------------
1425 // "changed" from m_vAdjust
1426 //-----------------------------------------------------------------------------
1428 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1431 wxapp_install_idle_handler();
1433 if (g_blockEventsOnDrag
) return;
1434 if (!win
->m_hasVMT
) return;
1436 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1437 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1439 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1440 event
.SetEventObject( win
);
1441 win
->GetEventHandler()->ProcessEvent( event
);
1444 //-----------------------------------------------------------------------------
1445 // "changed" from m_hAdjust
1446 //-----------------------------------------------------------------------------
1448 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1451 wxapp_install_idle_handler();
1453 if (g_blockEventsOnDrag
) return;
1454 if (!win
->m_hasVMT
) return;
1456 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1457 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1459 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1460 event
.SetEventObject( win
);
1461 win
->GetEventHandler()->ProcessEvent( event
);
1464 //-----------------------------------------------------------------------------
1465 // "button_press_event" from scrollbar
1466 //-----------------------------------------------------------------------------
1468 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1469 GdkEventButton
*WXUNUSED(gdk_event
),
1473 wxapp_install_idle_handler();
1475 // don't test here as we can release the mouse while being over
1476 // a different window then the slider
1478 // if (gdk_event->window != widget->slider) return FALSE;
1480 win
->SetScrolling( TRUE
);
1485 //-----------------------------------------------------------------------------
1486 // "button_release_event" from scrollbar
1487 //-----------------------------------------------------------------------------
1489 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1490 GdkEventButton
*WXUNUSED(gdk_event
),
1494 // don't test here as we can release the mouse while being over
1495 // a different window then the slider
1497 // if (gdk_event->window != widget->slider) return FALSE;
1499 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1501 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1502 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_hAdjust
), "value_changed" );
1504 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_vAdjust
), "value_changed" );
1506 win
->SetScrolling( FALSE
);
1511 // ----------------------------------------------------------------------------
1512 // this wxWindowBase function is implemented here (in platform-specific file)
1513 // because it is static and so couldn't be made virtual
1514 // ----------------------------------------------------------------------------
1516 wxWindow
*wxWindowBase::FindFocus()
1518 return g_focusWindow
;
1521 //-----------------------------------------------------------------------------
1522 // "realize" from m_widget
1523 //-----------------------------------------------------------------------------
1525 /* we cannot set colours, fonts and cursors before the widget has
1526 been realized, so we do this directly after realization */
1529 gtk_window_realized_callback( GtkWidget
* WXUNUSED(widget
), wxWindow
*win
)
1532 wxapp_install_idle_handler();
1534 if (win
->m_delayedFont
)
1535 win
->SetFont( win
->GetFont() );
1537 if (win
->m_delayedBackgroundColour
)
1538 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1540 if (win
->m_delayedForegroundColour
)
1541 win
->SetForegroundColour( win
->GetForegroundColour() );
1543 win
->SetCursor( win
->GetCursor() );
1548 //-----------------------------------------------------------------------------
1549 // InsertChild for wxWindow.
1550 //-----------------------------------------------------------------------------
1552 /* Callback for wxWindow. This very strange beast has to be used because
1553 * C++ has no virtual methods in a constructor. We have to emulate a
1554 * virtual function here as wxNotebook requires a different way to insert
1555 * a child in it. I had opted for creating a wxNotebookPage window class
1556 * which would have made this superfluous (such in the MDI window system),
1557 * but no-one was listening to me... */
1559 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1561 gtk_myfixed_put( GTK_MYFIXED(parent
->m_wxwindow
),
1562 GTK_WIDGET(child
->m_widget
),
1568 if (parent
->HasFlag(wxTAB_TRAVERSAL
))
1570 /* we now allow a window to get the focus as long as it
1571 doesn't have any children. */
1572 GTK_WIDGET_UNSET_FLAGS( parent
->m_wxwindow
, GTK_CAN_FOCUS
);
1576 //-----------------------------------------------------------------------------
1578 //-----------------------------------------------------------------------------
1580 wxWindow
* wxGetActiveWindow()
1582 return g_focusWindow
;
1585 //-----------------------------------------------------------------------------
1587 //-----------------------------------------------------------------------------
1589 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1591 void wxWindow::Init()
1597 m_widget
= (GtkWidget
*) NULL
;
1598 m_wxwindow
= (GtkWidget
*) NULL
;
1608 m_needParent
= TRUE
;
1609 m_isBeingDeleted
= FALSE
;
1611 m_hasScrolling
= FALSE
;
1612 m_isScrolling
= FALSE
;
1614 m_hAdjust
= (GtkAdjustment
*) NULL
;
1615 m_vAdjust
= (GtkAdjustment
*) NULL
;
1616 m_oldHorizontalPos
= 0.0;
1617 m_oldVerticalPos
= 0.0;
1620 m_scrollGC
= (GdkGC
*) NULL
;
1621 m_widgetStyle
= (GtkStyle
*) NULL
;
1623 m_insertCallback
= wxInsertChildInWindow
;
1625 m_isStaticBox
= FALSE
;
1626 m_acceptsFocus
= FALSE
;
1629 wxWindow::wxWindow()
1634 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1635 const wxPoint
&pos
, const wxSize
&size
,
1636 long style
, const wxString
&name
)
1640 Create( parent
, id
, pos
, size
, style
, name
);
1643 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1644 const wxPoint
&pos
, const wxSize
&size
,
1645 long style
, const wxString
&name
)
1647 PreCreation( parent
, id
, pos
, size
, style
, name
);
1649 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1650 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1653 debug_focus_in( m_widget
, _T("wxWindow::m_widget"), name
);
1656 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1659 debug_focus_in( scrolledWindow
->hscrollbar
, _T("wxWindow::hsrcollbar"), name
);
1660 debug_focus_in( scrolledWindow
->vscrollbar
, _T("wxWindow::vsrcollbar"), name
);
1663 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1664 scroll_class
->scrollbar_spacing
= 0;
1666 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1668 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
1669 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
1671 m_wxwindow
= gtk_myfixed_new();
1674 debug_focus_in( m_wxwindow
, _T("wxWindow::m_wxwindow"), name
);
1677 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1679 #if (GTK_MINOR_VERSION > 0)
1680 GtkMyFixed
*myfixed
= GTK_MYFIXED(m_wxwindow
);
1682 if (HasFlag(wxRAISED_BORDER
))
1684 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_OUT
);
1686 else if (HasFlag(wxSUNKEN_BORDER
))
1688 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_IN
);
1692 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_NONE
);
1694 #else // GTK_MINOR_VERSION == 0
1695 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
1697 if (HasFlag(wxRAISED_BORDER
))
1699 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1701 else if (HasFlag(wxSUNKEN_BORDER
))
1703 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1707 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1709 #endif // GTK_MINOR_VERSION
1711 if (HasFlag(wxTAB_TRAVERSAL
))
1713 /* we now allow a window to get the focus as long as it
1714 doesn't have any children. */
1715 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1716 m_acceptsFocus
= FALSE
;
1720 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1721 m_acceptsFocus
= TRUE
;
1724 #if (GTK_MINOR_VERSION == 0)
1725 // shut the viewport up
1726 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1727 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1728 #endif // GTK_MINOR_VERSION == 0
1730 // I _really_ don't want scrollbars in the beginning
1731 m_vAdjust
->lower
= 0.0;
1732 m_vAdjust
->upper
= 1.0;
1733 m_vAdjust
->value
= 0.0;
1734 m_vAdjust
->step_increment
= 1.0;
1735 m_vAdjust
->page_increment
= 1.0;
1736 m_vAdjust
->page_size
= 5.0;
1737 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1738 m_hAdjust
->lower
= 0.0;
1739 m_hAdjust
->upper
= 1.0;
1740 m_hAdjust
->value
= 0.0;
1741 m_hAdjust
->step_increment
= 1.0;
1742 m_hAdjust
->page_increment
= 1.0;
1743 m_hAdjust
->page_size
= 5.0;
1744 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1746 // these handlers block mouse events to any window during scrolling such as
1747 // motion events and prevent GTK and wxWindows from fighting over where the
1750 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
1751 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1753 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
1754 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1756 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
1757 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1759 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
1760 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1762 // these handlers get notified when screen updates are required either when
1763 // scrolling or when the window size (and therefore scrollbar configuration)
1766 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
1767 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
1768 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
1769 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
1771 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
1772 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
1773 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
1774 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
1776 gtk_widget_show( m_wxwindow
);
1779 m_parent
->DoAddChild( this );
1788 wxWindow::~wxWindow()
1790 m_isBeingDeleted
= TRUE
;
1799 m_parent
->RemoveChild( this );
1803 gtk_style_unref( m_widgetStyle
);
1804 m_widgetStyle
= (GtkStyle
*) NULL
;
1809 gdk_gc_unref( m_scrollGC
);
1810 m_scrollGC
= (GdkGC
*) NULL
;
1815 gtk_widget_destroy( m_wxwindow
);
1816 m_wxwindow
= (GtkWidget
*) NULL
;
1821 gtk_widget_destroy( m_widget
);
1822 m_widget
= (GtkWidget
*) NULL
;
1826 void wxWindow::PreCreation( wxWindow
*parent
,
1831 const wxString
&name
)
1833 wxASSERT_MSG( !m_needParent
|| parent
, _T("Need complete parent.") );
1835 if ( !CreateBase(parent
, id
, pos
, size
, style
, name
) )
1837 wxFAIL_MSG(_T("window creation failed"));
1840 m_width
= WidthDefault(size
.x
);
1841 m_height
= HeightDefault(size
.y
);
1846 if (!parent
) /* some reasonable defaults */
1850 m_x
= (gdk_screen_width () - m_width
) / 2;
1851 if (m_x
< 10) m_x
= 10;
1855 m_y
= (gdk_screen_height () - m_height
) / 2;
1856 if (m_y
< 10) m_y
= 10;
1861 void wxWindow::PostCreation()
1863 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1867 /* these get reported to wxWindows -> wxPaintEvent */
1868 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1869 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1871 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1872 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1874 #if (GTK_MINOR_VERSION > 0)
1875 /* these are called when the "sunken" or "raised" borders are drawn */
1876 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
1877 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
1879 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
1880 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
1884 GtkWidget
*connect_widget
= GetConnectWidget();
1886 ConnectWidget( connect_widget
);
1888 /* we cannot set colours, fonts and cursors before the widget has
1889 been realized, so we do this directly after realization */
1890 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
1891 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
1896 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1898 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1899 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1901 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
1902 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
1904 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1905 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1907 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1908 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1910 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1911 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1913 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1914 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1916 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1917 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1919 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1920 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1922 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1923 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1926 bool wxWindow::Destroy()
1928 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1932 return wxWindowBase::Destroy();
1935 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1937 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1938 wxASSERT_MSG( (m_parent
!= NULL
), _T("wxWindow::SetSize requires parent.\n") );
1940 if (m_resizing
) return; /* I don't like recursions */
1943 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
1945 /* don't set the size for children of wxNotebook, just take the values. */
1953 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1955 if (x
!= -1) m_x
= x
;
1956 if (y
!= -1) m_y
= y
;
1957 if (width
!= -1) m_width
= width
;
1958 if (height
!= -1) m_height
= height
;
1968 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1970 if (width
== -1) m_width
= 80;
1973 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1975 if (height
== -1) m_height
= 26;
1978 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1979 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1980 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
1981 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
1985 if (GTK_WIDGET_HAS_DEFAULT(m_widget
))
1987 /* the default button has a border around it */
1991 /* this is the result of hours of debugging: the following code
1992 means that if we have a m_wxwindow and we set the size of
1993 m_widget, m_widget (which is a GtkScrolledWindow) does NOT
1994 automatically propagate its size down to its m_wxwindow,
1995 which is its client area. therefore, we have to tell the
1996 client area directly that it has to resize itself.
1997 this will lead to that m_widget (GtkScrolledWindow) will
1998 calculate how much size it needs for scrollbars etc and
1999 it will then call XXX_size_allocate of its child, which
2000 is m_wxwindow. m_wxwindow in turn will do the same with its
2001 children and so on. problems can arise if this happens
2002 before all the children have been realized as some widgets
2003 stupidy need to be realized during XXX_size_allocate (e.g.
2004 GtkNotebook) and they will segv if called otherwise. this
2005 emergency is tested in gtk_myfixed_size_allocate. Normally
2006 this shouldn't be needed and only gtk_widget_queue_resize()
2007 should be enough to provoke a resize at the next appropriate
2008 moment, but this seems to fail, e.g. when a wxNotebook contains
2009 a wxSplitterWindow: the splitter window's children won't
2010 show up properly resized then. */
2012 gtk_myfixed_set_size( GTK_MYFIXED(m_parent
->m_wxwindow
),
2017 m_height
+2*border
);
2022 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2023 event
.SetEventObject( this );
2024 GetEventHandler()->ProcessEvent( event
);
2029 void wxWindow::OnInternalIdle()
2034 void wxWindow::DoGetSize( int *width
, int *height
) const
2036 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2038 if (width
) (*width
) = m_width
;
2039 if (height
) (*height
) = m_height
;
2042 void wxWindow::DoSetClientSize( int width
, int height
)
2044 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2048 SetSize( width
, height
);
2055 if (!m_hasScrolling
)
2057 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
2059 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2061 dw
+= 2 * window_class
->xthickness
;
2062 dh
+= 2 * window_class
->ythickness
;
2067 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2068 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2070 #if (GTK_MINOR_VERSION == 0)
2071 GtkWidget
*viewport
= scroll_window
->viewport
;
2072 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2074 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2076 dw
+= 2 * viewport_class
->xthickness
;
2077 dh
+= 2 * viewport_class
->ythickness
;
2082 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2083 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2085 we use this instead: range.slider_width = 11 + 2*2pts edge
2088 if (scroll_window
->vscrollbar_visible
)
2090 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2091 dw
+= scroll_class
->scrollbar_spacing
;
2094 if (scroll_window
->hscrollbar_visible
)
2096 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2097 dh
+= scroll_class
->scrollbar_spacing
;
2101 SetSize( width
+dw
, height
+dh
);
2105 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2107 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2111 if (width
) (*width
) = m_width
;
2112 if (height
) (*height
) = m_height
;
2119 if (!m_hasScrolling
)
2121 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
2123 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2125 dw
+= 2 * window_class
->xthickness
;
2126 dh
+= 2 * window_class
->ythickness
;
2131 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2132 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2134 #if (GTK_MINOR_VERSION == 0)
2135 GtkWidget
*viewport
= scroll_window
->viewport
;
2136 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2138 if ( HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
) )
2140 dw
+= 2 * viewport_class
->xthickness
;
2141 dh
+= 2 * viewport_class
->ythickness
;
2145 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2146 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2148 we use this instead: range.slider_width = 11 + 2*2pts edge
2151 if (scroll_window
->vscrollbar_visible
)
2153 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2154 dw
+= scroll_class
->scrollbar_spacing
;
2157 if (scroll_window
->hscrollbar_visible
)
2159 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2160 dh
+= scroll_class
->scrollbar_spacing
;
2164 if (width
) (*width
) = m_width
- dw
;
2165 if (height
) (*height
) = m_height
- dh
;
2169 void wxWindow::DoGetPosition( int *x
, int *y
) const
2171 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2177 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2179 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2181 if (!m_widget
->window
) return;
2183 GdkWindow
*source
= (GdkWindow
*) NULL
;
2185 source
= m_wxwindow
->window
;
2187 source
= m_widget
->window
;
2191 gdk_window_get_origin( source
, &org_x
, &org_y
);
2195 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2197 org_x
+= m_widget
->allocation
.x
;
2198 org_y
+= m_widget
->allocation
.y
;
2206 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2208 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2210 if (!m_widget
->window
) return;
2212 GdkWindow
*source
= (GdkWindow
*) NULL
;
2214 source
= m_wxwindow
->window
;
2216 source
= m_widget
->window
;
2220 gdk_window_get_origin( source
, &org_x
, &org_y
);
2224 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2226 org_x
+= m_widget
->allocation
.x
;
2227 org_y
+= m_widget
->allocation
.y
;
2235 bool wxWindow::Show( bool show
)
2237 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2239 if (!wxWindowBase::Show(show
))
2246 gtk_widget_show( m_widget
);
2248 gtk_widget_hide( m_widget
);
2253 bool wxWindow::Enable( bool enable
)
2255 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2257 if (!wxWindowBase::Enable(enable
))
2263 gtk_widget_set_sensitive( m_widget
, enable
);
2265 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2270 int wxWindow::GetCharHeight() const
2272 wxCHECK_MSG( (m_widget
!= NULL
), 12, _T("invalid window") );
2274 wxCHECK_MSG( m_font
.Ok(), 12, _T("invalid font") );
2276 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2278 return font
->ascent
+ font
->descent
;
2281 int wxWindow::GetCharWidth() const
2283 wxCHECK_MSG( (m_widget
!= NULL
), 8, _T("invalid window") );
2285 wxCHECK_MSG( m_font
.Ok(), 8, _T("invalid font") );
2287 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2289 return gdk_string_width( font
, "H" );
2292 void wxWindow::GetTextExtent( const wxString
& string
,
2296 int *externalLeading
,
2297 const wxFont
*theFont
) const
2299 wxFont fontToUse
= m_font
;
2300 if (theFont
) fontToUse
= *theFont
;
2302 wxCHECK_RET( fontToUse
.Ok(), _T("invalid font") );
2304 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2305 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2306 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2307 if (descent
) (*descent
) = font
->descent
;
2308 if (externalLeading
) (*externalLeading
) = 0; // ??
2311 void wxWindow::SetFocus()
2313 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2315 GtkWidget
*connect_widget
= GetConnectWidget();
2318 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2320 gtk_widget_grab_focus (connect_widget
);
2322 else if (GTK_IS_CONTAINER(connect_widget
))
2324 gtk_container_focus( GTK_CONTAINER(connect_widget
), GTK_DIR_TAB_FORWARD
);
2332 bool wxWindow::AcceptsFocus() const
2334 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2337 bool wxWindow::Reparent( wxWindow
*newParent
)
2339 wxCHECK_MSG( (m_widget
!= NULL
), (wxWindow
*) NULL
, _T("invalid window") );
2341 gtk_widget_unparent( m_widget
);
2343 if ( !wxWindowBase::Reparent(newParent
) )
2349 void wxWindow::Raise()
2351 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2353 if (!m_widget
->window
) return;
2355 gdk_window_raise( m_widget
->window
);
2358 void wxWindow::Lower()
2360 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2362 if (!m_widget
->window
) return;
2364 gdk_window_lower( m_widget
->window
);
2367 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2369 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2371 if (!wxWindowBase::SetCursor(cursor
))
2373 // don't leave if the GTK widget has just
2375 if (!m_delayedCursor
) return FALSE
;
2378 GtkWidget
*connect_widget
= GetConnectWidget();
2379 if (!connect_widget
->window
)
2381 // indicate that a new style has been set
2382 // but it couldn't get applied as the
2383 // widget hasn't been realized yet.
2384 m_delayedCursor
= TRUE
;
2386 // pretend we have done something
2390 if ((m_widget
) && (m_widget
->window
))
2391 gdk_window_set_cursor( m_widget
->window
, GetCursor().GetCursor() );
2393 if ((m_wxwindow
) && (m_wxwindow
->window
))
2394 gdk_window_set_cursor( m_wxwindow
->window
, GetCursor().GetCursor() );
2400 void wxWindow::WarpPointer( int WXUNUSED(x
), int WXUNUSED(y
) )
2405 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2407 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2409 if (!m_widget
->window
) return;
2411 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2415 gdk_window_clear_area( m_wxwindow
->window
,
2417 rect
->width
, rect
->height
);
2421 gdk_window_clear( m_wxwindow
->window
);
2428 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2430 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2434 GdkRectangle gdk_rect
;
2435 gdk_rect
.x
= rect
->x
;
2436 gdk_rect
.y
= rect
->y
;
2437 gdk_rect
.width
= rect
->width
;
2438 gdk_rect
.height
= rect
->height
;
2441 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2443 gtk_widget_draw( m_widget
, &gdk_rect
);
2447 void wxWindow::Clear()
2449 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2451 if (!m_widget
->window
) return;
2453 if (m_wxwindow
&& m_wxwindow
->window
)
2455 gdk_window_clear( m_wxwindow
->window
);
2460 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2462 wxWindowBase::DoSetToolTip(tip
);
2465 m_tooltip
->Apply( this );
2468 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2470 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConv_current
->cWX2MB(tip
), (gchar
*) NULL
);
2472 #endif // wxUSE_TOOLTIPS
2474 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2476 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2478 if (!wxWindowBase::SetBackgroundColour(colour
))
2480 // don't leave if the GTK widget has just
2482 if (!m_delayedBackgroundColour
) return FALSE
;
2485 GtkWidget
*connect_widget
= GetConnectWidget();
2486 if (!connect_widget
->window
)
2488 // indicate that a new style has been set
2489 // but it couldn't get applied as the
2490 // widget hasn't been realized yet.
2491 m_delayedBackgroundColour
= TRUE
;
2493 // pretend we have done something
2497 if (m_wxwindow
&& m_wxwindow
->window
)
2499 /* wxMSW doesn't clear the window here. I don't do that either to
2500 provide compatibility. call Clear() to do the job. */
2502 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_wxwindow
->window
) );
2503 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
2506 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2508 if (sysbg
== m_backgroundColour
)
2510 m_backgroundColour
= wxNullColour
;
2512 m_backgroundColour
= sysbg
;
2522 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2524 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2526 if (!wxWindowBase::SetForegroundColour(colour
))
2528 // don't leave if the GTK widget has just
2530 if (!m_delayedForegroundColour
) return FALSE
;
2533 GtkWidget
*connect_widget
= GetConnectWidget();
2534 if (!connect_widget
->window
)
2536 // indicate that a new style has been set
2537 // but it couldn't get applied as the
2538 // widget hasn't been realized yet.
2539 m_delayedForegroundColour
= TRUE
;
2541 // pretend we have done something
2545 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2546 if (sysbg
== m_foregroundColour
)
2548 m_backgroundColour
= wxNullColour
;
2550 m_backgroundColour
= sysbg
;
2560 GtkStyle
*wxWindow::GetWidgetStyle()
2562 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2564 m_widgetStyle
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2566 return m_widgetStyle
;
2569 void wxWindow::SetWidgetStyle()
2571 GtkStyle
*style
= GetWidgetStyle();
2573 gdk_font_unref( style
->font
);
2574 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2576 if (m_foregroundColour
.Ok())
2578 m_foregroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2579 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2580 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2581 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2584 if (m_backgroundColour
.Ok())
2586 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2587 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2588 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2589 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2590 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2591 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2592 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2593 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2594 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2598 void wxWindow::ApplyWidgetStyle()
2602 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2604 menu
->SetInvokingWindow( win
);
2605 wxNode
*node
= menu
->GetItems().First();
2608 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2609 if (menuitem
->IsSubMenu())
2611 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2613 node
= node
->Next();
2617 static gint gs_pop_x
= 0;
2618 static gint gs_pop_y
= 0;
2620 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
2624 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
2629 bool wxWindow::PopupMenu( wxMenu
*menu
, int x
, int y
)
2631 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2633 wxCHECK_MSG( menu
!= NULL
, FALSE
, _T("invalid popup-menu") );
2635 SetInvokingWindow( menu
, this );
2643 GTK_MENU(menu
->m_menu
),
2644 (GtkWidget
*) NULL
, // parent menu shell
2645 (GtkWidget
*) NULL
, // parent menu item
2646 (GtkMenuPositionFunc
) pop_pos_callback
,
2647 (gpointer
) this, // client data
2648 0, // button used to activate it
2649 0 //gs_timeLastClick // the time of activation
2654 #if wxUSE_DRAG_AND_DROP
2656 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2658 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2660 GtkWidget
*dnd_widget
= GetConnectWidget();
2662 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
2664 if (m_dropTarget
) delete m_dropTarget
;
2665 m_dropTarget
= dropTarget
;
2667 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
2670 #endif // wxUSE_DRAG_AND_DROP
2672 GtkWidget
* wxWindow::GetConnectWidget()
2674 GtkWidget
*connect_widget
= m_widget
;
2675 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2677 return connect_widget
;
2680 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2682 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2683 return (window
== m_widget
->window
);
2686 bool wxWindow::SetFont( const wxFont
&font
)
2688 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T( "invalid window") );
2690 if (!wxWindowBase::SetFont(font
))
2692 // don't leave if the GTK widget has just
2694 if (!m_delayedFont
) return FALSE
;
2697 GtkWidget
*connect_widget
= GetConnectWidget();
2698 if (!connect_widget
->window
)
2700 // indicate that a new style has been set
2701 // but it couldn't get applied as the
2702 // widget hasn't been realized yet.
2703 m_delayedFont
= TRUE
;
2705 // pretend we have done something
2709 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2710 if ( sysbg
== m_backgroundColour
)
2712 m_backgroundColour
= wxNullColour
;
2714 m_backgroundColour
= sysbg
;
2724 void wxWindow::CaptureMouse()
2726 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2728 wxCHECK_RET( g_capturing
== FALSE
, _T("CaptureMouse called twice") );
2730 GtkWidget
*connect_widget
= GetConnectWidget();
2731 if (!connect_widget
->window
) return;
2733 gtk_grab_add( connect_widget
);
2734 gdk_pointer_grab( connect_widget
->window
, FALSE
,
2736 (GDK_BUTTON_PRESS_MASK
|
2737 GDK_BUTTON_RELEASE_MASK
|
2738 GDK_POINTER_MOTION_MASK
),
2745 void wxWindow::ReleaseMouse()
2747 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2749 wxCHECK_RET( g_capturing
== TRUE
, _T("ReleaseMouse called twice") );
2751 GtkWidget
*connect_widget
= GetConnectWidget();
2752 if (!connect_widget
->window
) return;
2754 gtk_grab_remove( connect_widget
);
2755 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2756 g_capturing
= FALSE
;
2759 bool wxWindow::IsRetained() const
2764 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2765 int range
, bool refresh
)
2767 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2769 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2771 m_hasScrolling
= TRUE
;
2773 if (orient
== wxHORIZONTAL
)
2775 float fpos
= (float)pos
;
2776 float frange
= (float)range
;
2777 float fthumb
= (float)thumbVisible
;
2778 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2779 if (fpos
< 0.0) fpos
= 0.0;
2781 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2782 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2784 SetScrollPos( orient
, pos
, refresh
);
2788 m_oldHorizontalPos
= fpos
;
2790 m_hAdjust
->lower
= 0.0;
2791 m_hAdjust
->upper
= frange
;
2792 m_hAdjust
->value
= fpos
;
2793 m_hAdjust
->step_increment
= 1.0;
2794 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2795 m_hAdjust
->page_size
= fthumb
;
2799 float fpos
= (float)pos
;
2800 float frange
= (float)range
;
2801 float fthumb
= (float)thumbVisible
;
2802 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2803 if (fpos
< 0.0) fpos
= 0.0;
2805 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2806 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2808 SetScrollPos( orient
, pos
, refresh
);
2812 m_oldVerticalPos
= fpos
;
2814 m_vAdjust
->lower
= 0.0;
2815 m_vAdjust
->upper
= frange
;
2816 m_vAdjust
->value
= fpos
;
2817 m_vAdjust
->step_increment
= 1.0;
2818 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2819 m_vAdjust
->page_size
= fthumb
;
2822 if (orient
== wxHORIZONTAL
)
2823 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2825 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2828 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2830 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2832 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2834 if (orient
== wxHORIZONTAL
)
2836 float fpos
= (float)pos
;
2837 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
2838 if (fpos
< 0.0) fpos
= 0.0;
2839 m_oldHorizontalPos
= fpos
;
2841 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2842 m_hAdjust
->value
= fpos
;
2846 float fpos
= (float)pos
;
2847 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
2848 if (fpos
< 0.0) fpos
= 0.0;
2849 m_oldVerticalPos
= fpos
;
2851 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2852 m_vAdjust
->value
= fpos
;
2855 if (!m_isScrolling
) /* prevent recursion */
2857 if (m_wxwindow
->window
)
2859 if (orient
== wxHORIZONTAL
)
2860 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2862 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2867 int wxWindow::GetScrollThumb( int orient
) const
2869 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2871 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2873 if (orient
== wxHORIZONTAL
)
2874 return (int)(m_hAdjust
->page_size
+0.5);
2876 return (int)(m_vAdjust
->page_size
+0.5);
2879 int wxWindow::GetScrollPos( int orient
) const
2881 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2883 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2885 if (orient
== wxHORIZONTAL
)
2886 return (int)(m_hAdjust
->value
+0.5);
2888 return (int)(m_vAdjust
->value
+0.5);
2891 int wxWindow::GetScrollRange( int orient
) const
2893 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2895 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2897 if (orient
== wxHORIZONTAL
)
2898 return (int)(m_hAdjust
->upper
+0.5);
2900 return (int)(m_vAdjust
->upper
+0.5);
2903 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2905 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2907 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2911 m_scrollGC
= gdk_gc_new( m_wxwindow
->window
);
2912 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
2915 wxNode
*node
= m_children
.First();
2918 wxWindow
*child
= (wxWindow
*) node
->Data();
2919 child
->Move( child
->m_x
+ dx
, child
->m_y
+ dy
);
2920 node
= node
->Next();
2925 GetClientSize( &cw
, &ch
);
2926 int w
= cw
- abs(dx
);
2927 int h
= ch
- abs(dy
);
2929 if ((h
< 0) || (w
< 0))
2937 if (dx
< 0) s_x
= -dx
;
2938 if (dy
< 0) s_y
= -dy
;
2941 if (dx
> 0) d_x
= dx
;
2942 if (dy
> 0) d_y
= dy
;
2944 gdk_window_copy_area( m_wxwindow
->window
, m_scrollGC
, d_x
, d_y
,
2945 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2948 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2949 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2950 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2951 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2953 Refresh( TRUE
, &rect
);
2957 void wxWindow::SetScrolling(bool scroll
)
2959 m_isScrolling
= g_blockEventsOnScroll
= scroll
;