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"
28 #include "wx/notebook.h"
29 #include "wx/statusbr.h"
31 #include "wx/gtk/win_gtk.h"
32 #include "gdk/gdkprivate.h"
33 #include "gdk/gdkkeysyms.h"
37 //-----------------------------------------------------------------------------
38 // documentation on internals
39 //-----------------------------------------------------------------------------
42 I have been asked several times about writing some documentation about
43 the GTK port of wxWindows, especially its internal structures. Obviously,
44 you cannot understand wxGTK without knowing a little about the GTK, but
45 some more information about what the wxWindow, which is the base class
46 for all other window classes, does seems required as well.
48 What does wxWindow do? It contains the common interface for the following
49 jobs of its descentants:
51 1) Define the rudimentary behaviour common to all window classes, such as
52 resizing, intercepting user input so as to make it possible to use these
53 events for special purposes in a derived class, window names etc.
55 2) Provide the possibility to contain and manage children, if the derived
56 class is allowed to contain children, which holds true for those window
57 classes, which do not display a native GTK widget. To name them, these
58 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
59 work classes are a special case and are handled a bit differently from
62 3) Provide the possibility to draw into a client area of a window. This,
63 too, only holds true for classes that do not display a native GTK widget
66 4) Provide the entire mechanism for scrolling widgets. This actaul inter-
67 face for this is usually in wxScrolledWidget, but the GTK implementation
70 5) A multitude of helper or extra methods for special purposes, such as
71 Drag'n'Drop, managing validators etc.
73 Normally one might expect, that one wxWindows class would always contain
74 one GTK widget. Under GTK, there is no such allround widget that has all
75 the functionality. Moreover, the GTK defines a client area as a different
76 widget from the actual widget you are handling. Last but not least some
77 special classes (e.g. wxFrame) handle different categories of widgets and
78 still have the possibility to draw something in the client area.
79 It was therefore required to write a special purpose GTK widget, that would
80 represent a client area in the sense of wxWindows capable to do the jobs
81 2), 3) and 4). I have written this class and it resides in win_gtk.c of
84 All windows must have a widget, with which they interact with other under-
85 lying GTK widget. It is this widget, e.g. that has to be resized etc and
86 thw wxWindow class has a member variable called m_widget which holds a
87 pointer to this widget. When the window class displays a GTK native widget,
88 this is the only GTK widget the class manages. When the class has a client
89 area for drawing into and for containing children it must have at least
90 one more GTK widget to handle (of the type GtkMyFixed, defined in win_gtk.c),
91 but there can be any number of widgets, handled by a class (e.g. the frame
92 class handles three). The common rule for all windows is only, that the
93 widget that interacts with the rest of GTK must be referenced in m_widget
94 and all other widgets must be children of this widget on the GTK level.
95 The top-most widget, which also represents the client area, must be in
96 the m_wxwindow field and must be of the type GtkMyFixed.
98 As I said, the window classes that display a GTK native widget only have
99 one widget, so in the case of e.g. the wxButton class m_widget holds a
100 pointer to a GtkButton widget. But windows with client areas (for drawing
101 and children) have a m_widget field that is a pointer to a GtkScrolled-
102 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
103 one is (in the GTK sense) a child of the GtkScrolledWindow.
105 If the m_wxwindow field is set, then all input to this widget is inter-
106 cepted and sent to the wxWindows class. If not, all input to the widget
107 that gets pointed to by m_widget gets intercepted and sent to the class.
111 //-----------------------------------------------------------------------------
113 //-----------------------------------------------------------------------------
115 extern wxList wxPendingDelete
;
116 extern wxList wxTopLevelWindows
;
117 extern bool g_blockEventsOnDrag
;
118 static bool g_capturing
= FALSE
;
120 // hack: we need something to pass to gtk_menu_popup, so we store the time of
121 // the last click here
122 static guint32 gs_timeLastClick
= 0;
124 //-----------------------------------------------------------------------------
125 // "expose_event" (of m_wxwindow, not of m_widget)
126 //-----------------------------------------------------------------------------
128 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
130 if (!win
->HasVMT()) return;
131 if (g_blockEventsOnDrag
) return;
133 win
->m_updateRegion
.Union( gdk_event
->area
.x
,
135 gdk_event
->area
.width
,
136 gdk_event
->area
.height
);
138 if (gdk_event
->count
> 0) return;
141 printf( "OnExpose from " );
142 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
143 printf( win->GetClassInfo()->GetClassName() );
147 wxPaintEvent
event( win
->GetId() );
148 event
.SetEventObject( win
);
149 win
->GetEventHandler()->ProcessEvent( event
);
151 win
->m_updateRegion
.Clear();
154 //-----------------------------------------------------------------------------
155 // "draw" (of m_wxwindow, not of m_widget)
156 //-----------------------------------------------------------------------------
158 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
160 if (!win
->HasVMT()) return;
161 if (g_blockEventsOnDrag
) return;
163 win
->m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
165 wxPaintEvent
event( win
->GetId() );
166 event
.SetEventObject( win
);
167 win
->GetEventHandler()->ProcessEvent( event
);
169 win
->m_updateRegion
.Clear();
172 //-----------------------------------------------------------------------------
174 //-----------------------------------------------------------------------------
176 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
178 if (!win
->HasVMT()) return FALSE
;
179 if (g_blockEventsOnDrag
) return FALSE
;
182 printf( "OnKeyPress from " );
183 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
184 printf( win->GetClassInfo()->GetClassName() );
189 switch (gdk_event
->keyval
)
191 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
192 case GDK_Tab
: key_code
= WXK_TAB
; break;
193 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
194 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
195 case GDK_Return
: key_code
= WXK_RETURN
; break;
196 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
197 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
198 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
199 case GDK_Delete
: key_code
= WXK_DELETE
; break;
200 case GDK_Home
: key_code
= WXK_HOME
; break;
201 case GDK_Left
: key_code
= WXK_LEFT
; break;
202 case GDK_Up
: key_code
= WXK_UP
; break;
203 case GDK_Right
: key_code
= WXK_RIGHT
; break;
204 case GDK_Down
: key_code
= WXK_DOWN
; break;
205 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
206 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
207 case GDK_Next
: key_code
= WXK_NEXT
; break;
208 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
209 case GDK_End
: key_code
= WXK_END
; break;
210 case GDK_Begin
: key_code
= WXK_HOME
; break;
211 case GDK_Select
: key_code
= WXK_SELECT
; break;
212 case GDK_Print
: key_code
= WXK_PRINT
; break;
213 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
214 case GDK_Insert
: key_code
= WXK_INSERT
; break;
215 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
216 case GDK_KP_Tab
: key_code
= WXK_TAB
; break;
217 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break;
218 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
219 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
220 case GDK_KP_Up
: key_code
= WXK_UP
; break;
221 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
222 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
223 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
224 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
225 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
226 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
227 case GDK_KP_End
: key_code
= WXK_END
; break;
228 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
229 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
230 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
231 case GDK_KP_Multiply
: key_code
= WXK_MULTIPLY
; break;
232 case GDK_KP_Add
: key_code
= WXK_ADD
; break;
233 case GDK_KP_Separator
: key_code
= WXK_SEPARATOR
; break;
234 case GDK_KP_Subtract
: key_code
= WXK_SUBTRACT
; break;
235 case GDK_KP_Decimal
: key_code
= WXK_DECIMAL
; break;
236 case GDK_KP_Divide
: key_code
= WXK_DIVIDE
; break;
237 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
238 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
239 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
240 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
241 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
242 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
243 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
244 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
245 case GDK_KP_8
: key_code
= WXK_NUMPAD7
; break;
246 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
247 case GDK_F1
: key_code
= WXK_F1
; break;
248 case GDK_F2
: key_code
= WXK_F2
; break;
249 case GDK_F3
: key_code
= WXK_F3
; break;
250 case GDK_F4
: key_code
= WXK_F4
; break;
251 case GDK_F5
: key_code
= WXK_F5
; break;
252 case GDK_F6
: key_code
= WXK_F6
; break;
253 case GDK_F7
: key_code
= WXK_F7
; break;
254 case GDK_F8
: key_code
= WXK_F8
; break;
255 case GDK_F9
: key_code
= WXK_F9
; break;
256 case GDK_F10
: key_code
= WXK_F10
; break;
257 case GDK_F11
: key_code
= WXK_F11
; break;
258 case GDK_F12
: key_code
= WXK_F12
; break;
261 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
262 key_code
= gdk_event
->keyval
;
266 if (!key_code
) return FALSE
;
268 wxKeyEvent
event( wxEVT_CHAR
);
269 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
270 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
271 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
272 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
273 event
.m_keyCode
= key_code
;
276 event
.SetEventObject( win
);
278 bool ret
= win
->GetEventHandler()->ProcessEvent( event
);
282 wxWindow
*ancestor
= win
;
285 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
288 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
289 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
292 ancestor
= ancestor
->GetParent();
298 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
299 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
305 //-----------------------------------------------------------------------------
306 // "button_press_event"
307 //-----------------------------------------------------------------------------
309 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
311 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
313 if (g_blockEventsOnDrag
) return TRUE
;
317 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
319 gtk_widget_grab_focus (win
->m_wxwindow
);
322 printf( "GrabFocus from " );
323 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
324 printf( win->GetClassInfo()->GetClassName() );
331 if (!win
->HasVMT()) return TRUE
;
334 printf( "OnButtonPress from " );
335 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
336 printf( win->GetClassInfo()->GetClassName() );
340 wxEventType event_type
= wxEVT_LEFT_DOWN
;
342 if (gdk_event
->button
== 1)
344 switch (gdk_event
->type
)
346 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
347 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
351 else if (gdk_event
->button
== 2)
353 switch (gdk_event
->type
)
355 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
356 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
360 else if (gdk_event
->button
== 3)
362 switch (gdk_event
->type
)
364 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
365 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
370 wxMouseEvent
event( event_type
);
371 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
372 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
373 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
374 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
375 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
376 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
377 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
379 event
.m_x
= (long)gdk_event
->x
;
380 event
.m_y
= (long)gdk_event
->y
;
382 // Some control don't have their own X window and thus cannot get
387 wxNode
*node
= win
->GetChildren()->First();
390 wxWindow
*child
= (wxWindow
*)node
->Data();
391 if ((child
->m_x
<= event
.m_x
) &&
392 (child
->m_y
<= event
.m_y
) &&
393 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
394 (child
->m_y
+child
->m_height
>= event
.m_y
))
397 event
.m_x
-= child
->m_x
;
398 event
.m_y
-= child
->m_y
;
405 event
.SetEventObject( win
);
407 gs_timeLastClick
= gdk_event
->time
;
409 if (win
->GetEventHandler()->ProcessEvent( event
))
410 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
415 //-----------------------------------------------------------------------------
416 // "button_release_event"
417 //-----------------------------------------------------------------------------
419 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
421 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
423 if (g_blockEventsOnDrag
) return TRUE
;
425 if (!win
->HasVMT()) return TRUE
;
428 printf( "OnButtonRelease from " );
429 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
430 printf( win->GetClassInfo()->GetClassName() );
434 wxEventType event_type
= wxEVT_NULL
;
436 switch (gdk_event
->button
)
438 case 1: event_type
= wxEVT_LEFT_UP
; break;
439 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
440 case 3: event_type
= wxEVT_RIGHT_UP
; break;
443 wxMouseEvent
event( event_type
);
444 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
445 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
446 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
447 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
448 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
449 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
450 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
451 event
.m_x
= (long)gdk_event
->x
;
452 event
.m_y
= (long)gdk_event
->y
;
454 // Some control don't have their own X window and thus cannot get
459 wxNode
*node
= win
->GetChildren()->First();
462 wxWindow
*child
= (wxWindow
*)node
->Data();
463 if ((child
->m_x
<= event
.m_x
) &&
464 (child
->m_y
<= event
.m_y
) &&
465 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
466 (child
->m_y
+child
->m_height
>= event
.m_y
))
469 event
.m_x
-= child
->m_x
;
470 event
.m_y
-= child
->m_y
;
477 event
.SetEventObject( win
);
479 if (win
->GetEventHandler()->ProcessEvent( event
))
480 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
485 //-----------------------------------------------------------------------------
486 // "motion_notify_event"
487 //-----------------------------------------------------------------------------
489 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
491 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
493 if (g_blockEventsOnDrag
) return TRUE
;
495 if (!win
->HasVMT()) return TRUE
;
498 printf( "OnMotion from " );
499 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
500 printf( win->GetClassInfo()->GetClassName() );
504 wxMouseEvent
event( wxEVT_MOTION
);
505 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
506 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
507 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
508 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
509 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
510 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
511 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
513 event
.m_x
= (long)gdk_event
->x
;
514 event
.m_y
= (long)gdk_event
->y
;
516 // Some control don't have their own X window and thus cannot get
521 wxNode
*node
= win
->GetChildren()->First();
524 wxWindow
*child
= (wxWindow
*)node
->Data();
525 if ((child
->m_x
<= event
.m_x
) &&
526 (child
->m_y
<= event
.m_y
) &&
527 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
528 (child
->m_y
+child
->m_height
>= event
.m_y
))
531 event
.m_x
-= child
->m_x
;
532 event
.m_y
-= child
->m_y
;
539 event
.SetEventObject( win
);
541 if (win
->GetEventHandler()->ProcessEvent( event
))
542 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
547 //-----------------------------------------------------------------------------
549 //-----------------------------------------------------------------------------
551 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
553 if (g_blockEventsOnDrag
) return TRUE
;
556 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
558 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
560 printf( "SetFocus flag from " );
561 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
562 printf( win->GetClassInfo()->GetClassName() );
568 if (!win
->HasVMT()) return TRUE
;
571 printf( "OnSetFocus from " );
572 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
573 printf( win->GetClassInfo()->GetClassName() );
575 printf( WXSTRINGCAST win->GetLabel() );
579 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
580 event
.SetEventObject( win
);
582 if (win
->GetEventHandler()->ProcessEvent( event
))
583 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
588 //-----------------------------------------------------------------------------
590 //-----------------------------------------------------------------------------
592 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
594 if (g_blockEventsOnDrag
) return TRUE
;
597 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
598 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
601 if (!win
->HasVMT()) return TRUE
;
604 printf( "OnKillFocus from " );
605 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
606 printf( win->GetClassInfo()->GetClassName() );
610 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
611 event
.SetEventObject( win
);
613 if (win
->GetEventHandler()->ProcessEvent( event
))
614 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
619 //-----------------------------------------------------------------------------
620 // "enter_notify_event"
621 //-----------------------------------------------------------------------------
623 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
625 if (widget
->window
!= gdk_event
->window
) return TRUE
;
627 if (g_blockEventsOnDrag
) return TRUE
;
629 if (!win
->HasVMT()) return TRUE
;
632 printf( "OnEnter from " );
633 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
634 printf( win->GetClassInfo()->GetClassName() );
638 if ((widget
->window
) && (win
->m_cursor
))
639 gdk_window_set_cursor( widget
->window
, win
->m_cursor
->GetCursor() );
641 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
642 event
.SetEventObject( win
);
644 if (win
->GetEventHandler()->ProcessEvent( event
))
645 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
650 //-----------------------------------------------------------------------------
651 // "leave_notify_event"
652 //-----------------------------------------------------------------------------
654 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
656 if (widget
->window
!= gdk_event
->window
) return TRUE
;
658 if (g_blockEventsOnDrag
) return TRUE
;
660 if (!win
->HasVMT()) return TRUE
;
663 printf( "OnLeave from " );
664 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
665 printf( win->GetClassInfo()->GetClassName() );
669 if ((widget
->window
) && (win
->m_cursor
))
670 gdk_window_set_cursor( widget
->window
, wxSTANDARD_CURSOR
->GetCursor() );
672 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
673 event
.SetEventObject( win
);
675 if (win
->GetEventHandler()->ProcessEvent( event
))
676 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
681 //-----------------------------------------------------------------------------
682 // "value_changed" from m_vAdjust
683 //-----------------------------------------------------------------------------
685 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
687 if (g_blockEventsOnDrag
) return;
690 printf( "OnVScroll from " );
691 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
692 printf( win->GetClassInfo()->GetClassName() );
696 if (!win
->HasVMT()) return;
698 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
699 if (fabs(diff
) < 0.2) return;
701 wxEventType command
= wxEVT_NULL
;
703 float line_step
= win
->m_vAdjust
->step_increment
;
704 float page_step
= win
->m_vAdjust
->page_increment
;
706 if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
707 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
708 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
709 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
710 else command
= wxEVT_SCROLL_THUMBTRACK
;
712 int value
= (int)(win
->m_vAdjust
->value
+0.5);
714 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
715 event
.SetEventObject( win
);
716 win
->GetEventHandler()->ProcessEvent( event
);
719 //-----------------------------------------------------------------------------
720 // "value_changed" from m_hAdjust
721 //-----------------------------------------------------------------------------
723 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
725 if (g_blockEventsOnDrag
) return;
728 printf( "OnHScroll from " );
729 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
730 printf( win->GetClassInfo()->GetClassName() );
734 if (!win
->HasVMT()) return;
736 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
737 if (fabs(diff
) < 0.2) return;
739 wxEventType command
= wxEVT_NULL
;
741 float line_step
= win
->m_hAdjust
->step_increment
;
742 float page_step
= win
->m_hAdjust
->page_increment
;
744 if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
745 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
746 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
747 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
748 else command
= wxEVT_SCROLL_THUMBTRACK
;
750 int value
= (int)(win
->m_hAdjust
->value
+0.5);
752 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
753 event
.SetEventObject( win
);
754 win
->GetEventHandler()->ProcessEvent( event
);
757 //-----------------------------------------------------------------------------
758 // "changed" from m_vAdjust
759 //-----------------------------------------------------------------------------
761 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
763 if (g_blockEventsOnDrag
) return;
766 printf( "OnVScroll change from " );
767 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
768 printf( win->GetClassInfo()->GetClassName() );
772 if (!win
->HasVMT()) return;
774 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
775 int value
= (int)(win
->m_vAdjust
->value
+0.5);
777 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
778 event
.SetEventObject( win
);
779 win
->GetEventHandler()->ProcessEvent( event
);
782 //-----------------------------------------------------------------------------
783 // "changed" from m_hAdjust
784 //-----------------------------------------------------------------------------
786 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
788 if (g_blockEventsOnDrag
) return;
791 printf( "OnHScroll change from " );
792 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
793 printf( win->GetClassInfo()->GetClassName() );
797 if (!win
->HasVMT()) return;
799 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
800 int value
= (int)(win
->m_hAdjust
->value
+0.5);
802 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
803 event
.SetEventObject( win
);
804 win
->GetEventHandler()->ProcessEvent( event
);
807 //-----------------------------------------------------------------------------
808 // "button_press_event" from scrollbar
809 //-----------------------------------------------------------------------------
811 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
813 if (gdk_event
->window
!= widget
->slider
) return FALSE
;
815 win
->m_isScrolling
= TRUE
;
820 //-----------------------------------------------------------------------------
821 // "button_release_event" from scrollbar
822 //-----------------------------------------------------------------------------
824 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
826 if (gdk_event
->window
!= widget
->slider
) return FALSE
;
828 GtkScrolledWindow
*s_window
= GTK_SCROLLED_WINDOW(win
->m_widget
);
830 if (widget
== GTK_RANGE(s_window
->vscrollbar
))
831 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_hAdjust
), "value_changed" );
833 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_vAdjust
), "value_changed" );
835 win
->m_isScrolling
= FALSE
;
840 //-----------------------------------------------------------------------------
841 // "drop_data_available_event"
842 //-----------------------------------------------------------------------------
844 static void gtk_window_drop_callback( GtkWidget
*widget
, GdkEvent
*event
, wxWindow
*win
)
846 if (!win
->HasVMT()) return;
848 if (win
->GetDropTarget())
852 gdk_window_get_pointer( widget
->window
, &x
, &y
, (GdkModifierType
*) NULL
);
853 win
->GetDropTarget()->Drop( event
, x
, y
);
857 g_free (event->dropdataavailable.data);
858 g_free (event->dropdataavailable.data_type);
862 //-----------------------------------------------------------------------------
864 //-----------------------------------------------------------------------------
866 IMPLEMENT_DYNAMIC_CLASS(wxWindow
,wxEvtHandler
)
868 BEGIN_EVENT_TABLE(wxWindow
, wxEvtHandler
)
869 EVT_SIZE(wxWindow::OnSize
)
870 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged
)
871 EVT_INIT_DIALOG(wxWindow::OnInitDialog
)
872 EVT_IDLE(wxWindow::OnIdle
)
877 m_widget
= (GtkWidget
*) NULL
;
878 m_wxwindow
= (GtkWidget
*) NULL
;
879 m_parent
= (wxWindow
*) NULL
;
880 m_children
.DeleteContents( FALSE
);
890 m_eventHandler
= this;
891 m_windowValidator
= (wxValidator
*) NULL
;
893 m_cursor
= (wxCursor
*) NULL
;
894 m_font
= *wxSWISS_FONT
;
896 m_windowName
= "noname";
897 m_constraints
= (wxLayoutConstraints
*) NULL
;
898 m_constraintsInvolvedIn
= (wxList
*) NULL
;
899 m_windowSizer
= (wxSizer
*) NULL
;
900 m_sizerParent
= (wxWindow
*) NULL
;
901 m_autoLayout
= FALSE
;
905 m_hasScrolling
= FALSE
;
906 m_isScrolling
= FALSE
;
907 m_hAdjust
= (GtkAdjustment
*) NULL
;
908 m_vAdjust
= (GtkAdjustment
*) NULL
;
909 m_oldHorizontalPos
= 0.0;
910 m_oldVerticalPos
= 0.0;
913 m_pDropTarget
= (wxDropTarget
*) NULL
;
915 m_hasOwnStyle
= FALSE
;
916 m_scrollGC
= (GdkGC
*) NULL
;
919 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
920 const wxPoint
&pos
, const wxSize
&size
,
921 long style
, const wxString
&name
)
927 m_cursor
= (wxCursor
*) NULL
;
929 PreCreation( parent
, id
, pos
, size
, style
, name
);
931 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
932 m_hasScrolling
= TRUE
;
934 GtkScrolledWindow
*s_window
= GTK_SCROLLED_WINDOW(m_widget
);
936 gtk_signal_connect( GTK_OBJECT(s_window
->vscrollbar
), "button_press_event",
937 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
939 gtk_signal_connect( GTK_OBJECT(s_window
->hscrollbar
), "button_press_event",
940 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
942 gtk_signal_connect( GTK_OBJECT(s_window
->vscrollbar
), "button_release_event",
943 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
945 gtk_signal_connect( GTK_OBJECT(s_window
->hscrollbar
), "button_release_event",
946 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
948 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
949 scroll_class
->scrollbar_spacing
= 0;
951 gtk_scrolled_window_set_policy( s_window
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
953 m_oldHorizontalPos
= 0.0;
954 m_oldVerticalPos
= 0.0;
956 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->hscrollbar
) );
957 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->vscrollbar
) );
959 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
960 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
961 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
962 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
964 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
965 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
966 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
967 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
969 GtkViewport
*viewport
= GTK_VIEWPORT(s_window
->viewport
);
971 if (m_windowStyle
& wxRAISED_BORDER
)
973 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
975 else if (m_windowStyle
& wxSUNKEN_BORDER
)
977 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
981 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
984 m_wxwindow
= gtk_myfixed_new();
986 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
988 if (m_windowStyle
& wxTAB_TRAVERSAL
== wxTAB_TRAVERSAL
)
989 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
991 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
993 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
995 // shut the viewport up
996 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
997 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
999 // I _really_ don't want scrollbars in the beginning
1000 m_vAdjust
->lower
= 0.0;
1001 m_vAdjust
->upper
= 1.0;
1002 m_vAdjust
->value
= 0.0;
1003 m_vAdjust
->step_increment
= 1.0;
1004 m_vAdjust
->page_increment
= 1.0;
1005 m_vAdjust
->page_size
= 5.0;
1006 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1007 m_hAdjust
->lower
= 0.0;
1008 m_hAdjust
->upper
= 1.0;
1009 m_hAdjust
->value
= 0.0;
1010 m_hAdjust
->step_increment
= 1.0;
1011 m_hAdjust
->page_increment
= 1.0;
1012 m_hAdjust
->page_size
= 5.0;
1013 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1015 gtk_widget_show( m_wxwindow
);
1024 wxWindow::~wxWindow()
1028 if (m_pDropTarget
) delete m_pDropTarget
;
1030 if (m_parent
) m_parent
->RemoveChild( this );
1031 if (m_widget
) Show( FALSE
);
1035 if (m_scrollGC
) gdk_gc_unref( m_scrollGC
);
1037 if (m_wxwindow
) gtk_widget_destroy( m_wxwindow
);
1039 if (m_widget
) gtk_widget_destroy( m_widget
);
1043 DeleteRelatedConstraints();
1046 // This removes any dangling pointers to this window
1047 // in other windows' constraintsInvolvedIn lists.
1048 UnsetConstraints(m_constraints
);
1049 delete m_constraints
;
1050 m_constraints
= (wxLayoutConstraints
*) NULL
;
1054 delete m_windowSizer
;
1055 m_windowSizer
= (wxSizer
*) NULL
;
1057 // If this is a child of a sizer, remove self from parent
1058 if (m_sizerParent
) m_sizerParent
->RemoveChild((wxWindow
*)this);
1060 // Just in case the window has been Closed, but
1061 // we're then deleting immediately: don't leave
1062 // dangling pointers.
1063 wxPendingDelete
.DeleteObject(this);
1065 // Just in case we've loaded a top-level window via
1066 // wxWindow::LoadNativeDialog but we weren't a dialog
1068 wxTopLevelWindows
.DeleteObject(this);
1070 if (m_windowValidator
) delete m_windowValidator
;
1073 void wxWindow::PreCreation( wxWindow
*parent
, wxWindowID id
,
1074 const wxPoint
&pos
, const wxSize
&size
,
1075 long style
, const wxString
&name
)
1077 if (m_needParent
&& (parent
== NULL
))
1078 wxFatalError( "Need complete parent.", name
);
1080 m_widget
= (GtkWidget
*) NULL
;
1083 m_children
.DeleteContents( FALSE
);
1087 if (m_width
== -1) m_width
= 20;
1089 if (m_height
== -1) m_height
= 20;
1095 m_eventHandler
= this;
1098 if (m_cursor
== NULL
)
1099 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1100 m_font
= *wxSWISS_FONT
;
1101 // m_backgroundColour = wxWHITE;
1102 m_foregroundColour
= wxBLACK
;
1103 m_windowStyle
= style
;
1104 m_windowName
= name
;
1105 m_constraints
= (wxLayoutConstraints
*) NULL
;
1106 m_constraintsInvolvedIn
= (wxList
*) NULL
;
1107 m_windowSizer
= (wxSizer
*) NULL
;
1108 m_sizerParent
= (wxWindow
*) NULL
;
1109 m_autoLayout
= FALSE
;
1110 m_hasScrolling
= FALSE
;
1111 m_isScrolling
= FALSE
;
1112 m_pDropTarget
= (wxDropTarget
*) NULL
;
1114 m_windowValidator
= (wxValidator
*) NULL
;
1115 m_hasOwnStyle
= FALSE
;
1118 void wxWindow::PostCreation()
1120 if (m_parent
) m_parent
->AddChild( this );
1124 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1125 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1127 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1128 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1131 ConnectWidget( GetConnectWidget() );
1133 if (m_widget
&& m_parent
) gtk_widget_realize( m_widget
);
1135 if (m_wxwindow
) gtk_widget_realize( m_wxwindow
);
1137 SetCursor( *wxSTANDARD_CURSOR
);
1142 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1144 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1145 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1147 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1148 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1150 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1151 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1153 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1154 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1156 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1157 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1159 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1160 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1162 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1163 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1165 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1166 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1169 bool wxWindow::HasVMT()
1174 bool wxWindow::Close( bool force
)
1176 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1178 wxCloseEvent
event(wxEVT_CLOSE_WINDOW
, m_windowId
);
1179 event
.SetEventObject(this);
1180 event
.SetForce(force
);
1182 return GetEventHandler()->ProcessEvent(event
);
1185 bool wxWindow::Destroy()
1187 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1194 bool wxWindow::DestroyChildren()
1199 while ((node
= GetChildren()->First()) != (wxNode
*)NULL
)
1202 if ((child
= (wxWindow
*)node
->Data()) != (wxWindow
*)NULL
)
1205 if (GetChildren()->Member(child
)) delete node
;
1212 void wxWindow::PrepareDC( wxDC
&WXUNUSED(dc
) )
1214 // are we to set fonts here ?
1217 void wxWindow::ImplementSetSize()
1219 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1220 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1221 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_minWidth
;
1222 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_minHeight
;
1223 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
1226 void wxWindow::ImplementSetPosition()
1228 if (IS_KIND_OF(this,wxFrame
) || IS_KIND_OF(this,wxDialog
))
1230 if ((m_x
!= -1) || (m_y
!= -1))
1231 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
1237 wxFAIL_MSG( "wxWindow::SetSize error.\n" );
1241 if ((m_parent
) && (m_parent
->m_wxwindow
))
1242 gtk_myfixed_move( GTK_MYFIXED(m_parent
->m_wxwindow
), m_widget
, m_x
, m_y
);
1244 // Don't do anything for children of wxNotebook and wxMDIChildFrame
1247 void wxWindow::SetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1249 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1251 if (m_resizing
) return; // I don't like recursions
1259 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1261 if (newX
== -1) newX
= m_x
;
1262 if (newY
== -1) newY
= m_y
;
1263 if (newW
== -1) newW
= m_width
;
1264 if (newH
== -1) newH
= m_height
;
1267 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1269 if (newW
== -1) newW
= 80;
1272 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1274 if (newH
== -1) newH
= 26;
1277 if ((m_x
!= newX
) || (m_y
!= newY
) || (!m_sizeSet
))
1281 ImplementSetPosition();
1283 if ((m_width
!= newW
) || (m_height
!= newH
) || (!m_sizeSet
))
1291 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1292 event
.SetEventObject( this );
1293 ProcessEvent( event
);
1298 void wxWindow::SetSize( int width
, int height
)
1300 SetSize( -1, -1, width
, height
, wxSIZE_USE_EXISTING
);
1303 void wxWindow::Move( int x
, int y
)
1305 SetSize( x
, y
, -1, -1, wxSIZE_USE_EXISTING
);
1308 void wxWindow::GetSize( int *width
, int *height
) const
1310 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1312 if (width
) (*width
) = m_width
;
1313 if (height
) (*height
) = m_height
;
1316 void wxWindow::SetClientSize( int width
, int height
)
1318 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1322 SetSize( width
, height
);
1329 if (!m_hasScrolling
)
1332 do we have sunken dialogs ?
1334 GtkStyleClass *window_class = m_wxwindow->style->klass;
1336 dw += 2 * window_class->xthickness;
1337 dh += 2 * window_class->ythickness;
1342 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1343 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1345 GtkWidget
*viewport
= scroll_window
->viewport
;
1346 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1348 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1349 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1351 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1352 (m_windowStyle
& wxSUNKEN_BORDER
))
1354 dw
+= 2 * viewport_class
->xthickness
;
1355 dh
+= 2 * viewport_class
->ythickness
;
1358 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1360 dw
+= vscrollbar
->allocation
.width
;
1361 dw
+= scroll_class
->scrollbar_spacing
;
1364 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1366 dh
+= hscrollbar
->allocation
.height
;
1367 dw
+= scroll_class
->scrollbar_spacing
;
1371 SetSize( width
+dw
, height
+dh
);
1375 void wxWindow::GetClientSize( int *width
, int *height
) const
1377 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1381 if (width
) (*width
) = m_width
;
1382 if (height
) (*height
) = m_height
;
1389 if (!m_hasScrolling
)
1392 do we have sunken dialogs ?
1394 GtkStyleClass *window_class = m_wxwindow->style->klass;
1396 dw += 2 * window_class->xthickness;
1397 dh += 2 * window_class->ythickness;
1402 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1403 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1405 GtkWidget
*viewport
= scroll_window
->viewport
;
1406 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1408 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1409 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1411 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1412 (m_windowStyle
& wxSUNKEN_BORDER
))
1414 dw
+= 2 * viewport_class
->xthickness
;
1415 dh
+= 2 * viewport_class
->ythickness
;
1418 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1420 // dw += vscrollbar->allocation.width;
1421 dw
+= 15; // range.slider_width = 11 + 2*2pts edge
1422 dw
+= scroll_class
->scrollbar_spacing
;
1425 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1427 // dh += hscrollbar->allocation.height;
1429 dh
+= scroll_class
->scrollbar_spacing
;
1433 if (width
) (*width
) = m_width
- dw
;
1434 if (height
) (*height
) = m_height
- dh
;
1438 void wxWindow::GetPosition( int *x
, int *y
) const
1440 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1446 void wxWindow::ClientToScreen( int *x
, int *y
)
1448 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1450 GdkWindow
*source
= (GdkWindow
*) NULL
;
1452 source
= m_wxwindow
->window
;
1454 source
= m_widget
->window
;
1458 gdk_window_get_origin( source
, &org_x
, &org_y
);
1462 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1464 org_x
+= m_widget
->allocation
.x
;
1465 org_y
+= m_widget
->allocation
.y
;
1473 void wxWindow::ScreenToClient( int *x
, int *y
)
1475 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1477 GdkWindow
*source
= (GdkWindow
*) NULL
;
1479 source
= m_wxwindow
->window
;
1481 source
= m_widget
->window
;
1485 gdk_window_get_origin( source
, &org_x
, &org_y
);
1489 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1491 org_x
+= m_widget
->allocation
.x
;
1492 org_y
+= m_widget
->allocation
.y
;
1500 void wxWindow::Centre( int direction
)
1502 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1504 if (IS_KIND_OF(this,wxDialog
) || IS_KIND_OF(this,wxFrame
))
1506 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (gdk_screen_width () - m_width
) / 2;
1507 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (gdk_screen_height () - m_height
) / 2;
1508 ImplementSetPosition();
1516 m_parent
->GetSize( &p_w
, &p_h
);
1517 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (p_w
- m_width
) / 2;
1518 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (p_h
- m_height
) / 2;
1519 ImplementSetPosition();
1524 void wxWindow::Fit()
1526 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1530 wxNode
*node
= GetChildren()->First();
1533 wxWindow
*win
= (wxWindow
*)node
->Data();
1535 win
->GetPosition(&wx
, &wy
);
1536 win
->GetSize(&ww
, &wh
);
1537 if ( wx
+ ww
> maxX
)
1539 if ( wy
+ wh
> maxY
)
1542 node
= node
->Next();
1544 SetClientSize(maxX
+ 5, maxY
+ 10);
1547 void wxWindow::SetSizeHints( int minW
, int minH
, int maxW
, int maxH
, int WXUNUSED(incW
), int WXUNUSED(incH
) )
1549 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1557 void wxWindow::OnSize( wxSizeEvent
&WXUNUSED(event
) )
1559 //if (GetAutoLayout()) Layout();
1562 bool wxWindow::Show( bool show
)
1564 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1567 gtk_widget_show( m_widget
);
1569 gtk_widget_hide( m_widget
);
1574 void wxWindow::Enable( bool enable
)
1576 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1578 m_isEnabled
= enable
;
1579 gtk_widget_set_sensitive( m_widget
, enable
);
1580 if (m_wxwindow
) gtk_widget_set_sensitive( m_wxwindow
, enable
);
1583 int wxWindow::GetCharHeight() const
1585 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1589 wxFAIL_MSG( "invalid font" );
1593 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1594 return font
->ascent
+ font
->descent
;
1597 int wxWindow::GetCharWidth() const
1599 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1603 wxFAIL_MSG( "invalid font" );
1607 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1608 return gdk_string_width( font
, "H" );
1611 void wxWindow::GetTextExtent( const wxString
& string
, int *x
, int *y
,
1612 int *descent
, int *externalLeading
, const wxFont
*theFont
, bool WXUNUSED(use16
) ) const
1614 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1616 wxFont fontToUse
= m_font
;
1617 if (theFont
) fontToUse
= *theFont
;
1619 if (!fontToUse
.Ok())
1621 wxFAIL_MSG( "invalid font" );
1624 wxASSERT_MSG( (m_font
.Ok()), "invalid font" );
1626 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
1627 if (x
) (*x
) = gdk_string_width( font
, string
);
1628 if (y
) (*y
) = font
->ascent
+ font
->descent
;
1629 if (descent
) (*descent
) = font
->descent
;
1630 if (externalLeading
) (*externalLeading
) = 0; // ??
1633 void wxWindow::MakeModal( bool modal
)
1636 // Disable all other windows
1637 if (this->IsKindOf(CLASSINFO(wxDialog
)) || this->IsKindOf(CLASSINFO(wxFrame
)))
1639 wxNode
*node
= wxTopLevelWindows
.First();
1642 wxWindow
*win
= (wxWindow
*)node
->Data();
1644 win
->Enable(!modal
);
1646 node
= node
->Next();
1651 void wxWindow::SetFocus()
1653 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1655 GtkWidget
*connect_widget
= GetConnectWidget();
1658 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) && !GTK_WIDGET_HAS_FOCUS (connect_widget
) )
1660 gtk_widget_grab_focus (connect_widget
);
1665 bool wxWindow::OnClose()
1670 void wxWindow::AddChild( wxWindow
*child
)
1672 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1673 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window need client area" );
1674 wxASSERT_MSG( (child
!= NULL
), "invalid child" );
1675 wxASSERT_MSG( (child
->m_widget
!= NULL
), "invalid child" );
1677 // Addchild is (often) called before the program
1678 // has left the parents constructor so that no
1679 // virtual tables work yet. The approach below
1680 // practically imitates virtual tables, i.e. it
1681 // implements a different AddChild() behaviour
1682 // for wxFrame, wxDialog, wxWindow and
1683 // wxMDIParentFrame.
1685 // wxFrame and wxDialog as children aren't placed into the parents
1687 if (( IS_KIND_OF(child
,wxFrame
) || IS_KIND_OF(child
,wxDialog
) ) &&
1688 (!IS_KIND_OF(child
,wxMDIChildFrame
)))
1690 m_children
.Append( child
);
1692 if ((child
->m_x
!= -1) && (child
->m_y
!= -1))
1693 gtk_widget_set_uposition( child
->m_widget
, child
->m_x
, child
->m_y
);
1698 // In the case of an wxMDIChildFrame descendant, we use the
1699 // client windows's AddChild()
1701 if (IS_KIND_OF(this,wxMDIParentFrame
))
1703 if (IS_KIND_OF(child
,wxMDIChildFrame
))
1705 wxMDIClientWindow
*client
= ((wxMDIParentFrame
*)this)->GetClientWindow();
1708 client
->AddChild( child
);
1714 // wxNotebook is very special, so it has a private AddChild()
1716 if (IS_KIND_OF(this,wxNotebook
))
1718 wxNotebook
*tab
= (wxNotebook
*)this;
1719 tab
->AddChild( child
);
1723 // wxFrame has a private AddChild
1725 if (IS_KIND_OF(this,wxFrame
) && !IS_KIND_OF(this,wxMDIChildFrame
))
1727 wxFrame
*frame
= (wxFrame
*)this;
1728 frame
->AddChild( child
);
1734 m_children
.Append( child
);
1735 if (m_wxwindow
) gtk_myfixed_put( GTK_MYFIXED(m_wxwindow
), child
->m_widget
,
1736 child
->m_x
, child
->m_y
);
1738 gtk_widget_set_usize( child
->m_widget
, child
->m_width
, child
->m_height
);
1741 wxList
*wxWindow::GetChildren()
1743 return (&m_children
);
1746 void wxWindow::RemoveChild( wxWindow
*child
)
1749 GetChildren()->DeleteObject( child
);
1750 child
->m_parent
= (wxWindow
*) NULL
;
1753 void wxWindow::SetReturnCode( int retCode
)
1755 m_retCode
= retCode
;
1758 int wxWindow::GetReturnCode()
1763 void wxWindow::Raise()
1765 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1767 if (m_widget
) gdk_window_raise( m_widget
->window
);
1770 void wxWindow::Lower()
1772 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1774 if (m_widget
) gdk_window_lower( m_widget
->window
);
1777 wxEvtHandler
*wxWindow::GetEventHandler()
1779 return m_eventHandler
;
1782 void wxWindow::SetEventHandler( wxEvtHandler
*handler
)
1784 m_eventHandler
= handler
;
1787 void wxWindow::PushEventHandler(wxEvtHandler
*handler
)
1789 handler
->SetNextHandler(GetEventHandler());
1790 SetEventHandler(handler
);
1793 wxEvtHandler
*wxWindow::PopEventHandler(bool deleteHandler
)
1795 if (GetEventHandler())
1797 wxEvtHandler
*handlerA
= GetEventHandler();
1798 wxEvtHandler
*handlerB
= handlerA
->GetNextHandler();
1799 handlerA
->SetNextHandler((wxEvtHandler
*) NULL
);
1800 SetEventHandler(handlerB
);
1804 return (wxEvtHandler
*) NULL
;
1810 return (wxEvtHandler
*) NULL
;
1813 wxValidator
*wxWindow::GetValidator()
1815 return m_windowValidator
;
1818 void wxWindow::SetValidator( const wxValidator
& validator
)
1820 if (m_windowValidator
) delete m_windowValidator
;
1821 m_windowValidator
= validator
.Clone();
1822 if (m_windowValidator
) m_windowValidator
->SetWindow(this);
1825 bool wxWindow::IsBeingDeleted()
1830 void wxWindow::SetId( wxWindowID id
)
1835 wxWindowID
wxWindow::GetId()
1840 void wxWindow::SetCursor( const wxCursor
&cursor
)
1842 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1844 if (m_cursor
== NULL
)
1846 wxFAIL_MSG( "wxWindow::SetCursor m_cursor == NULL" );
1847 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1852 if (*((wxCursor
*)&cursor
) == m_cursor
) return;
1857 *m_cursor
= *wxSTANDARD_CURSOR
;
1860 if ((m_widget
) && (m_widget
->window
))
1861 gdk_window_set_cursor( m_widget
->window
, m_cursor
->GetCursor() );
1863 if ((m_wxwindow
) && (m_wxwindow
->window
))
1864 gdk_window_set_cursor( m_wxwindow
->window
, m_cursor
->GetCursor() );
1867 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
1869 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1871 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
1874 gdk_window_clear_area( m_wxwindow
->window
,
1888 GetClientSize( &w
, &h
);
1890 GdkRectangle gdk_rect
;
1894 gdk_rect
.height
= h
;
1895 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1900 GdkRectangle gdk_rect
;
1901 gdk_rect
.x
= rect
->x
;
1902 gdk_rect
.y
= rect
->y
;
1903 gdk_rect
.width
= rect
->width
;
1904 gdk_rect
.height
= rect
->height
;
1907 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1909 gtk_widget_draw( m_widget
, &gdk_rect
);
1913 wxRegion
wxWindow::GetUpdateRegion() const
1915 return m_updateRegion
;
1918 bool wxWindow::IsExposed( int x
, int y
) const
1920 return (m_updateRegion
.Contains( x
, y
) != wxOutRegion
);
1923 bool wxWindow::IsExposed( int x
, int y
, int w
, int h
) const
1925 return (m_updateRegion
.Contains( x
, y
, w
, h
) != wxOutRegion
);
1928 bool wxWindow::IsExposed( const wxPoint
& pt
) const
1930 return (m_updateRegion
.Contains( pt
.x
, pt
.y
) != wxOutRegion
);
1933 bool wxWindow::IsExposed( const wxRect
& rect
) const
1935 return (m_updateRegion
.Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
) != wxOutRegion
);
1938 void wxWindow::Clear()
1940 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
1942 if (m_wxwindow
&& m_wxwindow
->window
) gdk_window_clear( m_wxwindow
->window
);
1945 wxColour
wxWindow::GetBackgroundColour() const
1947 return m_backgroundColour
;
1950 void wxWindow::SetBackgroundColourHelper( GdkWindow
*window
)
1952 if (!m_backgroundColour
.Ok()) return;
1954 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
1955 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
1956 gdk_window_clear( window
);
1959 void wxWindow::SetBackgroundColour( const wxColour
&colour
)
1961 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
1963 m_backgroundColour
= colour
;
1965 GtkWidget
*widget
= m_wxwindow
== NULL
? m_widget
: m_wxwindow
;
1966 SetBackgroundColourHelper( widget
->window
);
1969 wxColour
wxWindow::GetForegroundColour() const
1971 return m_foregroundColour
;
1974 void wxWindow::SetForegroundColour( const wxColour
&colour
)
1976 m_foregroundColour
= colour
;
1979 bool wxWindow::Validate()
1981 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
1983 wxNode
*node
= GetChildren()->First();
1986 wxWindow
*child
= (wxWindow
*)node
->Data();
1987 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->Validate(this))
1989 node
= node
->Next();
1994 bool wxWindow::TransferDataToWindow()
1996 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
1998 wxNode
*node
= GetChildren()->First();
2001 wxWindow
*child
= (wxWindow
*)node
->Data();
2002 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */
2003 !child
->GetValidator()->TransferToWindow() )
2005 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK
|wxICON_EXCLAMATION
);
2008 node
= node
->Next();
2013 bool wxWindow::TransferDataFromWindow()
2015 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2017 wxNode
*node
= GetChildren()->First();
2020 wxWindow
*child
= (wxWindow
*)node
->Data();
2021 if ( child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->TransferFromWindow() )
2023 node
= node
->Next();
2028 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable
& accel
)
2030 m_acceleratorTable
= accel
;
2033 void wxWindow::OnInitDialog( wxInitDialogEvent
&WXUNUSED(event
) )
2035 TransferDataToWindow();
2038 void wxWindow::InitDialog()
2040 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2042 wxInitDialogEvent
event(GetId());
2043 event
.SetEventObject( this );
2044 GetEventHandler()->ProcessEvent(event
);
2047 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2049 menu
->SetInvokingWindow( win
);
2050 wxNode
*node
= menu
->m_items
.First();
2053 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2054 if (menuitem
->IsSubMenu())
2055 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2056 node
= node
->Next();
2060 bool wxWindow::PopupMenu( wxMenu
*menu
, int WXUNUSED(x
), int WXUNUSED(y
) )
2062 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2064 SetInvokingWindow( menu
, this );
2066 GTK_MENU(menu
->m_menu
),
2067 (GtkWidget
*)NULL
, // parent menu shell
2068 (GtkWidget
*)NULL
, // parent menu item
2069 (GtkMenuPositionFunc
)NULL
,
2070 NULL
, // client data
2071 0, // button used to activate it
2072 0//gs_timeLastClick // the time of activation
2077 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2079 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2081 GtkWidget
*dnd_widget
= GetConnectWidget();
2083 DisconnectDnDWidget( dnd_widget
);
2085 if (m_pDropTarget
) delete m_pDropTarget
;
2086 m_pDropTarget
= dropTarget
;
2088 ConnectDnDWidget( dnd_widget
);
2091 wxDropTarget
*wxWindow::GetDropTarget() const
2093 return m_pDropTarget
;
2096 void wxWindow::ConnectDnDWidget( GtkWidget
*widget
)
2098 if (!m_pDropTarget
) return;
2100 m_pDropTarget
->RegisterWidget( widget
);
2102 gtk_signal_connect( GTK_OBJECT(widget
), "drop_data_available_event",
2103 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
2106 void wxWindow::DisconnectDnDWidget( GtkWidget
*widget
)
2108 if (!m_pDropTarget
) return;
2110 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
2111 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
2113 m_pDropTarget
->UnregisterWidget( widget
);
2116 GtkWidget
* wxWindow::GetConnectWidget()
2118 GtkWidget
*connect_widget
= m_widget
;
2119 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2121 return connect_widget
;
2124 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2126 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2127 return (window
== m_widget
->window
);
2130 void wxWindow::SetFont( const wxFont
&font
)
2132 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2134 if (((wxFont
*)&font
)->Ok())
2137 m_font
= *wxSWISS_FONT
;
2139 GtkStyle
*style
= (GtkStyle
*) NULL
;
2142 m_hasOwnStyle
= TRUE
;
2143 style
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2147 style
= gtk_widget_get_style( m_widget
);
2150 gdk_font_unref( style
->font
);
2151 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2153 gtk_widget_set_style( m_widget
, style
);
2156 wxFont
*wxWindow::GetFont()
2161 void wxWindow::SetWindowStyleFlag( long flag
)
2163 m_windowStyle
= flag
;
2166 long wxWindow::GetWindowStyleFlag() const
2168 return m_windowStyle
;
2171 void wxWindow::CaptureMouse()
2173 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2175 wxASSERT_MSG( (g_capturing
== FALSE
), "CaptureMouse called twice" );
2177 GtkWidget
*connect_widget
= GetConnectWidget();
2178 gtk_grab_add( connect_widget
);
2179 gdk_pointer_grab ( connect_widget
->window
, FALSE
,
2181 (GDK_BUTTON_PRESS_MASK
|
2182 GDK_BUTTON_RELEASE_MASK
|
2183 GDK_POINTER_MOTION_MASK
),
2184 (GdkWindow
*) NULL
, (GdkCursor
*) NULL
, GDK_CURRENT_TIME
);
2188 void wxWindow::ReleaseMouse()
2190 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2192 wxASSERT_MSG( (g_capturing
== TRUE
), "ReleaseMouse called twice" );
2194 GtkWidget
*connect_widget
= GetConnectWidget();
2195 gtk_grab_remove( connect_widget
);
2196 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2197 g_capturing
= FALSE
;
2200 void wxWindow::SetTitle( const wxString
&WXUNUSED(title
) )
2204 wxString
wxWindow::GetTitle() const
2206 return (wxString
&)m_windowName
;
2209 wxString
wxWindow::GetLabel() const
2214 void wxWindow::SetName( const wxString
&name
)
2216 m_windowName
= name
;
2219 wxString
wxWindow::GetName() const
2221 return (wxString
&)m_windowName
;
2224 bool wxWindow::IsShown() const
2229 bool wxWindow::IsRetained()
2234 wxWindow
*wxWindow::FindWindow( long id
)
2236 if (id
== m_windowId
) return this;
2237 wxNode
*node
= m_children
.First();
2240 wxWindow
*child
= (wxWindow
*)node
->Data();
2241 wxWindow
*res
= child
->FindWindow( id
);
2242 if (res
) return res
;
2243 node
= node
->Next();
2245 return (wxWindow
*) NULL
;
2248 wxWindow
*wxWindow::FindWindow( const wxString
& name
)
2250 if (name
== m_windowName
) return this;
2251 wxNode
*node
= m_children
.First();
2254 wxWindow
*child
= (wxWindow
*)node
->Data();
2255 wxWindow
*res
= child
->FindWindow( name
);
2256 if (res
) return res
;
2257 node
= node
->Next();
2259 return (wxWindow
*) NULL
;
2262 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2263 int range
, bool refresh
)
2265 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2267 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2269 if (!m_wxwindow
) return;
2271 if (orient
== wxHORIZONTAL
)
2273 float fpos
= (float)pos
;
2274 float frange
= (float)range
;
2275 float fthumb
= (float)thumbVisible
;
2277 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2278 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2280 SetScrollPos( orient
, pos
, refresh
);
2284 m_oldHorizontalPos
= fpos
;
2286 m_hAdjust
->lower
= 0.0;
2287 m_hAdjust
->upper
= frange
;
2288 m_hAdjust
->value
= fpos
;
2289 m_hAdjust
->step_increment
= 1.0;
2290 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2291 m_hAdjust
->page_size
= fthumb
;
2295 float fpos
= (float)pos
;
2296 float frange
= (float)range
;
2297 float fthumb
= (float)thumbVisible
;
2299 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2300 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2302 SetScrollPos( orient
, pos
, refresh
);
2306 m_oldVerticalPos
= fpos
;
2308 m_vAdjust
->lower
= 0.0;
2309 m_vAdjust
->upper
= frange
;
2310 m_vAdjust
->value
= fpos
;
2311 m_vAdjust
->step_increment
= 1.0;
2312 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2313 m_vAdjust
->page_size
= fthumb
;
2316 if (m_wxwindow
->window
)
2318 if (orient
== wxHORIZONTAL
)
2319 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2321 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2323 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
2327 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2329 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2331 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2333 if (!m_wxwindow
) return;
2335 if (orient
== wxHORIZONTAL
)
2337 float fpos
= (float)pos
;
2338 m_oldHorizontalPos
= fpos
;
2340 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2341 m_hAdjust
->value
= fpos
;
2345 float fpos
= (float)pos
;
2346 m_oldVerticalPos
= fpos
;
2347 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2348 m_vAdjust
->value
= fpos
;
2353 if (m_wxwindow
->window
)
2355 if (orient
== wxHORIZONTAL
)
2356 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2358 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2363 int wxWindow::GetScrollThumb( int orient
) const
2365 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2367 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2369 if (!m_wxwindow
) return 0;
2371 if (orient
== wxHORIZONTAL
)
2372 return (int)(m_hAdjust
->page_size
+0.5);
2374 return (int)(m_vAdjust
->page_size
+0.5);
2377 int wxWindow::GetScrollPos( int orient
) const
2379 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2381 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2383 if (!m_wxwindow
) return 0;
2385 if (orient
== wxHORIZONTAL
)
2386 return (int)(m_hAdjust
->value
+0.5);
2388 return (int)(m_vAdjust
->value
+0.5);
2391 int wxWindow::GetScrollRange( int orient
) const
2393 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2395 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2397 if (!m_wxwindow
) return 0;
2399 if (orient
== wxHORIZONTAL
)
2400 return (int)(m_hAdjust
->upper
+0.5);
2402 return (int)(m_vAdjust
->upper
+0.5);
2405 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2407 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2409 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2411 if (!m_wxwindow
) return;
2415 GetClientSize( &cw
, &ch
);
2417 int w
= cw
- abs(dx
);
2418 int h
= ch
- abs(dy
);
2419 if ((h
< 0) || (w
< 0))
2426 if (dx
< 0) s_x
= -dx
;
2427 if (dy
< 0) s_y
= -dy
;
2430 if (dx
> 0) d_x
= dx
;
2431 if (dy
> 0) d_y
= dy
;
2435 m_scrollGC
= gdk_gc_new( m_wxwindow
->window
);
2436 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
2439 gdk_window_copy_area( m_wxwindow
->window
, m_scrollGC
, d_x
, d_y
,
2440 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2443 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2444 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2445 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2446 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2448 Refresh( TRUE
, &rect
);
2451 //-------------------------------------------------------------------------------------
2453 //-------------------------------------------------------------------------------------
2455 wxLayoutConstraints
*wxWindow::GetConstraints() const
2457 return m_constraints
;
2460 void wxWindow::SetConstraints( wxLayoutConstraints
*constraints
)
2464 UnsetConstraints(m_constraints
);
2465 delete m_constraints
;
2467 m_constraints
= constraints
;
2470 // Make sure other windows know they're part of a 'meaningful relationship'
2471 if (m_constraints
->left
.GetOtherWindow() && (m_constraints
->left
.GetOtherWindow() != this))
2472 m_constraints
->left
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2473 if (m_constraints
->top
.GetOtherWindow() && (m_constraints
->top
.GetOtherWindow() != this))
2474 m_constraints
->top
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2475 if (m_constraints
->right
.GetOtherWindow() && (m_constraints
->right
.GetOtherWindow() != this))
2476 m_constraints
->right
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2477 if (m_constraints
->bottom
.GetOtherWindow() && (m_constraints
->bottom
.GetOtherWindow() != this))
2478 m_constraints
->bottom
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2479 if (m_constraints
->width
.GetOtherWindow() && (m_constraints
->width
.GetOtherWindow() != this))
2480 m_constraints
->width
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2481 if (m_constraints
->height
.GetOtherWindow() && (m_constraints
->height
.GetOtherWindow() != this))
2482 m_constraints
->height
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2483 if (m_constraints
->centreX
.GetOtherWindow() && (m_constraints
->centreX
.GetOtherWindow() != this))
2484 m_constraints
->centreX
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2485 if (m_constraints
->centreY
.GetOtherWindow() && (m_constraints
->centreY
.GetOtherWindow() != this))
2486 m_constraints
->centreY
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2492 void wxWindow::SetAutoLayout( bool autoLayout
)
2494 m_autoLayout
= autoLayout
;
2497 bool wxWindow::GetAutoLayout() const
2499 return m_autoLayout
;
2502 wxSizer
*wxWindow::GetSizer() const
2504 return m_windowSizer
;
2507 void wxWindow::SetSizerParent( wxWindow
*win
)
2509 m_sizerParent
= win
;
2512 wxWindow
*wxWindow::GetSizerParent() const
2514 return m_sizerParent
;
2517 // This removes any dangling pointers to this window
2518 // in other windows' constraintsInvolvedIn lists.
2519 void wxWindow::UnsetConstraints(wxLayoutConstraints
*c
)
2523 if (c
->left
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2524 c
->left
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2525 if (c
->top
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2526 c
->top
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2527 if (c
->right
.GetOtherWindow() && (c
->right
.GetOtherWindow() != this))
2528 c
->right
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2529 if (c
->bottom
.GetOtherWindow() && (c
->bottom
.GetOtherWindow() != this))
2530 c
->bottom
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2531 if (c
->width
.GetOtherWindow() && (c
->width
.GetOtherWindow() != this))
2532 c
->width
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2533 if (c
->height
.GetOtherWindow() && (c
->height
.GetOtherWindow() != this))
2534 c
->height
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2535 if (c
->centreX
.GetOtherWindow() && (c
->centreX
.GetOtherWindow() != this))
2536 c
->centreX
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2537 if (c
->centreY
.GetOtherWindow() && (c
->centreY
.GetOtherWindow() != this))
2538 c
->centreY
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2542 // Back-pointer to other windows we're involved with, so if we delete
2543 // this window, we must delete any constraints we're involved with.
2544 void wxWindow::AddConstraintReference(wxWindow
*otherWin
)
2546 if (!m_constraintsInvolvedIn
)
2547 m_constraintsInvolvedIn
= new wxList
;
2548 if (!m_constraintsInvolvedIn
->Member(otherWin
))
2549 m_constraintsInvolvedIn
->Append(otherWin
);
2552 // REMOVE back-pointer to other windows we're involved with.
2553 void wxWindow::RemoveConstraintReference(wxWindow
*otherWin
)
2555 if (m_constraintsInvolvedIn
)
2556 m_constraintsInvolvedIn
->DeleteObject(otherWin
);
2559 // Reset any constraints that mention this window
2560 void wxWindow::DeleteRelatedConstraints()
2562 if (m_constraintsInvolvedIn
)
2564 wxNode
*node
= m_constraintsInvolvedIn
->First();
2567 wxWindow
*win
= (wxWindow
*)node
->Data();
2568 wxNode
*next
= node
->Next();
2569 wxLayoutConstraints
*constr
= win
->GetConstraints();
2571 // Reset any constraints involving this window
2574 constr
->left
.ResetIfWin((wxWindow
*)this);
2575 constr
->top
.ResetIfWin((wxWindow
*)this);
2576 constr
->right
.ResetIfWin((wxWindow
*)this);
2577 constr
->bottom
.ResetIfWin((wxWindow
*)this);
2578 constr
->width
.ResetIfWin((wxWindow
*)this);
2579 constr
->height
.ResetIfWin((wxWindow
*)this);
2580 constr
->centreX
.ResetIfWin((wxWindow
*)this);
2581 constr
->centreY
.ResetIfWin((wxWindow
*)this);
2586 delete m_constraintsInvolvedIn
;
2587 m_constraintsInvolvedIn
= (wxList
*) NULL
;
2591 void wxWindow::SetSizer(wxSizer
*sizer
)
2593 m_windowSizer
= sizer
;
2595 sizer
->SetSizerParent((wxWindow
*)this);
2602 bool wxWindow::Layout()
2604 if (GetConstraints())
2607 GetClientSize(&w
, &h
);
2608 GetConstraints()->width
.SetValue(w
);
2609 GetConstraints()->height
.SetValue(h
);
2612 // If top level (one sizer), evaluate the sizer's constraints.
2616 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2617 GetSizer()->LayoutPhase1(&noChanges
);
2618 GetSizer()->LayoutPhase2(&noChanges
);
2619 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2624 // Otherwise, evaluate child constraints
2625 ResetConstraints(); // Mark all constraints as unevaluated
2626 DoPhase(1); // Just one phase need if no sizers involved
2628 SetConstraintSizes(); // Recursively set the real window sizes
2634 // Do a phase of evaluating constraints:
2635 // the default behaviour. wxSizers may do a similar
2636 // thing, but also impose their own 'constraints'
2637 // and order the evaluation differently.
2638 bool wxWindow::LayoutPhase1(int *noChanges
)
2640 wxLayoutConstraints
*constr
= GetConstraints();
2643 return constr
->SatisfyConstraints((wxWindow
*)this, noChanges
);
2649 bool wxWindow::LayoutPhase2(int *noChanges
)
2659 // Do a phase of evaluating child constraints
2660 bool wxWindow::DoPhase(int phase
)
2662 int noIterations
= 0;
2663 int maxIterations
= 500;
2667 while ((noChanges
> 0) && (noIterations
< maxIterations
))
2671 wxNode
*node
= GetChildren()->First();
2674 wxWindow
*child
= (wxWindow
*)node
->Data();
2675 if (!child
->IsKindOf(CLASSINFO(wxFrame
)) && !child
->IsKindOf(CLASSINFO(wxDialog
)))
2677 wxLayoutConstraints
*constr
= child
->GetConstraints();
2680 if (succeeded
.Member(child
))
2685 int tempNoChanges
= 0;
2686 bool success
= ( (phase
== 1) ? child
->LayoutPhase1(&tempNoChanges
) : child
->LayoutPhase2(&tempNoChanges
) ) ;
2687 noChanges
+= tempNoChanges
;
2690 succeeded
.Append(child
);
2695 node
= node
->Next();
2702 void wxWindow::ResetConstraints()
2704 wxLayoutConstraints
*constr
= GetConstraints();
2707 constr
->left
.SetDone(FALSE
);
2708 constr
->top
.SetDone(FALSE
);
2709 constr
->right
.SetDone(FALSE
);
2710 constr
->bottom
.SetDone(FALSE
);
2711 constr
->width
.SetDone(FALSE
);
2712 constr
->height
.SetDone(FALSE
);
2713 constr
->centreX
.SetDone(FALSE
);
2714 constr
->centreY
.SetDone(FALSE
);
2716 wxNode
*node
= GetChildren()->First();
2719 wxWindow
*win
= (wxWindow
*)node
->Data();
2720 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2721 win
->ResetConstraints();
2722 node
= node
->Next();
2726 // Need to distinguish between setting the 'fake' size for
2727 // windows and sizers, and setting the real values.
2728 void wxWindow::SetConstraintSizes(bool recurse
)
2730 wxLayoutConstraints
*constr
= GetConstraints();
2731 if (constr
&& constr
->left
.GetDone() && constr
->right
.GetDone() &&
2732 constr
->width
.GetDone() && constr
->height
.GetDone())
2734 int x
= constr
->left
.GetValue();
2735 int y
= constr
->top
.GetValue();
2736 int w
= constr
->width
.GetValue();
2737 int h
= constr
->height
.GetValue();
2739 // If we don't want to resize this window, just move it...
2740 if ((constr
->width
.GetRelationship() != wxAsIs
) ||
2741 (constr
->height
.GetRelationship() != wxAsIs
))
2743 // Calls Layout() recursively. AAAGH. How can we stop that.
2744 // Simply take Layout() out of non-top level OnSizes.
2745 SizerSetSize(x
, y
, w
, h
);
2754 char *windowClass
= this->GetClassInfo()->GetClassName();
2757 if (GetName() == "")
2758 winName
= _("unnamed");
2760 winName
= GetName();
2761 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass
, (const char *)winName
);
2762 if (!constr
->left
.GetDone())
2763 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2764 if (!constr
->right
.GetDone())
2765 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2766 if (!constr
->width
.GetDone())
2767 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2768 if (!constr
->height
.GetDone())
2769 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2770 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2775 wxNode
*node
= GetChildren()->First();
2778 wxWindow
*win
= (wxWindow
*)node
->Data();
2779 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2780 win
->SetConstraintSizes();
2781 node
= node
->Next();
2786 // This assumes that all sizers are 'on' the same
2787 // window, i.e. the parent of this window.
2788 void wxWindow::TransformSizerToActual(int *x
, int *y
) const
2790 if (!m_sizerParent
|| m_sizerParent
->IsKindOf(CLASSINFO(wxDialog
)) ||
2791 m_sizerParent
->IsKindOf(CLASSINFO(wxFrame
)) )
2795 m_sizerParent
->GetPosition(&xp
, &yp
);
2796 m_sizerParent
->TransformSizerToActual(&xp
, &yp
);
2801 void wxWindow::SizerSetSize(int x
, int y
, int w
, int h
)
2805 TransformSizerToActual(&xx
, &yy
);
2806 SetSize(xx
, yy
, w
, h
);
2809 void wxWindow::SizerMove(int x
, int y
)
2813 TransformSizerToActual(&xx
, &yy
);
2817 // Only set the size/position of the constraint (if any)
2818 void wxWindow::SetSizeConstraint(int x
, int y
, int w
, int h
)
2820 wxLayoutConstraints
*constr
= GetConstraints();
2825 constr
->left
.SetValue(x
);
2826 constr
->left
.SetDone(TRUE
);
2830 constr
->top
.SetValue(y
);
2831 constr
->top
.SetDone(TRUE
);
2835 constr
->width
.SetValue(w
);
2836 constr
->width
.SetDone(TRUE
);
2840 constr
->height
.SetValue(h
);
2841 constr
->height
.SetDone(TRUE
);
2846 void wxWindow::MoveConstraint(int x
, int y
)
2848 wxLayoutConstraints
*constr
= GetConstraints();
2853 constr
->left
.SetValue(x
);
2854 constr
->left
.SetDone(TRUE
);
2858 constr
->top
.SetValue(y
);
2859 constr
->top
.SetDone(TRUE
);
2864 void wxWindow::GetSizeConstraint(int *w
, int *h
) const
2866 wxLayoutConstraints
*constr
= GetConstraints();
2869 *w
= constr
->width
.GetValue();
2870 *h
= constr
->height
.GetValue();
2876 void wxWindow::GetClientSizeConstraint(int *w
, int *h
) const
2878 wxLayoutConstraints
*constr
= GetConstraints();
2881 *w
= constr
->width
.GetValue();
2882 *h
= constr
->height
.GetValue();
2885 GetClientSize(w
, h
);
2888 void wxWindow::GetPositionConstraint(int *x
, int *y
) const
2890 wxLayoutConstraints
*constr
= GetConstraints();
2893 *x
= constr
->left
.GetValue();
2894 *y
= constr
->top
.GetValue();
2900 bool wxWindow::AcceptsFocus() const
2902 return IsEnabled() && IsShown();
2905 void wxWindow::OnIdle(wxIdleEvent
& WXUNUSED(event
) )