1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #include "wx/window.h"
20 #include "wx/layout.h"
22 #include "wx/dialog.h"
23 #include "wx/msgdlg.h"
25 #if wxUSE_DRAG_AND_DROP
30 #include "wx/tooltip.h"
34 #include "wx/statusbr.h"
36 #include "wx/settings.h"
43 #include "gdk/gdkprivate.h"
44 #include "gdk/gdkkeysyms.h"
45 #include "wx/gtk/win_gtk.h"
47 #if (GTK_MINOR_VERSION == 0)
51 //-----------------------------------------------------------------------------
52 // documentation on internals
53 //-----------------------------------------------------------------------------
56 I have been asked several times about writing some documentation about
57 the GTK port of wxWindows, especially its internal structures. Obviously,
58 you cannot understand wxGTK without knowing a little about the GTK, but
59 some more information about what the wxWindow, which is the base class
60 for all other window classes, does seems required as well.
62 What does wxWindow do? It contains the common interface for the following
63 jobs of its descendants:
65 1) Define the rudimentary behaviour common to all window classes, such as
66 resizing, intercepting user input (so as to make it possible to use these
67 events for special purposes in a derived class), window names etc.
69 2) Provide the possibility to contain and manage children, if the derived
70 class is allowed to contain children, which holds true for those window
71 classes which do not display a native GTK widget. To name them, these
72 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
73 work classes are a special case and are handled a bit differently from
74 the rest. The same holds true for the wxNotebook class.
76 3) Provide the possibility to draw into a client area of a window. This,
77 too, only holds true for classes that do not display a native GTK widget
80 4) Provide the entire mechanism for scrolling widgets. This actual inter-
81 face for this is usually in wxScrolledWindow, but the GTK implementation
84 5) A multitude of helper or extra methods for special purposes, such as
85 Drag'n'Drop, managing validators etc.
87 Normally one might expect, that one wxWindows window would always correspond
88 to one GTK widget. Under GTK, there is no such allround widget that has all
89 the functionality. Moreover, the GTK defines a client area as a different
90 widget from the actual widget you are handling. Last but not least some
91 special classes (e.g. wxFrame) handle different categories of widgets and
92 still have the possibility to draw something in the client area.
93 It was therefore required to write a special purpose GTK widget, that would
94 represent a client area in the sense of wxWindows capable to do the jobs
95 2), 3) and 4). I have written this class and it resides in win_gtk.c of
98 All windows must have a widget, with which they interact with other under-
99 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
100 thw wxWindow class has a member variable called m_widget which holds a
101 pointer to this widget. When the window class represents a GTK native widget,
102 this is (in most cases) the only GTK widget the class manages. E.g. the
103 wxStatitText class handles only a GtkLabel widget a pointer to which you
104 can find in m_widget (defined in wxWindow)
106 When the class has a client area for drawing into and for containing children
107 it has to handle the client area widget (of the type GtkMyFixed, defined in
108 win_gtk.c), but there could be any number of widgets, handled by a class
109 The common rule for all windows is only, that the widget that interacts with
110 the rest of GTK must be referenced in m_widget and all other widgets must be
111 children of this widget on the GTK level. The top-most widget, which also
112 represents the client area, must be in the m_wxwindow field and must be of
115 As I said, the window classes that display a GTK native widget only have
116 one widget, so in the case of e.g. the wxButton class m_widget holds a
117 pointer to a GtkButton widget. But windows with client areas (for drawing
118 and children) have a m_widget field that is a pointer to a GtkScrolled-
119 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
120 one is (in the GTK sense) a child of the GtkScrolledWindow.
122 If the m_wxwindow field is set, then all input to this widget is inter-
123 cepted and sent to the wxWindows class. If not, all input to the widget
124 that gets pointed to by m_widget gets intercepted and sent to the class.
128 //-----------------------------------------------------------------------------
130 //-----------------------------------------------------------------------------
132 extern wxList wxPendingDelete
;
133 extern bool g_blockEventsOnDrag
;
134 extern bool g_blockEventsOnScroll
;
135 extern wxCursor g_globalCursor
;
136 static bool g_capturing
= FALSE
;
137 static wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
139 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
140 the last click here */
141 static guint32 gs_timeLastClick
= 0;
143 //-----------------------------------------------------------------------------
145 //-----------------------------------------------------------------------------
149 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
150 GdkEvent
*WXUNUSED(event
),
154 static bool s_done = FALSE;
157 wxLog::AddTraceMask("focus");
160 wxLogTrace(_T("FOCUS NOW AT: %s"), name);
166 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
172 wxChar
*s
= new wxChar
[tmp
.Length()+1];
176 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
177 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
182 //-----------------------------------------------------------------------------
184 //-----------------------------------------------------------------------------
186 extern void wxapp_install_idle_handler();
187 extern bool g_isIdle
;
189 //-----------------------------------------------------------------------------
190 // key event conversion routines
191 //-----------------------------------------------------------------------------
193 #if (GTK_MINOR_VERSION == 0)
195 gdk_keyval_to_upper (guint keyval
)
199 KeySym lower_val
= 0;
200 KeySym upper_val
= 0;
202 XConvertCase (keyval
, &lower_val
, &upper_val
);
209 static long map_to_unmodified_wx_keysym( KeySym keysym
)
216 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
218 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
224 case GDK_Super_R
: key_code
= WXK_ALT
; break;
225 case GDK_Menu
: key_code
= WXK_MENU
; break;
226 case GDK_Help
: key_code
= WXK_HELP
; break;
227 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
228 case GDK_ISO_Left_Tab
:
229 case GDK_Tab
: key_code
= WXK_TAB
; break;
230 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
231 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
232 case GDK_Return
: key_code
= WXK_RETURN
; break;
233 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
234 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
235 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
236 case GDK_Delete
: key_code
= WXK_DELETE
; break;
237 case GDK_Home
: key_code
= WXK_HOME
; break;
238 case GDK_Left
: key_code
= WXK_LEFT
; break;
239 case GDK_Up
: key_code
= WXK_UP
; break;
240 case GDK_Right
: key_code
= WXK_RIGHT
; break;
241 case GDK_Down
: key_code
= WXK_DOWN
; break;
242 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
243 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
244 case GDK_Next
: key_code
= WXK_NEXT
; break;
245 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
246 case GDK_End
: key_code
= WXK_END
; break;
247 case GDK_Begin
: key_code
= WXK_HOME
; break;
248 case GDK_Select
: key_code
= WXK_SELECT
; break;
249 case GDK_Print
: key_code
= WXK_PRINT
; break;
250 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
251 case GDK_Insert
: key_code
= WXK_INSERT
; break;
252 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
254 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
255 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
256 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
257 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
258 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
259 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
260 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
261 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
262 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
263 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
264 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
265 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
266 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
267 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
268 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
269 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
270 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
271 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
272 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
273 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
274 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
275 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
276 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
277 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
278 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
279 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
280 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
281 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
282 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
283 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
284 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
285 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
286 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
287 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
288 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
289 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
290 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
292 case GDK_F1
: key_code
= WXK_F1
; break;
293 case GDK_F2
: key_code
= WXK_F2
; break;
294 case GDK_F3
: key_code
= WXK_F3
; break;
295 case GDK_F4
: key_code
= WXK_F4
; break;
296 case GDK_F5
: key_code
= WXK_F5
; break;
297 case GDK_F6
: key_code
= WXK_F6
; break;
298 case GDK_F7
: key_code
= WXK_F7
; break;
299 case GDK_F8
: key_code
= WXK_F8
; break;
300 case GDK_F9
: key_code
= WXK_F9
; break;
301 case GDK_F10
: key_code
= WXK_F10
; break;
302 case GDK_F11
: key_code
= WXK_F11
; break;
303 case GDK_F12
: key_code
= WXK_F12
; break;
308 guint upper
= gdk_keyval_to_upper( keysym
);
309 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
318 static long map_to_wx_keysym( KeySym keysym
)
324 case GDK_Menu
: key_code
= WXK_MENU
; break;
325 case GDK_Help
: key_code
= WXK_HELP
; break;
326 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
327 case GDK_ISO_Left_Tab
:
328 case GDK_Tab
: key_code
= WXK_TAB
; break;
329 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
330 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
331 case GDK_Return
: key_code
= WXK_RETURN
; break;
332 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
333 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
334 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
335 case GDK_Delete
: key_code
= WXK_DELETE
; break;
336 case GDK_Home
: key_code
= WXK_HOME
; break;
337 case GDK_Left
: key_code
= WXK_LEFT
; break;
338 case GDK_Up
: key_code
= WXK_UP
; break;
339 case GDK_Right
: key_code
= WXK_RIGHT
; break;
340 case GDK_Down
: key_code
= WXK_DOWN
; break;
341 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
342 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
343 case GDK_Next
: key_code
= WXK_NEXT
; break;
344 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
345 case GDK_End
: key_code
= WXK_END
; break;
346 case GDK_Begin
: key_code
= WXK_HOME
; break;
347 case GDK_Select
: key_code
= WXK_SELECT
; break;
348 case GDK_Print
: key_code
= WXK_PRINT
; break;
349 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
350 case GDK_Insert
: key_code
= WXK_INSERT
; break;
351 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
353 case GDK_KP_0
: key_code
= '0'; break;
354 case GDK_KP_1
: key_code
= '1'; break;
355 case GDK_KP_2
: key_code
= '2'; break;
356 case GDK_KP_3
: key_code
= '3'; break;
357 case GDK_KP_4
: key_code
= '4'; break;
358 case GDK_KP_5
: key_code
= '5'; break;
359 case GDK_KP_6
: key_code
= '6'; break;
360 case GDK_KP_7
: key_code
= '7'; break;
361 case GDK_KP_8
: key_code
= '8'; break;
362 case GDK_KP_9
: key_code
= '9'; break;
363 case GDK_KP_Space
: key_code
= ' '; break;
364 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
365 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
366 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
367 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
368 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
369 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
370 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
371 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
372 case GDK_KP_Up
: key_code
= WXK_UP
; break;
373 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
374 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
375 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
376 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
377 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
378 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
379 case GDK_KP_End
: key_code
= WXK_END
; break;
380 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
381 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
382 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
383 case GDK_KP_Equal
: key_code
= '='; break;
384 case GDK_KP_Multiply
: key_code
= '*'; break;
385 case GDK_KP_Add
: key_code
= '+'; break;
386 case GDK_KP_Separator
: key_code
= ','; break;
387 case GDK_KP_Subtract
: key_code
= '-'; break;
388 case GDK_KP_Decimal
: key_code
= '.'; break;
389 case GDK_KP_Divide
: key_code
= '/'; break;
391 case GDK_F1
: key_code
= WXK_F1
; break;
392 case GDK_F2
: key_code
= WXK_F2
; break;
393 case GDK_F3
: key_code
= WXK_F3
; break;
394 case GDK_F4
: key_code
= WXK_F4
; break;
395 case GDK_F5
: key_code
= WXK_F5
; break;
396 case GDK_F6
: key_code
= WXK_F6
; break;
397 case GDK_F7
: key_code
= WXK_F7
; break;
398 case GDK_F8
: key_code
= WXK_F8
; break;
399 case GDK_F9
: key_code
= WXK_F9
; break;
400 case GDK_F10
: key_code
= WXK_F10
; break;
401 case GDK_F11
: key_code
= WXK_F11
; break;
402 case GDK_F12
: key_code
= WXK_F12
; break;
415 //-----------------------------------------------------------------------------
416 // local code (see below)
417 //-----------------------------------------------------------------------------
419 #if (GTK_MINOR_VERSION > 0)
421 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
429 if (win
->HasScrolling())
431 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
432 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
435 GtkWidget *hscrollbar = scroll_window->hscrollbar;
436 GtkWidget *vscrollbar = scroll_window->vscrollbar;
438 we use this instead: range.slider_width = 11 + 2*2pts edge
441 if (scroll_window
->vscrollbar_visible
)
443 dw
+= 15; /* dw += vscrollbar->allocation.width; */
444 dw
+= scroll_class
->scrollbar_spacing
;
447 if (scroll_window
->hscrollbar_visible
)
449 dh
+= 15; /* dh += hscrollbar->allocation.height; */
450 dh
+= scroll_class
->scrollbar_spacing
;
456 if (GTK_WIDGET_NO_WINDOW (widget
))
458 dx
+= widget
->allocation
.x
;
459 dy
+= widget
->allocation
.y
;
462 if (win
->HasFlag(wxRAISED_BORDER
))
464 gtk_draw_shadow( widget
->style
,
469 win
->m_width
-dw
, win
->m_height
-dh
);
473 if (win
->HasFlag(wxSUNKEN_BORDER
))
475 gtk_draw_shadow( widget
->style
,
480 win
->m_width
-dw
, win
->m_height
-dh
);
485 //-----------------------------------------------------------------------------
486 // "expose_event" of m_widget
487 //-----------------------------------------------------------------------------
489 static void gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
491 if (gdk_event
->count
> 0) return;
492 draw_frame( widget
, win
);
495 //-----------------------------------------------------------------------------
496 // "draw" of m_wxwindow
497 //-----------------------------------------------------------------------------
499 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
501 draw_frame( widget
, win
);
504 #endif // GTK_MINOR_VERSION > 0
506 //-----------------------------------------------------------------------------
507 // "expose_event" of m_wxwindow
508 //-----------------------------------------------------------------------------
510 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
512 if ( !win
->m_hasVMT
)
515 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
517 gdk_event
->area
.width
,
518 gdk_event
->area
.height
);
520 if ( gdk_event
->count
> 0 )
524 printf( "OnExpose from " );
525 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
526 printf( win->GetClassInfo()->GetClassName() );
530 wxPaintEvent
event( win
->GetId() );
531 event
.SetEventObject( win
);
532 win
->GetEventHandler()->ProcessEvent( event
);
534 win
->GetUpdateRegion().Clear();
537 //-----------------------------------------------------------------------------
538 // "draw" of m_wxwindow
539 //-----------------------------------------------------------------------------
541 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
544 wxapp_install_idle_handler();
549 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
550 rect
->width
, rect
->height
);
552 wxPaintEvent
event( win
->GetId() );
553 event
.SetEventObject( win
);
554 win
->GetEventHandler()->ProcessEvent( event
);
556 win
->GetUpdateRegion().Clear();
559 //-----------------------------------------------------------------------------
560 // "key_press_event" from any window
561 //-----------------------------------------------------------------------------
563 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
566 wxapp_install_idle_handler();
568 if (!win
->m_hasVMT
) return FALSE
;
569 if (g_blockEventsOnDrag
) return FALSE
;
572 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
573 if (gdk_event->state & GDK_SHIFT_MASK)
574 printf( "ShiftDown.\n" );
576 printf( "ShiftUp.\n" );
577 if (gdk_event->state & GDK_CONTROL_MASK)
578 printf( "ControlDown.\n" );
580 printf( "ControlUp.\n" );
585 GdkModifierType state
;
586 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
588 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
590 /* sending unknown key events doesn't really make sense */
591 if (key_code
== 0) return FALSE
;
595 wxKeyEvent
event( wxEVT_KEY_DOWN
);
596 event
.SetTimestamp( gdk_event
->time
);
597 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
598 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
599 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
600 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
601 event
.m_keyCode
= key_code
;
602 event
.m_scanCode
= gdk_event
->keyval
;
605 event
.SetEventObject( win
);
606 ret
= win
->GetEventHandler()->ProcessEvent( event
);
608 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
610 /* wxMSW doesn't send char events with Alt pressed */
611 if ((key_code
!= 0) &&
612 ((gdk_event
->state
& GDK_MOD1_MASK
) == 0) &&
613 ((gdk_event
->state
& GDK_MOD1_MASK
) == 0))
615 wxKeyEvent
event2( wxEVT_CHAR
);
616 event2
.SetTimestamp( gdk_event
->time
);
617 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
618 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
619 // event2.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
620 // event2.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
621 event2
.m_keyCode
= key_code
;
622 event2
.m_scanCode
= gdk_event
->keyval
;
625 event2
.SetEventObject( win
);
626 ret
= (ret
|| win
->GetEventHandler()->ProcessEvent( event2
));
631 wxWindow
*ancestor
= win
;
634 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
637 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
638 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
641 ancestor
= ancestor
->GetParent();
645 /* win is a control: tab can be propagated up */
647 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
648 (win
->HasFlag(wxTE_PROCESS_TAB
) == 0))
650 wxNavigationKeyEvent new_event
;
651 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
652 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
653 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
654 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
655 new_event
.SetCurrentFocus( win
);
656 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
659 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
661 (gdk_event
->keyval
== GDK_Escape
) )
663 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
664 new_event
.SetEventObject( win
);
665 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
668 #if (GTK_MINOR_VERSION > 0)
669 /* pressing F10 will activate the menu bar of the top frame */
671 (gdk_event
->keyval
== GDK_F10
) )
673 wxWindow
*ancestor
= win
;
676 if (wxIsKindOf(ancestor
,wxFrame
))
678 wxFrame
*frame
= (wxFrame
*) ancestor
;
679 wxMenuBar
*menubar
= frame
->GetMenuBar();
682 wxNode
*node
= menubar
->GetMenus().First();
685 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
686 // doesn't work correctly
687 // gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
693 ancestor
= ancestor
->GetParent();
699 Damn, I forgot why this didn't work, but it didn't work.
701 // win is a panel: up can be propagated to the panel
702 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
703 (gdk_event->keyval == GDK_Up))
705 win->m_parent->SetFocus();
709 // win is a panel: left/right can be propagated to the panel
710 if ((!ret) && (win->m_wxwindow) &&
711 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
712 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
714 wxNavigationKeyEvent new_event;
715 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
716 new_event.SetCurrentFocus( win );
717 ret = win->GetEventHandler()->ProcessEvent( new_event );
723 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
730 //-----------------------------------------------------------------------------
731 // "key_release_event" from any window
732 //-----------------------------------------------------------------------------
734 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
737 wxapp_install_idle_handler();
739 if (!win
->m_hasVMT
) return FALSE
;
740 if (g_blockEventsOnDrag
) return FALSE
;
743 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
744 if (gdk_event->state & GDK_SHIFT_MASK)
745 printf( "ShiftDown.\n" );
747 printf( "ShiftUp.\n" );
748 if (gdk_event->state & GDK_CONTROL_MASK)
749 printf( "ControlDown.\n" );
751 printf( "ControlUp.\n" );
755 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
757 /* sending unknown key events doesn't really make sense */
758 if (key_code
== 0) return FALSE
;
762 GdkModifierType state
;
763 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
765 wxKeyEvent
event( wxEVT_KEY_UP
);
766 event
.SetTimestamp( gdk_event
->time
);
767 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
768 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
769 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
770 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
771 event
.m_keyCode
= key_code
;
772 event
.m_scanCode
= gdk_event
->keyval
;
775 event
.SetEventObject( win
);
777 if (win
->GetEventHandler()->ProcessEvent( event
))
779 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
786 //-----------------------------------------------------------------------------
787 // "button_press_event"
788 //-----------------------------------------------------------------------------
790 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
793 wxapp_install_idle_handler();
796 wxPrintf( _T("1) OnButtonPress from ") );
797 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
798 wxPrintf( win->GetClassInfo()->GetClassName() );
799 wxPrintf( _T(".\n") );
801 if (!win
->m_hasVMT
) return FALSE
;
802 if (g_blockEventsOnDrag
) return TRUE
;
803 if (g_blockEventsOnScroll
) return TRUE
;
805 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
809 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
811 gtk_widget_grab_focus (win
->m_wxwindow
);
814 wxPrintf( _T("GrabFocus from ") );
815 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
816 wxPrintf( win->GetClassInfo()->GetClassName() );
817 wxPrintf( _T(".\n") );
824 wxPrintf( _T("2) OnButtonPress from ") );
825 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
826 wxPrintf( win->GetClassInfo()->GetClassName() );
827 wxPrintf( _T(".\n") );
830 wxEventType event_type
= wxEVT_LEFT_DOWN
;
832 if (gdk_event
->button
== 1)
834 switch (gdk_event
->type
)
836 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
837 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
841 else if (gdk_event
->button
== 2)
843 switch (gdk_event
->type
)
845 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
846 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
850 else if (gdk_event
->button
== 3)
852 switch (gdk_event
->type
)
854 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
855 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
860 wxMouseEvent
event( event_type
);
861 event
.SetTimestamp( gdk_event
->time
);
862 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
863 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
864 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
865 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
866 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
867 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
868 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
870 event
.m_x
= (long)gdk_event
->x
;
871 event
.m_y
= (long)gdk_event
->y
;
873 // Some control don't have their own X window and thus cannot get
878 wxNode
*node
= win
->GetChildren().First();
881 wxWindow
*child
= (wxWindow
*)node
->Data();
883 if (child
->m_isStaticBox
)
885 // wxStaticBox is transparent in the box itself
888 int xx1
= child
->m_x
;
889 int yy1
= child
->m_y
;
890 int xx2
= child
->m_x
+ child
->m_width
;
891 int yy2
= child
->m_x
+ child
->m_height
;
894 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
896 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
898 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
900 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
903 event
.m_x
-= child
->m_x
;
904 event
.m_y
-= child
->m_y
;
911 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
912 (child
->m_x
<= event
.m_x
) &&
913 (child
->m_y
<= event
.m_y
) &&
914 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
915 (child
->m_y
+child
->m_height
>= event
.m_y
))
918 event
.m_x
-= child
->m_x
;
919 event
.m_y
-= child
->m_y
;
927 event
.SetEventObject( win
);
929 gs_timeLastClick
= gdk_event
->time
;
931 if (win
->GetEventHandler()->ProcessEvent( event
))
933 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
940 //-----------------------------------------------------------------------------
941 // "button_release_event"
942 //-----------------------------------------------------------------------------
944 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
947 wxapp_install_idle_handler();
949 if (!win
->m_hasVMT
) return FALSE
;
950 if (g_blockEventsOnDrag
) return FALSE
;
951 if (g_blockEventsOnScroll
) return FALSE
;
953 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
956 printf( "OnButtonRelease from " );
957 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
958 printf( win->GetClassInfo()->GetClassName() );
962 wxEventType event_type
= wxEVT_NULL
;
964 switch (gdk_event
->button
)
966 case 1: event_type
= wxEVT_LEFT_UP
; break;
967 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
968 case 3: event_type
= wxEVT_RIGHT_UP
; break;
971 wxMouseEvent
event( event_type
);
972 event
.SetTimestamp( gdk_event
->time
);
973 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
974 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
975 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
976 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
977 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
978 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
979 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
980 event
.m_x
= (long)gdk_event
->x
;
981 event
.m_y
= (long)gdk_event
->y
;
983 // Some control don't have their own X window and thus cannot get
988 wxNode
*node
= win
->GetChildren().First();
991 wxWindow
*child
= (wxWindow
*)node
->Data();
993 if (child
->m_isStaticBox
)
995 // wxStaticBox is transparent in the box itself
998 int xx1
= child
->m_x
;
999 int yy1
= child
->m_y
;
1000 int xx2
= child
->m_x
+ child
->m_width
;
1001 int yy2
= child
->m_x
+ child
->m_height
;
1004 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1006 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1008 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1010 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1013 event
.m_x
-= child
->m_x
;
1014 event
.m_y
-= child
->m_y
;
1021 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1022 (child
->m_x
<= event
.m_x
) &&
1023 (child
->m_y
<= event
.m_y
) &&
1024 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
1025 (child
->m_y
+child
->m_height
>= event
.m_y
))
1028 event
.m_x
-= child
->m_x
;
1029 event
.m_y
-= child
->m_y
;
1033 node
= node
->Next();
1037 event
.SetEventObject( win
);
1039 if (win
->GetEventHandler()->ProcessEvent( event
))
1041 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1048 //-----------------------------------------------------------------------------
1049 // "motion_notify_event"
1050 //-----------------------------------------------------------------------------
1052 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1055 wxapp_install_idle_handler();
1057 if (!win
->m_hasVMT
) return FALSE
;
1058 if (g_blockEventsOnDrag
) return FALSE
;
1059 if (g_blockEventsOnScroll
) return FALSE
;
1061 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1063 if (gdk_event
->is_hint
)
1067 GdkModifierType state
;
1068 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1071 gdk_event
->state
= state
;
1075 printf( "OnMotion from " );
1076 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1077 printf( win->GetClassInfo()->GetClassName() );
1081 wxMouseEvent
event( wxEVT_MOTION
);
1082 event
.SetTimestamp( gdk_event
->time
);
1083 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1084 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1085 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1086 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1087 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1088 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1089 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1091 event
.m_x
= (long)gdk_event
->x
;
1092 event
.m_y
= (long)gdk_event
->y
;
1094 // Some control don't have their own X window and thus cannot get
1099 wxNode
*node
= win
->GetChildren().First();
1102 wxWindow
*child
= (wxWindow
*)node
->Data();
1104 if (child
->m_isStaticBox
)
1106 // wxStaticBox is transparent in the box itself
1109 int xx1
= child
->m_x
;
1110 int yy1
= child
->m_y
;
1111 int xx2
= child
->m_x
+ child
->m_width
;
1112 int yy2
= child
->m_x
+ child
->m_height
;
1115 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1117 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1119 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1121 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1124 event
.m_x
-= child
->m_x
;
1125 event
.m_y
-= child
->m_y
;
1132 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1133 (child
->m_x
<= event
.m_x
) &&
1134 (child
->m_y
<= event
.m_y
) &&
1135 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
1136 (child
->m_y
+child
->m_height
>= event
.m_y
))
1139 event
.m_x
-= child
->m_x
;
1140 event
.m_y
-= child
->m_y
;
1144 node
= node
->Next();
1148 event
.SetEventObject( win
);
1150 if (win
->GetEventHandler()->ProcessEvent( event
))
1152 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1159 //-----------------------------------------------------------------------------
1161 //-----------------------------------------------------------------------------
1163 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1166 wxapp_install_idle_handler();
1168 if (!win
->m_hasVMT
) return FALSE
;
1169 if (g_blockEventsOnDrag
) return FALSE
;
1171 g_focusWindow
= win
;
1173 if (win
->m_wxwindow
)
1175 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1177 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1179 printf( "SetFocus flag from " );
1180 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1181 printf( win->GetClassInfo()->GetClassName() );
1189 printf( "OnSetFocus from " );
1190 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1191 printf( win->GetClassInfo()->GetClassName() );
1193 printf( WXSTRINGCAST win->GetLabel() );
1197 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1198 event
.SetEventObject( win
);
1200 if (win
->GetEventHandler()->ProcessEvent( event
))
1202 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1209 //-----------------------------------------------------------------------------
1210 // "focus_out_event"
1211 //-----------------------------------------------------------------------------
1213 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1216 wxapp_install_idle_handler();
1218 if (!win
->m_hasVMT
) return FALSE
;
1219 if (g_blockEventsOnDrag
) return FALSE
;
1221 if (win
->m_wxwindow
)
1223 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1224 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1228 printf( "OnKillFocus from " );
1229 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1230 printf( win->GetClassInfo()->GetClassName() );
1234 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1235 event
.SetEventObject( win
);
1237 if (win
->GetEventHandler()->ProcessEvent( event
))
1239 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1246 //-----------------------------------------------------------------------------
1247 // "enter_notify_event"
1248 //-----------------------------------------------------------------------------
1250 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1253 wxapp_install_idle_handler();
1255 if (!win
->m_hasVMT
) return FALSE
;
1256 if (g_blockEventsOnDrag
) return FALSE
;
1258 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1260 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1261 #if (GTK_MINOR_VERSION > 0)
1262 event
.SetTimestamp( gdk_event
->time
);
1264 event
.SetEventObject( win
);
1268 GdkModifierType state
= (GdkModifierType
)0;
1270 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1272 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1273 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1274 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1275 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1276 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1277 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1278 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1280 event
.m_x
= (long)x
;
1281 event
.m_y
= (long)y
;
1283 if (win
->GetEventHandler()->ProcessEvent( event
))
1285 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1292 //-----------------------------------------------------------------------------
1293 // "leave_notify_event"
1294 //-----------------------------------------------------------------------------
1296 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1299 wxapp_install_idle_handler();
1301 if (!win
->m_hasVMT
) return FALSE
;
1302 if (g_blockEventsOnDrag
) return FALSE
;
1304 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1306 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1307 #if (GTK_MINOR_VERSION > 0)
1308 event
.SetTimestamp( gdk_event
->time
);
1310 event
.SetEventObject( win
);
1314 GdkModifierType state
= (GdkModifierType
)0;
1316 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1318 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1319 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1320 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1321 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1322 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1323 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1324 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1326 event
.m_x
= (long)x
;
1327 event
.m_y
= (long)y
;
1329 if (win
->GetEventHandler()->ProcessEvent( event
))
1331 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1338 //-----------------------------------------------------------------------------
1339 // "value_changed" from m_vAdjust
1340 //-----------------------------------------------------------------------------
1342 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1345 wxapp_install_idle_handler();
1347 if (g_blockEventsOnDrag
) return;
1349 if (!win
->m_hasVMT
) return;
1351 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
1352 if (fabs(diff
) < 0.2) return;
1353 win
->m_oldVerticalPos
= win
->m_vAdjust
->value
;
1355 wxEventType command
= wxEVT_NULL
;
1357 float line_step
= win
->m_vAdjust
->step_increment
;
1358 float page_step
= win
->m_vAdjust
->page_increment
;
1360 if (win
->IsScrolling())
1362 command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1366 if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->lower
) < 0.2) command
= wxEVT_SCROLLWIN_BOTTOM
;
1367 else if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->upper
) < 0.2) command
= wxEVT_SCROLLWIN_TOP
;
1368 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1369 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEUP
;
1370 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1371 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEUP
;
1372 else command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1375 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1377 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1378 event
.SetEventObject( win
);
1379 win
->GetEventHandler()->ProcessEvent( event
);
1382 //-----------------------------------------------------------------------------
1383 // "value_changed" from m_hAdjust
1384 //-----------------------------------------------------------------------------
1386 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1389 wxapp_install_idle_handler();
1391 if (g_blockEventsOnDrag
) return;
1392 if (!win
->m_hasVMT
) return;
1394 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
1395 if (fabs(diff
) < 0.2) return;
1396 win
->m_oldHorizontalPos
= win
->m_hAdjust
->value
;
1398 wxEventType command
= wxEVT_NULL
;
1400 float line_step
= win
->m_hAdjust
->step_increment
;
1401 float page_step
= win
->m_hAdjust
->page_increment
;
1403 if (win
->IsScrolling())
1405 command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1409 if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->lower
) < 0.2) command
= wxEVT_SCROLLWIN_BOTTOM
;
1410 else if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->upper
) < 0.2) command
= wxEVT_SCROLLWIN_TOP
;
1411 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1412 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEUP
;
1413 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1414 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEUP
;
1415 else command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1418 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1420 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1421 event
.SetEventObject( win
);
1422 win
->GetEventHandler()->ProcessEvent( event
);
1425 //-----------------------------------------------------------------------------
1426 // "changed" from m_vAdjust
1427 //-----------------------------------------------------------------------------
1429 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1432 wxapp_install_idle_handler();
1434 if (g_blockEventsOnDrag
) return;
1435 if (!win
->m_hasVMT
) return;
1437 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1438 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1440 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1441 event
.SetEventObject( win
);
1442 win
->GetEventHandler()->ProcessEvent( event
);
1445 //-----------------------------------------------------------------------------
1446 // "changed" from m_hAdjust
1447 //-----------------------------------------------------------------------------
1449 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1452 wxapp_install_idle_handler();
1454 if (g_blockEventsOnDrag
) return;
1455 if (!win
->m_hasVMT
) return;
1457 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1458 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1460 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1461 event
.SetEventObject( win
);
1462 win
->GetEventHandler()->ProcessEvent( event
);
1465 //-----------------------------------------------------------------------------
1466 // "button_press_event" from scrollbar
1467 //-----------------------------------------------------------------------------
1469 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1470 GdkEventButton
*WXUNUSED(gdk_event
),
1474 wxapp_install_idle_handler();
1476 // don't test here as we can release the mouse while being over
1477 // a different window then the slider
1479 // if (gdk_event->window != widget->slider) return FALSE;
1481 win
->SetScrolling( TRUE
);
1486 //-----------------------------------------------------------------------------
1487 // "button_release_event" from scrollbar
1488 //-----------------------------------------------------------------------------
1490 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1491 GdkEventButton
*WXUNUSED(gdk_event
),
1495 // don't test here as we can release the mouse while being over
1496 // a different window then the slider
1498 // if (gdk_event->window != widget->slider) return FALSE;
1500 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1502 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1503 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_hAdjust
), "value_changed" );
1505 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_vAdjust
), "value_changed" );
1507 win
->SetScrolling( FALSE
);
1512 // ----------------------------------------------------------------------------
1513 // this wxWindowBase function is implemented here (in platform-specific file)
1514 // because it is static and so couldn't be made virtual
1515 // ----------------------------------------------------------------------------
1517 wxWindow
*wxWindowBase::FindFocus()
1519 return g_focusWindow
;
1522 //-----------------------------------------------------------------------------
1523 // "realize" from m_widget
1524 //-----------------------------------------------------------------------------
1526 /* we cannot set colours, fonts and cursors before the widget has
1527 been realized, so we do this directly after realization */
1530 gtk_window_realized_callback( GtkWidget
* WXUNUSED(widget
), wxWindow
*win
)
1533 wxapp_install_idle_handler();
1535 if (win
->m_delayedFont
)
1536 win
->SetFont( win
->GetFont() );
1538 if (win
->m_delayedBackgroundColour
)
1539 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1541 if (win
->m_delayedForegroundColour
)
1542 win
->SetForegroundColour( win
->GetForegroundColour() );
1544 win
->SetCursor( win
->GetCursor() );
1546 wxWindowCreateEvent
event( win
);
1547 event
.SetEventObject( win
);
1548 win
->GetEventHandler()->ProcessEvent( event
);
1553 //-----------------------------------------------------------------------------
1554 // InsertChild for wxWindow.
1555 //-----------------------------------------------------------------------------
1557 /* Callback for wxWindow. This very strange beast has to be used because
1558 * C++ has no virtual methods in a constructor. We have to emulate a
1559 * virtual function here as wxNotebook requires a different way to insert
1560 * a child in it. I had opted for creating a wxNotebookPage window class
1561 * which would have made this superfluous (such in the MDI window system),
1562 * but no-one was listening to me... */
1564 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1566 gtk_myfixed_put( GTK_MYFIXED(parent
->m_wxwindow
),
1567 GTK_WIDGET(child
->m_widget
),
1573 if (parent
->HasFlag(wxTAB_TRAVERSAL
))
1575 /* we now allow a window to get the focus as long as it
1576 doesn't have any children. */
1577 GTK_WIDGET_UNSET_FLAGS( parent
->m_wxwindow
, GTK_CAN_FOCUS
);
1581 //-----------------------------------------------------------------------------
1583 //-----------------------------------------------------------------------------
1585 wxWindow
* wxGetActiveWindow()
1587 return g_focusWindow
;
1590 //-----------------------------------------------------------------------------
1592 //-----------------------------------------------------------------------------
1594 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1596 void wxWindow::Init()
1602 m_widget
= (GtkWidget
*) NULL
;
1603 m_wxwindow
= (GtkWidget
*) NULL
;
1613 m_needParent
= TRUE
;
1614 m_isBeingDeleted
= FALSE
;
1616 m_hasScrolling
= FALSE
;
1617 m_isScrolling
= FALSE
;
1619 m_hAdjust
= (GtkAdjustment
*) NULL
;
1620 m_vAdjust
= (GtkAdjustment
*) NULL
;
1621 m_oldHorizontalPos
= 0.0;
1622 m_oldVerticalPos
= 0.0;
1625 m_scrollGC
= (GdkGC
*) NULL
;
1626 m_widgetStyle
= (GtkStyle
*) NULL
;
1628 m_insertCallback
= (wxInsertChildFunction
) NULL
;
1630 m_isStaticBox
= FALSE
;
1631 m_acceptsFocus
= FALSE
;
1634 wxWindow::wxWindow()
1639 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1640 const wxPoint
&pos
, const wxSize
&size
,
1641 long style
, const wxString
&name
)
1645 Create( parent
, id
, pos
, size
, style
, name
);
1648 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1649 const wxPoint
&pos
, const wxSize
&size
,
1650 long style
, const wxString
&name
)
1652 PreCreation( parent
, id
, pos
, size
, style
, name
);
1654 m_insertCallback
= wxInsertChildInWindow
;
1656 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1657 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1660 debug_focus_in( m_widget
, _T("wxWindow::m_widget"), name
);
1663 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1666 debug_focus_in( scrolledWindow
->hscrollbar
, _T("wxWindow::hsrcollbar"), name
);
1667 debug_focus_in( scrolledWindow
->vscrollbar
, _T("wxWindow::vsrcollbar"), name
);
1670 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1671 scroll_class
->scrollbar_spacing
= 0;
1673 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1675 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
1676 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
1678 m_wxwindow
= gtk_myfixed_new();
1681 debug_focus_in( m_wxwindow
, _T("wxWindow::m_wxwindow"), name
);
1684 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1686 #if (GTK_MINOR_VERSION > 0)
1687 GtkMyFixed
*myfixed
= GTK_MYFIXED(m_wxwindow
);
1689 if (HasFlag(wxRAISED_BORDER
))
1691 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_OUT
);
1693 else if (HasFlag(wxSUNKEN_BORDER
))
1695 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_IN
);
1699 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_NONE
);
1701 #else // GTK_MINOR_VERSION == 0
1702 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
1704 if (HasFlag(wxRAISED_BORDER
))
1706 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1708 else if (HasFlag(wxSUNKEN_BORDER
))
1710 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1714 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1716 #endif // GTK_MINOR_VERSION
1718 if (HasFlag(wxTAB_TRAVERSAL
))
1720 /* we now allow a window to get the focus as long as it
1721 doesn't have any children. */
1722 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1723 m_acceptsFocus
= FALSE
;
1727 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1728 m_acceptsFocus
= TRUE
;
1731 #if (GTK_MINOR_VERSION == 0)
1732 // shut the viewport up
1733 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1734 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1735 #endif // GTK_MINOR_VERSION == 0
1737 // I _really_ don't want scrollbars in the beginning
1738 m_vAdjust
->lower
= 0.0;
1739 m_vAdjust
->upper
= 1.0;
1740 m_vAdjust
->value
= 0.0;
1741 m_vAdjust
->step_increment
= 1.0;
1742 m_vAdjust
->page_increment
= 1.0;
1743 m_vAdjust
->page_size
= 5.0;
1744 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1745 m_hAdjust
->lower
= 0.0;
1746 m_hAdjust
->upper
= 1.0;
1747 m_hAdjust
->value
= 0.0;
1748 m_hAdjust
->step_increment
= 1.0;
1749 m_hAdjust
->page_increment
= 1.0;
1750 m_hAdjust
->page_size
= 5.0;
1751 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1753 // these handlers block mouse events to any window during scrolling such as
1754 // motion events and prevent GTK and wxWindows from fighting over where the
1757 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
1758 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1760 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
1761 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1763 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
1764 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1766 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
1767 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1769 // these handlers get notified when screen updates are required either when
1770 // scrolling or when the window size (and therefore scrollbar configuration)
1773 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
1774 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
1775 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
1776 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
1778 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
1779 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
1780 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
1781 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
1783 gtk_widget_show( m_wxwindow
);
1786 m_parent
->DoAddChild( this );
1795 wxWindow::~wxWindow()
1797 m_isBeingDeleted
= TRUE
;
1806 m_parent
->RemoveChild( this );
1810 gtk_style_unref( m_widgetStyle
);
1811 m_widgetStyle
= (GtkStyle
*) NULL
;
1816 gdk_gc_unref( m_scrollGC
);
1817 m_scrollGC
= (GdkGC
*) NULL
;
1822 gtk_widget_destroy( m_wxwindow
);
1823 m_wxwindow
= (GtkWidget
*) NULL
;
1828 gtk_widget_destroy( m_widget
);
1829 m_widget
= (GtkWidget
*) NULL
;
1833 void wxWindow::PreCreation( wxWindow
*parent
,
1838 const wxString
&name
)
1840 wxASSERT_MSG( !m_needParent
|| parent
, _T("Need complete parent.") );
1842 if ( !CreateBase(parent
, id
, pos
, size
, style
, name
) )
1844 wxFAIL_MSG(_T("window creation failed"));
1847 m_width
= WidthDefault(size
.x
);
1848 m_height
= HeightDefault(size
.y
);
1853 if (!parent
) /* some reasonable defaults */
1857 m_x
= (gdk_screen_width () - m_width
) / 2;
1858 if (m_x
< 10) m_x
= 10;
1862 m_y
= (gdk_screen_height () - m_height
) / 2;
1863 if (m_y
< 10) m_y
= 10;
1868 void wxWindow::PostCreation()
1870 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1874 /* these get reported to wxWindows -> wxPaintEvent */
1875 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1876 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1878 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1879 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1881 #if (GTK_MINOR_VERSION > 0)
1882 /* these are called when the "sunken" or "raised" borders are drawn */
1883 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
1884 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
1886 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
1887 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
1891 GtkWidget
*connect_widget
= GetConnectWidget();
1893 ConnectWidget( connect_widget
);
1895 /* we cannot set colours, fonts and cursors before the widget has
1896 been realized, so we do this directly after realization */
1897 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
1898 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
1903 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1905 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1906 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1908 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
1909 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
1911 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1912 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1914 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1915 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1917 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1918 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1920 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1921 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1923 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1924 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1926 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1927 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1929 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1930 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1933 bool wxWindow::Destroy()
1935 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1939 return wxWindowBase::Destroy();
1942 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1944 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1945 wxASSERT_MSG( (m_parent
!= NULL
), _T("wxWindow::SetSize requires parent.\n") );
1947 if (m_resizing
) return; /* I don't like recursions */
1950 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
1952 /* don't set the size for children of wxNotebook, just take the values. */
1960 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1962 if (x
!= -1) m_x
= x
;
1963 if (y
!= -1) m_y
= y
;
1964 if (width
!= -1) m_width
= width
;
1965 if (height
!= -1) m_height
= height
;
1975 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1977 if (width
== -1) m_width
= 80;
1980 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1982 if (height
== -1) m_height
= 26;
1985 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1986 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1987 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
1988 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
1991 int bottom_border
= 0;
1993 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
1995 /* the default button has a border around it */
2000 /* this is the result of hours of debugging: the following code
2001 means that if we have a m_wxwindow and we set the size of
2002 m_widget, m_widget (which is a GtkScrolledWindow) does NOT
2003 automatically propagate its size down to its m_wxwindow,
2004 which is its client area. therefore, we have to tell the
2005 client area directly that it has to resize itself.
2006 this will lead to that m_widget (GtkScrolledWindow) will
2007 calculate how much size it needs for scrollbars etc and
2008 it will then call XXX_size_allocate of its child, which
2009 is m_wxwindow. m_wxwindow in turn will do the same with its
2010 children and so on. problems can arise if this happens
2011 before all the children have been realized as some widgets
2012 stupidy need to be realized during XXX_size_allocate (e.g.
2013 GtkNotebook) and they will segv if called otherwise. this
2014 emergency is tested in gtk_myfixed_size_allocate. Normally
2015 this shouldn't be needed and only gtk_widget_queue_resize()
2016 should be enough to provoke a resize at the next appropriate
2017 moment, but this seems to fail, e.g. when a wxNotebook contains
2018 a wxSplitterWindow: the splitter window's children won't
2019 show up properly resized then. */
2021 gtk_myfixed_set_size( GTK_MYFIXED(m_parent
->m_wxwindow
),
2026 m_height
+border
+bottom_border
);
2031 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2032 event
.SetEventObject( this );
2033 GetEventHandler()->ProcessEvent( event
);
2038 void wxWindow::OnInternalIdle()
2040 GdkWindow
*window
= GetConnectWidget()->window
;
2043 wxCursor cursor
= m_cursor
;
2044 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2046 if (m_currentGdkCursor
!= cursor
)
2048 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2049 m_currentGdkCursor
= cursor
;
2056 void wxWindow::DoGetSize( int *width
, int *height
) const
2058 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2060 if (width
) (*width
) = m_width
;
2061 if (height
) (*height
) = m_height
;
2064 void wxWindow::DoSetClientSize( int width
, int height
)
2066 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2070 SetSize( width
, height
);
2077 if (!m_hasScrolling
)
2079 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
2081 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2083 dw
+= 2 * window_class
->xthickness
;
2084 dh
+= 2 * window_class
->ythickness
;
2089 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2090 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2092 #if (GTK_MINOR_VERSION == 0)
2093 GtkWidget
*viewport
= scroll_window
->viewport
;
2094 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2096 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2098 dw
+= 2 * viewport_class
->xthickness
;
2099 dh
+= 2 * viewport_class
->ythickness
;
2104 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2105 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2107 we use this instead: range.slider_width = 11 + 2*2pts edge
2110 if (scroll_window
->vscrollbar_visible
)
2112 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2113 dw
+= scroll_class
->scrollbar_spacing
;
2116 if (scroll_window
->hscrollbar_visible
)
2118 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2119 dh
+= scroll_class
->scrollbar_spacing
;
2123 SetSize( width
+dw
, height
+dh
);
2127 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2129 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2133 if (width
) (*width
) = m_width
;
2134 if (height
) (*height
) = m_height
;
2141 if (!m_hasScrolling
)
2143 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
2145 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2147 dw
+= 2 * window_class
->xthickness
;
2148 dh
+= 2 * window_class
->ythickness
;
2153 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2154 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2156 #if (GTK_MINOR_VERSION == 0)
2157 GtkWidget
*viewport
= scroll_window
->viewport
;
2158 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2160 if ( HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
) )
2162 dw
+= 2 * viewport_class
->xthickness
;
2163 dh
+= 2 * viewport_class
->ythickness
;
2167 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2168 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2170 we use this instead: range.slider_width = 11 + 2*2pts edge
2173 if (scroll_window
->vscrollbar_visible
)
2175 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2176 dw
+= scroll_class
->scrollbar_spacing
;
2179 if (scroll_window
->hscrollbar_visible
)
2181 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2182 dh
+= scroll_class
->scrollbar_spacing
;
2186 if (width
) (*width
) = m_width
- dw
;
2187 if (height
) (*height
) = m_height
- dh
;
2191 void wxWindow::DoGetPosition( int *x
, int *y
) const
2193 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2199 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2201 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2203 if (!m_widget
->window
) return;
2205 GdkWindow
*source
= (GdkWindow
*) NULL
;
2207 source
= m_wxwindow
->window
;
2209 source
= m_widget
->window
;
2213 gdk_window_get_origin( source
, &org_x
, &org_y
);
2217 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2219 org_x
+= m_widget
->allocation
.x
;
2220 org_y
+= m_widget
->allocation
.y
;
2228 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2230 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2232 if (!m_widget
->window
) return;
2234 GdkWindow
*source
= (GdkWindow
*) NULL
;
2236 source
= m_wxwindow
->window
;
2238 source
= m_widget
->window
;
2242 gdk_window_get_origin( source
, &org_x
, &org_y
);
2246 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2248 org_x
+= m_widget
->allocation
.x
;
2249 org_y
+= m_widget
->allocation
.y
;
2257 bool wxWindow::Show( bool show
)
2259 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2261 if (!wxWindowBase::Show(show
))
2268 gtk_widget_show( m_widget
);
2270 gtk_widget_hide( m_widget
);
2275 bool wxWindow::Enable( bool enable
)
2277 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2279 if (!wxWindowBase::Enable(enable
))
2285 gtk_widget_set_sensitive( m_widget
, enable
);
2287 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2292 int wxWindow::GetCharHeight() const
2294 wxCHECK_MSG( (m_widget
!= NULL
), 12, _T("invalid window") );
2296 wxCHECK_MSG( m_font
.Ok(), 12, _T("invalid font") );
2298 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2300 return font
->ascent
+ font
->descent
;
2303 int wxWindow::GetCharWidth() const
2305 wxCHECK_MSG( (m_widget
!= NULL
), 8, _T("invalid window") );
2307 wxCHECK_MSG( m_font
.Ok(), 8, _T("invalid font") );
2309 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2311 return gdk_string_width( font
, "H" );
2314 void wxWindow::GetTextExtent( const wxString
& string
,
2318 int *externalLeading
,
2319 const wxFont
*theFont
) const
2321 wxFont fontToUse
= m_font
;
2322 if (theFont
) fontToUse
= *theFont
;
2324 wxCHECK_RET( fontToUse
.Ok(), _T("invalid font") );
2326 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2327 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2328 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2329 if (descent
) (*descent
) = font
->descent
;
2330 if (externalLeading
) (*externalLeading
) = 0; // ??
2333 void wxWindow::SetFocus()
2335 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2337 GtkWidget
*connect_widget
= GetConnectWidget();
2340 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2342 gtk_widget_grab_focus (connect_widget
);
2344 else if (GTK_IS_CONTAINER(connect_widget
))
2346 gtk_container_focus( GTK_CONTAINER(connect_widget
), GTK_DIR_TAB_FORWARD
);
2354 bool wxWindow::AcceptsFocus() const
2356 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2359 bool wxWindow::Reparent( wxWindow
*newParent
)
2361 wxCHECK_MSG( (m_widget
!= NULL
), (wxWindow
*) NULL
, _T("invalid window") );
2363 gtk_widget_unparent( m_widget
);
2365 if ( !wxWindowBase::Reparent(newParent
) )
2371 void wxWindow::DoAddChild(wxWindow
*child
)
2373 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
2375 wxASSERT_MSG( (child
!= NULL
), _T("invalid child window") );
2377 wxASSERT_MSG( (m_insertCallback
!= NULL
), _T("invalid child insertion function") );
2382 /* insert GTK representation */
2383 (*m_insertCallback
)(this, child
);
2386 void wxWindow::Raise()
2388 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2390 if (!m_widget
->window
) return;
2392 gdk_window_raise( m_widget
->window
);
2395 void wxWindow::Lower()
2397 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2399 if (!m_widget
->window
) return;
2401 gdk_window_lower( m_widget
->window
);
2404 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2406 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2408 if (!wxWindowBase::SetCursor(cursor
))
2410 // don't leave if the GTK widget has just
2412 if (!m_delayedCursor
) return FALSE
;
2415 GtkWidget
*connect_widget
= GetConnectWidget();
2416 if (!connect_widget
->window
)
2418 // indicate that a new style has been set
2419 // but it couldn't get applied as the
2420 // widget hasn't been realized yet.
2421 m_delayedCursor
= TRUE
;
2423 // pretend we have done something
2427 // gdk_window_set_cursor( connect_widget->window, GetCursor().GetCursor() );
2433 void wxWindow::WarpPointer( int WXUNUSED(x
), int WXUNUSED(y
) )
2438 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2440 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2442 if (!m_widget
->window
) return;
2444 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2448 gdk_window_clear_area( m_wxwindow
->window
,
2450 rect
->width
, rect
->height
);
2454 gdk_window_clear( m_wxwindow
->window
);
2461 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2463 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2467 GdkRectangle gdk_rect
;
2468 gdk_rect
.x
= rect
->x
;
2469 gdk_rect
.y
= rect
->y
;
2470 gdk_rect
.width
= rect
->width
;
2471 gdk_rect
.height
= rect
->height
;
2474 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2476 gtk_widget_draw( m_widget
, &gdk_rect
);
2480 void wxWindow::Clear()
2482 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2484 if (!m_widget
->window
) return;
2486 if (m_wxwindow
&& m_wxwindow
->window
)
2488 gdk_window_clear( m_wxwindow
->window
);
2493 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2495 wxWindowBase::DoSetToolTip(tip
);
2498 m_tooltip
->Apply( this );
2501 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2503 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConv_current
->cWX2MB(tip
), (gchar
*) NULL
);
2505 #endif // wxUSE_TOOLTIPS
2507 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2509 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2511 if (!wxWindowBase::SetBackgroundColour(colour
))
2513 // don't leave if the GTK widget has just
2515 if (!m_delayedBackgroundColour
) return FALSE
;
2518 GtkWidget
*connect_widget
= GetConnectWidget();
2519 if (!connect_widget
->window
)
2521 // indicate that a new style has been set
2522 // but it couldn't get applied as the
2523 // widget hasn't been realized yet.
2524 m_delayedBackgroundColour
= TRUE
;
2526 // pretend we have done something
2530 if (m_wxwindow
&& m_wxwindow
->window
)
2532 /* wxMSW doesn't clear the window here. I don't do that either to
2533 provide compatibility. call Clear() to do the job. */
2535 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_wxwindow
->window
) );
2536 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
2539 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2541 if (sysbg
== m_backgroundColour
)
2543 m_backgroundColour
= wxNullColour
;
2545 m_backgroundColour
= sysbg
;
2555 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2557 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2559 if (!wxWindowBase::SetForegroundColour(colour
))
2561 // don't leave if the GTK widget has just
2563 if (!m_delayedForegroundColour
) return FALSE
;
2566 GtkWidget
*connect_widget
= GetConnectWidget();
2567 if (!connect_widget
->window
)
2569 // indicate that a new style has been set
2570 // but it couldn't get applied as the
2571 // widget hasn't been realized yet.
2572 m_delayedForegroundColour
= TRUE
;
2574 // pretend we have done something
2578 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2579 if (sysbg
== m_foregroundColour
)
2581 m_backgroundColour
= wxNullColour
;
2583 m_backgroundColour
= sysbg
;
2593 GtkStyle
*wxWindow::GetWidgetStyle()
2595 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2597 m_widgetStyle
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2599 return m_widgetStyle
;
2602 void wxWindow::SetWidgetStyle()
2604 GtkStyle
*style
= GetWidgetStyle();
2606 gdk_font_unref( style
->font
);
2607 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2609 if (m_foregroundColour
.Ok())
2611 m_foregroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2612 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2613 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2614 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2617 if (m_backgroundColour
.Ok())
2619 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2620 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2621 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2622 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2623 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2624 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2625 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2626 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2627 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2631 void wxWindow::ApplyWidgetStyle()
2635 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2637 menu
->SetInvokingWindow( win
);
2638 wxNode
*node
= menu
->GetItems().First();
2641 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2642 if (menuitem
->IsSubMenu())
2644 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2646 node
= node
->Next();
2650 static gint gs_pop_x
= 0;
2651 static gint gs_pop_y
= 0;
2653 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
2657 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
2662 bool wxWindow::PopupMenu( wxMenu
*menu
, int x
, int y
)
2664 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2666 wxCHECK_MSG( menu
!= NULL
, FALSE
, _T("invalid popup-menu") );
2668 SetInvokingWindow( menu
, this );
2676 GTK_MENU(menu
->m_menu
),
2677 (GtkWidget
*) NULL
, // parent menu shell
2678 (GtkWidget
*) NULL
, // parent menu item
2679 (GtkMenuPositionFunc
) pop_pos_callback
,
2680 (gpointer
) this, // client data
2681 0, // button used to activate it
2682 0 //gs_timeLastClick // the time of activation
2687 #if wxUSE_DRAG_AND_DROP
2689 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2691 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2693 GtkWidget
*dnd_widget
= GetConnectWidget();
2695 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
2697 if (m_dropTarget
) delete m_dropTarget
;
2698 m_dropTarget
= dropTarget
;
2700 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
2703 #endif // wxUSE_DRAG_AND_DROP
2705 GtkWidget
* wxWindow::GetConnectWidget()
2707 GtkWidget
*connect_widget
= m_widget
;
2708 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2710 return connect_widget
;
2713 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2715 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2716 return (window
== m_widget
->window
);
2719 bool wxWindow::SetFont( const wxFont
&font
)
2721 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T( "invalid window") );
2723 if (!wxWindowBase::SetFont(font
))
2725 // don't leave if the GTK widget has just
2727 if (!m_delayedFont
) return FALSE
;
2730 GtkWidget
*connect_widget
= GetConnectWidget();
2731 if (!connect_widget
->window
)
2733 // indicate that a new style has been set
2734 // but it couldn't get applied as the
2735 // widget hasn't been realized yet.
2736 m_delayedFont
= TRUE
;
2738 // pretend we have done something
2742 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2743 if ( sysbg
== m_backgroundColour
)
2745 m_backgroundColour
= wxNullColour
;
2747 m_backgroundColour
= sysbg
;
2757 void wxWindow::CaptureMouse()
2759 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2761 wxCHECK_RET( g_capturing
== FALSE
, _T("CaptureMouse called twice") );
2763 GtkWidget
*connect_widget
= GetConnectWidget();
2764 if (!connect_widget
->window
) return;
2766 gtk_grab_add( connect_widget
);
2767 gdk_pointer_grab( connect_widget
->window
, FALSE
,
2769 (GDK_BUTTON_PRESS_MASK
|
2770 GDK_BUTTON_RELEASE_MASK
|
2771 GDK_POINTER_MOTION_MASK
),
2778 void wxWindow::ReleaseMouse()
2780 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2782 wxCHECK_RET( g_capturing
== TRUE
, _T("ReleaseMouse called twice") );
2784 GtkWidget
*connect_widget
= GetConnectWidget();
2785 if (!connect_widget
->window
) return;
2787 gtk_grab_remove( connect_widget
);
2788 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2789 g_capturing
= FALSE
;
2792 bool wxWindow::IsRetained() const
2797 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2798 int range
, bool refresh
)
2800 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2802 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2804 m_hasScrolling
= TRUE
;
2806 if (orient
== wxHORIZONTAL
)
2808 float fpos
= (float)pos
;
2809 float frange
= (float)range
;
2810 float fthumb
= (float)thumbVisible
;
2811 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2812 if (fpos
< 0.0) fpos
= 0.0;
2814 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2815 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2817 SetScrollPos( orient
, pos
, refresh
);
2821 m_oldHorizontalPos
= fpos
;
2823 m_hAdjust
->lower
= 0.0;
2824 m_hAdjust
->upper
= frange
;
2825 m_hAdjust
->value
= fpos
;
2826 m_hAdjust
->step_increment
= 1.0;
2827 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2828 m_hAdjust
->page_size
= fthumb
;
2832 float fpos
= (float)pos
;
2833 float frange
= (float)range
;
2834 float fthumb
= (float)thumbVisible
;
2835 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2836 if (fpos
< 0.0) fpos
= 0.0;
2838 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2839 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2841 SetScrollPos( orient
, pos
, refresh
);
2845 m_oldVerticalPos
= fpos
;
2847 m_vAdjust
->lower
= 0.0;
2848 m_vAdjust
->upper
= frange
;
2849 m_vAdjust
->value
= fpos
;
2850 m_vAdjust
->step_increment
= 1.0;
2851 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2852 m_vAdjust
->page_size
= fthumb
;
2855 if (orient
== wxHORIZONTAL
)
2856 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2858 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2861 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2863 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2865 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2867 if (orient
== wxHORIZONTAL
)
2869 float fpos
= (float)pos
;
2870 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
2871 if (fpos
< 0.0) fpos
= 0.0;
2872 m_oldHorizontalPos
= fpos
;
2874 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2875 m_hAdjust
->value
= fpos
;
2879 float fpos
= (float)pos
;
2880 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
2881 if (fpos
< 0.0) fpos
= 0.0;
2882 m_oldVerticalPos
= fpos
;
2884 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2885 m_vAdjust
->value
= fpos
;
2888 if (!m_isScrolling
) /* prevent recursion */
2890 if (m_wxwindow
->window
)
2892 if (orient
== wxHORIZONTAL
)
2893 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2895 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2900 int wxWindow::GetScrollThumb( int orient
) const
2902 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2904 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2906 if (orient
== wxHORIZONTAL
)
2907 return (int)(m_hAdjust
->page_size
+0.5);
2909 return (int)(m_vAdjust
->page_size
+0.5);
2912 int wxWindow::GetScrollPos( int orient
) const
2914 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2916 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2918 if (orient
== wxHORIZONTAL
)
2919 return (int)(m_hAdjust
->value
+0.5);
2921 return (int)(m_vAdjust
->value
+0.5);
2924 int wxWindow::GetScrollRange( int orient
) const
2926 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2928 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2930 if (orient
== wxHORIZONTAL
)
2931 return (int)(m_hAdjust
->upper
+0.5);
2933 return (int)(m_vAdjust
->upper
+0.5);
2936 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2938 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2940 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2944 m_scrollGC
= gdk_gc_new( m_wxwindow
->window
);
2945 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
2948 wxNode
*node
= m_children
.First();
2951 wxWindow
*child
= (wxWindow
*) node
->Data();
2952 child
->Move( child
->m_x
+ dx
, child
->m_y
+ dy
);
2953 node
= node
->Next();
2958 GetClientSize( &cw
, &ch
);
2959 int w
= cw
- abs(dx
);
2960 int h
= ch
- abs(dy
);
2962 if ((h
< 0) || (w
< 0))
2970 if (dx
< 0) s_x
= -dx
;
2971 if (dy
< 0) s_y
= -dy
;
2974 if (dx
> 0) d_x
= dx
;
2975 if (dy
> 0) d_y
= dy
;
2977 gdk_window_copy_area( m_wxwindow
->window
, m_scrollGC
, d_x
, d_y
,
2978 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2981 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2982 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2983 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2984 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2986 Refresh( TRUE
, &rect
);
2990 void wxWindow::SetScrolling(bool scroll
)
2992 m_isScrolling
= g_blockEventsOnScroll
= scroll
;