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"
49 //-----------------------------------------------------------------------------
50 // documentation on internals
51 //-----------------------------------------------------------------------------
54 I have been asked several times about writing some documentation about
55 the GTK port of wxWindows, especially its internal structures. Obviously,
56 you cannot understand wxGTK without knowing a little about the GTK, but
57 some more information about what the wxWindow, which is the base class
58 for all other window classes, does seems required as well.
60 What does wxWindow do? It contains the common interface for the following
61 jobs of its descendants:
63 1) Define the rudimentary behaviour common to all window classes, such as
64 resizing, intercepting user input (so as to make it possible to use these
65 events for special purposes in a derived class), window names etc.
67 2) Provide the possibility to contain and manage children, if the derived
68 class is allowed to contain children, which holds true for those window
69 classes which do not display a native GTK widget. To name them, these
70 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
71 work classes are a special case and are handled a bit differently from
72 the rest. The same holds true for the wxNotebook class.
74 3) Provide the possibility to draw into a client area of a window. This,
75 too, only holds true for classes that do not display a native GTK widget
78 4) Provide the entire mechanism for scrolling widgets. This actual inter-
79 face for this is usually in wxScrolledWindow, but the GTK implementation
82 5) A multitude of helper or extra methods for special purposes, such as
83 Drag'n'Drop, managing validators etc.
85 Normally one might expect, that one wxWindows window would always correspond
86 to one GTK widget. Under GTK, there is no such allround widget that has all
87 the functionality. Moreover, the GTK defines a client area as a different
88 widget from the actual widget you are handling. Last but not least some
89 special classes (e.g. wxFrame) handle different categories of widgets and
90 still have the possibility to draw something in the client area.
91 It was therefore required to write a special purpose GTK widget, that would
92 represent a client area in the sense of wxWindows capable to do the jobs
93 2), 3) and 4). I have written this class and it resides in win_gtk.c of
96 All windows must have a widget, with which they interact with other under-
97 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
98 thw wxWindow class has a member variable called m_widget which holds a
99 pointer to this widget. When the window class represents a GTK native widget,
100 this is (in most cases) the only GTK widget the class manages. E.g. the
101 wxStatitText class handles only a GtkLabel widget a pointer to which you
102 can find in m_widget (defined in wxWindow)
104 When the class has a client area for drawing into and for containing children
105 it has to handle the client area widget (of the type GtkMyFixed, defined in
106 win_gtk.c), but there could be any number of widgets, handled by a class
107 The common rule for all windows is only, that the widget that interacts with
108 the rest of GTK must be referenced in m_widget and all other widgets must be
109 children of this widget on the GTK level. The top-most widget, which also
110 represents the client area, must be in the m_wxwindow field and must be of
113 As I said, the window classes that display a GTK native widget only have
114 one widget, so in the case of e.g. the wxButton class m_widget holds a
115 pointer to a GtkButton widget. But windows with client areas (for drawing
116 and children) have a m_widget field that is a pointer to a GtkScrolled-
117 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
118 one is (in the GTK sense) a child of the GtkScrolledWindow.
120 If the m_wxwindow field is set, then all input to this widget is inter-
121 cepted and sent to the wxWindows class. If not, all input to the widget
122 that gets pointed to by m_widget gets intercepted and sent to the class.
126 //-----------------------------------------------------------------------------
128 //-----------------------------------------------------------------------------
130 extern wxList wxPendingDelete
;
131 extern bool g_blockEventsOnDrag
;
132 extern bool g_blockEventsOnScroll
;
133 extern wxCursor g_globalCursor
;
134 static wxWindow
*g_captureWindow
= (wxWindow
*) NULL
;
135 static wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
137 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
138 the last click here */
139 static guint32 gs_timeLastClick
= 0;
141 //-----------------------------------------------------------------------------
143 //-----------------------------------------------------------------------------
147 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
148 GdkEvent
*WXUNUSED(event
),
152 static bool s_done = FALSE;
155 wxLog::AddTraceMask("focus");
158 wxLogTrace(_T("FOCUS NOW AT: %s"), name);
164 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
170 wxChar
*s
= new wxChar
[tmp
.Length()+1];
174 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
175 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
180 //-----------------------------------------------------------------------------
181 // missing gdk functions
182 //-----------------------------------------------------------------------------
185 gdk_window_warp_pointer (GdkWindow
*window
,
189 GdkWindowPrivate
*priv
;
192 window
= (GdkWindow
*) &gdk_root_parent
;
194 priv
= (GdkWindowPrivate
*) window
;
196 if (!priv
->destroyed
)
198 XWarpPointer (priv
->xdisplay
,
199 None
, /* not source window -> move from anywhere */
200 priv
->xwindow
, /* dest window */
201 0, 0, 0, 0, /* not source window -> move from anywhere */
206 //-----------------------------------------------------------------------------
208 //-----------------------------------------------------------------------------
210 extern void wxapp_install_idle_handler();
211 extern bool g_isIdle
;
213 //-----------------------------------------------------------------------------
214 // key event conversion routines
215 //-----------------------------------------------------------------------------
217 #if (GTK_MINOR_VERSION == 0)
219 gdk_keyval_to_upper (guint keyval
)
223 KeySym lower_val
= 0;
224 KeySym upper_val
= 0;
226 XConvertCase (keyval
, &lower_val
, &upper_val
);
233 static long map_to_unmodified_wx_keysym( KeySym keysym
)
240 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
242 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
248 case GDK_Super_R
: key_code
= WXK_ALT
; break;
249 case GDK_Menu
: key_code
= WXK_MENU
; break;
250 case GDK_Help
: key_code
= WXK_HELP
; break;
251 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
252 case GDK_ISO_Left_Tab
:
253 case GDK_Tab
: key_code
= WXK_TAB
; break;
254 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
255 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
256 case GDK_Return
: key_code
= WXK_RETURN
; break;
257 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
258 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
259 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
260 case GDK_Delete
: key_code
= WXK_DELETE
; break;
261 case GDK_Home
: key_code
= WXK_HOME
; break;
262 case GDK_Left
: key_code
= WXK_LEFT
; break;
263 case GDK_Up
: key_code
= WXK_UP
; break;
264 case GDK_Right
: key_code
= WXK_RIGHT
; break;
265 case GDK_Down
: key_code
= WXK_DOWN
; break;
266 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
267 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
268 case GDK_Next
: key_code
= WXK_NEXT
; break;
269 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
270 case GDK_End
: key_code
= WXK_END
; break;
271 case GDK_Begin
: key_code
= WXK_HOME
; break;
272 case GDK_Select
: key_code
= WXK_SELECT
; break;
273 case GDK_Print
: key_code
= WXK_PRINT
; break;
274 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
275 case GDK_Insert
: key_code
= WXK_INSERT
; break;
276 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
278 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
279 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
280 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
281 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
282 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
283 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
284 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
285 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
286 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
287 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
288 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
289 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
290 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
291 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
292 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
293 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
294 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
295 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
296 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
297 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
298 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
299 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
300 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
301 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
302 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
303 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
304 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
305 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
306 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
307 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
308 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
309 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
310 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
311 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
312 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
313 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
314 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
316 case GDK_F1
: key_code
= WXK_F1
; break;
317 case GDK_F2
: key_code
= WXK_F2
; break;
318 case GDK_F3
: key_code
= WXK_F3
; break;
319 case GDK_F4
: key_code
= WXK_F4
; break;
320 case GDK_F5
: key_code
= WXK_F5
; break;
321 case GDK_F6
: key_code
= WXK_F6
; break;
322 case GDK_F7
: key_code
= WXK_F7
; break;
323 case GDK_F8
: key_code
= WXK_F8
; break;
324 case GDK_F9
: key_code
= WXK_F9
; break;
325 case GDK_F10
: key_code
= WXK_F10
; break;
326 case GDK_F11
: key_code
= WXK_F11
; break;
327 case GDK_F12
: key_code
= WXK_F12
; break;
332 guint upper
= gdk_keyval_to_upper( keysym
);
333 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
342 static long map_to_wx_keysym( KeySym keysym
)
348 case GDK_Menu
: key_code
= WXK_MENU
; break;
349 case GDK_Help
: key_code
= WXK_HELP
; break;
350 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
351 case GDK_ISO_Left_Tab
:
352 case GDK_Tab
: key_code
= WXK_TAB
; break;
353 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
354 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
355 case GDK_Return
: key_code
= WXK_RETURN
; break;
356 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
357 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
358 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
359 case GDK_Delete
: key_code
= WXK_DELETE
; break;
360 case GDK_Home
: key_code
= WXK_HOME
; break;
361 case GDK_Left
: key_code
= WXK_LEFT
; break;
362 case GDK_Up
: key_code
= WXK_UP
; break;
363 case GDK_Right
: key_code
= WXK_RIGHT
; break;
364 case GDK_Down
: key_code
= WXK_DOWN
; break;
365 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
366 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
367 case GDK_Next
: key_code
= WXK_NEXT
; break;
368 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
369 case GDK_End
: key_code
= WXK_END
; break;
370 case GDK_Begin
: key_code
= WXK_HOME
; break;
371 case GDK_Select
: key_code
= WXK_SELECT
; break;
372 case GDK_Print
: key_code
= WXK_PRINT
; break;
373 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
374 case GDK_Insert
: key_code
= WXK_INSERT
; break;
375 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
377 case GDK_KP_0
: key_code
= '0'; break;
378 case GDK_KP_1
: key_code
= '1'; break;
379 case GDK_KP_2
: key_code
= '2'; break;
380 case GDK_KP_3
: key_code
= '3'; break;
381 case GDK_KP_4
: key_code
= '4'; break;
382 case GDK_KP_5
: key_code
= '5'; break;
383 case GDK_KP_6
: key_code
= '6'; break;
384 case GDK_KP_7
: key_code
= '7'; break;
385 case GDK_KP_8
: key_code
= '8'; break;
386 case GDK_KP_9
: key_code
= '9'; break;
387 case GDK_KP_Space
: key_code
= ' '; break;
388 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
389 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
390 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
391 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
392 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
393 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
394 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
395 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
396 case GDK_KP_Up
: key_code
= WXK_UP
; break;
397 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
398 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
399 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
400 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
401 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
402 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
403 case GDK_KP_End
: key_code
= WXK_END
; break;
404 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
405 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
406 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
407 case GDK_KP_Equal
: key_code
= '='; break;
408 case GDK_KP_Multiply
: key_code
= '*'; break;
409 case GDK_KP_Add
: key_code
= '+'; break;
410 case GDK_KP_Separator
: key_code
= ','; break;
411 case GDK_KP_Subtract
: key_code
= '-'; break;
412 case GDK_KP_Decimal
: key_code
= '.'; break;
413 case GDK_KP_Divide
: key_code
= '/'; break;
415 case GDK_F1
: key_code
= WXK_F1
; break;
416 case GDK_F2
: key_code
= WXK_F2
; break;
417 case GDK_F3
: key_code
= WXK_F3
; break;
418 case GDK_F4
: key_code
= WXK_F4
; break;
419 case GDK_F5
: key_code
= WXK_F5
; break;
420 case GDK_F6
: key_code
= WXK_F6
; break;
421 case GDK_F7
: key_code
= WXK_F7
; break;
422 case GDK_F8
: key_code
= WXK_F8
; break;
423 case GDK_F9
: key_code
= WXK_F9
; break;
424 case GDK_F10
: key_code
= WXK_F10
; break;
425 case GDK_F11
: key_code
= WXK_F11
; break;
426 case GDK_F12
: key_code
= WXK_F12
; break;
439 //-----------------------------------------------------------------------------
440 // local code (see below)
441 //-----------------------------------------------------------------------------
443 #if (GTK_MINOR_VERSION > 0)
445 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
453 if (win
->HasScrolling())
455 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
456 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
459 GtkWidget *hscrollbar = scroll_window->hscrollbar;
460 GtkWidget *vscrollbar = scroll_window->vscrollbar;
462 we use this instead: range.slider_width = 11 + 2*2pts edge
465 if (scroll_window
->vscrollbar_visible
)
467 dw
+= 15; /* dw += vscrollbar->allocation.width; */
468 dw
+= scroll_class
->scrollbar_spacing
;
471 if (scroll_window
->hscrollbar_visible
)
473 dh
+= 15; /* dh += hscrollbar->allocation.height; */
474 dh
+= scroll_class
->scrollbar_spacing
;
480 if (GTK_WIDGET_NO_WINDOW (widget
))
482 dx
+= widget
->allocation
.x
;
483 dy
+= widget
->allocation
.y
;
486 if (win
->HasFlag(wxRAISED_BORDER
))
488 gtk_draw_shadow( widget
->style
,
493 win
->m_width
-dw
, win
->m_height
-dh
);
497 if (win
->HasFlag(wxSUNKEN_BORDER
))
499 gtk_draw_shadow( widget
->style
,
504 win
->m_width
-dw
, win
->m_height
-dh
);
509 //-----------------------------------------------------------------------------
510 // "expose_event" of m_widget
511 //-----------------------------------------------------------------------------
513 static void gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
515 if (gdk_event
->count
> 0) return;
516 draw_frame( widget
, win
);
519 //-----------------------------------------------------------------------------
520 // "draw" of m_wxwindow
521 //-----------------------------------------------------------------------------
523 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
525 draw_frame( widget
, win
);
528 #endif // GTK_MINOR_VERSION > 0
530 //-----------------------------------------------------------------------------
531 // "expose_event" of m_wxwindow
532 //-----------------------------------------------------------------------------
534 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
536 if ( !win
->m_hasVMT
)
539 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
541 gdk_event
->area
.width
,
542 gdk_event
->area
.height
);
544 if ( gdk_event
->count
> 0 )
548 printf( "OnExpose from " );
549 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
550 printf( win->GetClassInfo()->GetClassName() );
554 wxPaintEvent
event( win
->GetId() );
555 event
.SetEventObject( win
);
556 win
->GetEventHandler()->ProcessEvent( event
);
558 win
->GetUpdateRegion().Clear();
561 //-----------------------------------------------------------------------------
562 // "draw" of m_wxwindow
563 //-----------------------------------------------------------------------------
565 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
568 wxapp_install_idle_handler();
573 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
574 rect
->width
, rect
->height
);
576 wxPaintEvent
event( win
->GetId() );
577 event
.SetEventObject( win
);
578 win
->GetEventHandler()->ProcessEvent( event
);
580 win
->GetUpdateRegion().Clear();
583 //-----------------------------------------------------------------------------
584 // "key_press_event" from any window
585 //-----------------------------------------------------------------------------
587 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
590 wxapp_install_idle_handler();
592 if (!win
->m_hasVMT
) return FALSE
;
593 if (g_blockEventsOnDrag
) return FALSE
;
596 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
597 if (gdk_event->state & GDK_SHIFT_MASK)
598 printf( "ShiftDown.\n" );
600 printf( "ShiftUp.\n" );
601 if (gdk_event->state & GDK_CONTROL_MASK)
602 printf( "ControlDown.\n" );
604 printf( "ControlUp.\n" );
609 GdkModifierType state
;
610 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
612 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
614 /* sending unknown key events doesn't really make sense */
615 if (key_code
== 0) return FALSE
;
619 wxKeyEvent
event( wxEVT_KEY_DOWN
);
620 event
.SetTimestamp( gdk_event
->time
);
621 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
622 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
623 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
624 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
625 event
.m_keyCode
= key_code
;
626 event
.m_scanCode
= gdk_event
->keyval
;
629 event
.SetEventObject( win
);
630 ret
= win
->GetEventHandler()->ProcessEvent( event
);
632 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
637 wxWindow
*ancestor
= win
;
640 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
643 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
644 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
647 ancestor
= ancestor
->GetParent();
650 #endif // wxUSE_ACCEL
651 /* wxMSW doesn't send char events with Alt pressed */
652 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
653 will only be sent if it is not a menu accelerator. */
654 if ((key_code
!= 0) && ! ret
)
656 wxKeyEvent
event2( wxEVT_CHAR
);
657 event2
.SetTimestamp( gdk_event
->time
);
658 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
659 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
660 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
661 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
662 event2
.m_keyCode
= key_code
;
663 event2
.m_scanCode
= gdk_event
->keyval
;
666 event2
.SetEventObject( win
);
667 ret
= (ret
|| win
->GetEventHandler()->ProcessEvent( event2
));
671 /* win is a control: tab can be propagated up */
673 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
674 (win
->HasFlag(wxTE_PROCESS_TAB
) == 0))
676 wxNavigationKeyEvent new_event
;
677 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
678 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
679 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
680 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
681 new_event
.SetCurrentFocus( win
);
682 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
685 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
687 (gdk_event
->keyval
== GDK_Escape
) )
689 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
690 new_event
.SetEventObject( win
);
691 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
694 #if (GTK_MINOR_VERSION > 0)
695 /* pressing F10 will activate the menu bar of the top frame */
697 (gdk_event
->keyval
== GDK_F10
) )
699 wxWindow
*ancestor
= win
;
702 if (wxIsKindOf(ancestor
,wxFrame
))
704 wxFrame
*frame
= (wxFrame
*) ancestor
;
705 wxMenuBar
*menubar
= frame
->GetMenuBar();
708 wxNode
*node
= menubar
->GetMenus().First();
711 // doesn't work correctly
712 // wxMenu *firstMenu = (wxMenu*) node->Data();
713 // gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
719 ancestor
= ancestor
->GetParent();
725 Damn, I forgot why this didn't work, but it didn't work.
727 // win is a panel: up can be propagated to the panel
728 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
729 (gdk_event->keyval == GDK_Up))
731 win->m_parent->SetFocus();
735 // win is a panel: left/right can be propagated to the panel
736 if ((!ret) && (win->m_wxwindow) &&
737 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
738 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
740 wxNavigationKeyEvent new_event;
741 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
742 new_event.SetCurrentFocus( win );
743 ret = win->GetEventHandler()->ProcessEvent( new_event );
749 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
756 //-----------------------------------------------------------------------------
757 // "key_release_event" from any window
758 //-----------------------------------------------------------------------------
760 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
763 wxapp_install_idle_handler();
765 if (!win
->m_hasVMT
) return FALSE
;
766 if (g_blockEventsOnDrag
) return FALSE
;
769 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
770 if (gdk_event->state & GDK_SHIFT_MASK)
771 printf( "ShiftDown.\n" );
773 printf( "ShiftUp.\n" );
774 if (gdk_event->state & GDK_CONTROL_MASK)
775 printf( "ControlDown.\n" );
777 printf( "ControlUp.\n" );
781 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
783 /* sending unknown key events doesn't really make sense */
784 if (key_code
== 0) return FALSE
;
788 GdkModifierType state
;
789 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
791 wxKeyEvent
event( wxEVT_KEY_UP
);
792 event
.SetTimestamp( gdk_event
->time
);
793 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
794 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
795 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
796 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
797 event
.m_keyCode
= key_code
;
798 event
.m_scanCode
= gdk_event
->keyval
;
801 event
.SetEventObject( win
);
803 if (win
->GetEventHandler()->ProcessEvent( event
))
805 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
812 //-----------------------------------------------------------------------------
813 // "button_press_event"
814 //-----------------------------------------------------------------------------
816 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
819 wxapp_install_idle_handler();
822 wxPrintf( _T("1) OnButtonPress from ") );
823 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
824 wxPrintf( win->GetClassInfo()->GetClassName() );
825 wxPrintf( _T(".\n") );
827 if (!win
->m_hasVMT
) return FALSE
;
828 if (g_blockEventsOnDrag
) return TRUE
;
829 if (g_blockEventsOnScroll
) return TRUE
;
831 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
835 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
837 gtk_widget_grab_focus (win
->m_wxwindow
);
840 wxPrintf( _T("GrabFocus from ") );
841 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
842 wxPrintf( win->GetClassInfo()->GetClassName() );
843 wxPrintf( _T(".\n") );
850 wxPrintf( _T("2) OnButtonPress from ") );
851 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
852 wxPrintf( win->GetClassInfo()->GetClassName() );
853 wxPrintf( _T(".\n") );
856 wxEventType event_type
= wxEVT_LEFT_DOWN
;
858 if (gdk_event
->button
== 1)
860 switch (gdk_event
->type
)
862 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
863 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
867 else if (gdk_event
->button
== 2)
869 switch (gdk_event
->type
)
871 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
872 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
876 else if (gdk_event
->button
== 3)
878 switch (gdk_event
->type
)
880 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
881 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
886 wxMouseEvent
event( event_type
);
887 event
.SetTimestamp( gdk_event
->time
);
888 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
889 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
890 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
891 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
892 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
893 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
894 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
896 event
.m_x
= (long)gdk_event
->x
;
897 event
.m_y
= (long)gdk_event
->y
;
899 // Some control don't have their own X window and thus cannot get
902 if (!g_captureWindow
)
904 wxNode
*node
= win
->GetChildren().First();
907 wxWindow
*child
= (wxWindow
*)node
->Data();
909 if (child
->m_isStaticBox
)
911 // wxStaticBox is transparent in the box itself
914 int xx1
= child
->m_x
;
915 int yy1
= child
->m_y
;
916 int xx2
= child
->m_x
+ child
->m_width
;
917 int yy2
= child
->m_x
+ child
->m_height
;
920 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
922 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
924 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
926 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
929 event
.m_x
-= child
->m_x
;
930 event
.m_y
-= child
->m_y
;
937 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
938 (child
->m_x
<= event
.m_x
) &&
939 (child
->m_y
<= event
.m_y
) &&
940 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
941 (child
->m_y
+child
->m_height
>= event
.m_y
))
944 event
.m_x
-= child
->m_x
;
945 event
.m_y
-= child
->m_y
;
953 event
.SetEventObject( win
);
955 gs_timeLastClick
= gdk_event
->time
;
957 if (win
->GetEventHandler()->ProcessEvent( event
))
959 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
966 //-----------------------------------------------------------------------------
967 // "button_release_event"
968 //-----------------------------------------------------------------------------
970 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
973 wxapp_install_idle_handler();
975 if (!win
->m_hasVMT
) return FALSE
;
976 if (g_blockEventsOnDrag
) return FALSE
;
977 if (g_blockEventsOnScroll
) return FALSE
;
979 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
982 printf( "OnButtonRelease from " );
983 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
984 printf( win->GetClassInfo()->GetClassName() );
988 wxEventType event_type
= wxEVT_NULL
;
990 switch (gdk_event
->button
)
992 case 1: event_type
= wxEVT_LEFT_UP
; break;
993 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
994 case 3: event_type
= wxEVT_RIGHT_UP
; break;
997 wxMouseEvent
event( event_type
);
998 event
.SetTimestamp( gdk_event
->time
);
999 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1000 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1001 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1002 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1003 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1004 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1005 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1006 event
.m_x
= (long)gdk_event
->x
;
1007 event
.m_y
= (long)gdk_event
->y
;
1009 // Some control don't have their own X window and thus cannot get
1012 if (!g_captureWindow
)
1014 wxNode
*node
= win
->GetChildren().First();
1017 wxWindow
*child
= (wxWindow
*)node
->Data();
1019 if (child
->m_isStaticBox
)
1021 // wxStaticBox is transparent in the box itself
1024 int xx1
= child
->m_x
;
1025 int yy1
= child
->m_y
;
1026 int xx2
= child
->m_x
+ child
->m_width
;
1027 int yy2
= child
->m_x
+ child
->m_height
;
1030 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1032 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1034 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1036 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1039 event
.m_x
-= child
->m_x
;
1040 event
.m_y
-= child
->m_y
;
1047 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1048 (child
->m_x
<= event
.m_x
) &&
1049 (child
->m_y
<= event
.m_y
) &&
1050 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
1051 (child
->m_y
+child
->m_height
>= event
.m_y
))
1054 event
.m_x
-= child
->m_x
;
1055 event
.m_y
-= child
->m_y
;
1059 node
= node
->Next();
1063 event
.SetEventObject( win
);
1065 if (win
->GetEventHandler()->ProcessEvent( event
))
1067 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1074 //-----------------------------------------------------------------------------
1075 // "motion_notify_event"
1076 //-----------------------------------------------------------------------------
1078 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1081 wxapp_install_idle_handler();
1083 if (!win
->m_hasVMT
) return FALSE
;
1084 if (g_blockEventsOnDrag
) return FALSE
;
1085 if (g_blockEventsOnScroll
) return FALSE
;
1087 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1089 if (gdk_event
->is_hint
)
1093 GdkModifierType state
;
1094 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1097 gdk_event
->state
= state
;
1101 printf( "OnMotion from " );
1102 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1103 printf( win->GetClassInfo()->GetClassName() );
1107 wxMouseEvent
event( wxEVT_MOTION
);
1108 event
.SetTimestamp( gdk_event
->time
);
1109 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1110 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1111 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1112 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1113 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1114 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1115 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1117 event
.m_x
= (long)gdk_event
->x
;
1118 event
.m_y
= (long)gdk_event
->y
;
1120 // Some control don't have their own X window and thus cannot get
1123 if (!g_captureWindow
)
1125 wxNode
*node
= win
->GetChildren().First();
1128 wxWindow
*child
= (wxWindow
*)node
->Data();
1130 if (child
->m_isStaticBox
)
1132 // wxStaticBox is transparent in the box itself
1135 int xx1
= child
->m_x
;
1136 int yy1
= child
->m_y
;
1137 int xx2
= child
->m_x
+ child
->m_width
;
1138 int yy2
= child
->m_x
+ child
->m_height
;
1141 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1143 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1145 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1147 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1150 event
.m_x
-= child
->m_x
;
1151 event
.m_y
-= child
->m_y
;
1158 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1159 (child
->m_x
<= event
.m_x
) &&
1160 (child
->m_y
<= event
.m_y
) &&
1161 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
1162 (child
->m_y
+child
->m_height
>= event
.m_y
))
1165 event
.m_x
-= child
->m_x
;
1166 event
.m_y
-= child
->m_y
;
1170 node
= node
->Next();
1174 event
.SetEventObject( win
);
1176 if (win
->GetEventHandler()->ProcessEvent( event
))
1178 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1185 //-----------------------------------------------------------------------------
1187 //-----------------------------------------------------------------------------
1189 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1192 wxapp_install_idle_handler();
1194 if (!win
->m_hasVMT
) return FALSE
;
1195 if (g_blockEventsOnDrag
) return FALSE
;
1197 g_focusWindow
= win
;
1199 if (win
->m_wxwindow
)
1201 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1203 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1205 printf( "SetFocus flag from " );
1206 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1207 printf( win->GetClassInfo()->GetClassName() );
1215 printf( "OnSetFocus from " );
1216 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1217 printf( win->GetClassInfo()->GetClassName() );
1219 printf( WXSTRINGCAST win->GetLabel() );
1223 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1224 event
.SetEventObject( win
);
1226 if (win
->GetEventHandler()->ProcessEvent( event
))
1228 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1235 //-----------------------------------------------------------------------------
1236 // "focus_out_event"
1237 //-----------------------------------------------------------------------------
1239 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1242 wxapp_install_idle_handler();
1244 if (!win
->m_hasVMT
) return FALSE
;
1245 if (g_blockEventsOnDrag
) return FALSE
;
1247 if (win
->m_wxwindow
)
1249 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1250 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1254 printf( "OnKillFocus from " );
1255 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1256 printf( win->GetClassInfo()->GetClassName() );
1260 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1261 event
.SetEventObject( win
);
1263 if (win
->GetEventHandler()->ProcessEvent( event
))
1265 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1272 //-----------------------------------------------------------------------------
1273 // "enter_notify_event"
1274 //-----------------------------------------------------------------------------
1276 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1279 wxapp_install_idle_handler();
1281 if (!win
->m_hasVMT
) return FALSE
;
1282 if (g_blockEventsOnDrag
) return FALSE
;
1284 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1286 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1287 #if (GTK_MINOR_VERSION > 0)
1288 event
.SetTimestamp( gdk_event
->time
);
1290 event
.SetEventObject( win
);
1294 GdkModifierType state
= (GdkModifierType
)0;
1296 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1298 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1299 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1300 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1301 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1302 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1303 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1304 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1306 event
.m_x
= (long)x
;
1307 event
.m_y
= (long)y
;
1309 if (win
->GetEventHandler()->ProcessEvent( event
))
1311 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1318 //-----------------------------------------------------------------------------
1319 // "leave_notify_event"
1320 //-----------------------------------------------------------------------------
1322 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1325 wxapp_install_idle_handler();
1327 if (!win
->m_hasVMT
) return FALSE
;
1328 if (g_blockEventsOnDrag
) return FALSE
;
1330 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1332 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1333 #if (GTK_MINOR_VERSION > 0)
1334 event
.SetTimestamp( gdk_event
->time
);
1336 event
.SetEventObject( win
);
1340 GdkModifierType state
= (GdkModifierType
)0;
1342 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1344 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1345 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1346 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1347 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1348 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1349 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1350 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1352 event
.m_x
= (long)x
;
1353 event
.m_y
= (long)y
;
1355 if (win
->GetEventHandler()->ProcessEvent( event
))
1357 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1364 //-----------------------------------------------------------------------------
1365 // "value_changed" from m_vAdjust
1366 //-----------------------------------------------------------------------------
1368 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1371 wxapp_install_idle_handler();
1373 if (g_blockEventsOnDrag
) return;
1375 if (!win
->m_hasVMT
) return;
1377 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
1378 if (fabs(diff
) < 0.2) return;
1379 win
->m_oldVerticalPos
= win
->m_vAdjust
->value
;
1381 wxEventType command
= wxEVT_NULL
;
1383 float line_step
= win
->m_vAdjust
->step_increment
;
1384 float page_step
= win
->m_vAdjust
->page_increment
;
1386 if (win
->IsScrolling())
1388 command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1392 if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->lower
) < 0.2) command
= wxEVT_SCROLLWIN_BOTTOM
;
1393 else if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->upper
) < 0.2) command
= wxEVT_SCROLLWIN_TOP
;
1394 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1395 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEUP
;
1396 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1397 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEUP
;
1398 else command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1401 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1403 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1404 event
.SetEventObject( win
);
1405 win
->GetEventHandler()->ProcessEvent( event
);
1408 //-----------------------------------------------------------------------------
1409 // "value_changed" from m_hAdjust
1410 //-----------------------------------------------------------------------------
1412 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1415 wxapp_install_idle_handler();
1417 if (g_blockEventsOnDrag
) return;
1418 if (!win
->m_hasVMT
) return;
1420 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
1421 if (fabs(diff
) < 0.2) return;
1422 win
->m_oldHorizontalPos
= win
->m_hAdjust
->value
;
1424 wxEventType command
= wxEVT_NULL
;
1426 float line_step
= win
->m_hAdjust
->step_increment
;
1427 float page_step
= win
->m_hAdjust
->page_increment
;
1429 if (win
->IsScrolling())
1431 command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1435 if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->lower
) < 0.2) command
= wxEVT_SCROLLWIN_BOTTOM
;
1436 else if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->upper
) < 0.2) command
= wxEVT_SCROLLWIN_TOP
;
1437 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1438 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEUP
;
1439 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1440 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEUP
;
1441 else command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1444 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1446 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1447 event
.SetEventObject( win
);
1448 win
->GetEventHandler()->ProcessEvent( event
);
1451 //-----------------------------------------------------------------------------
1452 // "changed" from m_vAdjust
1453 //-----------------------------------------------------------------------------
1455 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1458 wxapp_install_idle_handler();
1460 if (g_blockEventsOnDrag
) return;
1461 if (!win
->m_hasVMT
) return;
1463 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1464 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1466 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1467 event
.SetEventObject( win
);
1468 win
->GetEventHandler()->ProcessEvent( event
);
1471 //-----------------------------------------------------------------------------
1472 // "changed" from m_hAdjust
1473 //-----------------------------------------------------------------------------
1475 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1478 wxapp_install_idle_handler();
1480 if (g_blockEventsOnDrag
) return;
1481 if (!win
->m_hasVMT
) return;
1483 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1484 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1486 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1487 event
.SetEventObject( win
);
1488 win
->GetEventHandler()->ProcessEvent( event
);
1491 //-----------------------------------------------------------------------------
1492 // "button_press_event" from scrollbar
1493 //-----------------------------------------------------------------------------
1495 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1496 GdkEventButton
*WXUNUSED(gdk_event
),
1500 wxapp_install_idle_handler();
1502 // don't test here as we can release the mouse while being over
1503 // a different window then the slider
1505 // if (gdk_event->window != widget->slider) return FALSE;
1507 win
->SetScrolling( TRUE
);
1512 //-----------------------------------------------------------------------------
1513 // "button_release_event" from scrollbar
1514 //-----------------------------------------------------------------------------
1516 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1517 GdkEventButton
*WXUNUSED(gdk_event
),
1521 // don't test here as we can release the mouse while being over
1522 // a different window then the slider
1524 // if (gdk_event->window != widget->slider) return FALSE;
1526 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1528 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1529 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_hAdjust
), "value_changed" );
1531 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_vAdjust
), "value_changed" );
1533 win
->SetScrolling( FALSE
);
1538 // ----------------------------------------------------------------------------
1539 // this wxWindowBase function is implemented here (in platform-specific file)
1540 // because it is static and so couldn't be made virtual
1541 // ----------------------------------------------------------------------------
1543 wxWindow
*wxWindowBase::FindFocus()
1545 return g_focusWindow
;
1548 //-----------------------------------------------------------------------------
1549 // "realize" from m_widget
1550 //-----------------------------------------------------------------------------
1552 /* we cannot set colours, fonts and cursors before the widget has
1553 been realized, so we do this directly after realization */
1556 gtk_window_realized_callback( GtkWidget
* WXUNUSED(widget
), wxWindow
*win
)
1559 wxapp_install_idle_handler();
1561 if (win
->m_delayedFont
)
1562 win
->SetFont( win
->GetFont() );
1564 if (win
->m_delayedBackgroundColour
)
1565 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1567 if (win
->m_delayedForegroundColour
)
1568 win
->SetForegroundColour( win
->GetForegroundColour() );
1570 win
->SetCursor( win
->GetCursor() );
1572 wxWindowCreateEvent
event( win
);
1573 event
.SetEventObject( win
);
1574 win
->GetEventHandler()->ProcessEvent( event
);
1579 //-----------------------------------------------------------------------------
1580 // InsertChild for wxWindow.
1581 //-----------------------------------------------------------------------------
1583 /* Callback for wxWindow. This very strange beast has to be used because
1584 * C++ has no virtual methods in a constructor. We have to emulate a
1585 * virtual function here as wxNotebook requires a different way to insert
1586 * a child in it. I had opted for creating a wxNotebookPage window class
1587 * which would have made this superfluous (such in the MDI window system),
1588 * but no-one was listening to me... */
1590 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1592 gtk_myfixed_put( GTK_MYFIXED(parent
->m_wxwindow
),
1593 GTK_WIDGET(child
->m_widget
),
1599 if (parent
->HasFlag(wxTAB_TRAVERSAL
))
1601 /* we now allow a window to get the focus as long as it
1602 doesn't have any children. */
1603 GTK_WIDGET_UNSET_FLAGS( parent
->m_wxwindow
, GTK_CAN_FOCUS
);
1607 //-----------------------------------------------------------------------------
1609 //-----------------------------------------------------------------------------
1611 wxWindow
* wxGetActiveWindow()
1613 return g_focusWindow
;
1616 //-----------------------------------------------------------------------------
1618 //-----------------------------------------------------------------------------
1620 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1622 void wxWindow::Init()
1628 m_widget
= (GtkWidget
*) NULL
;
1629 m_wxwindow
= (GtkWidget
*) NULL
;
1639 m_needParent
= TRUE
;
1640 m_isBeingDeleted
= FALSE
;
1642 m_hasScrolling
= FALSE
;
1643 m_isScrolling
= FALSE
;
1645 m_hAdjust
= (GtkAdjustment
*) NULL
;
1646 m_vAdjust
= (GtkAdjustment
*) NULL
;
1647 m_oldHorizontalPos
= 0.0;
1648 m_oldVerticalPos
= 0.0;
1651 m_scrollGC
= (GdkGC
*) NULL
;
1652 m_widgetStyle
= (GtkStyle
*) NULL
;
1654 m_insertCallback
= (wxInsertChildFunction
) NULL
;
1656 m_isStaticBox
= FALSE
;
1657 m_acceptsFocus
= FALSE
;
1660 wxWindow::wxWindow()
1665 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1666 const wxPoint
&pos
, const wxSize
&size
,
1667 long style
, const wxString
&name
)
1671 Create( parent
, id
, pos
, size
, style
, name
);
1674 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1675 const wxPoint
&pos
, const wxSize
&size
,
1676 long style
, const wxString
&name
)
1678 PreCreation( parent
, id
, pos
, size
, style
, name
);
1680 m_insertCallback
= wxInsertChildInWindow
;
1682 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1683 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1686 debug_focus_in( m_widget
, _T("wxWindow::m_widget"), name
);
1689 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1692 debug_focus_in( scrolledWindow
->hscrollbar
, _T("wxWindow::hsrcollbar"), name
);
1693 debug_focus_in( scrolledWindow
->vscrollbar
, _T("wxWindow::vsrcollbar"), name
);
1696 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1697 scroll_class
->scrollbar_spacing
= 0;
1699 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1701 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
1702 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
1704 m_wxwindow
= gtk_myfixed_new();
1707 debug_focus_in( m_wxwindow
, _T("wxWindow::m_wxwindow"), name
);
1710 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1712 #if (GTK_MINOR_VERSION > 0)
1713 GtkMyFixed
*myfixed
= GTK_MYFIXED(m_wxwindow
);
1715 if (HasFlag(wxRAISED_BORDER
))
1717 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_OUT
);
1719 else if (HasFlag(wxSUNKEN_BORDER
))
1721 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_IN
);
1725 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_NONE
);
1727 #else // GTK_MINOR_VERSION == 0
1728 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
1730 if (HasFlag(wxRAISED_BORDER
))
1732 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1734 else if (HasFlag(wxSUNKEN_BORDER
))
1736 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1740 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1742 #endif // GTK_MINOR_VERSION
1744 if (HasFlag(wxTAB_TRAVERSAL
))
1746 /* we now allow a window to get the focus as long as it
1747 doesn't have any children. */
1748 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1749 m_acceptsFocus
= FALSE
;
1753 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1754 m_acceptsFocus
= TRUE
;
1757 #if (GTK_MINOR_VERSION == 0)
1758 // shut the viewport up
1759 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1760 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1761 #endif // GTK_MINOR_VERSION == 0
1763 // I _really_ don't want scrollbars in the beginning
1764 m_vAdjust
->lower
= 0.0;
1765 m_vAdjust
->upper
= 1.0;
1766 m_vAdjust
->value
= 0.0;
1767 m_vAdjust
->step_increment
= 1.0;
1768 m_vAdjust
->page_increment
= 1.0;
1769 m_vAdjust
->page_size
= 5.0;
1770 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1771 m_hAdjust
->lower
= 0.0;
1772 m_hAdjust
->upper
= 1.0;
1773 m_hAdjust
->value
= 0.0;
1774 m_hAdjust
->step_increment
= 1.0;
1775 m_hAdjust
->page_increment
= 1.0;
1776 m_hAdjust
->page_size
= 5.0;
1777 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1779 // these handlers block mouse events to any window during scrolling such as
1780 // motion events and prevent GTK and wxWindows from fighting over where the
1783 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
1784 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1786 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
1787 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1789 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
1790 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1792 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
1793 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1795 // these handlers get notified when screen updates are required either when
1796 // scrolling or when the window size (and therefore scrollbar configuration)
1799 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
1800 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
1801 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
1802 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
1804 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
1805 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
1806 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
1807 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
1809 gtk_widget_show( m_wxwindow
);
1812 m_parent
->DoAddChild( this );
1821 wxWindow::~wxWindow()
1823 m_isBeingDeleted
= TRUE
;
1832 m_parent
->RemoveChild( this );
1836 gtk_style_unref( m_widgetStyle
);
1837 m_widgetStyle
= (GtkStyle
*) NULL
;
1842 gdk_gc_unref( m_scrollGC
);
1843 m_scrollGC
= (GdkGC
*) NULL
;
1848 gtk_widget_destroy( m_wxwindow
);
1849 m_wxwindow
= (GtkWidget
*) NULL
;
1854 gtk_widget_destroy( m_widget
);
1855 m_widget
= (GtkWidget
*) NULL
;
1859 void wxWindow::PreCreation( wxWindow
*parent
,
1864 const wxString
&name
)
1866 wxASSERT_MSG( !m_needParent
|| parent
, _T("Need complete parent.") );
1868 if ( !CreateBase(parent
, id
, pos
, size
, style
, name
) )
1870 wxFAIL_MSG(_T("window creation failed"));
1873 m_width
= WidthDefault(size
.x
);
1874 m_height
= HeightDefault(size
.y
);
1879 if (!parent
) /* some reasonable defaults */
1883 m_x
= (gdk_screen_width () - m_width
) / 2;
1884 if (m_x
< 10) m_x
= 10;
1888 m_y
= (gdk_screen_height () - m_height
) / 2;
1889 if (m_y
< 10) m_y
= 10;
1894 void wxWindow::PostCreation()
1896 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1900 /* these get reported to wxWindows -> wxPaintEvent */
1901 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1902 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1904 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1905 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1907 #if (GTK_MINOR_VERSION > 0)
1908 /* these are called when the "sunken" or "raised" borders are drawn */
1909 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
1910 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
1912 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
1913 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
1917 GtkWidget
*connect_widget
= GetConnectWidget();
1919 ConnectWidget( connect_widget
);
1921 /* we cannot set colours, fonts and cursors before the widget has
1922 been realized, so we do this directly after realization */
1923 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
1924 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
1929 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1931 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1932 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1934 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
1935 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
1937 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1938 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1940 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1941 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1943 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1944 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1946 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1947 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1949 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1950 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1952 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1953 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1955 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1956 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1959 bool wxWindow::Destroy()
1961 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1965 return wxWindowBase::Destroy();
1968 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1970 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1971 wxASSERT_MSG( (m_parent
!= NULL
), _T("wxWindow::SetSize requires parent.\n") );
1973 if (m_resizing
) return; /* I don't like recursions */
1976 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
1978 /* don't set the size for children of wxNotebook, just take the values. */
1986 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
1988 if (x
!= -1) m_x
= x
;
1989 if (y
!= -1) m_y
= y
;
1990 if (width
!= -1) m_width
= width
;
1991 if (height
!= -1) m_height
= height
;
2001 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2003 if (width
== -1) m_width
= 80;
2006 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2008 if (height
== -1) m_height
= 26;
2011 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2012 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2013 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2014 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2017 int bottom_border
= 0;
2019 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2021 /* the default button has a border around it */
2026 /* this is the result of hours of debugging: the following code
2027 means that if we have a m_wxwindow and we set the size of
2028 m_widget, m_widget (which is a GtkScrolledWindow) does NOT
2029 automatically propagate its size down to its m_wxwindow,
2030 which is its client area. therefore, we have to tell the
2031 client area directly that it has to resize itself.
2032 this will lead to that m_widget (GtkScrolledWindow) will
2033 calculate how much size it needs for scrollbars etc and
2034 it will then call XXX_size_allocate of its child, which
2035 is m_wxwindow. m_wxwindow in turn will do the same with its
2036 children and so on. problems can arise if this happens
2037 before all the children have been realized as some widgets
2038 stupidy need to be realized during XXX_size_allocate (e.g.
2039 GtkNotebook) and they will segv if called otherwise. this
2040 emergency is tested in gtk_myfixed_size_allocate. Normally
2041 this shouldn't be needed and only gtk_widget_queue_resize()
2042 should be enough to provoke a resize at the next appropriate
2043 moment, but this seems to fail, e.g. when a wxNotebook contains
2044 a wxSplitterWindow: the splitter window's children won't
2045 show up properly resized then. */
2047 gtk_myfixed_set_size( GTK_MYFIXED(m_parent
->m_wxwindow
),
2052 m_height
+border
+bottom_border
);
2057 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2058 event
.SetEventObject( this );
2059 GetEventHandler()->ProcessEvent( event
);
2064 void wxWindow::OnInternalIdle()
2066 GdkWindow
*window
= GetConnectWidget()->window
;
2069 wxCursor cursor
= m_cursor
;
2070 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2072 if (cursor
.Ok() && m_currentGdkCursor
!= cursor
)
2074 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2075 m_currentGdkCursor
= cursor
;
2082 void wxWindow::DoGetSize( int *width
, int *height
) const
2084 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2086 if (width
) (*width
) = m_width
;
2087 if (height
) (*height
) = m_height
;
2090 void wxWindow::DoSetClientSize( int width
, int height
)
2092 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2096 SetSize( width
, height
);
2103 if (!m_hasScrolling
)
2105 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
2107 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2109 dw
+= 2 * window_class
->xthickness
;
2110 dh
+= 2 * window_class
->ythickness
;
2115 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2116 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2118 #if (GTK_MINOR_VERSION == 0)
2119 GtkWidget
*viewport
= scroll_window
->viewport
;
2120 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2122 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2124 dw
+= 2 * viewport_class
->xthickness
;
2125 dh
+= 2 * viewport_class
->ythickness
;
2130 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2131 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2133 we use this instead: range.slider_width = 11 + 2*2pts edge
2136 if (scroll_window
->vscrollbar_visible
)
2138 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2139 dw
+= scroll_class
->scrollbar_spacing
;
2142 if (scroll_window
->hscrollbar_visible
)
2144 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2145 dh
+= scroll_class
->scrollbar_spacing
;
2149 SetSize( width
+dw
, height
+dh
);
2153 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2155 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2159 if (width
) (*width
) = m_width
;
2160 if (height
) (*height
) = m_height
;
2167 if (!m_hasScrolling
)
2169 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
2171 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2173 dw
+= 2 * window_class
->xthickness
;
2174 dh
+= 2 * window_class
->ythickness
;
2179 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2180 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2182 #if (GTK_MINOR_VERSION == 0)
2183 GtkWidget
*viewport
= scroll_window
->viewport
;
2184 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2186 if ( HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
) )
2188 dw
+= 2 * viewport_class
->xthickness
;
2189 dh
+= 2 * viewport_class
->ythickness
;
2193 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2194 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2196 we use this instead: range.slider_width = 11 + 2*2pts edge
2199 if (scroll_window
->vscrollbar_visible
)
2201 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2202 dw
+= scroll_class
->scrollbar_spacing
;
2205 if (scroll_window
->hscrollbar_visible
)
2207 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2208 dh
+= scroll_class
->scrollbar_spacing
;
2212 if (width
) (*width
) = m_width
- dw
;
2213 if (height
) (*height
) = m_height
- dh
;
2217 void wxWindow::DoGetPosition( int *x
, int *y
) const
2219 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2225 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2227 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2229 if (!m_widget
->window
) return;
2231 GdkWindow
*source
= (GdkWindow
*) NULL
;
2233 source
= m_wxwindow
->window
;
2235 source
= m_widget
->window
;
2239 gdk_window_get_origin( source
, &org_x
, &org_y
);
2243 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2245 org_x
+= m_widget
->allocation
.x
;
2246 org_y
+= m_widget
->allocation
.y
;
2254 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2256 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2258 if (!m_widget
->window
) return;
2260 GdkWindow
*source
= (GdkWindow
*) NULL
;
2262 source
= m_wxwindow
->window
;
2264 source
= m_widget
->window
;
2268 gdk_window_get_origin( source
, &org_x
, &org_y
);
2272 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2274 org_x
+= m_widget
->allocation
.x
;
2275 org_y
+= m_widget
->allocation
.y
;
2283 bool wxWindow::Show( bool show
)
2285 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2287 if (!wxWindowBase::Show(show
))
2294 gtk_widget_show( m_widget
);
2296 gtk_widget_hide( m_widget
);
2301 bool wxWindow::Enable( bool enable
)
2303 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2305 if (!wxWindowBase::Enable(enable
))
2311 gtk_widget_set_sensitive( m_widget
, enable
);
2313 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2318 int wxWindow::GetCharHeight() const
2320 wxCHECK_MSG( (m_widget
!= NULL
), 12, _T("invalid window") );
2322 wxCHECK_MSG( m_font
.Ok(), 12, _T("invalid font") );
2324 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2326 return font
->ascent
+ font
->descent
;
2329 int wxWindow::GetCharWidth() const
2331 wxCHECK_MSG( (m_widget
!= NULL
), 8, _T("invalid window") );
2333 wxCHECK_MSG( m_font
.Ok(), 8, _T("invalid font") );
2335 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2337 return gdk_string_width( font
, "H" );
2340 void wxWindow::GetTextExtent( const wxString
& string
,
2344 int *externalLeading
,
2345 const wxFont
*theFont
) const
2347 wxFont fontToUse
= m_font
;
2348 if (theFont
) fontToUse
= *theFont
;
2350 wxCHECK_RET( fontToUse
.Ok(), _T("invalid font") );
2352 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2353 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2354 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2355 if (descent
) (*descent
) = font
->descent
;
2356 if (externalLeading
) (*externalLeading
) = 0; // ??
2359 void wxWindow::SetFocus()
2361 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2363 GtkWidget
*connect_widget
= GetConnectWidget();
2366 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2368 gtk_widget_grab_focus (connect_widget
);
2370 else if (GTK_IS_CONTAINER(connect_widget
))
2372 gtk_container_focus( GTK_CONTAINER(connect_widget
), GTK_DIR_TAB_FORWARD
);
2380 bool wxWindow::AcceptsFocus() const
2382 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2385 bool wxWindow::Reparent( wxWindow
*newParent
)
2387 wxCHECK_MSG( (m_widget
!= NULL
), (wxWindow
*) NULL
, _T("invalid window") );
2389 wxWindow
*oldParent
= m_parent
;
2391 if ( !wxWindowBase::Reparent(newParent
) )
2396 gtk_container_remove( GTK_CONTAINER(oldParent
->m_wxwindow
), m_widget
);
2401 /* insert GTK representation */
2402 (*(newParent
->m_insertCallback
))(newParent
, this);
2408 void wxWindow::DoAddChild(wxWindow
*child
)
2410 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
2412 wxASSERT_MSG( (child
!= NULL
), _T("invalid child window") );
2414 wxASSERT_MSG( (m_insertCallback
!= NULL
), _T("invalid child insertion function") );
2419 /* insert GTK representation */
2420 (*m_insertCallback
)(this, child
);
2423 void wxWindow::Raise()
2425 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2427 if (!m_widget
->window
) return;
2429 gdk_window_raise( m_widget
->window
);
2432 void wxWindow::Lower()
2434 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2436 if (!m_widget
->window
) return;
2438 gdk_window_lower( m_widget
->window
);
2441 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2443 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2445 if (!wxWindowBase::SetCursor(cursor
))
2447 // don't leave if the GTK widget has just
2449 if (!m_delayedCursor
) return FALSE
;
2452 GtkWidget
*connect_widget
= GetConnectWidget();
2453 if (!connect_widget
->window
)
2455 // indicate that a new style has been set
2456 // but it couldn't get applied as the
2457 // widget hasn't been realized yet.
2458 m_delayedCursor
= TRUE
;
2460 // pretend we have done something
2464 // gdk_window_set_cursor( connect_widget->window, GetCursor().GetCursor() );
2470 void wxWindow::WarpPointer( int x
, int y
)
2472 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2474 GtkWidget
*connect_widget
= GetConnectWidget();
2475 if (connect_widget
->window
)
2477 /* we provide this function ourselves as it is
2479 gdk_window_warp_pointer( connect_widget
->window
, x
, y
);
2483 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2485 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2487 if (!m_widget
->window
) return;
2489 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2493 gdk_window_clear_area( m_wxwindow
->window
,
2495 rect
->width
, rect
->height
);
2499 gdk_window_clear( m_wxwindow
->window
);
2506 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2508 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2512 GdkRectangle gdk_rect
;
2513 gdk_rect
.x
= rect
->x
;
2514 gdk_rect
.y
= rect
->y
;
2515 gdk_rect
.width
= rect
->width
;
2516 gdk_rect
.height
= rect
->height
;
2519 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2521 gtk_widget_draw( m_widget
, &gdk_rect
);
2525 void wxWindow::Clear()
2527 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2529 if (!m_widget
->window
) return;
2531 if (m_wxwindow
&& m_wxwindow
->window
)
2533 gdk_window_clear( m_wxwindow
->window
);
2538 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2540 wxWindowBase::DoSetToolTip(tip
);
2543 m_tooltip
->Apply( this );
2546 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2548 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
2550 #endif // wxUSE_TOOLTIPS
2552 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2554 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2556 if (!wxWindowBase::SetBackgroundColour(colour
))
2558 // don't leave if the GTK widget has just
2560 if (!m_delayedBackgroundColour
) return FALSE
;
2563 GtkWidget
*connect_widget
= GetConnectWidget();
2564 if (!connect_widget
->window
)
2566 // indicate that a new style has been set
2567 // but it couldn't get applied as the
2568 // widget hasn't been realized yet.
2569 m_delayedBackgroundColour
= TRUE
;
2571 // pretend we have done something
2575 if (m_wxwindow
&& m_wxwindow
->window
)
2577 /* wxMSW doesn't clear the window here. I don't do that either to
2578 provide compatibility. call Clear() to do the job. */
2580 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_wxwindow
->window
) );
2581 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
2584 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2585 if (sysbg
== m_backgroundColour
)
2587 m_backgroundColour
= wxNullColour
;
2589 m_backgroundColour
= sysbg
;
2599 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2601 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2603 if (!wxWindowBase::SetForegroundColour(colour
))
2605 // don't leave if the GTK widget has just
2607 if (!m_delayedForegroundColour
) return FALSE
;
2610 GtkWidget
*connect_widget
= GetConnectWidget();
2611 if (!connect_widget
->window
)
2613 // indicate that a new style has been set
2614 // but it couldn't get applied as the
2615 // widget hasn't been realized yet.
2616 m_delayedForegroundColour
= TRUE
;
2618 // pretend we have done something
2622 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2623 if ( sysbg
== m_backgroundColour
)
2625 m_backgroundColour
= wxNullColour
;
2627 m_backgroundColour
= sysbg
;
2637 GtkStyle
*wxWindow::GetWidgetStyle()
2639 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2641 m_widgetStyle
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2643 return m_widgetStyle
;
2646 void wxWindow::SetWidgetStyle()
2648 GtkStyle
*style
= GetWidgetStyle();
2650 gdk_font_unref( style
->font
);
2651 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2653 if (m_foregroundColour
.Ok())
2655 m_foregroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2656 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2657 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2658 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2661 if (m_backgroundColour
.Ok())
2663 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2664 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2665 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2666 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2667 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2668 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2669 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2670 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2671 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2675 void wxWindow::ApplyWidgetStyle()
2679 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2681 menu
->SetInvokingWindow( win
);
2682 wxNode
*node
= menu
->GetItems().First();
2685 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2686 if (menuitem
->IsSubMenu())
2688 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2690 node
= node
->Next();
2694 static gint gs_pop_x
= 0;
2695 static gint gs_pop_y
= 0;
2697 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
2701 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
2706 bool wxWindow::PopupMenu( wxMenu
*menu
, int x
, int y
)
2708 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2710 wxCHECK_MSG( menu
!= NULL
, FALSE
, _T("invalid popup-menu") );
2712 SetInvokingWindow( menu
, this );
2720 GTK_MENU(menu
->m_menu
),
2721 (GtkWidget
*) NULL
, // parent menu shell
2722 (GtkWidget
*) NULL
, // parent menu item
2723 (GtkMenuPositionFunc
) pop_pos_callback
,
2724 (gpointer
) this, // client data
2725 0, // button used to activate it
2726 0 //gs_timeLastClick // the time of activation
2731 #if wxUSE_DRAG_AND_DROP
2733 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2735 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2737 GtkWidget
*dnd_widget
= GetConnectWidget();
2739 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
2741 if (m_dropTarget
) delete m_dropTarget
;
2742 m_dropTarget
= dropTarget
;
2744 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
2747 #endif // wxUSE_DRAG_AND_DROP
2749 GtkWidget
* wxWindow::GetConnectWidget()
2751 GtkWidget
*connect_widget
= m_widget
;
2752 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2754 return connect_widget
;
2757 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2759 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2760 return (window
== m_widget
->window
);
2763 bool wxWindow::SetFont( const wxFont
&font
)
2765 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T( "invalid window") );
2767 if (!wxWindowBase::SetFont(font
))
2769 // don't leave if the GTK widget has just
2771 if (!m_delayedFont
) return FALSE
;
2774 GtkWidget
*connect_widget
= GetConnectWidget();
2775 if (!connect_widget
->window
)
2777 // indicate that a new style has been set
2778 // but it couldn't get applied as the
2779 // widget hasn't been realized yet.
2780 m_delayedFont
= TRUE
;
2782 // pretend we have done something
2786 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2787 if ( sysbg
== m_backgroundColour
)
2789 m_backgroundColour
= wxNullColour
;
2791 m_backgroundColour
= sysbg
;
2801 void wxWindow::CaptureMouse()
2803 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2805 wxCHECK_RET( g_captureWindow
== NULL
, _T("CaptureMouse called twice") );
2807 GtkWidget
*connect_widget
= GetConnectWidget();
2808 if (!connect_widget
->window
) return;
2810 gdk_pointer_grab( connect_widget
->window
, FALSE
,
2812 (GDK_BUTTON_PRESS_MASK
|
2813 GDK_BUTTON_RELEASE_MASK
|
2814 GDK_POINTER_MOTION_MASK
),
2816 m_cursor
.GetCursor(),
2818 g_captureWindow
= this;
2821 void wxWindow::ReleaseMouse()
2823 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2825 wxCHECK_RET( g_captureWindow
, _T("ReleaseMouse called twice") );
2827 GtkWidget
*connect_widget
= GetConnectWidget();
2828 if (!connect_widget
->window
) return;
2830 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2831 g_captureWindow
= (wxWindow
*) NULL
;
2834 bool wxWindow::IsRetained() const
2839 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2840 int range
, bool refresh
)
2842 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2844 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2846 m_hasScrolling
= TRUE
;
2848 if (orient
== wxHORIZONTAL
)
2850 float fpos
= (float)pos
;
2851 float frange
= (float)range
;
2852 float fthumb
= (float)thumbVisible
;
2853 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2854 if (fpos
< 0.0) fpos
= 0.0;
2856 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2857 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2859 SetScrollPos( orient
, pos
, refresh
);
2863 m_oldHorizontalPos
= fpos
;
2865 m_hAdjust
->lower
= 0.0;
2866 m_hAdjust
->upper
= frange
;
2867 m_hAdjust
->value
= fpos
;
2868 m_hAdjust
->step_increment
= 1.0;
2869 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2870 m_hAdjust
->page_size
= fthumb
;
2874 float fpos
= (float)pos
;
2875 float frange
= (float)range
;
2876 float fthumb
= (float)thumbVisible
;
2877 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2878 if (fpos
< 0.0) fpos
= 0.0;
2880 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2881 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2883 SetScrollPos( orient
, pos
, refresh
);
2887 m_oldVerticalPos
= fpos
;
2889 m_vAdjust
->lower
= 0.0;
2890 m_vAdjust
->upper
= frange
;
2891 m_vAdjust
->value
= fpos
;
2892 m_vAdjust
->step_increment
= 1.0;
2893 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2894 m_vAdjust
->page_size
= fthumb
;
2897 if (orient
== wxHORIZONTAL
)
2898 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2900 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2903 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2905 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2907 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2909 if (orient
== wxHORIZONTAL
)
2911 float fpos
= (float)pos
;
2912 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
2913 if (fpos
< 0.0) fpos
= 0.0;
2914 m_oldHorizontalPos
= fpos
;
2916 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2917 m_hAdjust
->value
= fpos
;
2921 float fpos
= (float)pos
;
2922 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
2923 if (fpos
< 0.0) fpos
= 0.0;
2924 m_oldVerticalPos
= fpos
;
2926 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2927 m_vAdjust
->value
= fpos
;
2930 if (!m_isScrolling
) /* prevent recursion */
2932 if (m_wxwindow
->window
)
2934 if (orient
== wxHORIZONTAL
)
2935 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2937 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2942 int wxWindow::GetScrollThumb( int orient
) const
2944 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2946 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2948 if (orient
== wxHORIZONTAL
)
2949 return (int)(m_hAdjust
->page_size
+0.5);
2951 return (int)(m_vAdjust
->page_size
+0.5);
2954 int wxWindow::GetScrollPos( int orient
) const
2956 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2958 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2960 if (orient
== wxHORIZONTAL
)
2961 return (int)(m_hAdjust
->value
+0.5);
2963 return (int)(m_vAdjust
->value
+0.5);
2966 int wxWindow::GetScrollRange( int orient
) const
2968 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2970 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2972 if (orient
== wxHORIZONTAL
)
2973 return (int)(m_hAdjust
->upper
+0.5);
2975 return (int)(m_vAdjust
->upper
+0.5);
2978 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2980 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2982 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2986 m_scrollGC
= gdk_gc_new( m_wxwindow
->window
);
2987 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
2990 wxNode
*node
= m_children
.First();
2993 wxWindow
*child
= (wxWindow
*) node
->Data();
2996 child
->GetSize( &sx
, &sy
);
2997 child
->SetSize( child
->m_x
+ dx
, child
->m_y
+ dy
, sx
, sy
, wxSIZE_ALLOW_MINUS_ONE
);
2998 node
= node
->Next();
3003 GetClientSize( &cw
, &ch
);
3004 int w
= cw
- abs(dx
);
3005 int h
= ch
- abs(dy
);
3007 if ((h
< 0) || (w
< 0))
3015 if (dx
< 0) s_x
= -dx
;
3016 if (dy
< 0) s_y
= -dy
;
3019 if (dx
> 0) d_x
= dx
;
3020 if (dy
> 0) d_y
= dy
;
3022 gdk_window_copy_area( m_wxwindow
->window
, m_scrollGC
, d_x
, d_y
,
3023 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
3026 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
3027 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
3028 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
3029 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
3031 Refresh( TRUE
, &rect
);
3035 void wxWindow::SetScrolling(bool scroll
)
3037 m_isScrolling
= g_blockEventsOnScroll
= scroll
;