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 #if wxUSE_DRAG_AND_DROP
28 #include "wx/tooltip.h"
31 #include "wx/statusbr.h"
33 #include "wx/settings.h"
40 #include "gdk/gdkprivate.h"
41 #include "gdk/gdkkeysyms.h"
42 #include "wx/gtk/win_gtk.h"
44 //-----------------------------------------------------------------------------
45 // documentation on internals
46 //-----------------------------------------------------------------------------
49 I have been asked several times about writing some documentation about
50 the GTK port of wxWindows, especially its internal structures. Obviously,
51 you cannot understand wxGTK without knowing a little about the GTK, but
52 some more information about what the wxWindow, which is the base class
53 for all other window classes, does seems required as well.
55 What does wxWindow do? It contains the common interface for the following
56 jobs of its descendants:
58 1) Define the rudimentary behaviour common to all window classes, such as
59 resizing, intercepting user input (so as to make it possible to use these
60 events for special purposes in a derived class), window names etc.
62 2) Provide the possibility to contain and manage children, if the derived
63 class is allowed to contain children, which holds true for those window
64 classes which do not display a native GTK widget. To name them, these
65 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
66 work classes are a special case and are handled a bit differently from
67 the rest. The same holds true for the wxNotebook class.
69 3) Provide the possibility to draw into a client area of a window. This,
70 too, only holds true for classes that do not display a native GTK widget
73 4) Provide the entire mechanism for scrolling widgets. This actual inter-
74 face for this is usually in wxScrolledWindow, but the GTK implementation
77 5) A multitude of helper or extra methods for special purposes, such as
78 Drag'n'Drop, managing validators etc.
80 Normally one might expect, that one wxWindows window would always correspond
81 to one GTK widget. Under GTK, there is no such allround widget that has all
82 the functionality. Moreover, the GTK defines a client area as a different
83 widget from the actual widget you are handling. Last but not least some
84 special classes (e.g. wxFrame) handle different categories of widgets and
85 still have the possibility to draw something in the client area.
86 It was therefore required to write a special purpose GTK widget, that would
87 represent a client area in the sense of wxWindows capable to do the jobs
88 2), 3) and 4). I have written this class and it resides in win_gtk.c of
91 All windows must have a widget, with which they interact with other under-
92 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
93 thw wxWindow class has a member variable called m_widget which holds a
94 pointer to this widget. When the window class represents a GTK native widget,
95 this is (in most cases) the only GTK widget the class manages. E.g. the
96 wxStatitText class handles only a GtkLabel widget a pointer to which you
97 can find in m_widget (defined in wxWindow)
99 When the class has a client area for drawing into and for containing children
100 it has to handle the client area widget (of the type GtkMyFixed, defined in
101 win_gtk.c), but there could be any number of widgets, handled by a class
102 The common rule for all windows is only, that the widget that interacts with
103 the rest of GTK must be referenced in m_widget and all other widgets must be
104 children of this widget on the GTK level. The top-most widget, which also
105 represents the client area, must be in the m_wxwindow field and must be of
108 As I said, the window classes that display a GTK native widget only have
109 one widget, so in the case of e.g. the wxButton class m_widget holds a
110 pointer to a GtkButton widget. But windows with client areas (for drawing
111 and children) have a m_widget field that is a pointer to a GtkScrolled-
112 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
113 one is (in the GTK sense) a child of the GtkScrolledWindow.
115 If the m_wxwindow field is set, then all input to this widget is inter-
116 cepted and sent to the wxWindows class. If not, all input to the widget
117 that gets pointed to by m_widget gets intercepted and sent to the class.
121 //-------------------------------------------------------------------------
122 // conditional compilation
123 //-------------------------------------------------------------------------
125 #if (GTK_MINOR_VERSION == 1)
126 #if (GTK_MICRO_VERSION >= 5)
127 #define NEW_GTK_SCROLL_CODE
131 //-----------------------------------------------------------------------------
133 //-----------------------------------------------------------------------------
137 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
138 GdkEvent
*WXUNUSED(event
),
141 printf( "FOCUS NOW AT: " );
148 void debug_focus_in( GtkWidget
* widget
, const char* name
, const char *window
)
156 char *s
= new char[tmp
.Length()+1];
158 strcpy( s
, WXSTRINGCAST tmp
);
160 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
161 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
166 //-----------------------------------------------------------------------------
168 //-----------------------------------------------------------------------------
170 extern wxList wxPendingDelete
;
171 extern wxList wxTopLevelWindows
;
172 extern bool g_blockEventsOnDrag
;
173 extern bool g_blockEventsOnScroll
;
174 static bool g_capturing
= FALSE
;
175 static wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
177 // hack: we need something to pass to gtk_menu_popup, so we store the time of
178 // the last click here
179 static guint32 gs_timeLastClick
= 0;
181 //-----------------------------------------------------------------------------
182 // "expose_event" (of m_wxwindow, not of m_widget)
183 //-----------------------------------------------------------------------------
185 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
187 if (!win
->HasVMT()) return;
189 win
->m_updateRegion
.Union( gdk_event
->area
.x
,
191 gdk_event
->area
.width
,
192 gdk_event
->area
.height
);
194 if (gdk_event
->count
> 0) return;
197 printf( "OnExpose from " );
198 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
199 printf( win->GetClassInfo()->GetClassName() );
203 wxPaintEvent
event( win
->GetId() );
204 event
.SetEventObject( win
);
205 win
->GetEventHandler()->ProcessEvent( event
);
207 win
->m_updateRegion
.Clear();
210 //-----------------------------------------------------------------------------
211 // "draw" (of m_wxwindow, not of m_widget)
212 //-----------------------------------------------------------------------------
214 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
216 if (!win
->HasVMT()) return;
218 win
->m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
220 wxPaintEvent
event( win
->GetId() );
221 event
.SetEventObject( win
);
222 win
->GetEventHandler()->ProcessEvent( event
);
224 win
->m_updateRegion
.Clear();
227 //-----------------------------------------------------------------------------
228 // "key_press_event" from any window
229 //-----------------------------------------------------------------------------
231 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
233 if (!win
->HasVMT()) return FALSE
;
234 if (g_blockEventsOnDrag
) return FALSE
;
237 printf( "OnKeyPress from " );
238 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
239 printf( win->GetClassInfo()->GetClassName() );
244 switch (gdk_event
->keyval
)
246 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
247 case GDK_Tab
: key_code
= WXK_TAB
; break;
248 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
249 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
250 case GDK_Return
: key_code
= WXK_RETURN
; break;
251 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
252 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
253 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
254 case GDK_Delete
: key_code
= WXK_DELETE
; break;
255 case GDK_Home
: key_code
= WXK_HOME
; break;
256 case GDK_Left
: key_code
= WXK_LEFT
; break;
257 case GDK_Up
: key_code
= WXK_UP
; break;
258 case GDK_Right
: key_code
= WXK_RIGHT
; break;
259 case GDK_Down
: key_code
= WXK_DOWN
; break;
260 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
261 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
262 case GDK_Next
: key_code
= WXK_NEXT
; break;
263 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
264 case GDK_End
: key_code
= WXK_END
; break;
265 case GDK_Begin
: key_code
= WXK_HOME
; break;
266 case GDK_Select
: key_code
= WXK_SELECT
; break;
267 case GDK_Print
: key_code
= WXK_PRINT
; break;
268 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
269 case GDK_Insert
: key_code
= WXK_INSERT
; break;
270 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
271 case GDK_KP_Tab
: key_code
= WXK_TAB
; break;
272 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break;
273 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
274 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
275 case GDK_KP_Up
: key_code
= WXK_UP
; break;
276 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
277 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
278 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
279 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
280 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
281 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
282 case GDK_KP_End
: key_code
= WXK_END
; break;
283 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
284 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
285 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
286 case GDK_KP_Multiply
: key_code
= WXK_MULTIPLY
; break;
287 case GDK_KP_Add
: key_code
= WXK_ADD
; break;
288 case GDK_KP_Separator
: key_code
= WXK_SEPARATOR
; break;
289 case GDK_KP_Subtract
: key_code
= WXK_SUBTRACT
; break;
290 case GDK_KP_Decimal
: key_code
= WXK_DECIMAL
; break;
291 case GDK_KP_Divide
: key_code
= WXK_DIVIDE
; break;
292 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
293 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
294 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
295 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
296 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
297 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
298 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
299 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
300 case GDK_KP_8
: key_code
= WXK_NUMPAD7
; break;
301 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
302 case GDK_F1
: key_code
= WXK_F1
; break;
303 case GDK_F2
: key_code
= WXK_F2
; break;
304 case GDK_F3
: key_code
= WXK_F3
; break;
305 case GDK_F4
: key_code
= WXK_F4
; break;
306 case GDK_F5
: key_code
= WXK_F5
; break;
307 case GDK_F6
: key_code
= WXK_F6
; break;
308 case GDK_F7
: key_code
= WXK_F7
; break;
309 case GDK_F8
: key_code
= WXK_F8
; break;
310 case GDK_F9
: key_code
= WXK_F9
; break;
311 case GDK_F10
: key_code
= WXK_F10
; break;
312 case GDK_F11
: key_code
= WXK_F11
; break;
313 case GDK_F12
: key_code
= WXK_F12
; break;
316 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
317 key_code
= gdk_event
->keyval
;
321 if (!key_code
) return FALSE
;
323 wxKeyEvent
event( wxEVT_KEY_DOWN
);
324 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
325 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
326 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
327 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
328 event
.m_keyCode
= key_code
;
331 event
.SetEventObject( win
);
333 bool ret
= win
->GetEventHandler()->ProcessEvent( event
);
337 wxWindow
*ancestor
= win
;
340 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
343 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
344 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
347 ancestor
= ancestor
->GetParent();
351 // win is a control: tab can be propagated up
352 if ((!ret
) && (gdk_event
->keyval
== GDK_Tab
) && ((win
->m_windowStyle
& wxTE_PROCESS_TAB
) == 0))
354 wxNavigationKeyEvent new_event
;
355 new_event
.SetDirection( !(gdk_event
->state
& GDK_SHIFT_MASK
) );
356 new_event
.SetWindowChange( FALSE
);
357 new_event
.SetCurrentFocus( win
);
358 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
362 // win is a panel: up can be propagated to the panel
363 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
364 (gdk_event->keyval == GDK_Up))
366 win->m_parent->SetFocus();
370 // win is a panel: left/right can be propagated to the panel
371 if ((!ret) && (win->m_wxwindow) &&
372 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
373 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
375 wxNavigationKeyEvent new_event;
376 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
377 new_event.SetCurrentFocus( win );
378 ret = win->GetEventHandler()->ProcessEvent( new_event );
384 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
390 //-----------------------------------------------------------------------------
391 // "key_release_event" from any window
392 //-----------------------------------------------------------------------------
394 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
396 if (!win
->HasVMT()) return FALSE
;
397 if (g_blockEventsOnDrag
) return FALSE
;
400 printf( "OnKeyRelease from " );
401 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
402 printf( win->GetClassInfo()->GetClassName() );
407 switch (gdk_event
->keyval
)
409 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
410 case GDK_Tab
: key_code
= WXK_TAB
; break;
411 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
412 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
413 case GDK_Return
: key_code
= WXK_RETURN
; break;
414 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
415 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
416 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
417 case GDK_Delete
: key_code
= WXK_DELETE
; break;
418 case GDK_Home
: key_code
= WXK_HOME
; break;
419 case GDK_Left
: key_code
= WXK_LEFT
; break;
420 case GDK_Up
: key_code
= WXK_UP
; break;
421 case GDK_Right
: key_code
= WXK_RIGHT
; break;
422 case GDK_Down
: key_code
= WXK_DOWN
; break;
423 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
424 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
425 case GDK_Next
: key_code
= WXK_NEXT
; break;
426 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
427 case GDK_End
: key_code
= WXK_END
; break;
428 case GDK_Begin
: key_code
= WXK_HOME
; break;
429 case GDK_Select
: key_code
= WXK_SELECT
; break;
430 case GDK_Print
: key_code
= WXK_PRINT
; break;
431 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
432 case GDK_Insert
: key_code
= WXK_INSERT
; break;
433 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
434 case GDK_KP_Tab
: key_code
= WXK_TAB
; break;
435 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break;
436 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
437 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
438 case GDK_KP_Up
: key_code
= WXK_UP
; break;
439 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
440 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
441 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
442 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
443 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
444 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
445 case GDK_KP_End
: key_code
= WXK_END
; break;
446 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
447 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
448 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
449 case GDK_KP_Multiply
: key_code
= WXK_MULTIPLY
; break;
450 case GDK_KP_Add
: key_code
= WXK_ADD
; break;
451 case GDK_KP_Separator
: key_code
= WXK_SEPARATOR
; break;
452 case GDK_KP_Subtract
: key_code
= WXK_SUBTRACT
; break;
453 case GDK_KP_Decimal
: key_code
= WXK_DECIMAL
; break;
454 case GDK_KP_Divide
: key_code
= WXK_DIVIDE
; break;
455 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
456 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
457 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
458 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
459 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
460 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
461 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
462 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
463 case GDK_KP_8
: key_code
= WXK_NUMPAD7
; break;
464 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
465 case GDK_F1
: key_code
= WXK_F1
; break;
466 case GDK_F2
: key_code
= WXK_F2
; break;
467 case GDK_F3
: key_code
= WXK_F3
; break;
468 case GDK_F4
: key_code
= WXK_F4
; break;
469 case GDK_F5
: key_code
= WXK_F5
; break;
470 case GDK_F6
: key_code
= WXK_F6
; break;
471 case GDK_F7
: key_code
= WXK_F7
; break;
472 case GDK_F8
: key_code
= WXK_F8
; break;
473 case GDK_F9
: key_code
= WXK_F9
; break;
474 case GDK_F10
: key_code
= WXK_F10
; break;
475 case GDK_F11
: key_code
= WXK_F11
; break;
476 case GDK_F12
: key_code
= WXK_F12
; break;
479 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
480 key_code
= gdk_event
->keyval
;
484 if (!key_code
) return FALSE
;
486 wxKeyEvent
event( wxEVT_KEY_UP
);
487 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
488 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
489 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
490 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
491 event
.m_keyCode
= key_code
;
494 event
.SetEventObject( win
);
496 bool ret
= win
->GetEventHandler()->ProcessEvent( event
);
500 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
506 //-----------------------------------------------------------------------------
507 // "button_press_event"
508 //-----------------------------------------------------------------------------
510 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
512 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
514 if (g_blockEventsOnDrag
) return TRUE
;
515 if (g_blockEventsOnScroll
) return TRUE
;
519 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
521 gtk_widget_grab_focus (win
->m_wxwindow
);
524 printf( "GrabFocus from " );
525 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
526 printf( win->GetClassInfo()->GetClassName() );
533 if (!win
->HasVMT()) return TRUE
;
536 printf( "OnButtonPress from " );
537 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
538 printf( win->GetClassInfo()->GetClassName() );
542 wxEventType event_type
= wxEVT_LEFT_DOWN
;
544 if (gdk_event
->button
== 1)
546 switch (gdk_event
->type
)
548 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
549 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
553 else if (gdk_event
->button
== 2)
555 switch (gdk_event
->type
)
557 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
558 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
562 else if (gdk_event
->button
== 3)
564 switch (gdk_event
->type
)
566 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
567 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
572 wxMouseEvent
event( event_type
);
573 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
574 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
575 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
576 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
577 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
578 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
579 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
581 event
.m_x
= (long)gdk_event
->x
;
582 event
.m_y
= (long)gdk_event
->y
;
584 // Some control don't have their own X window and thus cannot get
589 wxNode
*node
= win
->GetChildren().First();
592 wxWindow
*child
= (wxWindow
*)node
->Data();
594 if (child
->m_isStaticBox
)
596 // wxStaticBox is transparent in the box itself
599 int xx1
= child
->m_x
;
600 int yy1
= child
->m_y
;
601 int xx2
= child
->m_x
+ child
->m_width
;
602 int yy2
= child
->m_x
+ child
->m_height
;
605 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
607 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
609 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
611 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
614 event
.m_x
-= child
->m_x
;
615 event
.m_y
-= child
->m_y
;
622 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
623 (child
->m_x
<= event
.m_x
) &&
624 (child
->m_y
<= event
.m_y
) &&
625 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
626 (child
->m_y
+child
->m_height
>= event
.m_y
))
629 event
.m_x
-= child
->m_x
;
630 event
.m_y
-= child
->m_y
;
638 wxPoint
pt(win
->GetClientAreaOrigin());
642 event
.SetEventObject( win
);
644 gs_timeLastClick
= gdk_event
->time
;
646 if (win
->GetEventHandler()->ProcessEvent( event
))
647 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
652 //-----------------------------------------------------------------------------
653 // "button_release_event"
654 //-----------------------------------------------------------------------------
656 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
658 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
660 if (g_blockEventsOnDrag
) return TRUE
;
661 if (g_blockEventsOnScroll
) return TRUE
;
663 if (!win
->HasVMT()) return TRUE
;
666 printf( "OnButtonRelease from " );
667 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
668 printf( win->GetClassInfo()->GetClassName() );
672 wxEventType event_type
= wxEVT_NULL
;
674 switch (gdk_event
->button
)
676 case 1: event_type
= wxEVT_LEFT_UP
; break;
677 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
678 case 3: event_type
= wxEVT_RIGHT_UP
; break;
681 wxMouseEvent
event( event_type
);
682 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
683 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
684 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
685 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
686 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
687 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
688 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
689 event
.m_x
= (long)gdk_event
->x
;
690 event
.m_y
= (long)gdk_event
->y
;
692 // Some control don't have their own X window and thus cannot get
697 wxNode
*node
= win
->GetChildren().First();
700 wxWindow
*child
= (wxWindow
*)node
->Data();
702 if (child
->m_isStaticBox
)
704 // wxStaticBox is transparent in the box itself
707 int xx1
= child
->m_x
;
708 int yy1
= child
->m_y
;
709 int xx2
= child
->m_x
+ child
->m_width
;
710 int yy2
= child
->m_x
+ child
->m_height
;
713 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
715 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
717 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
719 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
722 event
.m_x
-= child
->m_x
;
723 event
.m_y
-= child
->m_y
;
730 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
731 (child
->m_x
<= event
.m_x
) &&
732 (child
->m_y
<= event
.m_y
) &&
733 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
734 (child
->m_y
+child
->m_height
>= event
.m_y
))
737 event
.m_x
-= child
->m_x
;
738 event
.m_y
-= child
->m_y
;
746 wxPoint
pt(win
->GetClientAreaOrigin());
750 event
.SetEventObject( win
);
752 if (win
->GetEventHandler()->ProcessEvent( event
))
753 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
758 //-----------------------------------------------------------------------------
759 // "motion_notify_event"
760 //-----------------------------------------------------------------------------
762 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
764 if (gdk_event
->is_hint
)
768 GdkModifierType state
;
769 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
772 gdk_event
->state
= state
;
775 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
777 if (g_blockEventsOnDrag
) return TRUE
;
778 if (g_blockEventsOnScroll
) return TRUE
;
780 if (!win
->HasVMT()) return TRUE
;
783 printf( "OnMotion from " );
784 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
785 printf( win->GetClassInfo()->GetClassName() );
789 wxMouseEvent
event( wxEVT_MOTION
);
790 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
791 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
792 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
793 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
794 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
795 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
796 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
798 event
.m_x
= (long)gdk_event
->x
;
799 event
.m_y
= (long)gdk_event
->y
;
801 // Some control don't have their own X window and thus cannot get
806 wxNode
*node
= win
->GetChildren().First();
809 wxWindow
*child
= (wxWindow
*)node
->Data();
811 if (child
->m_isStaticBox
)
813 // wxStaticBox is transparent in the box itself
816 int xx1
= child
->m_x
;
817 int yy1
= child
->m_y
;
818 int xx2
= child
->m_x
+ child
->m_width
;
819 int yy2
= child
->m_x
+ child
->m_height
;
822 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
824 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
826 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
828 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
831 event
.m_x
-= child
->m_x
;
832 event
.m_y
-= child
->m_y
;
839 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
840 (child
->m_x
<= event
.m_x
) &&
841 (child
->m_y
<= event
.m_y
) &&
842 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
843 (child
->m_y
+child
->m_height
>= event
.m_y
))
846 event
.m_x
-= child
->m_x
;
847 event
.m_y
-= child
->m_y
;
855 wxPoint
pt(win
->GetClientAreaOrigin());
859 event
.SetEventObject( win
);
861 if (win
->GetEventHandler()->ProcessEvent( event
))
862 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
867 //-----------------------------------------------------------------------------
869 //-----------------------------------------------------------------------------
871 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
873 if (g_blockEventsOnDrag
) return TRUE
;
879 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
881 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
883 printf( "SetFocus flag from " );
884 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
885 printf( win->GetClassInfo()->GetClassName() );
891 if (!win
->HasVMT()) return TRUE
;
894 printf( "OnSetFocus from " );
895 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
896 printf( win->GetClassInfo()->GetClassName() );
898 printf( WXSTRINGCAST win->GetLabel() );
902 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
903 event
.SetEventObject( win
);
905 if (win
->GetEventHandler()->ProcessEvent( event
))
906 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
911 //-----------------------------------------------------------------------------
913 //-----------------------------------------------------------------------------
915 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
917 if (g_blockEventsOnDrag
) return TRUE
;
920 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
921 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
924 if (!win
->HasVMT()) return TRUE
;
927 printf( "OnKillFocus from " );
928 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
929 printf( win->GetClassInfo()->GetClassName() );
933 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
934 event
.SetEventObject( win
);
936 if (win
->GetEventHandler()->ProcessEvent( event
))
937 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
942 //-----------------------------------------------------------------------------
943 // "enter_notify_event"
944 //-----------------------------------------------------------------------------
946 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
948 if (g_blockEventsOnDrag
) return TRUE
;
950 if ((widget
->window
) && (win
->m_cursor
))
951 gdk_window_set_cursor( widget
->window
, win
->m_cursor
->GetCursor() );
953 if (widget
->window
!= gdk_event
->window
) return TRUE
;
955 if (!win
->HasVMT()) return TRUE
;
958 printf( "OnEnter from " );
959 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
960 printf( win->GetClassInfo()->GetClassName() );
964 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
965 event
.SetEventObject( win
);
969 GdkModifierType state
= (GdkModifierType
)0;
971 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
973 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
974 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
975 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
976 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
977 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
978 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
979 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
984 wxPoint
pt(win
->GetClientAreaOrigin());
988 if (win
->GetEventHandler()->ProcessEvent( event
))
989 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
994 //-----------------------------------------------------------------------------
995 // "leave_notify_event"
996 //-----------------------------------------------------------------------------
998 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1000 if (g_blockEventsOnDrag
) return TRUE
;
1002 if ((widget
->window
) && (win
->m_cursor
))
1003 gdk_window_set_cursor( widget
->window
, wxSTANDARD_CURSOR
->GetCursor() );
1005 if (widget
->window
!= gdk_event
->window
) return TRUE
;
1007 if (!win
->HasVMT()) return TRUE
;
1010 printf( "OnLeave from " );
1011 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1012 printf( win->GetClassInfo()->GetClassName() );
1016 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1017 event
.SetEventObject( win
);
1021 GdkModifierType state
= (GdkModifierType
)0;
1023 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1025 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1026 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1027 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1028 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1029 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1030 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1031 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1033 event
.m_x
= (long)x
;
1034 event
.m_y
= (long)y
;
1036 wxPoint
pt(win
->GetClientAreaOrigin());
1040 if (win
->GetEventHandler()->ProcessEvent( event
))
1041 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1046 //-----------------------------------------------------------------------------
1047 // "value_changed" from m_vAdjust
1048 //-----------------------------------------------------------------------------
1050 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1052 if (g_blockEventsOnDrag
) return;
1055 printf( "OnVScroll from " );
1056 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1057 printf( win->GetClassInfo()->GetClassName() );
1061 if (!win
->HasVMT()) return;
1063 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
1064 if (fabs(diff
) < 0.2) return;
1066 wxEventType command
= wxEVT_NULL
;
1068 float line_step
= win
->m_vAdjust
->step_increment
;
1069 float page_step
= win
->m_vAdjust
->page_increment
;
1071 if (win
->m_isScrolling
)
1073 command
= wxEVT_SCROLL_THUMBTRACK
;
1077 if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->lower
) < 0.2) command
= wxEVT_SCROLL_BOTTOM
;
1078 else if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->upper
) < 0.2) command
= wxEVT_SCROLL_TOP
;
1079 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
1080 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
1081 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
1082 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
1083 else command
= wxEVT_SCROLL_THUMBTRACK
;
1086 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1088 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
1089 event
.SetEventObject( win
);
1090 win
->GetEventHandler()->ProcessEvent( event
);
1093 //-----------------------------------------------------------------------------
1094 // "value_changed" from m_hAdjust
1095 //-----------------------------------------------------------------------------
1097 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1099 if (g_blockEventsOnDrag
) return;
1102 printf( "OnHScroll from " );
1103 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1104 printf( win->GetClassInfo()->GetClassName() );
1108 if (!win
->HasVMT()) return;
1110 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
1111 if (fabs(diff
) < 0.2) return;
1113 wxEventType command
= wxEVT_NULL
;
1115 float line_step
= win
->m_hAdjust
->step_increment
;
1116 float page_step
= win
->m_hAdjust
->page_increment
;
1118 if (win
->m_isScrolling
)
1120 command
= wxEVT_SCROLL_THUMBTRACK
;
1124 if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->lower
) < 0.2) command
= wxEVT_SCROLL_BOTTOM
;
1125 else if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->upper
) < 0.2) command
= wxEVT_SCROLL_TOP
;
1126 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
1127 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
1128 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
1129 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
1130 else command
= wxEVT_SCROLL_THUMBTRACK
;
1133 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1135 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
1136 event
.SetEventObject( win
);
1137 win
->GetEventHandler()->ProcessEvent( event
);
1140 //-----------------------------------------------------------------------------
1141 // "changed" from m_vAdjust
1142 //-----------------------------------------------------------------------------
1144 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1146 if (g_blockEventsOnDrag
) return;
1149 printf( "OnVScroll change from " );
1150 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1151 printf( win->GetClassInfo()->GetClassName() );
1155 if (!win
->HasVMT()) return;
1157 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
1158 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1160 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
1161 event
.SetEventObject( win
);
1162 win
->GetEventHandler()->ProcessEvent( event
);
1165 //-----------------------------------------------------------------------------
1166 // "changed" from m_hAdjust
1167 //-----------------------------------------------------------------------------
1169 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1171 if (g_blockEventsOnDrag
) return;
1174 printf( "OnHScroll change from " );
1175 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1176 printf( win->GetClassInfo()->GetClassName() );
1180 if (!win
->HasVMT()) return;
1182 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
1183 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1185 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
1186 event
.SetEventObject( win
);
1187 win
->GetEventHandler()->ProcessEvent( event
);
1190 //-----------------------------------------------------------------------------
1191 // "button_press_event" from scrollbar
1192 //-----------------------------------------------------------------------------
1194 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1195 GdkEventButton
*WXUNUSED(gdk_event
),
1198 // don't test here as we can release the mouse while being over
1199 // a different window then the slider
1201 // if (gdk_event->window != widget->slider) return FALSE;
1203 win
->m_isScrolling
= TRUE
;
1204 g_blockEventsOnScroll
= TRUE
;
1209 //-----------------------------------------------------------------------------
1210 // "button_release_event" from scrollbar
1211 //-----------------------------------------------------------------------------
1213 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1214 GdkEventButton
*WXUNUSED(gdk_event
),
1218 // don't test here as we can release the mouse while being over
1219 // a different window then the slider
1221 // if (gdk_event->window != widget->slider) return FALSE;
1223 GtkScrolledWindow
*s_window
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1225 if (widget
== GTK_RANGE(s_window
->vscrollbar
))
1226 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_hAdjust
), "value_changed" );
1228 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_vAdjust
), "value_changed" );
1230 win
->m_isScrolling
= FALSE
;
1231 g_blockEventsOnScroll
= FALSE
;
1236 //-----------------------------------------------------------------------------
1237 // InsertChild for wxWindow.
1238 //-----------------------------------------------------------------------------
1240 /* Callback for wxWindow. This very strange beast has to be used because
1241 * C++ has no virtual methods in a constructor. We have to emulate a
1242 * virtual function here as wxNotebook requires a different way to insert
1243 * a child in it. I had opted for creating a wxNotebookPage window class
1244 * which would have made this superfluous (such in the MDI window system),
1245 * but no-one was listening to me... */
1247 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1249 gtk_myfixed_put( GTK_MYFIXED(parent
->m_wxwindow
),
1250 GTK_WIDGET(child
->m_widget
),
1254 gtk_widget_set_usize( GTK_WIDGET(child
->m_widget
),
1258 if (wxIS_KIND_OF(parent
,wxFrame
))
1260 parent
->m_sizeSet
= FALSE
;
1263 if (parent
->m_windowStyle
& wxTAB_TRAVERSAL
)
1265 /* we now allow a window to get the focus as long as it
1266 doesn't have any children. */
1267 GTK_WIDGET_UNSET_FLAGS( parent
->m_wxwindow
, GTK_CAN_FOCUS
);
1271 //-----------------------------------------------------------------------------
1273 //-----------------------------------------------------------------------------
1275 wxWindow
* wxGetActiveWindow()
1277 return g_focusWindow
;
1280 //-----------------------------------------------------------------------------
1282 //-----------------------------------------------------------------------------
1284 IMPLEMENT_DYNAMIC_CLASS(wxWindow
,wxEvtHandler
)
1286 BEGIN_EVENT_TABLE(wxWindow
, wxEvtHandler
)
1287 EVT_SIZE(wxWindow::OnSize
)
1288 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged
)
1289 EVT_INIT_DIALOG(wxWindow::OnInitDialog
)
1290 EVT_KEY_DOWN(wxWindow::OnKeyDown
)
1293 wxWindow::wxWindow()
1295 m_widget
= (GtkWidget
*) NULL
;
1296 m_wxwindow
= (GtkWidget
*) NULL
;
1297 m_parent
= (wxWindow
*) NULL
;
1298 m_children
.DeleteContents( FALSE
);
1311 m_eventHandler
= this;
1312 m_windowValidator
= (wxValidator
*) NULL
;
1316 m_cursor
= (wxCursor
*) NULL
;
1317 m_font
= *wxSWISS_FONT
;
1319 m_windowName
= "noname";
1321 m_constraints
= (wxLayoutConstraints
*) NULL
;
1322 m_constraintsInvolvedIn
= (wxList
*) NULL
;
1323 m_windowSizer
= (wxSizer
*) NULL
;
1324 m_sizerParent
= (wxWindow
*) NULL
;
1325 m_autoLayout
= FALSE
;
1329 m_needParent
= TRUE
;
1331 m_hasScrolling
= FALSE
;
1332 m_isScrolling
= FALSE
;
1333 m_hAdjust
= (GtkAdjustment
*) NULL
;
1334 m_vAdjust
= (GtkAdjustment
*) NULL
;
1335 m_oldHorizontalPos
= 0.0;
1336 m_oldVerticalPos
= 0.0;
1341 #if wxUSE_DRAG_AND_DROP
1342 m_dropTarget
= (wxDropTarget
*) NULL
;
1345 m_scrollGC
= (GdkGC
*) NULL
;
1346 m_widgetStyle
= (GtkStyle
*) NULL
;
1348 m_insertCallback
= wxInsertChildInWindow
;
1350 m_clientObject
= (wxClientData
*) NULL
;
1351 m_clientData
= NULL
;
1353 m_isStaticBox
= FALSE
;
1354 m_acceptsFocus
= FALSE
;
1357 m_toolTip
= (wxToolTip
*) NULL
;
1358 #endif // wxUSE_TOOLTIPS
1361 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1362 const wxPoint
&pos
, const wxSize
&size
,
1363 long style
, const wxString
&name
)
1365 m_insertCallback
= wxInsertChildInWindow
;
1366 Create( parent
, id
, pos
, size
, style
, name
);
1369 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1370 const wxPoint
&pos
, const wxSize
&size
,
1371 long style
, const wxString
&name
)
1375 m_needParent
= TRUE
;
1377 PreCreation( parent
, id
, pos
, size
, style
, name
);
1379 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1380 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1383 debug_focus_in( m_widget
, "wxWindow::m_widget", name
);
1386 GtkScrolledWindow
*s_window
= GTK_SCROLLED_WINDOW(m_widget
);
1389 debug_focus_in( s_window
->hscrollbar
, "wxWindow::hsrcollbar", name
);
1390 debug_focus_in( s_window
->vscrollbar
, "wxWindow::vsrcollbar", name
);
1393 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1394 scroll_class
->scrollbar_spacing
= 0;
1396 gtk_scrolled_window_set_policy( s_window
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1398 m_oldHorizontalPos
= 0.0;
1399 m_oldVerticalPos
= 0.0;
1401 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->hscrollbar
) );
1402 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->vscrollbar
) );
1404 m_wxwindow
= gtk_myfixed_new();
1407 debug_focus_in( m_wxwindow
, "wxWindow::m_wxwindow", name
);
1410 #ifdef NEW_GTK_SCROLL_CODE
1411 gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(m_widget
), m_wxwindow
);
1412 GtkViewport
*viewport
= GTK_VIEWPORT(s_window
->child
);
1414 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1415 GtkViewport
*viewport
= GTK_VIEWPORT(s_window
->viewport
);
1419 debug_focus_in( GTK_WIDGET(viewport
), "wxWindow::viewport", name
);
1422 if (m_windowStyle
& wxRAISED_BORDER
)
1424 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1426 else if (m_windowStyle
& wxSUNKEN_BORDER
)
1428 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1432 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1435 if (m_windowStyle
& wxTAB_TRAVERSAL
)
1437 /* we now allow a window to get the focus as long as it
1438 doesn't have any children. */
1439 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1440 m_acceptsFocus
= FALSE
;
1444 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1445 m_acceptsFocus
= TRUE
;
1448 // shut the viewport up
1449 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1450 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1452 // I _really_ don't want scrollbars in the beginning
1453 m_vAdjust
->lower
= 0.0;
1454 m_vAdjust
->upper
= 1.0;
1455 m_vAdjust
->value
= 0.0;
1456 m_vAdjust
->step_increment
= 1.0;
1457 m_vAdjust
->page_increment
= 1.0;
1458 m_vAdjust
->page_size
= 5.0;
1459 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1460 m_hAdjust
->lower
= 0.0;
1461 m_hAdjust
->upper
= 1.0;
1462 m_hAdjust
->value
= 0.0;
1463 m_hAdjust
->step_increment
= 1.0;
1464 m_hAdjust
->page_increment
= 1.0;
1465 m_hAdjust
->page_size
= 5.0;
1466 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1468 // these handlers block mouse events to any window during scrolling
1469 // such as motion events and prevent GTK and wxWindows from fighting
1470 // over where the slider should be
1472 gtk_signal_connect( GTK_OBJECT(s_window
->vscrollbar
), "button_press_event",
1473 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1475 gtk_signal_connect( GTK_OBJECT(s_window
->hscrollbar
), "button_press_event",
1476 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1478 gtk_signal_connect( GTK_OBJECT(s_window
->vscrollbar
), "button_release_event",
1479 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1481 gtk_signal_connect( GTK_OBJECT(s_window
->hscrollbar
), "button_release_event",
1482 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1484 // these handers het notified when screen updates are required either when
1485 // scrolling or when the window size (and therefore scrollbar configuration)
1488 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
1489 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
1490 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
1491 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
1493 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
1494 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
1495 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
1496 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
1498 gtk_widget_show( m_wxwindow
);
1500 if (m_parent
) m_parent
->AddChild( this );
1502 (m_parent
->m_insertCallback
)( m_parent
, this );
1511 wxWindow::~wxWindow()
1513 // Remove potential dangling pointer
1514 if (GetParent() && GetParent()->IsKindOf(CLASSINFO(wxPanel
)))
1516 wxPanel
* panel
= (wxPanel
*) GetParent();
1517 if (panel
->GetLastFocus() == this)
1518 panel
->SetLastFocus((wxWindow
*) NULL
);
1523 #if wxUSE_DRAG_AND_DROP
1524 wxDELETE(m_dropTarget
);
1528 wxDELETE(m_toolTip
);
1529 #endif // wxUSE_TOOLTIPS
1531 if (m_parent
) m_parent
->RemoveChild( this );
1532 if (m_widget
) Show( FALSE
);
1536 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
1538 if (m_scrollGC
) gdk_gc_unref( m_scrollGC
);
1540 if (m_wxwindow
) gtk_widget_destroy( m_wxwindow
);
1542 if (m_widget
) gtk_widget_destroy( m_widget
);
1544 if (m_cursor
) delete m_cursor
;
1546 DeleteRelatedConstraints();
1549 // This removes any dangling pointers to this window
1550 // in other windows' constraintsInvolvedIn lists.
1551 UnsetConstraints(m_constraints
);
1552 delete m_constraints
;
1553 m_constraints
= (wxLayoutConstraints
*) NULL
;
1557 delete m_windowSizer
;
1558 m_windowSizer
= (wxSizer
*) NULL
;
1560 // If this is a child of a sizer, remove self from parent
1561 if (m_sizerParent
) m_sizerParent
->RemoveChild((wxWindow
*)this);
1563 // Just in case the window has been Closed, but
1564 // we're then deleting immediately: don't leave
1565 // dangling pointers.
1566 wxPendingDelete
.DeleteObject(this);
1568 // Just in case we've loaded a top-level window via
1569 // wxWindow::LoadNativeDialog but we weren't a dialog
1571 wxTopLevelWindows
.DeleteObject(this);
1573 if (m_windowValidator
) delete m_windowValidator
;
1575 if (m_clientObject
) delete m_clientObject
;
1578 void wxWindow::PreCreation( wxWindow
*parent
, wxWindowID id
,
1579 const wxPoint
&pos
, const wxSize
&size
,
1580 long style
, const wxString
&name
)
1582 wxASSERT_MSG( (!m_needParent
) || (parent
), "Need complete parent." );
1584 m_widget
= (GtkWidget
*) NULL
;
1585 m_wxwindow
= (GtkWidget
*) NULL
;
1588 m_children
.DeleteContents( FALSE
);
1591 if (m_width
== -1) m_width
= 20;
1593 if (m_height
== -1) m_height
= 20;
1598 if (!m_needParent
) // some reasonable defaults
1602 m_x
= (gdk_screen_width () - m_width
) / 2;
1603 if (m_x
< 10) m_x
= 10;
1607 m_y
= (gdk_screen_height () - m_height
) / 2;
1608 if (m_y
< 10) m_y
= 10;
1619 m_eventHandler
= this;
1621 m_windowId
= id
== -1 ? wxNewId() : id
;
1625 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1626 m_font
= *wxSWISS_FONT
;
1627 m_backgroundColour
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
1628 m_foregroundColour
= *wxBLACK
;
1629 m_windowStyle
= style
;
1630 m_windowName
= name
;
1632 m_constraints
= (wxLayoutConstraints
*) NULL
;
1633 m_constraintsInvolvedIn
= (wxList
*) NULL
;
1634 m_windowSizer
= (wxSizer
*) NULL
;
1635 m_sizerParent
= (wxWindow
*) NULL
;
1636 m_autoLayout
= FALSE
;
1638 m_hasScrolling
= FALSE
;
1639 m_isScrolling
= FALSE
;
1640 m_hAdjust
= (GtkAdjustment
*) NULL
;
1641 m_vAdjust
= (GtkAdjustment
*) NULL
;
1642 m_oldHorizontalPos
= 0.0;
1643 m_oldVerticalPos
= 0.0;
1648 #if wxUSE_DRAG_AND_DROP
1649 m_dropTarget
= (wxDropTarget
*) NULL
;
1652 m_windowValidator
= (wxValidator
*) NULL
;
1653 m_scrollGC
= (GdkGC
*) NULL
;
1654 m_widgetStyle
= (GtkStyle
*) NULL
;
1656 m_clientObject
= (wxClientData
*)NULL
;
1657 m_clientData
= NULL
;
1659 m_isStaticBox
= FALSE
;
1662 m_toolTip
= (wxToolTip
*) NULL
;
1663 #endif // wxUSE_TOOLTIPS
1666 void wxWindow::PostCreation()
1670 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1671 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1673 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1674 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1677 ConnectWidget( GetConnectWidget() );
1679 if (m_widget
&& m_parent
) gtk_widget_realize( m_widget
);
1681 if (m_wxwindow
) gtk_widget_realize( m_wxwindow
);
1683 SetCursor( *wxSTANDARD_CURSOR
);
1688 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1690 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1691 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1693 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
1694 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
1696 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1697 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1699 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1700 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1702 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1703 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1705 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1706 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1708 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1709 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1711 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1712 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1714 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1715 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1718 bool wxWindow::HasVMT()
1723 bool wxWindow::Close( bool force
)
1725 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1727 wxCloseEvent
event(wxEVT_CLOSE_WINDOW
, m_windowId
);
1728 event
.SetEventObject(this);
1729 event
.SetCanVeto(!force
);
1731 // return FALSE if window wasn't closed because the application vetoed the
1733 return GetEventHandler()->ProcessEvent(event
) && !event
.GetVeto();
1736 bool wxWindow::Destroy()
1738 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1745 bool wxWindow::DestroyChildren()
1748 while ((node
= m_children
.First()) != (wxNode
*)NULL
)
1751 if ((child
= (wxWindow
*)node
->Data()) != (wxWindow
*)NULL
)
1754 if (m_children
.Member(child
)) delete node
;
1760 void wxWindow::PrepareDC( wxDC
&WXUNUSED(dc
) )
1762 // are we to set fonts here ?
1765 wxPoint
wxWindow::GetClientAreaOrigin() const
1767 return wxPoint(0,0);
1770 void wxWindow::AdjustForParentClientOrigin( int& x
, int& y
, int sizeFlags
)
1772 if (((sizeFlags
& wxSIZE_NO_ADJUSTMENTS
) == 0) && GetParent())
1774 wxPoint
pt(GetParent()->GetClientAreaOrigin());
1780 void wxWindow::SetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1782 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1783 wxASSERT_MSG( (m_parent
!= NULL
), "wxWindow::SetSize requires parent.\n" );
1785 if (m_resizing
) return; // I don't like recursions
1788 if (m_parent
->m_wxwindow
== NULL
) // i.e. wxNotebook
1790 // don't set the size for children of wxNotebook, just take the values.
1798 int old_width
= m_width
;
1799 int old_height
= m_height
;
1801 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1803 if (x
!= -1) m_x
= x
;
1804 if (y
!= -1) m_y
= y
;
1805 if (width
!= -1) m_width
= width
;
1806 if (height
!= -1) m_height
= height
;
1816 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1818 if (width
== -1) m_width
= 80;
1821 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1823 if (height
== -1) m_height
= 26;
1826 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1827 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1828 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
1829 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
1831 wxPoint
pt( m_parent
->GetClientAreaOrigin() );
1832 gtk_myfixed_move( GTK_MYFIXED(m_parent
->m_wxwindow
), m_widget
, m_x
+pt
.x
, m_y
+pt
.y
);
1834 if ((old_width
!= m_width
) || (old_height
!= m_height
))
1835 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
1840 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1841 event
.SetEventObject( this );
1842 GetEventHandler()->ProcessEvent( event
);
1847 void wxWindow::OnInternalIdle()
1852 void wxWindow::SetSize( int width
, int height
)
1854 SetSize( -1, -1, width
, height
, wxSIZE_USE_EXISTING
);
1857 void wxWindow::Move( int x
, int y
)
1859 SetSize( x
, y
, -1, -1, wxSIZE_USE_EXISTING
);
1862 void wxWindow::GetSize( int *width
, int *height
) const
1864 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1866 if (width
) (*width
) = m_width
;
1867 if (height
) (*height
) = m_height
;
1870 void wxWindow::SetClientSize( int width
, int height
)
1872 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1876 SetSize( width
, height
);
1883 if (!m_hasScrolling
)
1885 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
1887 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1888 (m_windowStyle
& wxSUNKEN_BORDER
))
1890 dw
+= 2 * window_class
->xthickness
;
1891 dh
+= 2 * window_class
->ythickness
;
1896 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1897 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1899 #ifdef NEW_GTK_SCROLL_CODE
1900 GtkWidget
*viewport
= scroll_window
->child
;
1902 GtkWidget
*viewport
= scroll_window
->viewport
;
1905 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1907 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1908 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1910 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1911 (m_windowStyle
& wxSUNKEN_BORDER
))
1913 dw
+= 2 * viewport_class
->xthickness
;
1914 dh
+= 2 * viewport_class
->ythickness
;
1917 if (scroll_window
->vscrollbar_visible
)
1919 dw
+= vscrollbar
->allocation
.width
;
1920 dw
+= scroll_class
->scrollbar_spacing
;
1923 if (scroll_window
->hscrollbar_visible
)
1925 dh
+= hscrollbar
->allocation
.height
;
1926 dw
+= scroll_class
->scrollbar_spacing
;
1930 SetSize( width
+dw
, height
+dh
);
1934 void wxWindow::GetClientSize( int *width
, int *height
) const
1936 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1940 if (width
) (*width
) = m_width
;
1941 if (height
) (*height
) = m_height
;
1948 if (!m_hasScrolling
)
1950 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
1952 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1953 (m_windowStyle
& wxSUNKEN_BORDER
))
1955 dw
+= 2 * window_class
->xthickness
;
1956 dh
+= 2 * window_class
->ythickness
;
1961 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1962 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1964 #ifdef NEW_GTK_SCROLL_CODE
1965 GtkWidget
*viewport
= scroll_window
->child
;
1967 GtkWidget
*viewport
= scroll_window
->viewport
;
1970 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1972 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1973 (m_windowStyle
& wxSUNKEN_BORDER
))
1975 dw
+= 2 * viewport_class
->xthickness
;
1976 dh
+= 2 * viewport_class
->ythickness
;
1979 if (scroll_window
->vscrollbar_visible
)
1981 // dw += vscrollbar->allocation.width;
1982 dw
+= 15; // range.slider_width = 11 + 2*2pts edge
1983 dw
+= scroll_class
->scrollbar_spacing
;
1986 if (scroll_window
->hscrollbar_visible
)
1988 // dh += hscrollbar->allocation.height;
1990 dh
+= scroll_class
->scrollbar_spacing
;
1994 if (width
) (*width
) = m_width
- dw
;
1995 if (height
) (*height
) = m_height
- dh
;
1999 void wxWindow::GetPosition( int *x
, int *y
) const
2001 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2007 void wxWindow::ClientToScreen( int *x
, int *y
)
2009 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2011 GdkWindow
*source
= (GdkWindow
*) NULL
;
2013 source
= m_wxwindow
->window
;
2015 source
= m_widget
->window
;
2019 gdk_window_get_origin( source
, &org_x
, &org_y
);
2023 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2025 org_x
+= m_widget
->allocation
.x
;
2026 org_y
+= m_widget
->allocation
.y
;
2030 wxPoint
pt(GetClientAreaOrigin());
2038 void wxWindow::ScreenToClient( int *x
, int *y
)
2040 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2042 GdkWindow
*source
= (GdkWindow
*) NULL
;
2044 source
= m_wxwindow
->window
;
2046 source
= m_widget
->window
;
2050 gdk_window_get_origin( source
, &org_x
, &org_y
);
2054 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2056 org_x
+= m_widget
->allocation
.x
;
2057 org_y
+= m_widget
->allocation
.y
;
2061 wxPoint
pt(GetClientAreaOrigin());
2069 void wxWindow::Centre( int direction
)
2071 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2080 m_parent
->GetSize( &p_w
, &p_h
);
2081 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) x
= (p_w
- m_width
) / 2;
2082 if (direction
& wxVERTICAL
== wxVERTICAL
) y
= (p_h
- m_height
) / 2;
2086 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) x
= (gdk_screen_width () - m_width
) / 2;
2087 if (direction
& wxVERTICAL
== wxVERTICAL
) y
= (gdk_screen_height () - m_height
) / 2;
2093 void wxWindow::Fit()
2095 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2099 wxNode
*node
= m_children
.First();
2102 wxWindow
*win
= (wxWindow
*)node
->Data();
2104 win
->GetPosition(&wx
, &wy
);
2105 win
->GetSize(&ww
, &wh
);
2106 if (wx
+ ww
> maxX
) maxX
= wx
+ ww
;
2107 if (wy
+ wh
> maxY
) maxY
= wy
+ wh
;
2109 node
= node
->Next();
2112 SetClientSize(maxX
+ 7, maxY
+ 14);
2115 void wxWindow::SetSizeHints( int minW
, int minH
, int maxW
, int maxH
, int WXUNUSED(incW
), int WXUNUSED(incH
) )
2117 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2125 void wxWindow::OnSize( wxSizeEvent
&WXUNUSED(event
) )
2127 // if (GetAutoLayout()) Layout();
2130 bool wxWindow::Show( bool show
)
2132 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, "invalid window" );
2135 gtk_widget_show( m_widget
);
2137 gtk_widget_hide( m_widget
);
2144 void wxWindow::Enable( bool enable
)
2146 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2148 m_isEnabled
= enable
;
2150 gtk_widget_set_sensitive( m_widget
, enable
);
2151 if (m_wxwindow
) gtk_widget_set_sensitive( m_wxwindow
, enable
);
2154 int wxWindow::GetCharHeight() const
2156 wxCHECK_MSG( (m_widget
!= NULL
), 12, "invalid window" );
2158 wxCHECK_MSG( m_font
.Ok(), 12, "invalid font" );
2160 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2162 return font
->ascent
+ font
->descent
;
2165 int wxWindow::GetCharWidth() const
2167 wxCHECK_MSG( (m_widget
!= NULL
), 8, "invalid window" );
2169 wxCHECK_MSG( m_font
.Ok(), 8, "invalid font" );
2171 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2173 return gdk_string_width( font
, "H" );
2176 void wxWindow::GetTextExtent( const wxString
& string
, int *x
, int *y
,
2177 int *descent
, int *externalLeading
, const wxFont
*theFont
, bool WXUNUSED(use16
) ) const
2179 wxFont fontToUse
= m_font
;
2180 if (theFont
) fontToUse
= *theFont
;
2182 wxCHECK_RET( fontToUse
.Ok(), "invalid font" );
2184 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2185 if (x
) (*x
) = gdk_string_width( font
, string
);
2186 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2187 if (descent
) (*descent
) = font
->descent
;
2188 if (externalLeading
) (*externalLeading
) = 0; // ??
2191 void wxWindow::MakeModal( bool modal
)
2195 // Disable all other windows
2196 if (this->IsKindOf(CLASSINFO(wxDialog
)) || this->IsKindOf(CLASSINFO(wxFrame
)))
2198 wxNode
*node
= wxTopLevelWindows
.First();
2201 wxWindow
*win
= (wxWindow
*)node
->Data();
2202 if (win
!= this) win
->Enable(!modal
);
2204 node
= node
->Next();
2209 void wxWindow::OnKeyDown( wxKeyEvent
&event
)
2211 event
.SetEventType( wxEVT_CHAR
);
2213 if (!GetEventHandler()->ProcessEvent( event
))
2219 void wxWindow::SetFocus()
2221 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2223 GtkWidget
*connect_widget
= GetConnectWidget();
2226 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2228 gtk_widget_grab_focus (connect_widget
);
2230 else if (GTK_IS_CONTAINER(connect_widget
))
2232 gtk_container_focus( GTK_CONTAINER(connect_widget
), GTK_DIR_TAB_FORWARD
);
2240 wxWindow
*wxWindow::FindFocus()
2242 return g_focusWindow
;
2245 bool wxWindow::AcceptsFocus() const
2247 return IsEnabled() && IsShown() && m_acceptsFocus
;
2250 void wxWindow::AddChild( wxWindow
*child
)
2252 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2253 wxCHECK_RET( (child
!= NULL
), "invalid child" );
2255 m_children
.Append( child
);
2258 wxWindow
*wxWindow::ReParent( wxWindow
*newParent
)
2260 wxCHECK_MSG( (m_widget
!= NULL
), (wxWindow
*) NULL
, "invalid window" );
2262 wxWindow
*oldParent
= GetParent();
2264 if (oldParent
) oldParent
->RemoveChild( this );
2266 gtk_widget_unparent( m_widget
);
2270 newParent
->AddChild( this );
2271 (newParent
->m_insertCallback
)( newParent
, this );
2277 void wxWindow::RemoveChild( wxWindow
*child
)
2279 m_children
.DeleteObject( child
);
2280 child
->m_parent
= (wxWindow
*) NULL
;
2283 void wxWindow::SetReturnCode( int retCode
)
2285 m_retCode
= retCode
;
2288 int wxWindow::GetReturnCode()
2293 void wxWindow::Raise()
2295 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2297 if (m_widget
) gdk_window_raise( m_widget
->window
);
2300 void wxWindow::Lower()
2302 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2304 if (m_widget
) gdk_window_lower( m_widget
->window
);
2307 wxEvtHandler
*wxWindow::GetEventHandler() const
2309 return m_eventHandler
;
2312 void wxWindow::SetEventHandler( wxEvtHandler
*handler
)
2314 m_eventHandler
= handler
;
2317 void wxWindow::PushEventHandler(wxEvtHandler
*handler
)
2319 handler
->SetNextHandler(GetEventHandler());
2320 SetEventHandler(handler
);
2323 wxEvtHandler
*wxWindow::PopEventHandler(bool deleteHandler
)
2325 if (GetEventHandler())
2327 wxEvtHandler
*handlerA
= GetEventHandler();
2328 wxEvtHandler
*handlerB
= handlerA
->GetNextHandler();
2329 handlerA
->SetNextHandler((wxEvtHandler
*) NULL
);
2330 SetEventHandler(handlerB
);
2334 return (wxEvtHandler
*) NULL
;
2340 return (wxEvtHandler
*) NULL
;
2343 wxValidator
*wxWindow::GetValidator()
2345 return m_windowValidator
;
2348 void wxWindow::SetValidator( const wxValidator
& validator
)
2350 if (m_windowValidator
) delete m_windowValidator
;
2351 m_windowValidator
= validator
.Clone();
2352 if (m_windowValidator
) m_windowValidator
->SetWindow(this);
2355 void wxWindow::SetClientObject( wxClientData
*data
)
2357 if (m_clientObject
) delete m_clientObject
;
2358 m_clientObject
= data
;
2361 wxClientData
*wxWindow::GetClientObject()
2363 return m_clientObject
;
2366 void wxWindow::SetClientData( void *data
)
2368 m_clientData
= data
;
2371 void *wxWindow::GetClientData()
2373 return m_clientData
;
2376 bool wxWindow::IsBeingDeleted()
2381 void wxWindow::SetId( wxWindowID id
)
2386 wxWindowID
wxWindow::GetId() const
2391 void wxWindow::SetCursor( const wxCursor
&cursor
)
2393 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2397 if (cursor
== *m_cursor
) return;
2402 *m_cursor
= *wxSTANDARD_CURSOR
;
2405 if ((m_widget
) && (m_widget
->window
))
2406 gdk_window_set_cursor( m_widget
->window
, m_cursor
->GetCursor() );
2408 if ((m_wxwindow
) && (m_wxwindow
->window
))
2409 gdk_window_set_cursor( m_wxwindow
->window
, m_cursor
->GetCursor() );
2412 void wxWindow::WarpPointer( int WXUNUSED(x
), int WXUNUSED(y
) )
2417 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2419 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2421 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2425 gdk_window_clear_area( m_wxwindow
->window
,
2427 rect
->width
, rect
->height
);
2431 gdk_window_clear( m_wxwindow
->window
);
2438 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2440 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2444 GdkRectangle gdk_rect
;
2445 gdk_rect
.x
= rect
->x
;
2446 gdk_rect
.y
= rect
->y
;
2447 gdk_rect
.width
= rect
->width
;
2448 gdk_rect
.height
= rect
->height
;
2451 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2453 gtk_widget_draw( m_widget
, &gdk_rect
);
2457 wxRegion
wxWindow::GetUpdateRegion() const
2459 return m_updateRegion
;
2462 bool wxWindow::IsExposed( int x
, int y
) const
2464 return (m_updateRegion
.Contains( x
, y
) != wxOutRegion
);
2467 bool wxWindow::IsExposed( int x
, int y
, int w
, int h
) const
2469 return (m_updateRegion
.Contains( x
, y
, w
, h
) != wxOutRegion
);
2472 bool wxWindow::IsExposed( const wxPoint
& pt
) const
2474 return (m_updateRegion
.Contains( pt
.x
, pt
.y
) != wxOutRegion
);
2477 bool wxWindow::IsExposed( const wxRect
& rect
) const
2479 return (m_updateRegion
.Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
) != wxOutRegion
);
2482 void wxWindow::Clear()
2484 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2486 if (m_wxwindow
&& m_wxwindow
->window
)
2488 gdk_window_clear( m_wxwindow
->window
);
2493 void wxWindow::SetToolTip( const wxString
&tip
)
2497 m_toolTip
->SetTip( tip
);
2501 SetToolTip( new wxToolTip( tip
) );
2504 // setting empty tooltip text does not remove the tooltip any more for
2505 // wxMSW compatibility - use SetToolTip((wxToolTip *)NULL) for this
2508 void wxWindow::SetToolTip( wxToolTip
*tip
)
2512 m_toolTip
->SetTip( (char*) NULL
);
2519 m_toolTip
->Apply( this );
2522 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const char *tip
)
2524 gtk_tooltips_set_tip( tips
, GetConnectWidget(), tip
, (gchar
*) NULL
);
2526 #endif // wxUSE_TOOLTIPS
2528 wxColour
wxWindow::GetBackgroundColour() const
2530 return m_backgroundColour
;
2533 void wxWindow::SetBackgroundColour( const wxColour
&colour
)
2535 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2537 if (m_backgroundColour
== colour
) return;
2539 m_backgroundColour
= colour
;
2540 if (!m_backgroundColour
.Ok()) return;
2542 if (m_wxwindow
&& m_wxwindow
->window
)
2544 /* wxMSW doesn't clear the window here. I don't do that
2545 either to provide compatibility. call Clear() to do
2548 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_wxwindow
->window
) );
2549 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
2552 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2554 if (sysbg
.Red() == colour
.Red() &&
2555 sysbg
.Green() == colour
.Green() &&
2556 sysbg
.Blue() == colour
.Blue())
2558 m_backgroundColour
= wxNullColour
;
2560 m_backgroundColour
= sysbg
;
2568 wxColour
wxWindow::GetForegroundColour() const
2570 return m_foregroundColour
;
2573 void wxWindow::SetForegroundColour( const wxColour
&colour
)
2575 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2577 if (m_foregroundColour
== colour
) return;
2579 m_foregroundColour
= colour
;
2580 if (!m_foregroundColour
.Ok()) return;
2582 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2583 if (sysbg
.Red() == colour
.Red() &&
2584 sysbg
.Green() == colour
.Green() &&
2585 sysbg
.Blue() == colour
.Blue())
2587 m_backgroundColour
= wxNullColour
;
2589 m_backgroundColour
= sysbg
;
2597 GtkStyle
*wxWindow::GetWidgetStyle()
2599 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2603 gtk_widget_get_style( m_widget
) );
2605 return m_widgetStyle
;
2608 void wxWindow::SetWidgetStyle()
2610 GtkStyle
*style
= GetWidgetStyle();
2612 gdk_font_unref( style
->font
);
2613 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2615 if (m_foregroundColour
.Ok())
2617 m_foregroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2618 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2619 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2620 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2623 if (m_backgroundColour
.Ok())
2625 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2626 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2627 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2628 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2629 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2630 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2631 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2632 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2633 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2637 void wxWindow::ApplyWidgetStyle()
2641 bool wxWindow::Validate()
2643 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
2645 wxNode
*node
= m_children
.First();
2648 wxWindow
*child
= (wxWindow
*)node
->Data();
2649 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->Validate(this))
2653 node
= node
->Next();
2658 bool wxWindow::TransferDataToWindow()
2660 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
2662 wxNode
*node
= m_children
.First();
2665 wxWindow
*child
= (wxWindow
*)node
->Data();
2666 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */
2667 !child
->GetValidator()->TransferToWindow() )
2669 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK
|wxICON_EXCLAMATION
);
2672 node
= node
->Next();
2677 bool wxWindow::TransferDataFromWindow()
2679 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
2681 wxNode
*node
= m_children
.First();
2684 wxWindow
*child
= (wxWindow
*)node
->Data();
2685 if ( child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->TransferFromWindow() )
2689 node
= node
->Next();
2694 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable
& accel
)
2696 m_acceleratorTable
= accel
;
2699 void wxWindow::OnInitDialog( wxInitDialogEvent
&WXUNUSED(event
) )
2701 TransferDataToWindow();
2704 void wxWindow::InitDialog()
2706 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2708 wxInitDialogEvent
event(GetId());
2709 event
.SetEventObject( this );
2710 GetEventHandler()->ProcessEvent(event
);
2713 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2715 menu
->SetInvokingWindow( win
);
2716 wxNode
*node
= menu
->m_items
.First();
2719 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2720 if (menuitem
->IsSubMenu())
2722 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2724 node
= node
->Next();
2728 static gint gs_pop_x
= 0;
2729 static gint gs_pop_y
= 0;
2731 static void pop_pos_callback( GtkMenu
*menu
, gint
*x
, gint
*y
, wxWindow
*win
)
2733 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
2738 bool wxWindow::PopupMenu( wxMenu
*menu
, int x
, int y
)
2740 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
2742 wxCHECK_MSG( menu
!= NULL
, FALSE
, "invalid popup-menu" );
2744 SetInvokingWindow( menu
, this );
2752 GTK_MENU(menu
->m_menu
),
2753 (GtkWidget
*) NULL
, // parent menu shell
2754 (GtkWidget
*) NULL
, // parent menu item
2755 (GtkMenuPositionFunc
) pop_pos_callback
,
2756 (gpointer
) this, // client data
2757 0, // button used to activate it
2758 0 //gs_timeLastClick // the time of activation
2763 #if wxUSE_DRAG_AND_DROP
2765 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2767 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2769 GtkWidget
*dnd_widget
= GetConnectWidget();
2771 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
2773 if (m_dropTarget
) delete m_dropTarget
;
2774 m_dropTarget
= dropTarget
;
2776 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
2779 wxDropTarget
*wxWindow::GetDropTarget() const
2781 return m_dropTarget
;
2786 GtkWidget
* wxWindow::GetConnectWidget()
2788 GtkWidget
*connect_widget
= m_widget
;
2789 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2791 return connect_widget
;
2794 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2796 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2797 return (window
== m_widget
->window
);
2800 void wxWindow::SetFont( const wxFont
&font
)
2802 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2804 if (((wxFont
*)&font
)->Ok())
2807 m_font
= *wxSWISS_FONT
;
2809 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2810 if (sysbg
.Red() == m_backgroundColour
.Red() &&
2811 sysbg
.Green() == m_backgroundColour
.Green() &&
2812 sysbg
.Blue() == m_backgroundColour
.Blue())
2814 m_backgroundColour
= wxNullColour
;
2816 m_backgroundColour
= sysbg
;
2824 void wxWindow::SetWindowStyleFlag( long flag
)
2826 m_windowStyle
= flag
;
2829 long wxWindow::GetWindowStyleFlag() const
2831 return m_windowStyle
;
2834 void wxWindow::CaptureMouse()
2836 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2838 wxCHECK_RET( g_capturing
== FALSE
, "CaptureMouse called twice" );
2840 GtkWidget
*connect_widget
= GetConnectWidget();
2841 gtk_grab_add( connect_widget
);
2842 gdk_pointer_grab( connect_widget
->window
, FALSE
,
2844 (GDK_BUTTON_PRESS_MASK
|
2845 GDK_BUTTON_RELEASE_MASK
|
2846 GDK_POINTER_MOTION_MASK
),
2853 void wxWindow::ReleaseMouse()
2855 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2857 wxCHECK_RET( g_capturing
== TRUE
, "ReleaseMouse called twice" );
2859 GtkWidget
*connect_widget
= GetConnectWidget();
2860 gtk_grab_remove( connect_widget
);
2861 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2862 g_capturing
= FALSE
;
2865 void wxWindow::SetTitle( const wxString
&WXUNUSED(title
) )
2869 wxString
wxWindow::GetTitle() const
2871 return (wxString
&)m_windowName
;
2874 wxString
wxWindow::GetLabel() const
2879 void wxWindow::SetName( const wxString
&name
)
2881 m_windowName
= name
;
2884 wxString
wxWindow::GetName() const
2886 return (wxString
&)m_windowName
;
2889 bool wxWindow::IsShown() const
2894 bool wxWindow::IsRetained()
2899 wxWindow
*wxWindow::FindWindow( long id
)
2901 if (id
== m_windowId
) return this;
2902 wxNode
*node
= m_children
.First();
2905 wxWindow
*child
= (wxWindow
*)node
->Data();
2906 wxWindow
*res
= child
->FindWindow( id
);
2907 if (res
) return res
;
2908 node
= node
->Next();
2910 return (wxWindow
*) NULL
;
2913 wxWindow
*wxWindow::FindWindow( const wxString
& name
)
2915 if (name
== m_windowName
) return this;
2916 wxNode
*node
= m_children
.First();
2919 wxWindow
*child
= (wxWindow
*)node
->Data();
2920 wxWindow
*res
= child
->FindWindow( name
);
2921 if (res
) return res
;
2922 node
= node
->Next();
2924 return (wxWindow
*) NULL
;
2927 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2928 int range
, bool refresh
)
2930 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2932 wxCHECK_RET( m_wxwindow
!= NULL
, "window needs client area for scrolling" );
2934 m_hasScrolling
= TRUE
;
2936 if (orient
== wxHORIZONTAL
)
2938 float fpos
= (float)pos
;
2939 float frange
= (float)range
;
2940 float fthumb
= (float)thumbVisible
;
2941 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2942 if (fpos
< 0.0) fpos
= 0.0;
2944 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2945 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2947 SetScrollPos( orient
, pos
, refresh
);
2951 m_oldHorizontalPos
= fpos
;
2953 m_hAdjust
->lower
= 0.0;
2954 m_hAdjust
->upper
= frange
;
2955 m_hAdjust
->value
= fpos
;
2956 m_hAdjust
->step_increment
= 1.0;
2957 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2958 m_hAdjust
->page_size
= fthumb
;
2962 float fpos
= (float)pos
;
2963 float frange
= (float)range
;
2964 float fthumb
= (float)thumbVisible
;
2965 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2966 if (fpos
< 0.0) fpos
= 0.0;
2968 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2969 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2971 SetScrollPos( orient
, pos
, refresh
);
2975 m_oldVerticalPos
= fpos
;
2977 m_vAdjust
->lower
= 0.0;
2978 m_vAdjust
->upper
= frange
;
2979 m_vAdjust
->value
= fpos
;
2980 m_vAdjust
->step_increment
= 1.0;
2981 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2982 m_vAdjust
->page_size
= fthumb
;
2985 if (m_wxwindow
->window
)
2987 if (orient
== wxHORIZONTAL
)
2988 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2990 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2992 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
2996 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2998 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
3000 wxCHECK_RET( m_wxwindow
!= NULL
, "window needs client area for scrolling" );
3002 if (orient
== wxHORIZONTAL
)
3004 float fpos
= (float)pos
;
3005 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3006 if (fpos
< 0.0) fpos
= 0.0;
3007 m_oldHorizontalPos
= fpos
;
3009 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3010 m_hAdjust
->value
= fpos
;
3014 float fpos
= (float)pos
;
3015 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3016 if (fpos
< 0.0) fpos
= 0.0;
3017 m_oldVerticalPos
= fpos
;
3019 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3020 m_vAdjust
->value
= fpos
;
3025 if (m_wxwindow
->window
)
3027 if (orient
== wxHORIZONTAL
)
3028 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3030 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3035 int wxWindow::GetScrollThumb( int orient
) const
3037 wxCHECK_MSG( m_widget
!= NULL
, 0, "invalid window" );
3039 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, "window needs client area for scrolling" );
3041 if (orient
== wxHORIZONTAL
)
3042 return (int)(m_hAdjust
->page_size
+0.5);
3044 return (int)(m_vAdjust
->page_size
+0.5);
3047 int wxWindow::GetScrollPos( int orient
) const
3049 wxCHECK_MSG( m_widget
!= NULL
, 0, "invalid window" );
3051 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, "window needs client area for scrolling" );
3053 if (orient
== wxHORIZONTAL
)
3054 return (int)(m_hAdjust
->value
+0.5);
3056 return (int)(m_vAdjust
->value
+0.5);
3059 int wxWindow::GetScrollRange( int orient
) const
3061 wxCHECK_MSG( m_widget
!= NULL
, 0, "invalid window" );
3063 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, "window needs client area for scrolling" );
3065 if (orient
== wxHORIZONTAL
)
3066 return (int)(m_hAdjust
->upper
+0.5);
3068 return (int)(m_vAdjust
->upper
+0.5);
3071 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3073 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
3075 wxCHECK_RET( m_wxwindow
!= NULL
, "window needs client area for scrolling" );
3079 GetClientSize( &cw
, &ch
);
3081 int w
= cw
- abs(dx
);
3082 int h
= ch
- abs(dy
);
3083 if ((h
< 0) || (w
< 0))
3090 if (dx
< 0) s_x
= -dx
;
3091 if (dy
< 0) s_y
= -dy
;
3094 if (dx
> 0) d_x
= dx
;
3095 if (dy
> 0) d_y
= dy
;
3099 m_scrollGC
= gdk_gc_new( m_wxwindow
->window
);
3100 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
3103 gdk_window_copy_area( m_wxwindow
->window
, m_scrollGC
, d_x
, d_y
,
3104 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
3107 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
3108 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
3109 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
3110 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
3112 Refresh( TRUE
, &rect
);
3115 //-------------------------------------------------------------------------------------
3117 //-------------------------------------------------------------------------------------
3119 wxLayoutConstraints
*wxWindow::GetConstraints() const
3121 return m_constraints
;
3124 void wxWindow::SetConstraints( wxLayoutConstraints
*constraints
)
3128 UnsetConstraints(m_constraints
);
3129 delete m_constraints
;
3131 m_constraints
= constraints
;
3134 // Make sure other windows know they're part of a 'meaningful relationship'
3135 if (m_constraints
->left
.GetOtherWindow() && (m_constraints
->left
.GetOtherWindow() != this))
3136 m_constraints
->left
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
3137 if (m_constraints
->top
.GetOtherWindow() && (m_constraints
->top
.GetOtherWindow() != this))
3138 m_constraints
->top
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
3139 if (m_constraints
->right
.GetOtherWindow() && (m_constraints
->right
.GetOtherWindow() != this))
3140 m_constraints
->right
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
3141 if (m_constraints
->bottom
.GetOtherWindow() && (m_constraints
->bottom
.GetOtherWindow() != this))
3142 m_constraints
->bottom
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
3143 if (m_constraints
->width
.GetOtherWindow() && (m_constraints
->width
.GetOtherWindow() != this))
3144 m_constraints
->width
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
3145 if (m_constraints
->height
.GetOtherWindow() && (m_constraints
->height
.GetOtherWindow() != this))
3146 m_constraints
->height
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
3147 if (m_constraints
->centreX
.GetOtherWindow() && (m_constraints
->centreX
.GetOtherWindow() != this))
3148 m_constraints
->centreX
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
3149 if (m_constraints
->centreY
.GetOtherWindow() && (m_constraints
->centreY
.GetOtherWindow() != this))
3150 m_constraints
->centreY
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
3156 void wxWindow::SetAutoLayout( bool autoLayout
)
3158 m_autoLayout
= autoLayout
;
3161 bool wxWindow::GetAutoLayout() const
3163 return m_autoLayout
;
3166 wxSizer
*wxWindow::GetSizer() const
3168 return m_windowSizer
;
3171 void wxWindow::SetSizerParent( wxWindow
*win
)
3173 m_sizerParent
= win
;
3176 wxWindow
*wxWindow::GetSizerParent() const
3178 return m_sizerParent
;
3181 // This removes any dangling pointers to this window
3182 // in other windows' constraintsInvolvedIn lists.
3183 void wxWindow::UnsetConstraints(wxLayoutConstraints
*c
)
3187 if (c
->left
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
3188 c
->left
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
3189 if (c
->top
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
3190 c
->top
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
3191 if (c
->right
.GetOtherWindow() && (c
->right
.GetOtherWindow() != this))
3192 c
->right
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
3193 if (c
->bottom
.GetOtherWindow() && (c
->bottom
.GetOtherWindow() != this))
3194 c
->bottom
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
3195 if (c
->width
.GetOtherWindow() && (c
->width
.GetOtherWindow() != this))
3196 c
->width
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
3197 if (c
->height
.GetOtherWindow() && (c
->height
.GetOtherWindow() != this))
3198 c
->height
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
3199 if (c
->centreX
.GetOtherWindow() && (c
->centreX
.GetOtherWindow() != this))
3200 c
->centreX
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
3201 if (c
->centreY
.GetOtherWindow() && (c
->centreY
.GetOtherWindow() != this))
3202 c
->centreY
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
3206 // Back-pointer to other windows we're involved with, so if we delete
3207 // this window, we must delete any constraints we're involved with.
3208 void wxWindow::AddConstraintReference(wxWindow
*otherWin
)
3210 if (!m_constraintsInvolvedIn
)
3211 m_constraintsInvolvedIn
= new wxList
;
3212 if (!m_constraintsInvolvedIn
->Member(otherWin
))
3213 m_constraintsInvolvedIn
->Append(otherWin
);
3216 // REMOVE back-pointer to other windows we're involved with.
3217 void wxWindow::RemoveConstraintReference(wxWindow
*otherWin
)
3219 if (m_constraintsInvolvedIn
)
3220 m_constraintsInvolvedIn
->DeleteObject(otherWin
);
3223 // Reset any constraints that mention this window
3224 void wxWindow::DeleteRelatedConstraints()
3226 if (m_constraintsInvolvedIn
)
3228 wxNode
*node
= m_constraintsInvolvedIn
->First();
3231 wxWindow
*win
= (wxWindow
*)node
->Data();
3232 wxNode
*next
= node
->Next();
3233 wxLayoutConstraints
*constr
= win
->GetConstraints();
3235 // Reset any constraints involving this window
3238 constr
->left
.ResetIfWin((wxWindow
*)this);
3239 constr
->top
.ResetIfWin((wxWindow
*)this);
3240 constr
->right
.ResetIfWin((wxWindow
*)this);
3241 constr
->bottom
.ResetIfWin((wxWindow
*)this);
3242 constr
->width
.ResetIfWin((wxWindow
*)this);
3243 constr
->height
.ResetIfWin((wxWindow
*)this);
3244 constr
->centreX
.ResetIfWin((wxWindow
*)this);
3245 constr
->centreY
.ResetIfWin((wxWindow
*)this);
3250 delete m_constraintsInvolvedIn
;
3251 m_constraintsInvolvedIn
= (wxList
*) NULL
;
3255 void wxWindow::SetSizer(wxSizer
*sizer
)
3257 m_windowSizer
= sizer
;
3259 sizer
->SetSizerParent((wxWindow
*)this);
3266 bool wxWindow::Layout()
3268 if (GetConstraints())
3271 GetClientSize(&w
, &h
);
3272 GetConstraints()->width
.SetValue(w
);
3273 GetConstraints()->height
.SetValue(h
);
3276 // If top level (one sizer), evaluate the sizer's constraints.
3280 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
3281 GetSizer()->LayoutPhase1(&noChanges
);
3282 GetSizer()->LayoutPhase2(&noChanges
);
3283 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
3288 // Otherwise, evaluate child constraints
3289 ResetConstraints(); // Mark all constraints as unevaluated
3290 DoPhase(1); // Just one phase need if no sizers involved
3292 SetConstraintSizes(); // Recursively set the real window sizes
3298 // Do a phase of evaluating constraints:
3299 // the default behaviour. wxSizers may do a similar
3300 // thing, but also impose their own 'constraints'
3301 // and order the evaluation differently.
3302 bool wxWindow::LayoutPhase1(int *noChanges
)
3304 wxLayoutConstraints
*constr
= GetConstraints();
3307 return constr
->SatisfyConstraints((wxWindow
*)this, noChanges
);
3313 bool wxWindow::LayoutPhase2(int *noChanges
)
3323 // Do a phase of evaluating child constraints
3324 bool wxWindow::DoPhase(int phase
)
3326 int noIterations
= 0;
3327 int maxIterations
= 500;
3331 while ((noChanges
> 0) && (noIterations
< maxIterations
))
3335 wxNode
*node
= m_children
.First();
3338 wxWindow
*child
= (wxWindow
*)node
->Data();
3339 if (!child
->IsKindOf(CLASSINFO(wxFrame
)) && !child
->IsKindOf(CLASSINFO(wxDialog
)))
3341 wxLayoutConstraints
*constr
= child
->GetConstraints();
3344 if (succeeded
.Member(child
))
3349 int tempNoChanges
= 0;
3350 bool success
= ( (phase
== 1) ? child
->LayoutPhase1(&tempNoChanges
) : child
->LayoutPhase2(&tempNoChanges
) ) ;
3351 noChanges
+= tempNoChanges
;
3354 succeeded
.Append(child
);
3359 node
= node
->Next();
3366 void wxWindow::ResetConstraints()
3368 wxLayoutConstraints
*constr
= GetConstraints();
3371 constr
->left
.SetDone(FALSE
);
3372 constr
->top
.SetDone(FALSE
);
3373 constr
->right
.SetDone(FALSE
);
3374 constr
->bottom
.SetDone(FALSE
);
3375 constr
->width
.SetDone(FALSE
);
3376 constr
->height
.SetDone(FALSE
);
3377 constr
->centreX
.SetDone(FALSE
);
3378 constr
->centreY
.SetDone(FALSE
);
3380 wxNode
*node
= m_children
.First();
3383 wxWindow
*win
= (wxWindow
*)node
->Data();
3384 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
3385 win
->ResetConstraints();
3386 node
= node
->Next();
3390 // Need to distinguish between setting the 'fake' size for
3391 // windows and sizers, and setting the real values.
3392 void wxWindow::SetConstraintSizes(bool recurse
)
3394 wxLayoutConstraints
*constr
= GetConstraints();
3395 if (constr
&& constr
->left
.GetDone() && constr
->right
.GetDone() &&
3396 constr
->width
.GetDone() && constr
->height
.GetDone())
3398 int x
= constr
->left
.GetValue();
3399 int y
= constr
->top
.GetValue();
3400 int w
= constr
->width
.GetValue();
3401 int h
= constr
->height
.GetValue();
3403 // If we don't want to resize this window, just move it...
3404 if ((constr
->width
.GetRelationship() != wxAsIs
) ||
3405 (constr
->height
.GetRelationship() != wxAsIs
))
3407 // Calls Layout() recursively. AAAGH. How can we stop that.
3408 // Simply take Layout() out of non-top level OnSizes.
3409 SizerSetSize(x
, y
, w
, h
);
3418 char *windowClass
= this->GetClassInfo()->GetClassName();
3421 if (GetName() == "")
3422 winName
= "unnamed";
3424 winName
= GetName();
3425 wxLogDebug( "Constraint(s) not satisfied for window of type %s, name %s:\n",
3426 (const char *)windowClass
,
3427 (const char *)winName
);
3428 if (!constr
->left
.GetDone()) wxLogDebug( " unsatisfied 'left' constraint.\n" );
3429 if (!constr
->right
.GetDone()) wxLogDebug( " unsatisfied 'right' constraint.\n" );
3430 if (!constr
->width
.GetDone()) wxLogDebug( " unsatisfied 'width' constraint.\n" );
3431 if (!constr
->height
.GetDone()) wxLogDebug( " unsatisfied 'height' constraint.\n" );
3432 wxLogDebug( "Please check constraints: try adding AsIs() constraints.\n" );
3437 wxNode
*node
= m_children
.First();
3440 wxWindow
*win
= (wxWindow
*)node
->Data();
3441 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
3442 win
->SetConstraintSizes();
3443 node
= node
->Next();
3448 // This assumes that all sizers are 'on' the same
3449 // window, i.e. the parent of this window.
3450 void wxWindow::TransformSizerToActual(int *x
, int *y
) const
3452 if (!m_sizerParent
|| m_sizerParent
->IsKindOf(CLASSINFO(wxDialog
)) ||
3453 m_sizerParent
->IsKindOf(CLASSINFO(wxFrame
)) )
3457 m_sizerParent
->GetPosition(&xp
, &yp
);
3458 m_sizerParent
->TransformSizerToActual(&xp
, &yp
);
3463 void wxWindow::SizerSetSize(int x
, int y
, int w
, int h
)
3467 TransformSizerToActual(&xx
, &yy
);
3468 SetSize(xx
, yy
, w
, h
);
3471 void wxWindow::SizerMove(int x
, int y
)
3475 TransformSizerToActual(&xx
, &yy
);
3479 // Only set the size/position of the constraint (if any)
3480 void wxWindow::SetSizeConstraint(int x
, int y
, int w
, int h
)
3482 wxLayoutConstraints
*constr
= GetConstraints();
3487 constr
->left
.SetValue(x
);
3488 constr
->left
.SetDone(TRUE
);
3492 constr
->top
.SetValue(y
);
3493 constr
->top
.SetDone(TRUE
);
3497 constr
->width
.SetValue(w
);
3498 constr
->width
.SetDone(TRUE
);
3502 constr
->height
.SetValue(h
);
3503 constr
->height
.SetDone(TRUE
);
3508 void wxWindow::MoveConstraint(int x
, int y
)
3510 wxLayoutConstraints
*constr
= GetConstraints();
3515 constr
->left
.SetValue(x
);
3516 constr
->left
.SetDone(TRUE
);
3520 constr
->top
.SetValue(y
);
3521 constr
->top
.SetDone(TRUE
);
3526 void wxWindow::GetSizeConstraint(int *w
, int *h
) const
3528 wxLayoutConstraints
*constr
= GetConstraints();
3531 *w
= constr
->width
.GetValue();
3532 *h
= constr
->height
.GetValue();
3538 void wxWindow::GetClientSizeConstraint(int *w
, int *h
) const
3540 wxLayoutConstraints
*constr
= GetConstraints();
3543 *w
= constr
->width
.GetValue();
3544 *h
= constr
->height
.GetValue();
3547 GetClientSize(w
, h
);
3550 void wxWindow::GetPositionConstraint(int *x
, int *y
) const
3552 wxLayoutConstraints
*constr
= GetConstraints();
3555 *x
= constr
->left
.GetValue();
3556 *y
= constr
->top
.GetValue();