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 wxWindow
*oldParent
= m_parent
;
2389 if ( !wxWindowBase::Reparent(newParent
) )
2394 gtk_container_remove( GTK_CONTAINER(oldParent
->m_wxwindow
), m_widget
);
2399 /* insert GTK representation */
2400 (*(newParent
->m_insertCallback
))(newParent
, this);
2406 void wxWindow::DoAddChild(wxWindow
*child
)
2408 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
2410 wxASSERT_MSG( (child
!= NULL
), _T("invalid child window") );
2412 wxASSERT_MSG( (m_insertCallback
!= NULL
), _T("invalid child insertion function") );
2417 /* insert GTK representation */
2418 (*m_insertCallback
)(this, child
);
2421 void wxWindow::Raise()
2423 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2425 if (!m_widget
->window
) return;
2427 gdk_window_raise( m_widget
->window
);
2430 void wxWindow::Lower()
2432 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2434 if (!m_widget
->window
) return;
2436 gdk_window_lower( m_widget
->window
);
2439 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2441 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2443 if (!wxWindowBase::SetCursor(cursor
))
2445 // don't leave if the GTK widget has just
2447 if (!m_delayedCursor
) return FALSE
;
2450 GtkWidget
*connect_widget
= GetConnectWidget();
2451 if (!connect_widget
->window
)
2453 // indicate that a new style has been set
2454 // but it couldn't get applied as the
2455 // widget hasn't been realized yet.
2456 m_delayedCursor
= TRUE
;
2458 // pretend we have done something
2462 // gdk_window_set_cursor( connect_widget->window, GetCursor().GetCursor() );
2468 void wxWindow::WarpPointer( int x
, int y
)
2470 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2472 GtkWidget
*connect_widget
= GetConnectWidget();
2473 if (connect_widget
->window
)
2475 /* we provide this function ourselves as it is
2477 gdk_window_warp_pointer( connect_widget
->window
, x
, y
);
2481 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2483 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2485 if (!m_widget
->window
) return;
2487 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2491 gdk_window_clear_area( m_wxwindow
->window
,
2493 rect
->width
, rect
->height
);
2497 gdk_window_clear( m_wxwindow
->window
);
2504 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2506 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2510 GdkRectangle gdk_rect
;
2511 gdk_rect
.x
= rect
->x
;
2512 gdk_rect
.y
= rect
->y
;
2513 gdk_rect
.width
= rect
->width
;
2514 gdk_rect
.height
= rect
->height
;
2517 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2519 gtk_widget_draw( m_widget
, &gdk_rect
);
2523 void wxWindow::Clear()
2525 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2527 if (!m_widget
->window
) return;
2529 if (m_wxwindow
&& m_wxwindow
->window
)
2531 gdk_window_clear( m_wxwindow
->window
);
2536 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2538 wxWindowBase::DoSetToolTip(tip
);
2541 m_tooltip
->Apply( this );
2544 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2546 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConv_current
->cWX2MB(tip
), (gchar
*) NULL
);
2548 #endif // wxUSE_TOOLTIPS
2550 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2552 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2554 if (!wxWindowBase::SetBackgroundColour(colour
))
2556 // don't leave if the GTK widget has just
2558 if (!m_delayedBackgroundColour
) return FALSE
;
2561 GtkWidget
*connect_widget
= GetConnectWidget();
2562 if (!connect_widget
->window
)
2564 // indicate that a new style has been set
2565 // but it couldn't get applied as the
2566 // widget hasn't been realized yet.
2567 m_delayedBackgroundColour
= TRUE
;
2569 // pretend we have done something
2573 if (m_wxwindow
&& m_wxwindow
->window
)
2575 /* wxMSW doesn't clear the window here. I don't do that either to
2576 provide compatibility. call Clear() to do the job. */
2578 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_wxwindow
->window
) );
2579 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
2582 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2584 if (sysbg
== m_backgroundColour
)
2586 m_backgroundColour
= wxNullColour
;
2588 m_backgroundColour
= sysbg
;
2598 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2600 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2602 if (!wxWindowBase::SetForegroundColour(colour
))
2604 // don't leave if the GTK widget has just
2606 if (!m_delayedForegroundColour
) return FALSE
;
2609 GtkWidget
*connect_widget
= GetConnectWidget();
2610 if (!connect_widget
->window
)
2612 // indicate that a new style has been set
2613 // but it couldn't get applied as the
2614 // widget hasn't been realized yet.
2615 m_delayedForegroundColour
= TRUE
;
2617 // pretend we have done something
2621 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2622 if (sysbg
== m_foregroundColour
)
2624 m_backgroundColour
= wxNullColour
;
2626 m_backgroundColour
= sysbg
;
2636 GtkStyle
*wxWindow::GetWidgetStyle()
2638 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2640 m_widgetStyle
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2642 return m_widgetStyle
;
2645 void wxWindow::SetWidgetStyle()
2647 GtkStyle
*style
= GetWidgetStyle();
2649 gdk_font_unref( style
->font
);
2650 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2652 if (m_foregroundColour
.Ok())
2654 m_foregroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2655 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2656 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2657 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2660 if (m_backgroundColour
.Ok())
2662 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2663 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2664 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2665 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2666 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2667 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2668 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2669 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2670 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2674 void wxWindow::ApplyWidgetStyle()
2678 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2680 menu
->SetInvokingWindow( win
);
2681 wxNode
*node
= menu
->GetItems().First();
2684 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2685 if (menuitem
->IsSubMenu())
2687 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2689 node
= node
->Next();
2693 static gint gs_pop_x
= 0;
2694 static gint gs_pop_y
= 0;
2696 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
2700 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
2705 bool wxWindow::PopupMenu( wxMenu
*menu
, int x
, int y
)
2707 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2709 wxCHECK_MSG( menu
!= NULL
, FALSE
, _T("invalid popup-menu") );
2711 SetInvokingWindow( menu
, this );
2719 GTK_MENU(menu
->m_menu
),
2720 (GtkWidget
*) NULL
, // parent menu shell
2721 (GtkWidget
*) NULL
, // parent menu item
2722 (GtkMenuPositionFunc
) pop_pos_callback
,
2723 (gpointer
) this, // client data
2724 0, // button used to activate it
2725 0 //gs_timeLastClick // the time of activation
2730 #if wxUSE_DRAG_AND_DROP
2732 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2734 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2736 GtkWidget
*dnd_widget
= GetConnectWidget();
2738 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
2740 if (m_dropTarget
) delete m_dropTarget
;
2741 m_dropTarget
= dropTarget
;
2743 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
2746 #endif // wxUSE_DRAG_AND_DROP
2748 GtkWidget
* wxWindow::GetConnectWidget()
2750 GtkWidget
*connect_widget
= m_widget
;
2751 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2753 return connect_widget
;
2756 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2758 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2759 return (window
== m_widget
->window
);
2762 bool wxWindow::SetFont( const wxFont
&font
)
2764 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T( "invalid window") );
2766 if (!wxWindowBase::SetFont(font
))
2768 // don't leave if the GTK widget has just
2770 if (!m_delayedFont
) return FALSE
;
2773 GtkWidget
*connect_widget
= GetConnectWidget();
2774 if (!connect_widget
->window
)
2776 // indicate that a new style has been set
2777 // but it couldn't get applied as the
2778 // widget hasn't been realized yet.
2779 m_delayedFont
= TRUE
;
2781 // pretend we have done something
2785 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2786 if ( sysbg
== m_backgroundColour
)
2788 m_backgroundColour
= wxNullColour
;
2790 m_backgroundColour
= sysbg
;
2800 void wxWindow::CaptureMouse()
2802 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2804 wxCHECK_RET( g_capturing
== FALSE
, _T("CaptureMouse called twice") );
2806 GtkWidget
*connect_widget
= GetConnectWidget();
2807 if (!connect_widget
->window
) return;
2809 gtk_grab_add( connect_widget
);
2810 gdk_pointer_grab( connect_widget
->window
, FALSE
,
2812 (GDK_BUTTON_PRESS_MASK
|
2813 GDK_BUTTON_RELEASE_MASK
|
2814 GDK_POINTER_MOTION_MASK
),
2821 void wxWindow::ReleaseMouse()
2823 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2825 wxCHECK_RET( g_capturing
== TRUE
, _T("ReleaseMouse called twice") );
2827 GtkWidget
*connect_widget
= GetConnectWidget();
2828 if (!connect_widget
->window
) return;
2830 gtk_grab_remove( connect_widget
);
2831 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2832 g_capturing
= FALSE
;
2835 bool wxWindow::IsRetained() const
2840 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2841 int range
, bool refresh
)
2843 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2845 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2847 m_hasScrolling
= TRUE
;
2849 if (orient
== wxHORIZONTAL
)
2851 float fpos
= (float)pos
;
2852 float frange
= (float)range
;
2853 float fthumb
= (float)thumbVisible
;
2854 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2855 if (fpos
< 0.0) fpos
= 0.0;
2857 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2858 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2860 SetScrollPos( orient
, pos
, refresh
);
2864 m_oldHorizontalPos
= fpos
;
2866 m_hAdjust
->lower
= 0.0;
2867 m_hAdjust
->upper
= frange
;
2868 m_hAdjust
->value
= fpos
;
2869 m_hAdjust
->step_increment
= 1.0;
2870 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2871 m_hAdjust
->page_size
= fthumb
;
2875 float fpos
= (float)pos
;
2876 float frange
= (float)range
;
2877 float fthumb
= (float)thumbVisible
;
2878 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2879 if (fpos
< 0.0) fpos
= 0.0;
2881 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2882 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2884 SetScrollPos( orient
, pos
, refresh
);
2888 m_oldVerticalPos
= fpos
;
2890 m_vAdjust
->lower
= 0.0;
2891 m_vAdjust
->upper
= frange
;
2892 m_vAdjust
->value
= fpos
;
2893 m_vAdjust
->step_increment
= 1.0;
2894 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2895 m_vAdjust
->page_size
= fthumb
;
2898 if (orient
== wxHORIZONTAL
)
2899 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2901 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2904 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2906 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2908 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2910 if (orient
== wxHORIZONTAL
)
2912 float fpos
= (float)pos
;
2913 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
2914 if (fpos
< 0.0) fpos
= 0.0;
2915 m_oldHorizontalPos
= fpos
;
2917 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2918 m_hAdjust
->value
= fpos
;
2922 float fpos
= (float)pos
;
2923 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
2924 if (fpos
< 0.0) fpos
= 0.0;
2925 m_oldVerticalPos
= fpos
;
2927 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2928 m_vAdjust
->value
= fpos
;
2931 if (!m_isScrolling
) /* prevent recursion */
2933 if (m_wxwindow
->window
)
2935 if (orient
== wxHORIZONTAL
)
2936 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2938 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2943 int wxWindow::GetScrollThumb( int orient
) const
2945 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2947 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2949 if (orient
== wxHORIZONTAL
)
2950 return (int)(m_hAdjust
->page_size
+0.5);
2952 return (int)(m_vAdjust
->page_size
+0.5);
2955 int wxWindow::GetScrollPos( int orient
) const
2957 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2959 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2961 if (orient
== wxHORIZONTAL
)
2962 return (int)(m_hAdjust
->value
+0.5);
2964 return (int)(m_vAdjust
->value
+0.5);
2967 int wxWindow::GetScrollRange( int orient
) const
2969 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2971 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2973 if (orient
== wxHORIZONTAL
)
2974 return (int)(m_hAdjust
->upper
+0.5);
2976 return (int)(m_vAdjust
->upper
+0.5);
2979 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2981 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2983 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2987 m_scrollGC
= gdk_gc_new( m_wxwindow
->window
);
2988 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
2991 wxNode
*node
= m_children
.First();
2994 wxWindow
*child
= (wxWindow
*) node
->Data();
2995 child
->Move( child
->m_x
+ dx
, child
->m_y
+ dy
);
2996 node
= node
->Next();
3001 GetClientSize( &cw
, &ch
);
3002 int w
= cw
- abs(dx
);
3003 int h
= ch
- abs(dy
);
3005 if ((h
< 0) || (w
< 0))
3013 if (dx
< 0) s_x
= -dx
;
3014 if (dy
< 0) s_y
= -dy
;
3017 if (dx
> 0) d_x
= dx
;
3018 if (dy
> 0) d_y
= dy
;
3020 gdk_window_copy_area( m_wxwindow
->window
, m_scrollGC
, d_x
, d_y
,
3021 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
3024 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
3025 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
3026 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
3027 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
3029 Refresh( TRUE
, &rect
);
3033 void wxWindow::SetScrolling(bool scroll
)
3035 m_isScrolling
= g_blockEventsOnScroll
= scroll
;