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 bool g_capturing
= FALSE
;
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
);
634 /* wxMSW doesn't send char events with Alt pressed */
635 if ((key_code
!= 0) &&
636 ((gdk_event
->state
& GDK_MOD1_MASK
) == 0) &&
637 ((gdk_event
->state
& GDK_MOD1_MASK
) == 0))
639 wxKeyEvent
event2( wxEVT_CHAR
);
640 event2
.SetTimestamp( gdk_event
->time
);
641 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
642 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
643 // event2.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
644 // event2.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
645 event2
.m_keyCode
= key_code
;
646 event2
.m_scanCode
= gdk_event
->keyval
;
649 event2
.SetEventObject( win
);
650 ret
= (ret
|| win
->GetEventHandler()->ProcessEvent( event2
));
655 wxWindow
*ancestor
= win
;
658 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
661 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
662 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
665 ancestor
= ancestor
->GetParent();
669 /* win is a control: tab can be propagated up */
671 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
672 (win
->HasFlag(wxTE_PROCESS_TAB
) == 0))
674 wxNavigationKeyEvent new_event
;
675 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
676 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
677 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
678 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
679 new_event
.SetCurrentFocus( win
);
680 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
683 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
685 (gdk_event
->keyval
== GDK_Escape
) )
687 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
688 new_event
.SetEventObject( win
);
689 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
692 #if (GTK_MINOR_VERSION > 0)
693 /* pressing F10 will activate the menu bar of the top frame */
695 (gdk_event
->keyval
== GDK_F10
) )
697 wxWindow
*ancestor
= win
;
700 if (wxIsKindOf(ancestor
,wxFrame
))
702 wxFrame
*frame
= (wxFrame
*) ancestor
;
703 wxMenuBar
*menubar
= frame
->GetMenuBar();
706 wxNode
*node
= menubar
->GetMenus().First();
709 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
710 // doesn't work correctly
711 // gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
717 ancestor
= ancestor
->GetParent();
723 Damn, I forgot why this didn't work, but it didn't work.
725 // win is a panel: up can be propagated to the panel
726 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
727 (gdk_event->keyval == GDK_Up))
729 win->m_parent->SetFocus();
733 // win is a panel: left/right can be propagated to the panel
734 if ((!ret) && (win->m_wxwindow) &&
735 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
736 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
738 wxNavigationKeyEvent new_event;
739 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
740 new_event.SetCurrentFocus( win );
741 ret = win->GetEventHandler()->ProcessEvent( new_event );
747 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
754 //-----------------------------------------------------------------------------
755 // "key_release_event" from any window
756 //-----------------------------------------------------------------------------
758 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
761 wxapp_install_idle_handler();
763 if (!win
->m_hasVMT
) return FALSE
;
764 if (g_blockEventsOnDrag
) return FALSE
;
767 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
768 if (gdk_event->state & GDK_SHIFT_MASK)
769 printf( "ShiftDown.\n" );
771 printf( "ShiftUp.\n" );
772 if (gdk_event->state & GDK_CONTROL_MASK)
773 printf( "ControlDown.\n" );
775 printf( "ControlUp.\n" );
779 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
781 /* sending unknown key events doesn't really make sense */
782 if (key_code
== 0) return FALSE
;
786 GdkModifierType state
;
787 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
789 wxKeyEvent
event( wxEVT_KEY_UP
);
790 event
.SetTimestamp( gdk_event
->time
);
791 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
792 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
793 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
794 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
795 event
.m_keyCode
= key_code
;
796 event
.m_scanCode
= gdk_event
->keyval
;
799 event
.SetEventObject( win
);
801 if (win
->GetEventHandler()->ProcessEvent( event
))
803 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
810 //-----------------------------------------------------------------------------
811 // "button_press_event"
812 //-----------------------------------------------------------------------------
814 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
817 wxapp_install_idle_handler();
820 wxPrintf( _T("1) OnButtonPress from ") );
821 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
822 wxPrintf( win->GetClassInfo()->GetClassName() );
823 wxPrintf( _T(".\n") );
825 if (!win
->m_hasVMT
) return FALSE
;
826 if (g_blockEventsOnDrag
) return TRUE
;
827 if (g_blockEventsOnScroll
) return TRUE
;
829 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
833 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
835 gtk_widget_grab_focus (win
->m_wxwindow
);
838 wxPrintf( _T("GrabFocus from ") );
839 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
840 wxPrintf( win->GetClassInfo()->GetClassName() );
841 wxPrintf( _T(".\n") );
848 wxPrintf( _T("2) OnButtonPress from ") );
849 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
850 wxPrintf( win->GetClassInfo()->GetClassName() );
851 wxPrintf( _T(".\n") );
854 wxEventType event_type
= wxEVT_LEFT_DOWN
;
856 if (gdk_event
->button
== 1)
858 switch (gdk_event
->type
)
860 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
861 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
865 else if (gdk_event
->button
== 2)
867 switch (gdk_event
->type
)
869 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
870 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
874 else if (gdk_event
->button
== 3)
876 switch (gdk_event
->type
)
878 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
879 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
884 wxMouseEvent
event( event_type
);
885 event
.SetTimestamp( gdk_event
->time
);
886 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
887 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
888 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
889 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
890 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
891 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
892 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
894 event
.m_x
= (long)gdk_event
->x
;
895 event
.m_y
= (long)gdk_event
->y
;
897 // Some control don't have their own X window and thus cannot get
902 wxNode
*node
= win
->GetChildren().First();
905 wxWindow
*child
= (wxWindow
*)node
->Data();
907 if (child
->m_isStaticBox
)
909 // wxStaticBox is transparent in the box itself
912 int xx1
= child
->m_x
;
913 int yy1
= child
->m_y
;
914 int xx2
= child
->m_x
+ child
->m_width
;
915 int yy2
= child
->m_x
+ child
->m_height
;
918 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
920 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
922 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
924 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
927 event
.m_x
-= child
->m_x
;
928 event
.m_y
-= child
->m_y
;
935 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
936 (child
->m_x
<= event
.m_x
) &&
937 (child
->m_y
<= event
.m_y
) &&
938 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
939 (child
->m_y
+child
->m_height
>= event
.m_y
))
942 event
.m_x
-= child
->m_x
;
943 event
.m_y
-= child
->m_y
;
951 event
.SetEventObject( win
);
953 gs_timeLastClick
= gdk_event
->time
;
955 if (win
->GetEventHandler()->ProcessEvent( event
))
957 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
964 //-----------------------------------------------------------------------------
965 // "button_release_event"
966 //-----------------------------------------------------------------------------
968 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
971 wxapp_install_idle_handler();
973 if (!win
->m_hasVMT
) return FALSE
;
974 if (g_blockEventsOnDrag
) return FALSE
;
975 if (g_blockEventsOnScroll
) return FALSE
;
977 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
980 printf( "OnButtonRelease from " );
981 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
982 printf( win->GetClassInfo()->GetClassName() );
986 wxEventType event_type
= wxEVT_NULL
;
988 switch (gdk_event
->button
)
990 case 1: event_type
= wxEVT_LEFT_UP
; break;
991 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
992 case 3: event_type
= wxEVT_RIGHT_UP
; break;
995 wxMouseEvent
event( event_type
);
996 event
.SetTimestamp( gdk_event
->time
);
997 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
998 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
999 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1000 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1001 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1002 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1003 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1004 event
.m_x
= (long)gdk_event
->x
;
1005 event
.m_y
= (long)gdk_event
->y
;
1007 // Some control don't have their own X window and thus cannot get
1012 wxNode
*node
= win
->GetChildren().First();
1015 wxWindow
*child
= (wxWindow
*)node
->Data();
1017 if (child
->m_isStaticBox
)
1019 // wxStaticBox is transparent in the box itself
1022 int xx1
= child
->m_x
;
1023 int yy1
= child
->m_y
;
1024 int xx2
= child
->m_x
+ child
->m_width
;
1025 int yy2
= child
->m_x
+ child
->m_height
;
1028 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1030 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1032 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1034 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1037 event
.m_x
-= child
->m_x
;
1038 event
.m_y
-= child
->m_y
;
1045 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1046 (child
->m_x
<= event
.m_x
) &&
1047 (child
->m_y
<= event
.m_y
) &&
1048 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
1049 (child
->m_y
+child
->m_height
>= event
.m_y
))
1052 event
.m_x
-= child
->m_x
;
1053 event
.m_y
-= child
->m_y
;
1057 node
= node
->Next();
1061 event
.SetEventObject( win
);
1063 if (win
->GetEventHandler()->ProcessEvent( event
))
1065 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1072 //-----------------------------------------------------------------------------
1073 // "motion_notify_event"
1074 //-----------------------------------------------------------------------------
1076 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1079 wxapp_install_idle_handler();
1081 if (!win
->m_hasVMT
) return FALSE
;
1082 if (g_blockEventsOnDrag
) return FALSE
;
1083 if (g_blockEventsOnScroll
) return FALSE
;
1085 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1087 if (gdk_event
->is_hint
)
1091 GdkModifierType state
;
1092 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1095 gdk_event
->state
= state
;
1099 printf( "OnMotion from " );
1100 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1101 printf( win->GetClassInfo()->GetClassName() );
1105 wxMouseEvent
event( wxEVT_MOTION
);
1106 event
.SetTimestamp( gdk_event
->time
);
1107 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1108 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1109 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1110 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1111 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1112 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1113 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1115 event
.m_x
= (long)gdk_event
->x
;
1116 event
.m_y
= (long)gdk_event
->y
;
1118 // Some control don't have their own X window and thus cannot get
1123 wxNode
*node
= win
->GetChildren().First();
1126 wxWindow
*child
= (wxWindow
*)node
->Data();
1128 if (child
->m_isStaticBox
)
1130 // wxStaticBox is transparent in the box itself
1133 int xx1
= child
->m_x
;
1134 int yy1
= child
->m_y
;
1135 int xx2
= child
->m_x
+ child
->m_width
;
1136 int yy2
= child
->m_x
+ child
->m_height
;
1139 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1141 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1143 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1145 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1148 event
.m_x
-= child
->m_x
;
1149 event
.m_y
-= child
->m_y
;
1156 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1157 (child
->m_x
<= event
.m_x
) &&
1158 (child
->m_y
<= event
.m_y
) &&
1159 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
1160 (child
->m_y
+child
->m_height
>= event
.m_y
))
1163 event
.m_x
-= child
->m_x
;
1164 event
.m_y
-= child
->m_y
;
1168 node
= node
->Next();
1172 event
.SetEventObject( win
);
1174 if (win
->GetEventHandler()->ProcessEvent( event
))
1176 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1183 //-----------------------------------------------------------------------------
1185 //-----------------------------------------------------------------------------
1187 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1190 wxapp_install_idle_handler();
1192 if (!win
->m_hasVMT
) return FALSE
;
1193 if (g_blockEventsOnDrag
) return FALSE
;
1195 g_focusWindow
= win
;
1197 if (win
->m_wxwindow
)
1199 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1201 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1203 printf( "SetFocus flag from " );
1204 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1205 printf( win->GetClassInfo()->GetClassName() );
1213 printf( "OnSetFocus from " );
1214 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1215 printf( win->GetClassInfo()->GetClassName() );
1217 printf( WXSTRINGCAST win->GetLabel() );
1221 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1222 event
.SetEventObject( win
);
1224 if (win
->GetEventHandler()->ProcessEvent( event
))
1226 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1233 //-----------------------------------------------------------------------------
1234 // "focus_out_event"
1235 //-----------------------------------------------------------------------------
1237 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1240 wxapp_install_idle_handler();
1242 if (!win
->m_hasVMT
) return FALSE
;
1243 if (g_blockEventsOnDrag
) return FALSE
;
1245 if (win
->m_wxwindow
)
1247 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1248 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1252 printf( "OnKillFocus from " );
1253 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1254 printf( win->GetClassInfo()->GetClassName() );
1258 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1259 event
.SetEventObject( win
);
1261 if (win
->GetEventHandler()->ProcessEvent( event
))
1263 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1270 //-----------------------------------------------------------------------------
1271 // "enter_notify_event"
1272 //-----------------------------------------------------------------------------
1274 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1277 wxapp_install_idle_handler();
1279 if (!win
->m_hasVMT
) return FALSE
;
1280 if (g_blockEventsOnDrag
) return FALSE
;
1282 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1284 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1285 #if (GTK_MINOR_VERSION > 0)
1286 event
.SetTimestamp( gdk_event
->time
);
1288 event
.SetEventObject( win
);
1292 GdkModifierType state
= (GdkModifierType
)0;
1294 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1296 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1297 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1298 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1299 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1300 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1301 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1302 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1304 event
.m_x
= (long)x
;
1305 event
.m_y
= (long)y
;
1307 if (win
->GetEventHandler()->ProcessEvent( event
))
1309 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1316 //-----------------------------------------------------------------------------
1317 // "leave_notify_event"
1318 //-----------------------------------------------------------------------------
1320 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1323 wxapp_install_idle_handler();
1325 if (!win
->m_hasVMT
) return FALSE
;
1326 if (g_blockEventsOnDrag
) return FALSE
;
1328 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1330 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1331 #if (GTK_MINOR_VERSION > 0)
1332 event
.SetTimestamp( gdk_event
->time
);
1334 event
.SetEventObject( win
);
1338 GdkModifierType state
= (GdkModifierType
)0;
1340 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1342 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1343 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1344 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1345 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1346 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1347 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1348 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1350 event
.m_x
= (long)x
;
1351 event
.m_y
= (long)y
;
1353 if (win
->GetEventHandler()->ProcessEvent( event
))
1355 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1362 //-----------------------------------------------------------------------------
1363 // "value_changed" from m_vAdjust
1364 //-----------------------------------------------------------------------------
1366 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1369 wxapp_install_idle_handler();
1371 if (g_blockEventsOnDrag
) return;
1373 if (!win
->m_hasVMT
) return;
1375 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
1376 if (fabs(diff
) < 0.2) return;
1377 win
->m_oldVerticalPos
= win
->m_vAdjust
->value
;
1379 wxEventType command
= wxEVT_NULL
;
1381 float line_step
= win
->m_vAdjust
->step_increment
;
1382 float page_step
= win
->m_vAdjust
->page_increment
;
1384 if (win
->IsScrolling())
1386 command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1390 if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->lower
) < 0.2) command
= wxEVT_SCROLLWIN_BOTTOM
;
1391 else if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->upper
) < 0.2) command
= wxEVT_SCROLLWIN_TOP
;
1392 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1393 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEUP
;
1394 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1395 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEUP
;
1396 else command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1399 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1401 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1402 event
.SetEventObject( win
);
1403 win
->GetEventHandler()->ProcessEvent( event
);
1406 //-----------------------------------------------------------------------------
1407 // "value_changed" from m_hAdjust
1408 //-----------------------------------------------------------------------------
1410 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1413 wxapp_install_idle_handler();
1415 if (g_blockEventsOnDrag
) return;
1416 if (!win
->m_hasVMT
) return;
1418 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
1419 if (fabs(diff
) < 0.2) return;
1420 win
->m_oldHorizontalPos
= win
->m_hAdjust
->value
;
1422 wxEventType command
= wxEVT_NULL
;
1424 float line_step
= win
->m_hAdjust
->step_increment
;
1425 float page_step
= win
->m_hAdjust
->page_increment
;
1427 if (win
->IsScrolling())
1429 command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1433 if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->lower
) < 0.2) command
= wxEVT_SCROLLWIN_BOTTOM
;
1434 else if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->upper
) < 0.2) command
= wxEVT_SCROLLWIN_TOP
;
1435 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1436 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLLWIN_LINEUP
;
1437 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1438 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLLWIN_PAGEUP
;
1439 else command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1442 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1444 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1445 event
.SetEventObject( win
);
1446 win
->GetEventHandler()->ProcessEvent( event
);
1449 //-----------------------------------------------------------------------------
1450 // "changed" from m_vAdjust
1451 //-----------------------------------------------------------------------------
1453 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1456 wxapp_install_idle_handler();
1458 if (g_blockEventsOnDrag
) return;
1459 if (!win
->m_hasVMT
) return;
1461 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1462 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1464 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1465 event
.SetEventObject( win
);
1466 win
->GetEventHandler()->ProcessEvent( event
);
1469 //-----------------------------------------------------------------------------
1470 // "changed" from m_hAdjust
1471 //-----------------------------------------------------------------------------
1473 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1476 wxapp_install_idle_handler();
1478 if (g_blockEventsOnDrag
) return;
1479 if (!win
->m_hasVMT
) return;
1481 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1482 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1484 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1485 event
.SetEventObject( win
);
1486 win
->GetEventHandler()->ProcessEvent( event
);
1489 //-----------------------------------------------------------------------------
1490 // "button_press_event" from scrollbar
1491 //-----------------------------------------------------------------------------
1493 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1494 GdkEventButton
*WXUNUSED(gdk_event
),
1498 wxapp_install_idle_handler();
1500 // don't test here as we can release the mouse while being over
1501 // a different window then the slider
1503 // if (gdk_event->window != widget->slider) return FALSE;
1505 win
->SetScrolling( TRUE
);
1510 //-----------------------------------------------------------------------------
1511 // "button_release_event" from scrollbar
1512 //-----------------------------------------------------------------------------
1514 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1515 GdkEventButton
*WXUNUSED(gdk_event
),
1519 // don't test here as we can release the mouse while being over
1520 // a different window then the slider
1522 // if (gdk_event->window != widget->slider) return FALSE;
1524 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1526 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1527 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_hAdjust
), "value_changed" );
1529 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_vAdjust
), "value_changed" );
1531 win
->SetScrolling( FALSE
);
1536 // ----------------------------------------------------------------------------
1537 // this wxWindowBase function is implemented here (in platform-specific file)
1538 // because it is static and so couldn't be made virtual
1539 // ----------------------------------------------------------------------------
1541 wxWindow
*wxWindowBase::FindFocus()
1543 return g_focusWindow
;
1546 //-----------------------------------------------------------------------------
1547 // "realize" from m_widget
1548 //-----------------------------------------------------------------------------
1550 /* we cannot set colours, fonts and cursors before the widget has
1551 been realized, so we do this directly after realization */
1554 gtk_window_realized_callback( GtkWidget
* WXUNUSED(widget
), wxWindow
*win
)
1557 wxapp_install_idle_handler();
1559 if (win
->m_delayedFont
)
1560 win
->SetFont( win
->GetFont() );
1562 if (win
->m_delayedBackgroundColour
)
1563 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1565 if (win
->m_delayedForegroundColour
)
1566 win
->SetForegroundColour( win
->GetForegroundColour() );
1568 win
->SetCursor( win
->GetCursor() );
1570 wxWindowCreateEvent
event( win
);
1571 event
.SetEventObject( win
);
1572 win
->GetEventHandler()->ProcessEvent( event
);
1577 //-----------------------------------------------------------------------------
1578 // InsertChild for wxWindow.
1579 //-----------------------------------------------------------------------------
1581 /* Callback for wxWindow. This very strange beast has to be used because
1582 * C++ has no virtual methods in a constructor. We have to emulate a
1583 * virtual function here as wxNotebook requires a different way to insert
1584 * a child in it. I had opted for creating a wxNotebookPage window class
1585 * which would have made this superfluous (such in the MDI window system),
1586 * but no-one was listening to me... */
1588 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1590 gtk_myfixed_put( GTK_MYFIXED(parent
->m_wxwindow
),
1591 GTK_WIDGET(child
->m_widget
),
1597 if (parent
->HasFlag(wxTAB_TRAVERSAL
))
1599 /* we now allow a window to get the focus as long as it
1600 doesn't have any children. */
1601 GTK_WIDGET_UNSET_FLAGS( parent
->m_wxwindow
, GTK_CAN_FOCUS
);
1605 //-----------------------------------------------------------------------------
1607 //-----------------------------------------------------------------------------
1609 wxWindow
* wxGetActiveWindow()
1611 return g_focusWindow
;
1614 //-----------------------------------------------------------------------------
1616 //-----------------------------------------------------------------------------
1618 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1620 void wxWindow::Init()
1626 m_widget
= (GtkWidget
*) NULL
;
1627 m_wxwindow
= (GtkWidget
*) NULL
;
1637 m_needParent
= TRUE
;
1638 m_isBeingDeleted
= FALSE
;
1640 m_hasScrolling
= FALSE
;
1641 m_isScrolling
= FALSE
;
1643 m_hAdjust
= (GtkAdjustment
*) NULL
;
1644 m_vAdjust
= (GtkAdjustment
*) NULL
;
1645 m_oldHorizontalPos
= 0.0;
1646 m_oldVerticalPos
= 0.0;
1649 m_scrollGC
= (GdkGC
*) NULL
;
1650 m_widgetStyle
= (GtkStyle
*) NULL
;
1652 m_insertCallback
= (wxInsertChildFunction
) NULL
;
1654 m_isStaticBox
= FALSE
;
1655 m_acceptsFocus
= FALSE
;
1658 wxWindow::wxWindow()
1663 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1664 const wxPoint
&pos
, const wxSize
&size
,
1665 long style
, const wxString
&name
)
1669 Create( parent
, id
, pos
, size
, style
, name
);
1672 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1673 const wxPoint
&pos
, const wxSize
&size
,
1674 long style
, const wxString
&name
)
1676 PreCreation( parent
, id
, pos
, size
, style
, name
);
1678 m_insertCallback
= wxInsertChildInWindow
;
1680 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1681 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1684 debug_focus_in( m_widget
, _T("wxWindow::m_widget"), name
);
1687 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1690 debug_focus_in( scrolledWindow
->hscrollbar
, _T("wxWindow::hsrcollbar"), name
);
1691 debug_focus_in( scrolledWindow
->vscrollbar
, _T("wxWindow::vsrcollbar"), name
);
1694 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1695 scroll_class
->scrollbar_spacing
= 0;
1697 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1699 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
1700 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
1702 m_wxwindow
= gtk_myfixed_new();
1705 debug_focus_in( m_wxwindow
, _T("wxWindow::m_wxwindow"), name
);
1708 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1710 #if (GTK_MINOR_VERSION > 0)
1711 GtkMyFixed
*myfixed
= GTK_MYFIXED(m_wxwindow
);
1713 if (HasFlag(wxRAISED_BORDER
))
1715 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_OUT
);
1717 else if (HasFlag(wxSUNKEN_BORDER
))
1719 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_IN
);
1723 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_NONE
);
1725 #else // GTK_MINOR_VERSION == 0
1726 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
1728 if (HasFlag(wxRAISED_BORDER
))
1730 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1732 else if (HasFlag(wxSUNKEN_BORDER
))
1734 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1738 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1740 #endif // GTK_MINOR_VERSION
1742 if (HasFlag(wxTAB_TRAVERSAL
))
1744 /* we now allow a window to get the focus as long as it
1745 doesn't have any children. */
1746 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1747 m_acceptsFocus
= FALSE
;
1751 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1752 m_acceptsFocus
= TRUE
;
1755 #if (GTK_MINOR_VERSION == 0)
1756 // shut the viewport up
1757 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1758 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1759 #endif // GTK_MINOR_VERSION == 0
1761 // I _really_ don't want scrollbars in the beginning
1762 m_vAdjust
->lower
= 0.0;
1763 m_vAdjust
->upper
= 1.0;
1764 m_vAdjust
->value
= 0.0;
1765 m_vAdjust
->step_increment
= 1.0;
1766 m_vAdjust
->page_increment
= 1.0;
1767 m_vAdjust
->page_size
= 5.0;
1768 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1769 m_hAdjust
->lower
= 0.0;
1770 m_hAdjust
->upper
= 1.0;
1771 m_hAdjust
->value
= 0.0;
1772 m_hAdjust
->step_increment
= 1.0;
1773 m_hAdjust
->page_increment
= 1.0;
1774 m_hAdjust
->page_size
= 5.0;
1775 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1777 // these handlers block mouse events to any window during scrolling such as
1778 // motion events and prevent GTK and wxWindows from fighting over where the
1781 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
1782 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1784 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
1785 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1787 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
1788 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1790 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
1791 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1793 // these handlers get notified when screen updates are required either when
1794 // scrolling or when the window size (and therefore scrollbar configuration)
1797 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
1798 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
1799 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
1800 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
1802 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
1803 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
1804 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
1805 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
1807 gtk_widget_show( m_wxwindow
);
1810 m_parent
->DoAddChild( this );
1819 wxWindow::~wxWindow()
1821 m_isBeingDeleted
= TRUE
;
1830 m_parent
->RemoveChild( this );
1834 gtk_style_unref( m_widgetStyle
);
1835 m_widgetStyle
= (GtkStyle
*) NULL
;
1840 gdk_gc_unref( m_scrollGC
);
1841 m_scrollGC
= (GdkGC
*) NULL
;
1846 gtk_widget_destroy( m_wxwindow
);
1847 m_wxwindow
= (GtkWidget
*) NULL
;
1852 gtk_widget_destroy( m_widget
);
1853 m_widget
= (GtkWidget
*) NULL
;
1857 void wxWindow::PreCreation( wxWindow
*parent
,
1862 const wxString
&name
)
1864 wxASSERT_MSG( !m_needParent
|| parent
, _T("Need complete parent.") );
1866 if ( !CreateBase(parent
, id
, pos
, size
, style
, name
) )
1868 wxFAIL_MSG(_T("window creation failed"));
1871 m_width
= WidthDefault(size
.x
);
1872 m_height
= HeightDefault(size
.y
);
1877 if (!parent
) /* some reasonable defaults */
1881 m_x
= (gdk_screen_width () - m_width
) / 2;
1882 if (m_x
< 10) m_x
= 10;
1886 m_y
= (gdk_screen_height () - m_height
) / 2;
1887 if (m_y
< 10) m_y
= 10;
1892 void wxWindow::PostCreation()
1894 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1898 /* these get reported to wxWindows -> wxPaintEvent */
1899 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1900 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1902 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1903 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1905 #if (GTK_MINOR_VERSION > 0)
1906 /* these are called when the "sunken" or "raised" borders are drawn */
1907 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
1908 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
1910 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
1911 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
1915 GtkWidget
*connect_widget
= GetConnectWidget();
1917 ConnectWidget( connect_widget
);
1919 /* we cannot set colours, fonts and cursors before the widget has
1920 been realized, so we do this directly after realization */
1921 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
1922 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
1927 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1929 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1930 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1932 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
1933 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
1935 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1936 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1938 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1939 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1941 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1942 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1944 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1945 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1947 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1948 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1950 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1951 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1953 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1954 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1957 bool wxWindow::Destroy()
1959 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1963 return wxWindowBase::Destroy();
1966 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1968 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1969 wxASSERT_MSG( (m_parent
!= NULL
), _T("wxWindow::SetSize requires parent.\n") );
1971 if (m_resizing
) return; /* I don't like recursions */
1974 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
1976 /* don't set the size for children of wxNotebook, just take the values. */
1984 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1986 if (x
!= -1) m_x
= x
;
1987 if (y
!= -1) m_y
= y
;
1988 if (width
!= -1) m_width
= width
;
1989 if (height
!= -1) m_height
= height
;
1999 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2001 if (width
== -1) m_width
= 80;
2004 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2006 if (height
== -1) m_height
= 26;
2009 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2010 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2011 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2012 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2015 int bottom_border
= 0;
2017 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2019 /* the default button has a border around it */
2024 /* this is the result of hours of debugging: the following code
2025 means that if we have a m_wxwindow and we set the size of
2026 m_widget, m_widget (which is a GtkScrolledWindow) does NOT
2027 automatically propagate its size down to its m_wxwindow,
2028 which is its client area. therefore, we have to tell the
2029 client area directly that it has to resize itself.
2030 this will lead to that m_widget (GtkScrolledWindow) will
2031 calculate how much size it needs for scrollbars etc and
2032 it will then call XXX_size_allocate of its child, which
2033 is m_wxwindow. m_wxwindow in turn will do the same with its
2034 children and so on. problems can arise if this happens
2035 before all the children have been realized as some widgets
2036 stupidy need to be realized during XXX_size_allocate (e.g.
2037 GtkNotebook) and they will segv if called otherwise. this
2038 emergency is tested in gtk_myfixed_size_allocate. Normally
2039 this shouldn't be needed and only gtk_widget_queue_resize()
2040 should be enough to provoke a resize at the next appropriate
2041 moment, but this seems to fail, e.g. when a wxNotebook contains
2042 a wxSplitterWindow: the splitter window's children won't
2043 show up properly resized then. */
2045 gtk_myfixed_set_size( GTK_MYFIXED(m_parent
->m_wxwindow
),
2050 m_height
+border
+bottom_border
);
2055 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2056 event
.SetEventObject( this );
2057 GetEventHandler()->ProcessEvent( event
);
2062 void wxWindow::OnInternalIdle()
2064 GdkWindow
*window
= GetConnectWidget()->window
;
2067 wxCursor cursor
= m_cursor
;
2068 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2070 if (m_currentGdkCursor
!= cursor
)
2072 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2073 m_currentGdkCursor
= cursor
;
2080 void wxWindow::DoGetSize( int *width
, int *height
) const
2082 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2084 if (width
) (*width
) = m_width
;
2085 if (height
) (*height
) = m_height
;
2088 void wxWindow::DoSetClientSize( int width
, int height
)
2090 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2094 SetSize( width
, height
);
2101 if (!m_hasScrolling
)
2103 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
2105 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2107 dw
+= 2 * window_class
->xthickness
;
2108 dh
+= 2 * window_class
->ythickness
;
2113 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2114 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2116 #if (GTK_MINOR_VERSION == 0)
2117 GtkWidget
*viewport
= scroll_window
->viewport
;
2118 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2120 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2122 dw
+= 2 * viewport_class
->xthickness
;
2123 dh
+= 2 * viewport_class
->ythickness
;
2128 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2129 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2131 we use this instead: range.slider_width = 11 + 2*2pts edge
2134 if (scroll_window
->vscrollbar_visible
)
2136 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2137 dw
+= scroll_class
->scrollbar_spacing
;
2140 if (scroll_window
->hscrollbar_visible
)
2142 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2143 dh
+= scroll_class
->scrollbar_spacing
;
2147 SetSize( width
+dw
, height
+dh
);
2151 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2153 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2157 if (width
) (*width
) = m_width
;
2158 if (height
) (*height
) = m_height
;
2165 if (!m_hasScrolling
)
2167 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
2169 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2171 dw
+= 2 * window_class
->xthickness
;
2172 dh
+= 2 * window_class
->ythickness
;
2177 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2178 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2180 #if (GTK_MINOR_VERSION == 0)
2181 GtkWidget
*viewport
= scroll_window
->viewport
;
2182 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2184 if ( HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
) )
2186 dw
+= 2 * viewport_class
->xthickness
;
2187 dh
+= 2 * viewport_class
->ythickness
;
2191 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2192 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2194 we use this instead: range.slider_width = 11 + 2*2pts edge
2197 if (scroll_window
->vscrollbar_visible
)
2199 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2200 dw
+= scroll_class
->scrollbar_spacing
;
2203 if (scroll_window
->hscrollbar_visible
)
2205 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2206 dh
+= scroll_class
->scrollbar_spacing
;
2210 if (width
) (*width
) = m_width
- dw
;
2211 if (height
) (*height
) = m_height
- dh
;
2215 void wxWindow::DoGetPosition( int *x
, int *y
) const
2217 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2223 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2225 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2227 if (!m_widget
->window
) return;
2229 GdkWindow
*source
= (GdkWindow
*) NULL
;
2231 source
= m_wxwindow
->window
;
2233 source
= m_widget
->window
;
2237 gdk_window_get_origin( source
, &org_x
, &org_y
);
2241 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2243 org_x
+= m_widget
->allocation
.x
;
2244 org_y
+= m_widget
->allocation
.y
;
2252 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2254 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2256 if (!m_widget
->window
) return;
2258 GdkWindow
*source
= (GdkWindow
*) NULL
;
2260 source
= m_wxwindow
->window
;
2262 source
= m_widget
->window
;
2266 gdk_window_get_origin( source
, &org_x
, &org_y
);
2270 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2272 org_x
+= m_widget
->allocation
.x
;
2273 org_y
+= m_widget
->allocation
.y
;
2281 bool wxWindow::Show( bool show
)
2283 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2285 if (!wxWindowBase::Show(show
))
2292 gtk_widget_show( m_widget
);
2294 gtk_widget_hide( m_widget
);
2299 bool wxWindow::Enable( bool enable
)
2301 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2303 if (!wxWindowBase::Enable(enable
))
2309 gtk_widget_set_sensitive( m_widget
, enable
);
2311 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2316 int wxWindow::GetCharHeight() const
2318 wxCHECK_MSG( (m_widget
!= NULL
), 12, _T("invalid window") );
2320 wxCHECK_MSG( m_font
.Ok(), 12, _T("invalid font") );
2322 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2324 return font
->ascent
+ font
->descent
;
2327 int wxWindow::GetCharWidth() const
2329 wxCHECK_MSG( (m_widget
!= NULL
), 8, _T("invalid window") );
2331 wxCHECK_MSG( m_font
.Ok(), 8, _T("invalid font") );
2333 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2335 return gdk_string_width( font
, "H" );
2338 void wxWindow::GetTextExtent( const wxString
& string
,
2342 int *externalLeading
,
2343 const wxFont
*theFont
) const
2345 wxFont fontToUse
= m_font
;
2346 if (theFont
) fontToUse
= *theFont
;
2348 wxCHECK_RET( fontToUse
.Ok(), _T("invalid font") );
2350 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2351 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2352 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2353 if (descent
) (*descent
) = font
->descent
;
2354 if (externalLeading
) (*externalLeading
) = 0; // ??
2357 void wxWindow::SetFocus()
2359 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2361 GtkWidget
*connect_widget
= GetConnectWidget();
2364 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2366 gtk_widget_grab_focus (connect_widget
);
2368 else if (GTK_IS_CONTAINER(connect_widget
))
2370 gtk_container_focus( GTK_CONTAINER(connect_widget
), GTK_DIR_TAB_FORWARD
);
2378 bool wxWindow::AcceptsFocus() const
2380 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2383 bool wxWindow::Reparent( wxWindow
*newParent
)
2385 wxCHECK_MSG( (m_widget
!= NULL
), (wxWindow
*) NULL
, _T("invalid window") );
2387 gtk_widget_unparent( m_widget
);
2389 if ( !wxWindowBase::Reparent(newParent
) )
2395 void wxWindow::DoAddChild(wxWindow
*child
)
2397 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
2399 wxASSERT_MSG( (child
!= NULL
), _T("invalid child window") );
2401 wxASSERT_MSG( (m_insertCallback
!= NULL
), _T("invalid child insertion function") );
2406 /* insert GTK representation */
2407 (*m_insertCallback
)(this, child
);
2410 void wxWindow::Raise()
2412 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2414 if (!m_widget
->window
) return;
2416 gdk_window_raise( m_widget
->window
);
2419 void wxWindow::Lower()
2421 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2423 if (!m_widget
->window
) return;
2425 gdk_window_lower( m_widget
->window
);
2428 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2430 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2432 if (!wxWindowBase::SetCursor(cursor
))
2434 // don't leave if the GTK widget has just
2436 if (!m_delayedCursor
) return FALSE
;
2439 GtkWidget
*connect_widget
= GetConnectWidget();
2440 if (!connect_widget
->window
)
2442 // indicate that a new style has been set
2443 // but it couldn't get applied as the
2444 // widget hasn't been realized yet.
2445 m_delayedCursor
= TRUE
;
2447 // pretend we have done something
2451 // gdk_window_set_cursor( connect_widget->window, GetCursor().GetCursor() );
2457 void wxWindow::WarpPointer( int x
, int y
)
2459 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2461 GtkWidget
*connect_widget
= GetConnectWidget();
2462 if (connect_widget
->window
)
2464 /* we provide this function ourselves as it is
2466 gdk_window_warp_pointer( connect_widget
->window
, x
, y
);
2470 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2472 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2474 if (!m_widget
->window
) return;
2476 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2480 gdk_window_clear_area( m_wxwindow
->window
,
2482 rect
->width
, rect
->height
);
2486 gdk_window_clear( m_wxwindow
->window
);
2493 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2495 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2499 GdkRectangle gdk_rect
;
2500 gdk_rect
.x
= rect
->x
;
2501 gdk_rect
.y
= rect
->y
;
2502 gdk_rect
.width
= rect
->width
;
2503 gdk_rect
.height
= rect
->height
;
2506 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2508 gtk_widget_draw( m_widget
, &gdk_rect
);
2512 void wxWindow::Clear()
2514 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2516 if (!m_widget
->window
) return;
2518 if (m_wxwindow
&& m_wxwindow
->window
)
2520 gdk_window_clear( m_wxwindow
->window
);
2525 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2527 wxWindowBase::DoSetToolTip(tip
);
2530 m_tooltip
->Apply( this );
2533 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2535 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConv_current
->cWX2MB(tip
), (gchar
*) NULL
);
2537 #endif // wxUSE_TOOLTIPS
2539 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2541 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2543 if (!wxWindowBase::SetBackgroundColour(colour
))
2545 // don't leave if the GTK widget has just
2547 if (!m_delayedBackgroundColour
) return FALSE
;
2550 GtkWidget
*connect_widget
= GetConnectWidget();
2551 if (!connect_widget
->window
)
2553 // indicate that a new style has been set
2554 // but it couldn't get applied as the
2555 // widget hasn't been realized yet.
2556 m_delayedBackgroundColour
= TRUE
;
2558 // pretend we have done something
2562 if (m_wxwindow
&& m_wxwindow
->window
)
2564 /* wxMSW doesn't clear the window here. I don't do that either to
2565 provide compatibility. call Clear() to do the job. */
2567 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_wxwindow
->window
) );
2568 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
2571 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2573 if (sysbg
== m_backgroundColour
)
2575 m_backgroundColour
= wxNullColour
;
2577 m_backgroundColour
= sysbg
;
2587 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2589 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2591 if (!wxWindowBase::SetForegroundColour(colour
))
2593 // don't leave if the GTK widget has just
2595 if (!m_delayedForegroundColour
) return FALSE
;
2598 GtkWidget
*connect_widget
= GetConnectWidget();
2599 if (!connect_widget
->window
)
2601 // indicate that a new style has been set
2602 // but it couldn't get applied as the
2603 // widget hasn't been realized yet.
2604 m_delayedForegroundColour
= TRUE
;
2606 // pretend we have done something
2610 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2611 if (sysbg
== m_foregroundColour
)
2613 m_backgroundColour
= wxNullColour
;
2615 m_backgroundColour
= sysbg
;
2625 GtkStyle
*wxWindow::GetWidgetStyle()
2627 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2629 m_widgetStyle
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2631 return m_widgetStyle
;
2634 void wxWindow::SetWidgetStyle()
2636 GtkStyle
*style
= GetWidgetStyle();
2638 gdk_font_unref( style
->font
);
2639 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2641 if (m_foregroundColour
.Ok())
2643 m_foregroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2644 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2645 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2646 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2649 if (m_backgroundColour
.Ok())
2651 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2652 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2653 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2654 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2655 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2656 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2657 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2658 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2659 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2663 void wxWindow::ApplyWidgetStyle()
2667 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2669 menu
->SetInvokingWindow( win
);
2670 wxNode
*node
= menu
->GetItems().First();
2673 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2674 if (menuitem
->IsSubMenu())
2676 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2678 node
= node
->Next();
2682 static gint gs_pop_x
= 0;
2683 static gint gs_pop_y
= 0;
2685 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
2689 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
2694 bool wxWindow::PopupMenu( wxMenu
*menu
, int x
, int y
)
2696 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2698 wxCHECK_MSG( menu
!= NULL
, FALSE
, _T("invalid popup-menu") );
2700 SetInvokingWindow( menu
, this );
2708 GTK_MENU(menu
->m_menu
),
2709 (GtkWidget
*) NULL
, // parent menu shell
2710 (GtkWidget
*) NULL
, // parent menu item
2711 (GtkMenuPositionFunc
) pop_pos_callback
,
2712 (gpointer
) this, // client data
2713 0, // button used to activate it
2714 0 //gs_timeLastClick // the time of activation
2719 #if wxUSE_DRAG_AND_DROP
2721 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2723 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2725 GtkWidget
*dnd_widget
= GetConnectWidget();
2727 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
2729 if (m_dropTarget
) delete m_dropTarget
;
2730 m_dropTarget
= dropTarget
;
2732 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
2735 #endif // wxUSE_DRAG_AND_DROP
2737 GtkWidget
* wxWindow::GetConnectWidget()
2739 GtkWidget
*connect_widget
= m_widget
;
2740 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2742 return connect_widget
;
2745 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2747 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2748 return (window
== m_widget
->window
);
2751 bool wxWindow::SetFont( const wxFont
&font
)
2753 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T( "invalid window") );
2755 if (!wxWindowBase::SetFont(font
))
2757 // don't leave if the GTK widget has just
2759 if (!m_delayedFont
) return FALSE
;
2762 GtkWidget
*connect_widget
= GetConnectWidget();
2763 if (!connect_widget
->window
)
2765 // indicate that a new style has been set
2766 // but it couldn't get applied as the
2767 // widget hasn't been realized yet.
2768 m_delayedFont
= TRUE
;
2770 // pretend we have done something
2774 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2775 if ( sysbg
== m_backgroundColour
)
2777 m_backgroundColour
= wxNullColour
;
2779 m_backgroundColour
= sysbg
;
2789 void wxWindow::CaptureMouse()
2791 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2793 wxCHECK_RET( g_capturing
== FALSE
, _T("CaptureMouse called twice") );
2795 GtkWidget
*connect_widget
= GetConnectWidget();
2796 if (!connect_widget
->window
) return;
2798 gtk_grab_add( connect_widget
);
2799 gdk_pointer_grab( connect_widget
->window
, FALSE
,
2801 (GDK_BUTTON_PRESS_MASK
|
2802 GDK_BUTTON_RELEASE_MASK
|
2803 GDK_POINTER_MOTION_MASK
),
2810 void wxWindow::ReleaseMouse()
2812 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2814 wxCHECK_RET( g_capturing
== TRUE
, _T("ReleaseMouse called twice") );
2816 GtkWidget
*connect_widget
= GetConnectWidget();
2817 if (!connect_widget
->window
) return;
2819 gtk_grab_remove( connect_widget
);
2820 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2821 g_capturing
= FALSE
;
2824 bool wxWindow::IsRetained() const
2829 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2830 int range
, bool refresh
)
2832 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2834 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2836 m_hasScrolling
= TRUE
;
2838 if (orient
== wxHORIZONTAL
)
2840 float fpos
= (float)pos
;
2841 float frange
= (float)range
;
2842 float fthumb
= (float)thumbVisible
;
2843 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2844 if (fpos
< 0.0) fpos
= 0.0;
2846 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2847 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2849 SetScrollPos( orient
, pos
, refresh
);
2853 m_oldHorizontalPos
= fpos
;
2855 m_hAdjust
->lower
= 0.0;
2856 m_hAdjust
->upper
= frange
;
2857 m_hAdjust
->value
= fpos
;
2858 m_hAdjust
->step_increment
= 1.0;
2859 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2860 m_hAdjust
->page_size
= fthumb
;
2864 float fpos
= (float)pos
;
2865 float frange
= (float)range
;
2866 float fthumb
= (float)thumbVisible
;
2867 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2868 if (fpos
< 0.0) fpos
= 0.0;
2870 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2871 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2873 SetScrollPos( orient
, pos
, refresh
);
2877 m_oldVerticalPos
= fpos
;
2879 m_vAdjust
->lower
= 0.0;
2880 m_vAdjust
->upper
= frange
;
2881 m_vAdjust
->value
= fpos
;
2882 m_vAdjust
->step_increment
= 1.0;
2883 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2884 m_vAdjust
->page_size
= fthumb
;
2887 if (orient
== wxHORIZONTAL
)
2888 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2890 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2893 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2895 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2897 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2899 if (orient
== wxHORIZONTAL
)
2901 float fpos
= (float)pos
;
2902 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
2903 if (fpos
< 0.0) fpos
= 0.0;
2904 m_oldHorizontalPos
= fpos
;
2906 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2907 m_hAdjust
->value
= fpos
;
2911 float fpos
= (float)pos
;
2912 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
2913 if (fpos
< 0.0) fpos
= 0.0;
2914 m_oldVerticalPos
= fpos
;
2916 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2917 m_vAdjust
->value
= fpos
;
2920 if (!m_isScrolling
) /* prevent recursion */
2922 if (m_wxwindow
->window
)
2924 if (orient
== wxHORIZONTAL
)
2925 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2927 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2932 int wxWindow::GetScrollThumb( int orient
) const
2934 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2936 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2938 if (orient
== wxHORIZONTAL
)
2939 return (int)(m_hAdjust
->page_size
+0.5);
2941 return (int)(m_vAdjust
->page_size
+0.5);
2944 int wxWindow::GetScrollPos( int orient
) const
2946 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2948 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2950 if (orient
== wxHORIZONTAL
)
2951 return (int)(m_hAdjust
->value
+0.5);
2953 return (int)(m_vAdjust
->value
+0.5);
2956 int wxWindow::GetScrollRange( int orient
) const
2958 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2960 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2962 if (orient
== wxHORIZONTAL
)
2963 return (int)(m_hAdjust
->upper
+0.5);
2965 return (int)(m_vAdjust
->upper
+0.5);
2968 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2970 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2972 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2976 m_scrollGC
= gdk_gc_new( m_wxwindow
->window
);
2977 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
2980 wxNode
*node
= m_children
.First();
2983 wxWindow
*child
= (wxWindow
*) node
->Data();
2984 child
->Move( child
->m_x
+ dx
, child
->m_y
+ dy
);
2985 node
= node
->Next();
2990 GetClientSize( &cw
, &ch
);
2991 int w
= cw
- abs(dx
);
2992 int h
= ch
- abs(dy
);
2994 if ((h
< 0) || (w
< 0))
3002 if (dx
< 0) s_x
= -dx
;
3003 if (dy
< 0) s_y
= -dy
;
3006 if (dx
> 0) d_x
= dx
;
3007 if (dy
> 0) d_y
= dy
;
3009 gdk_window_copy_area( m_wxwindow
->window
, m_scrollGC
, d_x
, d_y
,
3010 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
3013 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
3014 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
3015 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
3016 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
3018 Refresh( TRUE
, &rect
);
3022 void wxWindow::SetScrolling(bool scroll
)
3024 m_isScrolling
= g_blockEventsOnScroll
= scroll
;