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"
24 #include "wx/dcclient.h"
27 #include "wx/statusbr.h"
29 #include "gdk/gdkprivate.h"
30 #include "gdk/gdkkeysyms.h"
34 //-----------------------------------------------------------------------------
35 // documentation on internals
36 //-----------------------------------------------------------------------------
39 I have been asked several times about writing some documentation about
40 the GTK port of wxWindows, especially its internal structures. Obviously,
41 you cannot understand wxGTK without knowing a little about the GTK, but
42 some more information about what the wxWindow, which is the base class
43 for all other window classes, does seems required as well.
45 What does wxWindow do? It contains the common interface for the following
46 jobs of its descentants:
48 1) Define the rudimentary behaviour common to all window classes, such as
49 resizing, intercepting user input so as to make it possible to use these
50 events for special purposes in a derived class, window names etc.
52 2) Provide the possibility to contain and manage children, if the derived
53 class is allowed to contain children, which holds true for those window
54 classes, which do not display a native GTK widget. To name them, these
55 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
56 work classes are a special case and are handled a bit differently from
59 3) Provide the possibility to draw into a client area of a window. This,
60 too, only holds true for classes that do not display a native GTK widget
63 4) Provide the entire mechanism for scrolling widgets. This actaul inter-
64 face for this is usually in wxScrolledWidget, but the GTK implementation
67 5) A multitude of helper or extra methods for special purposes, such as
68 Drag'n'Drop, managing validators etc.
70 Normally one might expect, that one wxWindows class would always contain
71 one GTK widget. Under GTK, there is no such allround widget that has all
72 the functionality. Moreover, the GTK defines a client area as a different
73 widget from the actual widget you are handling. Last but not least some
74 special classes (e.g. wxFrame) handle different categories of widgets and
75 still have the possibility to draw something in the client area.
76 It was therefore required to write a special purpose GTK widget, that would
77 represent a client area in the sense of wxWindows capable to do the jobs
78 2), 3) and 4). I have written this class and it resides in win_gtk.c of
81 All windows must have a widget, with which they interact with other under-
82 lying GTK widget. It is this widget, e.g. that has to be resized etc and
83 thw wxWindow class has a member variable called m_widget which holds a
84 pointer to this widget. When the window class displays a GTK native widget,
85 this is the only GTK widget the class manages. When the class has a client
86 area for drawing into and for containing children it must have at least
87 one more GTK widget to handle (of the type GtkMyFixed, defined in win_gtk.c),
88 but there can be any number of widgets, handled by a class (e.g. the frame
89 class handles three). The common rule for all windows is only, that the
90 widget that interacts with the rest of GTK must be referenced in m_widget
91 and all other widgets must be children of this widget on the GTK level.
92 The top-most widget, which also represents the client area, must be in
93 the m_wxwindow field and must be of the type GtkMyFixed.
95 As I said, the window classes that display a GTK native widget only have
96 one widget, so in the case of e.g. the wxButton class m_widget holds a
97 pointer to a GtkButton widget. But windows with client areas (for drawing
98 and children) have a m_widget field that is a pointer to a GtkScrolled-
99 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
100 one is (in the GTK sense) a child of the GtkScrolledWindow.
102 If the m_wxwindow field is set, then all input to this widget is inter-
103 cepted and sent to the wxWindows class. If not, all input to the widget
104 that gets pointed to by m_widget gets intercepted and sent to the class.
108 //-----------------------------------------------------------------------------
110 //-----------------------------------------------------------------------------
112 extern wxList wxPendingDelete
;
113 extern wxList wxTopLevelWindows
;
114 extern bool g_blockEventsOnDrag
;
115 static bool g_capturing
= FALSE
;
117 // hack: we need something to pass to gtk_menu_popup, so we store the time of
118 // the last click here
119 static guint32 gs_timeLastClick
= 0;
121 //-----------------------------------------------------------------------------
122 // "expose_event" (of m_wxwindow, not of m_widget)
123 //-----------------------------------------------------------------------------
125 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
127 if (!win
->HasVMT()) return;
128 if (g_blockEventsOnDrag
) return;
130 win
->m_updateRegion
.Union( gdk_event
->area
.x
,
132 gdk_event
->area
.width
,
133 gdk_event
->area
.height
);
135 if (gdk_event
->count
> 0) return;
138 printf( "OnExpose from " );
139 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
140 printf( win->GetClassInfo()->GetClassName() );
144 wxPaintEvent
event( win
->GetId() );
145 event
.SetEventObject( win
);
146 win
->GetEventHandler()->ProcessEvent( event
);
148 win
->m_updateRegion
.Clear();
151 //-----------------------------------------------------------------------------
152 // "draw" (of m_wxwindow, not of m_widget)
153 //-----------------------------------------------------------------------------
155 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
157 if (!win
->HasVMT()) return;
158 if (g_blockEventsOnDrag
) return;
160 win
->m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
162 wxPaintEvent
event( win
->GetId() );
163 event
.SetEventObject( win
);
164 win
->GetEventHandler()->ProcessEvent( event
);
166 win
->m_updateRegion
.Clear();
169 //-----------------------------------------------------------------------------
171 //-----------------------------------------------------------------------------
173 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
175 if (!win
->HasVMT()) return FALSE
;
176 if (g_blockEventsOnDrag
) return FALSE
;
179 printf( "OnKeyPress from " );
180 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
181 printf( win->GetClassInfo()->GetClassName() );
186 switch (gdk_event
->keyval
)
188 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
189 case GDK_Tab
: key_code
= WXK_TAB
; break;
190 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
191 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
192 case GDK_Return
: key_code
= WXK_RETURN
; break;
193 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
194 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
195 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
196 case GDK_Delete
: key_code
= WXK_DELETE
; break;
197 case GDK_Home
: key_code
= WXK_HOME
; break;
198 case GDK_Left
: key_code
= WXK_LEFT
; break;
199 case GDK_Up
: key_code
= WXK_UP
; break;
200 case GDK_Right
: key_code
= WXK_RIGHT
; break;
201 case GDK_Down
: key_code
= WXK_DOWN
; break;
202 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
203 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
204 case GDK_Next
: key_code
= WXK_NEXT
; break;
205 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
206 case GDK_End
: key_code
= WXK_END
; break;
207 case GDK_Begin
: key_code
= WXK_HOME
; break;
208 case GDK_Select
: key_code
= WXK_SELECT
; break;
209 case GDK_Print
: key_code
= WXK_PRINT
; break;
210 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
211 case GDK_Insert
: key_code
= WXK_INSERT
; break;
212 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
213 case GDK_KP_Tab
: key_code
= WXK_TAB
; break;
214 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break;
215 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
216 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
217 case GDK_KP_Up
: key_code
= WXK_UP
; break;
218 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
219 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
220 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
221 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
222 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
223 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
224 case GDK_KP_End
: key_code
= WXK_END
; break;
225 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
226 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
227 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
228 case GDK_KP_Multiply
: key_code
= WXK_MULTIPLY
; break;
229 case GDK_KP_Add
: key_code
= WXK_ADD
; break;
230 case GDK_KP_Separator
: key_code
= WXK_SEPARATOR
; break;
231 case GDK_KP_Subtract
: key_code
= WXK_SUBTRACT
; break;
232 case GDK_KP_Decimal
: key_code
= WXK_DECIMAL
; break;
233 case GDK_KP_Divide
: key_code
= WXK_DIVIDE
; break;
234 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
235 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
236 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
237 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
238 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
239 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
240 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
241 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
242 case GDK_KP_8
: key_code
= WXK_NUMPAD7
; break;
243 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
244 case GDK_F1
: key_code
= WXK_F1
; break;
245 case GDK_F2
: key_code
= WXK_F2
; break;
246 case GDK_F3
: key_code
= WXK_F3
; break;
247 case GDK_F4
: key_code
= WXK_F4
; break;
248 case GDK_F5
: key_code
= WXK_F5
; break;
249 case GDK_F6
: key_code
= WXK_F6
; break;
250 case GDK_F7
: key_code
= WXK_F7
; break;
251 case GDK_F8
: key_code
= WXK_F8
; break;
252 case GDK_F9
: key_code
= WXK_F9
; break;
253 case GDK_F10
: key_code
= WXK_F10
; break;
254 case GDK_F11
: key_code
= WXK_F11
; break;
255 case GDK_F12
: key_code
= WXK_F12
; break;
258 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
259 key_code
= gdk_event
->keyval
;
263 if (!key_code
) return FALSE
;
265 wxKeyEvent
event( wxEVT_CHAR
);
266 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
267 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
268 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
269 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
270 event
.m_keyCode
= key_code
;
273 event
.SetEventObject( win
);
275 bool ret
= win
->GetEventHandler()->ProcessEvent( event
);
279 wxWindow
*ancestor
= win
;
282 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
285 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
286 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
289 ancestor
= ancestor
->GetParent();
295 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
296 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
302 //-----------------------------------------------------------------------------
303 // "button_press_event"
304 //-----------------------------------------------------------------------------
306 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
308 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
310 if (g_blockEventsOnDrag
) return TRUE
;
314 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
316 gtk_widget_grab_focus (win
->m_wxwindow
);
319 printf( "GrabFocus from " );
320 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
321 printf( win->GetClassInfo()->GetClassName() );
328 if (!win
->HasVMT()) return TRUE
;
331 printf( "OnButtonPress from " );
332 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
333 printf( win->GetClassInfo()->GetClassName() );
337 wxEventType event_type
= wxEVT_LEFT_DOWN
;
339 if (gdk_event
->button
== 1)
341 switch (gdk_event
->type
)
343 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
344 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
348 else if (gdk_event
->button
== 2)
350 switch (gdk_event
->type
)
352 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
353 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
357 else if (gdk_event
->button
== 3)
359 switch (gdk_event
->type
)
361 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
362 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
367 wxMouseEvent
event( event_type
);
368 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
369 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
370 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
371 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
372 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
373 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
374 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
376 event
.m_x
= (long)gdk_event
->x
;
377 event
.m_y
= (long)gdk_event
->y
;
379 // Some control don't have their own X window and thus cannot get
384 wxNode
*node
= win
->GetChildren()->First();
387 wxWindow
*child
= (wxWindow
*)node
->Data();
388 if ((child
->m_x
<= event
.m_x
) &&
389 (child
->m_y
<= event
.m_y
) &&
390 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
391 (child
->m_y
+child
->m_height
>= event
.m_y
))
394 event
.m_x
-= child
->m_x
;
395 event
.m_y
-= child
->m_y
;
402 event
.SetEventObject( win
);
404 gs_timeLastClick
= gdk_event
->time
;
406 if (win
->GetEventHandler()->ProcessEvent( event
))
407 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
412 //-----------------------------------------------------------------------------
413 // "button_release_event"
414 //-----------------------------------------------------------------------------
416 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
418 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
420 if (g_blockEventsOnDrag
) return TRUE
;
422 if (!win
->HasVMT()) return TRUE
;
425 printf( "OnButtonRelease from " );
426 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
427 printf( win->GetClassInfo()->GetClassName() );
431 wxEventType event_type
= wxEVT_NULL
;
433 switch (gdk_event
->button
)
435 case 1: event_type
= wxEVT_LEFT_UP
; break;
436 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
437 case 3: event_type
= wxEVT_RIGHT_UP
; break;
440 wxMouseEvent
event( event_type
);
441 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
442 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
443 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
444 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
445 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
446 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
447 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
448 event
.m_x
= (long)gdk_event
->x
;
449 event
.m_y
= (long)gdk_event
->y
;
451 // Some control don't have their own X window and thus cannot get
456 wxNode
*node
= win
->GetChildren()->First();
459 wxWindow
*child
= (wxWindow
*)node
->Data();
460 if ((child
->m_x
<= event
.m_x
) &&
461 (child
->m_y
<= event
.m_y
) &&
462 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
463 (child
->m_y
+child
->m_height
>= event
.m_y
))
466 event
.m_x
-= child
->m_x
;
467 event
.m_y
-= child
->m_y
;
474 event
.SetEventObject( win
);
476 if (win
->GetEventHandler()->ProcessEvent( event
))
477 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
482 //-----------------------------------------------------------------------------
483 // "motion_notify_event"
484 //-----------------------------------------------------------------------------
486 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
488 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
490 if (g_blockEventsOnDrag
) return TRUE
;
492 if (!win
->HasVMT()) return TRUE
;
495 printf( "OnMotion from " );
496 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
497 printf( win->GetClassInfo()->GetClassName() );
501 wxMouseEvent
event( wxEVT_MOTION
);
502 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
503 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
504 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
505 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
506 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
507 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
508 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
510 event
.m_x
= (long)gdk_event
->x
;
511 event
.m_y
= (long)gdk_event
->y
;
513 // Some control don't have their own X window and thus cannot get
518 wxNode
*node
= win
->GetChildren()->First();
521 wxWindow
*child
= (wxWindow
*)node
->Data();
522 if ((child
->m_x
<= event
.m_x
) &&
523 (child
->m_y
<= event
.m_y
) &&
524 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
525 (child
->m_y
+child
->m_height
>= event
.m_y
))
528 event
.m_x
-= child
->m_x
;
529 event
.m_y
-= child
->m_y
;
536 event
.SetEventObject( win
);
538 if (win
->GetEventHandler()->ProcessEvent( event
))
539 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
544 //-----------------------------------------------------------------------------
546 //-----------------------------------------------------------------------------
548 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
550 if (g_blockEventsOnDrag
) return TRUE
;
553 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
555 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
557 printf( "SetFocus flag from " );
558 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
559 printf( win->GetClassInfo()->GetClassName() );
565 if (!win
->HasVMT()) return TRUE
;
568 printf( "OnSetFocus from " );
569 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
570 printf( win->GetClassInfo()->GetClassName() );
572 printf( WXSTRINGCAST win->GetLabel() );
576 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
577 event
.SetEventObject( win
);
579 if (win
->GetEventHandler()->ProcessEvent( event
))
580 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
585 //-----------------------------------------------------------------------------
587 //-----------------------------------------------------------------------------
589 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
591 if (g_blockEventsOnDrag
) return TRUE
;
594 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
595 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
598 if (!win
->HasVMT()) return TRUE
;
601 printf( "OnKillFocus from " );
602 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
603 printf( win->GetClassInfo()->GetClassName() );
607 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
608 event
.SetEventObject( win
);
610 if (win
->GetEventHandler()->ProcessEvent( event
))
611 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
616 //-----------------------------------------------------------------------------
617 // "enter_notify_event"
618 //-----------------------------------------------------------------------------
620 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
622 if (widget
->window
!= gdk_event
->window
) return TRUE
;
624 if (g_blockEventsOnDrag
) return TRUE
;
626 if (!win
->HasVMT()) return TRUE
;
629 printf( "OnEnter from " );
630 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
631 printf( win->GetClassInfo()->GetClassName() );
635 if ((widget
->window
) && (win
->m_cursor
))
636 gdk_window_set_cursor( widget
->window
, win
->m_cursor
->GetCursor() );
638 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
639 event
.SetEventObject( win
);
641 if (win
->GetEventHandler()->ProcessEvent( event
))
642 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
647 //-----------------------------------------------------------------------------
648 // "leave_notify_event"
649 //-----------------------------------------------------------------------------
651 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
653 if (widget
->window
!= gdk_event
->window
) return TRUE
;
655 if (g_blockEventsOnDrag
) return TRUE
;
657 if (!win
->HasVMT()) return TRUE
;
660 printf( "OnLeave from " );
661 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
662 printf( win->GetClassInfo()->GetClassName() );
666 if ((widget
->window
) && (win
->m_cursor
))
667 gdk_window_set_cursor( widget
->window
, wxSTANDARD_CURSOR
->GetCursor() );
669 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
670 event
.SetEventObject( win
);
672 if (win
->GetEventHandler()->ProcessEvent( event
))
673 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
678 //-----------------------------------------------------------------------------
679 // "value_changed" from m_vAdjust
680 //-----------------------------------------------------------------------------
682 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
684 if (g_blockEventsOnDrag
) return;
687 printf( "OnVScroll from " );
688 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
689 printf( win->GetClassInfo()->GetClassName() );
693 if (!win
->HasVMT()) return;
695 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
696 if (fabs(diff
) < 0.2) return;
698 wxEventType command
= wxEVT_NULL
;
700 float line_step
= win
->m_vAdjust
->step_increment
;
701 float page_step
= win
->m_vAdjust
->page_increment
;
703 if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
704 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
705 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
706 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
707 else command
= wxEVT_SCROLL_THUMBTRACK
;
709 int value
= (int)(win
->m_vAdjust
->value
+0.5);
711 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
712 event
.SetEventObject( win
);
713 win
->GetEventHandler()->ProcessEvent( event
);
716 //-----------------------------------------------------------------------------
717 // "value_changed" from m_hAdjust
718 //-----------------------------------------------------------------------------
720 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
722 if (g_blockEventsOnDrag
) return;
725 printf( "OnHScroll from " );
726 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
727 printf( win->GetClassInfo()->GetClassName() );
731 if (!win
->HasVMT()) return;
733 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
734 if (fabs(diff
) < 0.2) return;
736 wxEventType command
= wxEVT_NULL
;
738 float line_step
= win
->m_hAdjust
->step_increment
;
739 float page_step
= win
->m_hAdjust
->page_increment
;
741 if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
742 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
743 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
744 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
745 else command
= wxEVT_SCROLL_THUMBTRACK
;
747 int value
= (int)(win
->m_hAdjust
->value
+0.5);
749 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
750 event
.SetEventObject( win
);
751 win
->GetEventHandler()->ProcessEvent( event
);
754 //-----------------------------------------------------------------------------
755 // "changed" from m_vAdjust
756 //-----------------------------------------------------------------------------
758 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
760 if (g_blockEventsOnDrag
) return;
763 printf( "OnVScroll change from " );
764 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
765 printf( win->GetClassInfo()->GetClassName() );
769 if (!win
->HasVMT()) return;
771 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
772 int value
= (int)(win
->m_vAdjust
->value
+0.5);
774 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
775 event
.SetEventObject( win
);
776 win
->GetEventHandler()->ProcessEvent( event
);
779 //-----------------------------------------------------------------------------
780 // "changed" from m_hAdjust
781 //-----------------------------------------------------------------------------
783 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
785 if (g_blockEventsOnDrag
) return;
788 printf( "OnHScroll change from " );
789 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
790 printf( win->GetClassInfo()->GetClassName() );
794 if (!win
->HasVMT()) return;
796 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
797 int value
= (int)(win
->m_hAdjust
->value
+0.5);
799 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
800 event
.SetEventObject( win
);
801 win
->GetEventHandler()->ProcessEvent( event
);
804 //-----------------------------------------------------------------------------
805 // "button_press_event" from scrollbar
806 //-----------------------------------------------------------------------------
808 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
810 if (gdk_event
->window
!= widget
->slider
) return FALSE
;
812 win
->m_isScrolling
= TRUE
;
817 //-----------------------------------------------------------------------------
818 // "button_release_event" from scrollbar
819 //-----------------------------------------------------------------------------
821 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
823 if (gdk_event
->window
!= widget
->slider
) return FALSE
;
825 GtkScrolledWindow
*s_window
= GTK_SCROLLED_WINDOW(win
->m_widget
);
827 if (widget
== GTK_RANGE(s_window
->vscrollbar
))
828 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_hAdjust
), "value_changed" );
830 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_vAdjust
), "value_changed" );
832 win
->m_isScrolling
= FALSE
;
837 //-----------------------------------------------------------------------------
838 // "drop_data_available_event"
839 //-----------------------------------------------------------------------------
841 static void gtk_window_drop_callback( GtkWidget
*widget
, GdkEventDropDataAvailable
*event
, wxWindow
*win
)
843 if (!win
->HasVMT()) return;
845 if (win
->GetDropTarget())
849 gdk_window_get_pointer( widget
->window
, &x
, &y
, (GdkModifierType
*) NULL
);
851 printf( "Drop data is of type %s.\n", event
->data_type
);
853 win
->GetDropTarget()->OnDrop( x
, y
, (const void*)event
->data
, (size_t)event
->data_numbytes
);
857 g_free (event->dropdataavailable.data);
858 g_free (event->dropdataavailable.data_type);
862 //-----------------------------------------------------------------------------
863 // InsertChild for wxWindow.
864 //-----------------------------------------------------------------------------
866 // Callback for wxWindow. This very strange beast has to be used because
867 // C++ has no virtual methods in a constructor. We have to emulate a
868 // virtual function here as wxNotebook requires a different way to insert
869 // a child in it. I had opted for creating a wxNotebookPage window class
870 // which would have made this superflouus (such in the MDI window system),
871 // but no-one is listening to me...
873 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
875 gtk_myfixed_put( GTK_MYFIXED(parent
->m_wxwindow
),
876 GTK_WIDGET(child
->m_widget
),
880 gtk_widget_set_usize( GTK_WIDGET(child
->m_widget
),
885 //-----------------------------------------------------------------------------
887 //-----------------------------------------------------------------------------
889 IMPLEMENT_DYNAMIC_CLASS(wxWindow
,wxEvtHandler
)
891 BEGIN_EVENT_TABLE(wxWindow
, wxEvtHandler
)
892 EVT_SIZE(wxWindow::OnSize
)
893 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged
)
894 EVT_INIT_DIALOG(wxWindow::OnInitDialog
)
895 EVT_IDLE(wxWindow::OnIdle
)
900 m_widget
= (GtkWidget
*) NULL
;
901 m_wxwindow
= (GtkWidget
*) NULL
;
902 m_parent
= (wxWindow
*) NULL
;
903 m_children
.DeleteContents( FALSE
);
913 m_eventHandler
= this;
914 m_windowValidator
= (wxValidator
*) NULL
;
916 m_cursor
= (wxCursor
*) NULL
;
917 m_font
= *wxSWISS_FONT
;
919 m_windowName
= "noname";
920 m_constraints
= (wxLayoutConstraints
*) NULL
;
921 m_constraintsInvolvedIn
= (wxList
*) NULL
;
922 m_windowSizer
= (wxSizer
*) NULL
;
923 m_sizerParent
= (wxWindow
*) NULL
;
924 m_autoLayout
= FALSE
;
928 m_hasScrolling
= FALSE
;
929 m_isScrolling
= FALSE
;
930 m_hAdjust
= (GtkAdjustment
*) NULL
;
931 m_vAdjust
= (GtkAdjustment
*) NULL
;
932 m_oldHorizontalPos
= 0.0;
933 m_oldVerticalPos
= 0.0;
936 m_pDropTarget
= (wxDropTarget
*) NULL
;
938 m_scrollGC
= (GdkGC
*) NULL
;
939 m_widgetStyle
= (GtkStyle
*) NULL
;
940 m_insertCallback
= wxInsertChildInWindow
;
943 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
944 const wxPoint
&pos
, const wxSize
&size
,
945 long style
, const wxString
&name
)
947 m_insertCallback
= wxInsertChildInWindow
;
948 Create( parent
, id
, pos
, size
, style
, name
);
951 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
952 const wxPoint
&pos
, const wxSize
&size
,
953 long style
, const wxString
&name
)
959 PreCreation( parent
, id
, pos
, size
, style
, name
);
961 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
962 m_hasScrolling
= TRUE
;
964 GtkScrolledWindow
*s_window
= GTK_SCROLLED_WINDOW(m_widget
);
966 gtk_signal_connect( GTK_OBJECT(s_window
->vscrollbar
), "button_press_event",
967 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
969 gtk_signal_connect( GTK_OBJECT(s_window
->hscrollbar
), "button_press_event",
970 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
972 gtk_signal_connect( GTK_OBJECT(s_window
->vscrollbar
), "button_release_event",
973 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
975 gtk_signal_connect( GTK_OBJECT(s_window
->hscrollbar
), "button_release_event",
976 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
978 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
979 scroll_class
->scrollbar_spacing
= 0;
981 gtk_scrolled_window_set_policy( s_window
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
983 m_oldHorizontalPos
= 0.0;
984 m_oldVerticalPos
= 0.0;
986 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->hscrollbar
) );
987 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->vscrollbar
) );
989 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
990 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
991 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
992 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
994 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
995 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
996 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
997 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
999 GtkViewport
*viewport
= GTK_VIEWPORT(s_window
->viewport
);
1001 if (m_windowStyle
& wxRAISED_BORDER
)
1003 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1005 else if (m_windowStyle
& wxSUNKEN_BORDER
)
1007 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1011 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1014 m_wxwindow
= gtk_myfixed_new();
1016 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1018 if (m_windowStyle
& wxTAB_TRAVERSAL
== wxTAB_TRAVERSAL
)
1019 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1021 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1023 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1025 // shut the viewport up
1026 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1027 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1029 // I _really_ don't want scrollbars in the beginning
1030 m_vAdjust
->lower
= 0.0;
1031 m_vAdjust
->upper
= 1.0;
1032 m_vAdjust
->value
= 0.0;
1033 m_vAdjust
->step_increment
= 1.0;
1034 m_vAdjust
->page_increment
= 1.0;
1035 m_vAdjust
->page_size
= 5.0;
1036 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1037 m_hAdjust
->lower
= 0.0;
1038 m_hAdjust
->upper
= 1.0;
1039 m_hAdjust
->value
= 0.0;
1040 m_hAdjust
->step_increment
= 1.0;
1041 m_hAdjust
->page_increment
= 1.0;
1042 m_hAdjust
->page_size
= 5.0;
1043 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1045 gtk_widget_show( m_wxwindow
);
1047 if (m_parent
) m_parent
->AddChild( this );
1049 (m_parent
->m_insertCallback
)( m_parent
, this );
1058 wxWindow::~wxWindow()
1062 if (m_pDropTarget
) delete m_pDropTarget
;
1064 if (m_parent
) m_parent
->RemoveChild( this );
1065 if (m_widget
) Show( FALSE
);
1069 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
1071 if (m_scrollGC
) gdk_gc_unref( m_scrollGC
);
1073 if (m_wxwindow
) gtk_widget_destroy( m_wxwindow
);
1075 if (m_widget
) gtk_widget_destroy( m_widget
);
1079 DeleteRelatedConstraints();
1082 // This removes any dangling pointers to this window
1083 // in other windows' constraintsInvolvedIn lists.
1084 UnsetConstraints(m_constraints
);
1085 delete m_constraints
;
1086 m_constraints
= (wxLayoutConstraints
*) NULL
;
1090 delete m_windowSizer
;
1091 m_windowSizer
= (wxSizer
*) NULL
;
1093 // If this is a child of a sizer, remove self from parent
1094 if (m_sizerParent
) m_sizerParent
->RemoveChild((wxWindow
*)this);
1096 // Just in case the window has been Closed, but
1097 // we're then deleting immediately: don't leave
1098 // dangling pointers.
1099 wxPendingDelete
.DeleteObject(this);
1101 // Just in case we've loaded a top-level window via
1102 // wxWindow::LoadNativeDialog but we weren't a dialog
1104 wxTopLevelWindows
.DeleteObject(this);
1106 if (m_windowValidator
) delete m_windowValidator
;
1109 void wxWindow::PreCreation( wxWindow
*parent
, wxWindowID id
,
1110 const wxPoint
&pos
, const wxSize
&size
,
1111 long style
, const wxString
&name
)
1113 if (m_needParent
&& (parent
== NULL
))
1114 wxFatalError( "Need complete parent.", name
);
1116 m_widget
= (GtkWidget
*) NULL
;
1119 m_children
.DeleteContents( FALSE
);
1122 if (m_width
== -1) m_width
= 20;
1124 if (m_height
== -1) m_height
= 20;
1129 if (!m_needParent
) // some reasonable defaults
1133 m_x
= (gdk_screen_width () - m_width
) / 2;
1134 if (m_x
< 10) m_x
= 10;
1138 m_y
= (gdk_screen_height () - m_height
) / 2;
1139 if (m_y
< 10) m_y
= 10;
1148 m_eventHandler
= this;
1151 if (m_cursor
== NULL
)
1152 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1153 m_font
= *wxSWISS_FONT
;
1154 // m_backgroundColour = wxWHITE;
1155 // m_foregroundColour = wxBLACK;
1156 m_windowStyle
= style
;
1157 m_windowName
= name
;
1158 m_constraints
= (wxLayoutConstraints
*) NULL
;
1159 m_constraintsInvolvedIn
= (wxList
*) NULL
;
1160 m_windowSizer
= (wxSizer
*) NULL
;
1161 m_sizerParent
= (wxWindow
*) NULL
;
1162 m_autoLayout
= FALSE
;
1163 m_hasScrolling
= FALSE
;
1164 m_isScrolling
= FALSE
;
1165 m_pDropTarget
= (wxDropTarget
*) NULL
;
1167 m_windowValidator
= (wxValidator
*) NULL
;
1168 m_scrollGC
= (GdkGC
*) NULL
;
1169 m_widgetStyle
= (GtkStyle
*) NULL
;
1172 void wxWindow::PostCreation()
1176 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1177 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1179 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1180 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1183 ConnectWidget( GetConnectWidget() );
1185 if (m_widget
&& m_parent
) gtk_widget_realize( m_widget
);
1187 if (m_wxwindow
) gtk_widget_realize( m_wxwindow
);
1189 SetCursor( *wxSTANDARD_CURSOR
);
1194 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1196 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1197 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1199 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1200 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1202 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1203 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1205 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1206 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1208 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1209 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1211 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1212 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1214 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1215 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1217 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1218 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1221 bool wxWindow::HasVMT()
1226 bool wxWindow::Close( bool force
)
1228 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1230 wxCloseEvent
event(wxEVT_CLOSE_WINDOW
, m_windowId
);
1231 event
.SetEventObject(this);
1232 event
.SetForce(force
);
1234 return GetEventHandler()->ProcessEvent(event
);
1237 bool wxWindow::Destroy()
1239 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1246 bool wxWindow::DestroyChildren()
1251 while ((node
= GetChildren()->First()) != (wxNode
*)NULL
)
1254 if ((child
= (wxWindow
*)node
->Data()) != (wxWindow
*)NULL
)
1257 if (GetChildren()->Member(child
)) delete node
;
1264 void wxWindow::PrepareDC( wxDC
&WXUNUSED(dc
) )
1266 // are we to set fonts here ?
1269 wxPoint
wxWindow::GetClientAreaOrigin() const
1271 return wxPoint(0,0);
1274 void wxWindow::AdjustForParentClientOrigin( int& x
, int& y
, int sizeFlags
)
1276 if (((sizeFlags
& wxSIZE_NO_ADJUSTMENTS
) == 0) && GetParent())
1278 wxPoint
pt(GetParent()->GetClientAreaOrigin());
1284 void wxWindow::ImplementSetSize()
1286 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1287 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1288 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_minWidth
;
1289 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_minHeight
;
1290 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
1293 void wxWindow::ImplementSetPosition()
1297 wxFAIL_MSG( "wxWindow::SetSize error.\n" );
1301 if ((m_parent
) && (m_parent
->m_wxwindow
))
1302 gtk_myfixed_move( GTK_MYFIXED(m_parent
->m_wxwindow
), m_widget
, m_x
, m_y
);
1304 // Don't do anything for children of wxNotebook and wxMDIChildFrame
1307 void wxWindow::SetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1309 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1311 if (m_resizing
) return; // I don't like recursions
1319 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1321 if (newX
== -1) newX
= m_x
;
1322 if (newY
== -1) newY
= m_y
;
1323 if (newW
== -1) newW
= m_width
;
1324 if (newH
== -1) newH
= m_height
;
1327 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1329 if (newW
== -1) newW
= 80;
1332 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1334 if (newH
== -1) newH
= 26;
1337 AdjustForParentClientOrigin( newX
, newY
, sizeFlags
);
1339 if ((m_x
!= newX
) || (m_y
!= newY
) || (!m_sizeSet
))
1343 ImplementSetPosition();
1346 if ((m_width
!= newW
) || (m_height
!= newH
) || (!m_sizeSet
))
1354 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1355 event
.SetEventObject( this );
1356 ProcessEvent( event
);
1361 void wxWindow::SetSize( int width
, int height
)
1363 SetSize( -1, -1, width
, height
, wxSIZE_USE_EXISTING
);
1366 void wxWindow::Move( int x
, int y
)
1368 SetSize( x
, y
, -1, -1, wxSIZE_USE_EXISTING
);
1371 void wxWindow::GetSize( int *width
, int *height
) const
1373 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1375 if (width
) (*width
) = m_width
;
1376 if (height
) (*height
) = m_height
;
1379 void wxWindow::SetClientSize( int width
, int height
)
1381 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1385 SetSize( width
, height
);
1392 if (!m_hasScrolling
)
1395 do we have sunken dialogs ?
1397 GtkStyleClass *window_class = m_wxwindow->style->klass;
1399 dw += 2 * window_class->xthickness;
1400 dh += 2 * window_class->ythickness;
1405 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1406 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1408 GtkWidget
*viewport
= scroll_window
->viewport
;
1409 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1411 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1412 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1414 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1415 (m_windowStyle
& wxSUNKEN_BORDER
))
1417 dw
+= 2 * viewport_class
->xthickness
;
1418 dh
+= 2 * viewport_class
->ythickness
;
1421 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1423 dw
+= vscrollbar
->allocation
.width
;
1424 dw
+= scroll_class
->scrollbar_spacing
;
1427 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1429 dh
+= hscrollbar
->allocation
.height
;
1430 dw
+= scroll_class
->scrollbar_spacing
;
1434 SetSize( width
+dw
, height
+dh
);
1438 void wxWindow::GetClientSize( int *width
, int *height
) const
1440 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1444 if (width
) (*width
) = m_width
;
1445 if (height
) (*height
) = m_height
;
1452 if (!m_hasScrolling
)
1455 do we have sunken dialogs ?
1457 GtkStyleClass *window_class = m_wxwindow->style->klass;
1459 dw += 2 * window_class->xthickness;
1460 dh += 2 * window_class->ythickness;
1465 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1466 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1468 GtkWidget
*viewport
= scroll_window
->viewport
;
1469 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1471 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1472 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1474 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1475 (m_windowStyle
& wxSUNKEN_BORDER
))
1477 dw
+= 2 * viewport_class
->xthickness
;
1478 dh
+= 2 * viewport_class
->ythickness
;
1481 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1483 // dw += vscrollbar->allocation.width;
1484 dw
+= 15; // range.slider_width = 11 + 2*2pts edge
1485 dw
+= scroll_class
->scrollbar_spacing
;
1488 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1490 // dh += hscrollbar->allocation.height;
1492 dh
+= scroll_class
->scrollbar_spacing
;
1496 if (width
) (*width
) = m_width
- dw
;
1497 if (height
) (*height
) = m_height
- dh
;
1501 void wxWindow::GetPosition( int *x
, int *y
) const
1503 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1510 wxPoint
pt(GetParent()->GetClientAreaOrigin());
1519 void wxWindow::ClientToScreen( int *x
, int *y
)
1521 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1523 GdkWindow
*source
= (GdkWindow
*) NULL
;
1525 source
= m_wxwindow
->window
;
1527 source
= m_widget
->window
;
1531 gdk_window_get_origin( source
, &org_x
, &org_y
);
1535 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1537 org_x
+= m_widget
->allocation
.x
;
1538 org_y
+= m_widget
->allocation
.y
;
1542 wxPoint
pt(GetClientAreaOrigin());
1550 void wxWindow::ScreenToClient( int *x
, int *y
)
1552 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1554 GdkWindow
*source
= (GdkWindow
*) NULL
;
1556 source
= m_wxwindow
->window
;
1558 source
= m_widget
->window
;
1562 gdk_window_get_origin( source
, &org_x
, &org_y
);
1566 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1568 org_x
+= m_widget
->allocation
.x
;
1569 org_y
+= m_widget
->allocation
.y
;
1573 wxPoint
pt(GetClientAreaOrigin());
1581 void wxWindow::Centre( int direction
)
1583 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1585 if (IS_KIND_OF(this,wxDialog
) || IS_KIND_OF(this,wxFrame
))
1587 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (gdk_screen_width () - m_width
) / 2;
1588 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (gdk_screen_height () - m_height
) / 2;
1589 ImplementSetPosition();
1597 m_parent
->GetSize( &p_w
, &p_h
);
1598 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (p_w
- m_width
) / 2;
1599 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (p_h
- m_height
) / 2;
1600 ImplementSetPosition();
1605 void wxWindow::Fit()
1607 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1611 wxNode
*node
= GetChildren()->First();
1614 wxWindow
*win
= (wxWindow
*)node
->Data();
1616 win
->GetPosition(&wx
, &wy
);
1617 win
->GetSize(&ww
, &wh
);
1618 if ( wx
+ ww
> maxX
)
1620 if ( wy
+ wh
> maxY
)
1623 node
= node
->Next();
1625 SetClientSize(maxX
+ 5, maxY
+ 10);
1628 void wxWindow::SetSizeHints( int minW
, int minH
, int maxW
, int maxH
, int WXUNUSED(incW
), int WXUNUSED(incH
) )
1630 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1638 void wxWindow::OnSize( wxSizeEvent
&WXUNUSED(event
) )
1640 //if (GetAutoLayout()) Layout();
1643 bool wxWindow::Show( bool show
)
1645 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1648 gtk_widget_show( m_widget
);
1650 gtk_widget_hide( m_widget
);
1655 void wxWindow::Enable( bool enable
)
1657 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1659 m_isEnabled
= enable
;
1660 gtk_widget_set_sensitive( m_widget
, enable
);
1661 if (m_wxwindow
) gtk_widget_set_sensitive( m_wxwindow
, enable
);
1664 int wxWindow::GetCharHeight() const
1666 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1670 wxFAIL_MSG( "invalid font" );
1674 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1675 return font
->ascent
+ font
->descent
;
1678 int wxWindow::GetCharWidth() const
1680 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1684 wxFAIL_MSG( "invalid font" );
1688 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1689 return gdk_string_width( font
, "H" );
1692 void wxWindow::GetTextExtent( const wxString
& string
, int *x
, int *y
,
1693 int *descent
, int *externalLeading
, const wxFont
*theFont
, bool WXUNUSED(use16
) ) const
1695 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1697 wxFont fontToUse
= m_font
;
1698 if (theFont
) fontToUse
= *theFont
;
1700 if (!fontToUse
.Ok())
1702 wxFAIL_MSG( "invalid font" );
1705 wxASSERT_MSG( (m_font
.Ok()), "invalid font" );
1707 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
1708 if (x
) (*x
) = gdk_string_width( font
, string
);
1709 if (y
) (*y
) = font
->ascent
+ font
->descent
;
1710 if (descent
) (*descent
) = font
->descent
;
1711 if (externalLeading
) (*externalLeading
) = 0; // ??
1714 void wxWindow::MakeModal( bool modal
)
1717 // Disable all other windows
1718 if (this->IsKindOf(CLASSINFO(wxDialog
)) || this->IsKindOf(CLASSINFO(wxFrame
)))
1720 wxNode
*node
= wxTopLevelWindows
.First();
1723 wxWindow
*win
= (wxWindow
*)node
->Data();
1725 win
->Enable(!modal
);
1727 node
= node
->Next();
1732 void wxWindow::SetFocus()
1734 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1736 GtkWidget
*connect_widget
= GetConnectWidget();
1739 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) && !GTK_WIDGET_HAS_FOCUS (connect_widget
) )
1741 gtk_widget_grab_focus (connect_widget
);
1746 bool wxWindow::OnClose()
1751 void wxWindow::AddChild( wxWindow
*child
)
1753 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1754 wxASSERT_MSG( (child
!= NULL
), "invalid child" );
1756 m_children
.Append( child
);
1759 wxList
*wxWindow::GetChildren()
1761 return (&m_children
);
1764 void wxWindow::RemoveChild( wxWindow
*child
)
1766 if (GetChildren()) GetChildren()->DeleteObject( child
);
1767 child
->m_parent
= (wxWindow
*) NULL
;
1770 void wxWindow::SetReturnCode( int retCode
)
1772 m_retCode
= retCode
;
1775 int wxWindow::GetReturnCode()
1780 void wxWindow::Raise()
1782 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1784 if (m_widget
) gdk_window_raise( m_widget
->window
);
1787 void wxWindow::Lower()
1789 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1791 if (m_widget
) gdk_window_lower( m_widget
->window
);
1794 wxEvtHandler
*wxWindow::GetEventHandler()
1796 return m_eventHandler
;
1799 void wxWindow::SetEventHandler( wxEvtHandler
*handler
)
1801 m_eventHandler
= handler
;
1804 void wxWindow::PushEventHandler(wxEvtHandler
*handler
)
1806 handler
->SetNextHandler(GetEventHandler());
1807 SetEventHandler(handler
);
1810 wxEvtHandler
*wxWindow::PopEventHandler(bool deleteHandler
)
1812 if (GetEventHandler())
1814 wxEvtHandler
*handlerA
= GetEventHandler();
1815 wxEvtHandler
*handlerB
= handlerA
->GetNextHandler();
1816 handlerA
->SetNextHandler((wxEvtHandler
*) NULL
);
1817 SetEventHandler(handlerB
);
1821 return (wxEvtHandler
*) NULL
;
1827 return (wxEvtHandler
*) NULL
;
1830 wxValidator
*wxWindow::GetValidator()
1832 return m_windowValidator
;
1835 void wxWindow::SetValidator( const wxValidator
& validator
)
1837 if (m_windowValidator
) delete m_windowValidator
;
1838 m_windowValidator
= validator
.Clone();
1839 if (m_windowValidator
) m_windowValidator
->SetWindow(this);
1842 bool wxWindow::IsBeingDeleted()
1847 void wxWindow::SetId( wxWindowID id
)
1852 wxWindowID
wxWindow::GetId()
1857 void wxWindow::SetCursor( const wxCursor
&cursor
)
1859 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1861 if (m_cursor
== NULL
)
1863 wxFAIL_MSG( "wxWindow::SetCursor m_cursor == NULL" );
1864 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1869 if (*((wxCursor
*)&cursor
) == m_cursor
) return;
1874 *m_cursor
= *wxSTANDARD_CURSOR
;
1877 if ((m_widget
) && (m_widget
->window
))
1878 gdk_window_set_cursor( m_widget
->window
, m_cursor
->GetCursor() );
1880 if ((m_wxwindow
) && (m_wxwindow
->window
))
1881 gdk_window_set_cursor( m_wxwindow
->window
, m_cursor
->GetCursor() );
1884 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
1886 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1888 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
1891 gdk_window_clear_area( m_wxwindow
->window
,
1905 GetClientSize( &w
, &h
);
1907 GdkRectangle gdk_rect
;
1911 gdk_rect
.height
= h
;
1912 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1917 GdkRectangle gdk_rect
;
1918 gdk_rect
.x
= rect
->x
;
1919 gdk_rect
.y
= rect
->y
;
1920 gdk_rect
.width
= rect
->width
;
1921 gdk_rect
.height
= rect
->height
;
1924 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1926 gtk_widget_draw( m_widget
, &gdk_rect
);
1930 wxRegion
wxWindow::GetUpdateRegion() const
1932 return m_updateRegion
;
1935 bool wxWindow::IsExposed( int x
, int y
) const
1937 return (m_updateRegion
.Contains( x
, y
) != wxOutRegion
);
1940 bool wxWindow::IsExposed( int x
, int y
, int w
, int h
) const
1942 return (m_updateRegion
.Contains( x
, y
, w
, h
) != wxOutRegion
);
1945 bool wxWindow::IsExposed( const wxPoint
& pt
) const
1947 return (m_updateRegion
.Contains( pt
.x
, pt
.y
) != wxOutRegion
);
1950 bool wxWindow::IsExposed( const wxRect
& rect
) const
1952 return (m_updateRegion
.Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
) != wxOutRegion
);
1955 void wxWindow::Clear()
1957 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
1959 if (m_wxwindow
&& m_wxwindow
->window
) gdk_window_clear( m_wxwindow
->window
);
1962 wxColour
wxWindow::GetBackgroundColour() const
1964 return m_backgroundColour
;
1967 void wxWindow::SetBackgroundColour( const wxColour
&colour
)
1969 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
1971 m_backgroundColour
= colour
;
1972 if (!m_backgroundColour
.Ok()) return;
1976 GdkWindow
*window
= m_wxwindow
->window
;
1977 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
1978 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
1979 gdk_window_clear( window
);
1985 wxColour
wxWindow::GetForegroundColour() const
1987 return m_foregroundColour
;
1990 void wxWindow::SetForegroundColour( const wxColour
&colour
)
1992 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
1994 m_foregroundColour
= colour
;
1995 if (!m_foregroundColour
.Ok()) return;
2000 GtkStyle
*wxWindow::GetWidgetStyle()
2002 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2006 gtk_widget_get_style( m_widget
) );
2008 return m_widgetStyle
;
2011 void wxWindow::SetWidgetStyle()
2013 GtkStyle
*style
= GetWidgetStyle();
2015 gdk_font_unref( style
->font
);
2016 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2018 if (m_foregroundColour
.Ok())
2020 m_foregroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2021 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2022 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2023 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2026 if (m_backgroundColour
.Ok())
2028 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2029 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2030 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2031 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2032 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2033 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2034 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2035 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2036 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2040 void wxWindow::ApplyWidgetStyle()
2044 bool wxWindow::Validate()
2046 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
2048 wxNode
*node
= GetChildren()->First();
2051 wxWindow
*child
= (wxWindow
*)node
->Data();
2052 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->Validate(this))
2054 node
= node
->Next();
2059 bool wxWindow::TransferDataToWindow()
2061 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
2063 wxNode
*node
= GetChildren()->First();
2066 wxWindow
*child
= (wxWindow
*)node
->Data();
2067 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */
2068 !child
->GetValidator()->TransferToWindow() )
2070 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK
|wxICON_EXCLAMATION
);
2073 node
= node
->Next();
2078 bool wxWindow::TransferDataFromWindow()
2080 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2082 wxNode
*node
= GetChildren()->First();
2085 wxWindow
*child
= (wxWindow
*)node
->Data();
2086 if ( child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->TransferFromWindow() )
2088 node
= node
->Next();
2093 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable
& accel
)
2095 m_acceleratorTable
= accel
;
2098 void wxWindow::OnInitDialog( wxInitDialogEvent
&WXUNUSED(event
) )
2100 TransferDataToWindow();
2103 void wxWindow::InitDialog()
2105 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2107 wxInitDialogEvent
event(GetId());
2108 event
.SetEventObject( this );
2109 GetEventHandler()->ProcessEvent(event
);
2112 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2114 menu
->SetInvokingWindow( win
);
2115 wxNode
*node
= menu
->m_items
.First();
2118 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2119 if (menuitem
->IsSubMenu())
2120 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2121 node
= node
->Next();
2125 bool wxWindow::PopupMenu( wxMenu
*menu
, int WXUNUSED(x
), int WXUNUSED(y
) )
2127 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
2129 wxCHECK_MSG( menu
!= NULL
, FALSE
, "invalid popup-menu" );
2131 SetInvokingWindow( menu
, this );
2133 GTK_MENU(menu
->m_menu
),
2134 (GtkWidget
*)NULL
, // parent menu shell
2135 (GtkWidget
*)NULL
, // parent menu item
2136 (GtkMenuPositionFunc
)NULL
,
2137 NULL
, // client data
2138 0, // button used to activate it
2139 0//gs_timeLastClick // the time of activation
2144 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2146 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2148 GtkWidget
*dnd_widget
= GetConnectWidget();
2150 DisconnectDnDWidget( dnd_widget
);
2152 if (m_pDropTarget
) delete m_pDropTarget
;
2153 m_pDropTarget
= dropTarget
;
2155 ConnectDnDWidget( dnd_widget
);
2158 wxDropTarget
*wxWindow::GetDropTarget() const
2160 return m_pDropTarget
;
2163 void wxWindow::ConnectDnDWidget( GtkWidget
*widget
)
2165 if (!m_pDropTarget
) return;
2167 m_pDropTarget
->RegisterWidget( widget
);
2169 gtk_signal_connect( GTK_OBJECT(widget
), "drop_data_available_event",
2170 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
2173 void wxWindow::DisconnectDnDWidget( GtkWidget
*widget
)
2175 if (!m_pDropTarget
) return;
2177 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
2178 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
2180 m_pDropTarget
->UnregisterWidget( widget
);
2183 GtkWidget
* wxWindow::GetConnectWidget()
2185 GtkWidget
*connect_widget
= m_widget
;
2186 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2188 return connect_widget
;
2191 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2193 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2194 return (window
== m_widget
->window
);
2197 void wxWindow::SetFont( const wxFont
&font
)
2199 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2201 if (((wxFont
*)&font
)->Ok())
2204 m_font
= *wxSWISS_FONT
;
2209 wxFont
*wxWindow::GetFont()
2214 void wxWindow::SetWindowStyleFlag( long flag
)
2216 m_windowStyle
= flag
;
2219 long wxWindow::GetWindowStyleFlag() const
2221 return m_windowStyle
;
2224 void wxWindow::CaptureMouse()
2226 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2228 wxCHECK_RET( g_capturing
== FALSE
, "CaptureMouse called twice" );
2230 GtkWidget
*connect_widget
= GetConnectWidget();
2231 gtk_grab_add( connect_widget
);
2232 gdk_pointer_grab ( connect_widget
->window
, FALSE
,
2234 (GDK_BUTTON_PRESS_MASK
|
2235 GDK_BUTTON_RELEASE_MASK
|
2236 GDK_POINTER_MOTION_MASK
),
2237 (GdkWindow
*) NULL
, (GdkCursor
*) NULL
, GDK_CURRENT_TIME
);
2241 void wxWindow::ReleaseMouse()
2243 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2245 wxCHECK_RET( g_capturing
== TRUE
, "ReleaseMouse called twice" );
2247 GtkWidget
*connect_widget
= GetConnectWidget();
2248 gtk_grab_remove( connect_widget
);
2249 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2250 g_capturing
= FALSE
;
2253 void wxWindow::SetTitle( const wxString
&WXUNUSED(title
) )
2257 wxString
wxWindow::GetTitle() const
2259 return (wxString
&)m_windowName
;
2262 wxString
wxWindow::GetLabel() const
2267 void wxWindow::SetName( const wxString
&name
)
2269 m_windowName
= name
;
2272 wxString
wxWindow::GetName() const
2274 return (wxString
&)m_windowName
;
2277 bool wxWindow::IsShown() const
2282 bool wxWindow::IsRetained()
2287 wxWindow
*wxWindow::FindWindow( long id
)
2289 if (id
== m_windowId
) return this;
2290 wxNode
*node
= m_children
.First();
2293 wxWindow
*child
= (wxWindow
*)node
->Data();
2294 wxWindow
*res
= child
->FindWindow( id
);
2295 if (res
) return res
;
2296 node
= node
->Next();
2298 return (wxWindow
*) NULL
;
2301 wxWindow
*wxWindow::FindWindow( const wxString
& name
)
2303 if (name
== m_windowName
) return this;
2304 wxNode
*node
= m_children
.First();
2307 wxWindow
*child
= (wxWindow
*)node
->Data();
2308 wxWindow
*res
= child
->FindWindow( name
);
2309 if (res
) return res
;
2310 node
= node
->Next();
2312 return (wxWindow
*) NULL
;
2315 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2316 int range
, bool refresh
)
2318 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2320 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2322 if (!m_wxwindow
) return;
2324 if (orient
== wxHORIZONTAL
)
2326 float fpos
= (float)pos
;
2327 float frange
= (float)range
;
2328 float fthumb
= (float)thumbVisible
;
2330 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2331 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2333 SetScrollPos( orient
, pos
, refresh
);
2337 m_oldHorizontalPos
= fpos
;
2339 m_hAdjust
->lower
= 0.0;
2340 m_hAdjust
->upper
= frange
;
2341 m_hAdjust
->value
= fpos
;
2342 m_hAdjust
->step_increment
= 1.0;
2343 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2344 m_hAdjust
->page_size
= fthumb
;
2348 float fpos
= (float)pos
;
2349 float frange
= (float)range
;
2350 float fthumb
= (float)thumbVisible
;
2352 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2353 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2355 SetScrollPos( orient
, pos
, refresh
);
2359 m_oldVerticalPos
= fpos
;
2361 m_vAdjust
->lower
= 0.0;
2362 m_vAdjust
->upper
= frange
;
2363 m_vAdjust
->value
= fpos
;
2364 m_vAdjust
->step_increment
= 1.0;
2365 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2366 m_vAdjust
->page_size
= fthumb
;
2369 if (m_wxwindow
->window
)
2371 if (orient
== wxHORIZONTAL
)
2372 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2374 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2376 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
2380 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2382 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2384 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2386 if (!m_wxwindow
) return;
2388 if (orient
== wxHORIZONTAL
)
2390 float fpos
= (float)pos
;
2391 m_oldHorizontalPos
= fpos
;
2393 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2394 m_hAdjust
->value
= fpos
;
2398 float fpos
= (float)pos
;
2399 m_oldVerticalPos
= fpos
;
2400 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2401 m_vAdjust
->value
= fpos
;
2406 if (m_wxwindow
->window
)
2408 if (orient
== wxHORIZONTAL
)
2409 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2411 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2416 int wxWindow::GetScrollThumb( int orient
) const
2418 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2420 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2422 if (!m_wxwindow
) return 0;
2424 if (orient
== wxHORIZONTAL
)
2425 return (int)(m_hAdjust
->page_size
+0.5);
2427 return (int)(m_vAdjust
->page_size
+0.5);
2430 int wxWindow::GetScrollPos( int orient
) const
2432 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2434 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2436 if (!m_wxwindow
) return 0;
2438 if (orient
== wxHORIZONTAL
)
2439 return (int)(m_hAdjust
->value
+0.5);
2441 return (int)(m_vAdjust
->value
+0.5);
2444 int wxWindow::GetScrollRange( int orient
) const
2446 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2448 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2450 if (!m_wxwindow
) return 0;
2452 if (orient
== wxHORIZONTAL
)
2453 return (int)(m_hAdjust
->upper
+0.5);
2455 return (int)(m_vAdjust
->upper
+0.5);
2458 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2460 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2462 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2464 if (!m_wxwindow
) return;
2468 GetClientSize( &cw
, &ch
);
2470 int w
= cw
- abs(dx
);
2471 int h
= ch
- abs(dy
);
2472 if ((h
< 0) || (w
< 0))
2479 if (dx
< 0) s_x
= -dx
;
2480 if (dy
< 0) s_y
= -dy
;
2483 if (dx
> 0) d_x
= dx
;
2484 if (dy
> 0) d_y
= dy
;
2488 m_scrollGC
= gdk_gc_new( m_wxwindow
->window
);
2489 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
2492 gdk_window_copy_area( m_wxwindow
->window
, m_scrollGC
, d_x
, d_y
,
2493 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2496 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2497 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2498 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2499 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2501 Refresh( TRUE
, &rect
);
2504 //-------------------------------------------------------------------------------------
2506 //-------------------------------------------------------------------------------------
2508 wxLayoutConstraints
*wxWindow::GetConstraints() const
2510 return m_constraints
;
2513 void wxWindow::SetConstraints( wxLayoutConstraints
*constraints
)
2517 UnsetConstraints(m_constraints
);
2518 delete m_constraints
;
2520 m_constraints
= constraints
;
2523 // Make sure other windows know they're part of a 'meaningful relationship'
2524 if (m_constraints
->left
.GetOtherWindow() && (m_constraints
->left
.GetOtherWindow() != this))
2525 m_constraints
->left
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2526 if (m_constraints
->top
.GetOtherWindow() && (m_constraints
->top
.GetOtherWindow() != this))
2527 m_constraints
->top
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2528 if (m_constraints
->right
.GetOtherWindow() && (m_constraints
->right
.GetOtherWindow() != this))
2529 m_constraints
->right
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2530 if (m_constraints
->bottom
.GetOtherWindow() && (m_constraints
->bottom
.GetOtherWindow() != this))
2531 m_constraints
->bottom
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2532 if (m_constraints
->width
.GetOtherWindow() && (m_constraints
->width
.GetOtherWindow() != this))
2533 m_constraints
->width
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2534 if (m_constraints
->height
.GetOtherWindow() && (m_constraints
->height
.GetOtherWindow() != this))
2535 m_constraints
->height
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2536 if (m_constraints
->centreX
.GetOtherWindow() && (m_constraints
->centreX
.GetOtherWindow() != this))
2537 m_constraints
->centreX
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2538 if (m_constraints
->centreY
.GetOtherWindow() && (m_constraints
->centreY
.GetOtherWindow() != this))
2539 m_constraints
->centreY
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2545 void wxWindow::SetAutoLayout( bool autoLayout
)
2547 m_autoLayout
= autoLayout
;
2550 bool wxWindow::GetAutoLayout() const
2552 return m_autoLayout
;
2555 wxSizer
*wxWindow::GetSizer() const
2557 return m_windowSizer
;
2560 void wxWindow::SetSizerParent( wxWindow
*win
)
2562 m_sizerParent
= win
;
2565 wxWindow
*wxWindow::GetSizerParent() const
2567 return m_sizerParent
;
2570 // This removes any dangling pointers to this window
2571 // in other windows' constraintsInvolvedIn lists.
2572 void wxWindow::UnsetConstraints(wxLayoutConstraints
*c
)
2576 if (c
->left
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2577 c
->left
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2578 if (c
->top
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2579 c
->top
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2580 if (c
->right
.GetOtherWindow() && (c
->right
.GetOtherWindow() != this))
2581 c
->right
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2582 if (c
->bottom
.GetOtherWindow() && (c
->bottom
.GetOtherWindow() != this))
2583 c
->bottom
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2584 if (c
->width
.GetOtherWindow() && (c
->width
.GetOtherWindow() != this))
2585 c
->width
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2586 if (c
->height
.GetOtherWindow() && (c
->height
.GetOtherWindow() != this))
2587 c
->height
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2588 if (c
->centreX
.GetOtherWindow() && (c
->centreX
.GetOtherWindow() != this))
2589 c
->centreX
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2590 if (c
->centreY
.GetOtherWindow() && (c
->centreY
.GetOtherWindow() != this))
2591 c
->centreY
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2595 // Back-pointer to other windows we're involved with, so if we delete
2596 // this window, we must delete any constraints we're involved with.
2597 void wxWindow::AddConstraintReference(wxWindow
*otherWin
)
2599 if (!m_constraintsInvolvedIn
)
2600 m_constraintsInvolvedIn
= new wxList
;
2601 if (!m_constraintsInvolvedIn
->Member(otherWin
))
2602 m_constraintsInvolvedIn
->Append(otherWin
);
2605 // REMOVE back-pointer to other windows we're involved with.
2606 void wxWindow::RemoveConstraintReference(wxWindow
*otherWin
)
2608 if (m_constraintsInvolvedIn
)
2609 m_constraintsInvolvedIn
->DeleteObject(otherWin
);
2612 // Reset any constraints that mention this window
2613 void wxWindow::DeleteRelatedConstraints()
2615 if (m_constraintsInvolvedIn
)
2617 wxNode
*node
= m_constraintsInvolvedIn
->First();
2620 wxWindow
*win
= (wxWindow
*)node
->Data();
2621 wxNode
*next
= node
->Next();
2622 wxLayoutConstraints
*constr
= win
->GetConstraints();
2624 // Reset any constraints involving this window
2627 constr
->left
.ResetIfWin((wxWindow
*)this);
2628 constr
->top
.ResetIfWin((wxWindow
*)this);
2629 constr
->right
.ResetIfWin((wxWindow
*)this);
2630 constr
->bottom
.ResetIfWin((wxWindow
*)this);
2631 constr
->width
.ResetIfWin((wxWindow
*)this);
2632 constr
->height
.ResetIfWin((wxWindow
*)this);
2633 constr
->centreX
.ResetIfWin((wxWindow
*)this);
2634 constr
->centreY
.ResetIfWin((wxWindow
*)this);
2639 delete m_constraintsInvolvedIn
;
2640 m_constraintsInvolvedIn
= (wxList
*) NULL
;
2644 void wxWindow::SetSizer(wxSizer
*sizer
)
2646 m_windowSizer
= sizer
;
2648 sizer
->SetSizerParent((wxWindow
*)this);
2655 bool wxWindow::Layout()
2657 if (GetConstraints())
2660 GetClientSize(&w
, &h
);
2661 GetConstraints()->width
.SetValue(w
);
2662 GetConstraints()->height
.SetValue(h
);
2665 // If top level (one sizer), evaluate the sizer's constraints.
2669 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2670 GetSizer()->LayoutPhase1(&noChanges
);
2671 GetSizer()->LayoutPhase2(&noChanges
);
2672 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2677 // Otherwise, evaluate child constraints
2678 ResetConstraints(); // Mark all constraints as unevaluated
2679 DoPhase(1); // Just one phase need if no sizers involved
2681 SetConstraintSizes(); // Recursively set the real window sizes
2687 // Do a phase of evaluating constraints:
2688 // the default behaviour. wxSizers may do a similar
2689 // thing, but also impose their own 'constraints'
2690 // and order the evaluation differently.
2691 bool wxWindow::LayoutPhase1(int *noChanges
)
2693 wxLayoutConstraints
*constr
= GetConstraints();
2696 return constr
->SatisfyConstraints((wxWindow
*)this, noChanges
);
2702 bool wxWindow::LayoutPhase2(int *noChanges
)
2712 // Do a phase of evaluating child constraints
2713 bool wxWindow::DoPhase(int phase
)
2715 int noIterations
= 0;
2716 int maxIterations
= 500;
2720 while ((noChanges
> 0) && (noIterations
< maxIterations
))
2724 wxNode
*node
= GetChildren()->First();
2727 wxWindow
*child
= (wxWindow
*)node
->Data();
2728 if (!child
->IsKindOf(CLASSINFO(wxFrame
)) && !child
->IsKindOf(CLASSINFO(wxDialog
)))
2730 wxLayoutConstraints
*constr
= child
->GetConstraints();
2733 if (succeeded
.Member(child
))
2738 int tempNoChanges
= 0;
2739 bool success
= ( (phase
== 1) ? child
->LayoutPhase1(&tempNoChanges
) : child
->LayoutPhase2(&tempNoChanges
) ) ;
2740 noChanges
+= tempNoChanges
;
2743 succeeded
.Append(child
);
2748 node
= node
->Next();
2755 void wxWindow::ResetConstraints()
2757 wxLayoutConstraints
*constr
= GetConstraints();
2760 constr
->left
.SetDone(FALSE
);
2761 constr
->top
.SetDone(FALSE
);
2762 constr
->right
.SetDone(FALSE
);
2763 constr
->bottom
.SetDone(FALSE
);
2764 constr
->width
.SetDone(FALSE
);
2765 constr
->height
.SetDone(FALSE
);
2766 constr
->centreX
.SetDone(FALSE
);
2767 constr
->centreY
.SetDone(FALSE
);
2769 wxNode
*node
= GetChildren()->First();
2772 wxWindow
*win
= (wxWindow
*)node
->Data();
2773 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2774 win
->ResetConstraints();
2775 node
= node
->Next();
2779 // Need to distinguish between setting the 'fake' size for
2780 // windows and sizers, and setting the real values.
2781 void wxWindow::SetConstraintSizes(bool recurse
)
2783 wxLayoutConstraints
*constr
= GetConstraints();
2784 if (constr
&& constr
->left
.GetDone() && constr
->right
.GetDone() &&
2785 constr
->width
.GetDone() && constr
->height
.GetDone())
2787 int x
= constr
->left
.GetValue();
2788 int y
= constr
->top
.GetValue();
2789 int w
= constr
->width
.GetValue();
2790 int h
= constr
->height
.GetValue();
2792 // If we don't want to resize this window, just move it...
2793 if ((constr
->width
.GetRelationship() != wxAsIs
) ||
2794 (constr
->height
.GetRelationship() != wxAsIs
))
2796 // Calls Layout() recursively. AAAGH. How can we stop that.
2797 // Simply take Layout() out of non-top level OnSizes.
2798 SizerSetSize(x
, y
, w
, h
);
2807 char *windowClass
= this->GetClassInfo()->GetClassName();
2810 if (GetName() == "")
2811 winName
= _("unnamed");
2813 winName
= GetName();
2814 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass
, (const char *)winName
);
2815 if (!constr
->left
.GetDone())
2816 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2817 if (!constr
->right
.GetDone())
2818 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2819 if (!constr
->width
.GetDone())
2820 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2821 if (!constr
->height
.GetDone())
2822 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2823 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2828 wxNode
*node
= GetChildren()->First();
2831 wxWindow
*win
= (wxWindow
*)node
->Data();
2832 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2833 win
->SetConstraintSizes();
2834 node
= node
->Next();
2839 // This assumes that all sizers are 'on' the same
2840 // window, i.e. the parent of this window.
2841 void wxWindow::TransformSizerToActual(int *x
, int *y
) const
2843 if (!m_sizerParent
|| m_sizerParent
->IsKindOf(CLASSINFO(wxDialog
)) ||
2844 m_sizerParent
->IsKindOf(CLASSINFO(wxFrame
)) )
2848 m_sizerParent
->GetPosition(&xp
, &yp
);
2849 m_sizerParent
->TransformSizerToActual(&xp
, &yp
);
2854 void wxWindow::SizerSetSize(int x
, int y
, int w
, int h
)
2858 TransformSizerToActual(&xx
, &yy
);
2859 SetSize(xx
, yy
, w
, h
);
2862 void wxWindow::SizerMove(int x
, int y
)
2866 TransformSizerToActual(&xx
, &yy
);
2870 // Only set the size/position of the constraint (if any)
2871 void wxWindow::SetSizeConstraint(int x
, int y
, int w
, int h
)
2873 wxLayoutConstraints
*constr
= GetConstraints();
2878 constr
->left
.SetValue(x
);
2879 constr
->left
.SetDone(TRUE
);
2883 constr
->top
.SetValue(y
);
2884 constr
->top
.SetDone(TRUE
);
2888 constr
->width
.SetValue(w
);
2889 constr
->width
.SetDone(TRUE
);
2893 constr
->height
.SetValue(h
);
2894 constr
->height
.SetDone(TRUE
);
2899 void wxWindow::MoveConstraint(int x
, int y
)
2901 wxLayoutConstraints
*constr
= GetConstraints();
2906 constr
->left
.SetValue(x
);
2907 constr
->left
.SetDone(TRUE
);
2911 constr
->top
.SetValue(y
);
2912 constr
->top
.SetDone(TRUE
);
2917 void wxWindow::GetSizeConstraint(int *w
, int *h
) const
2919 wxLayoutConstraints
*constr
= GetConstraints();
2922 *w
= constr
->width
.GetValue();
2923 *h
= constr
->height
.GetValue();
2929 void wxWindow::GetClientSizeConstraint(int *w
, int *h
) const
2931 wxLayoutConstraints
*constr
= GetConstraints();
2934 *w
= constr
->width
.GetValue();
2935 *h
= constr
->height
.GetValue();
2938 GetClientSize(w
, h
);
2941 void wxWindow::GetPositionConstraint(int *x
, int *y
) const
2943 wxLayoutConstraints
*constr
= GetConstraints();
2946 *x
= constr
->left
.GetValue();
2947 *y
= constr
->top
.GetValue();
2953 bool wxWindow::AcceptsFocus() const
2955 return IsEnabled() && IsShown();
2958 void wxWindow::OnIdle(wxIdleEvent
& WXUNUSED(event
) )